Revert "Merge backports 3.19-rc1."

This reverts commit 8d993c265e5f74b4489d9423bc2ad2c37e8f77ab.
because of an inadvertent non-merge commit.

Change-Id: I83179943b19a386729a691f850ab6fda48f237ed
diff --git a/.local-symbols b/.local-symbols
index ab02e9a..82cfa7c 100644
--- a/.local-symbols
+++ b/.local-symbols
@@ -1,25 +1,24 @@
-BACKPORT_DIR=
 BACKPORTS_VERSION=
 BACKPORTED_KERNEL_VERSION=
 BACKPORTED_KERNEL_NAME=
 WIRELESS=
 NET_CORE=
 EXPERT=
-BPAUTO_BUILD_CORDIC=
-BPAUTO_CORDIC=
-BPAUTO_BUILD_AVERAGE=
-BPAUTO_AVERAGE=
-BPAUTO_MII=
-BPAUTO_BUILD_DMA_SHARED_HELPERS=
-BPAUTO_BUILD_LEDS=
-BPAUTO_NEW_LEDS=
-BPAUTO_LEDS_CLASS=
-BPAUTO_LEDS_TRIGGERS=
-BPAUTO_USERSEL_BUILD_ALL=
-BPAUTO_CRYPTO_CCM=
-BPAUTO_BUILD_CRYPTO_CCM=
-BPAUTO_WANT_DEV_COREDUMP=
-BPAUTO_BUILD_WANT_DEV_COREDUMP=
+BACKPORT_BUILD_CORDIC=
+BACKPORT_CORDIC=
+BACKPORT_BUILD_AVERAGE=
+BACKPORT_AVERAGE=
+BACKPORT_MII=
+BACKPORT_BUILD_DMA_SHARED_HELPERS=
+BACKPORT_BUILD_LEDS=
+BACKPORT_NEW_LEDS=
+BACKPORT_LEDS_CLASS=
+BACKPORT_LEDS_TRIGGERS=
+BACKPORT_USERSEL_BUILD_ALL=
+BACKPORT_CRYPTO_CCM=
+BACKPORT_BUILD_CRYPTO_CCM=
+BACKPORT_WANT_DEV_COREDUMP=
+BACKPORT_BUILD_WANT_DEV_COREDUMP=
 CFG80211=
 NL80211_TESTMODE=
 CFG80211_DEVELOPER_WARNINGS=
@@ -40,7 +39,6 @@
 MAC80211_HAS_RC=
 MAC80211_RC_MINSTREL=
 MAC80211_RC_MINSTREL_HT=
-MAC80211_RC_MINSTREL_VHT=
 MAC80211_RC_DEFAULT_MINSTREL=
 MAC80211_RC_DEFAULT=
 MAC80211_MESH=
@@ -53,7 +51,6 @@
 MAC80211_MLME_DEBUG=
 MAC80211_STA_DEBUG=
 MAC80211_HT_DEBUG=
-MAC80211_OCB_DEBUG=
 MAC80211_IBSS_DEBUG=
 MAC80211_PS_DEBUG=
 MAC80211_MPL_DEBUG=
@@ -65,8 +62,6 @@
 MAC80211_TDLS_DEBUG=
 MAC80211_DEBUG_COUNTERS=
 BT=
-BT_BREDR=
-BT_LE=
 BT_6LOWPAN=
 BT_RFCOMM=
 BT_RFCOMM_TTY=
@@ -125,7 +120,6 @@
 ATH5K=
 ATH5K_DEBUG=
 ATH5K_TRACER=
-ATH5K_AHB=
 ATH5K_PCI=
 ATH5K_TEST_CHANNELS=
 ATH9K_HW=
@@ -143,7 +137,6 @@
 ATH9K_WOW=
 ATH9K_RFKILL=
 ATH9K_CHANNEL_CONTEXT=
-ATH9K_PCOEM=
 ATH9K_HTC=
 ATH9K_HTC_DEBUGFS=
 CARL9170=
@@ -545,12 +538,10 @@
 IR_MCEUSB=
 IR_ITE_CIR=
 IR_FINTEK=
-IR_MESON=
 IR_NUVOTON=
 IR_REDRAT3=
 IR_STREAMZAP=
 IR_WINBOND_CIR=
-IR_IGORPLUGUSB=
 IR_IGUANA=
 IR_TTUSBIR=
 IR_RX51=
@@ -632,6 +623,7 @@
 VIDEO_PVRUSB2_DVB=
 VIDEO_PVRUSB2_DEBUGIFC=
 VIDEO_HDPVR=
+VIDEO_TLG2300=
 VIDEO_USBVISION=
 VIDEO_STK1160_COMMON=
 VIDEO_STK1160_AC97=
@@ -763,12 +755,12 @@
 DVB_HOPPER=
 DVB_NGENE=
 DVB_DDBRIDGE=
-DVB_SMIPCIE=
 V4L_PLATFORM_DRIVERS=
 VIDEO_VIA_CAMERA=
 VIDEO_SH_VOU=
 VIDEO_VIU=
 VIDEO_TIMBERDALE=
+VIDEO_VINO=
 VIDEO_M32R_AR=
 VIDEO_M32R_AR_M64278=
 VIDEO_OMAP3=
@@ -787,7 +779,7 @@
 VIDEO_TI_VPE=
 VIDEO_TI_VPE_DEBUG=
 V4L_TEST_DRIVERS=
-VIDEO_VIM2M=
+VIDEO_MEM2MEM_TESTDEV=
 VIDEO_CAFE_CCIC=
 VIDEO_MMP_CAMERA=
 VIDEO_DAVINCI_VPIF_DISPLAY=
@@ -828,6 +820,11 @@
 VIDEO_SAMSUNG_S5P_MIXER_DEBUG=
 VIDEO_VIVID=
 SMS_SDIO_DRV=
+MEDIA_PARPORT_SUPPORT=
+VIDEO_BWQCAM=
+VIDEO_CQCAM=
+VIDEO_PMS=
+VIDEO_W9966=
 RADIO_ADAPTERS=
 RADIO_TEA575X=
 RADIO_SI470X=
@@ -917,6 +914,7 @@
 VIDEO_ML86V7667=
 VIDEO_SAA7110=
 VIDEO_SAA711X=
+VIDEO_SAA7191=
 VIDEO_TVP514X=
 VIDEO_TVP5150=
 VIDEO_TVP7002=
@@ -1009,7 +1007,6 @@
 MEDIA_TUNER_E4000=
 MEDIA_TUNER_FC2580=
 MEDIA_TUNER_M88TS2022=
-MEDIA_TUNER_M88RS6000T=
 MEDIA_TUNER_TUA9001=
 MEDIA_TUNER_SI2157=
 MEDIA_TUNER_IT913X=
@@ -1116,11 +1113,11 @@
 DVB_AF9033=
 DVB_DUMMY_FE=
 DVB_DRX39XYJ=
-6LOWPAN=
 IEEE802154=
 IEEE802154_6LOWPAN=
 MAC802154=
 IEEE802154_DRIVERS=
+IEEE802154_FAKEHARD=
 IEEE802154_FAKELB=
 IEEE802154_AT86RF230=
 IEEE802154_MRF24J40=
diff --git a/Kconfig b/Kconfig
index 9684574..b14a268 100644
--- a/Kconfig
+++ b/Kconfig
@@ -1,8 +1,5 @@
-mainmenu "Backports from $BACKPORTED_KERNEL_NAME $BACKPORTED_KERNEL_VERSION (backports $BACKPORTS_VERSION)"
+mainmenu "Linux Backports from $BACKPORTED_KERNEL_NAME $BACKPORTED_KERNEL_VERSION (with backports $BACKPORTS_VERSION)"
 
-config BACKPORT_DIR
-	string
-	option env="BACKPORT_DIR"
 config BACKPORTS_VERSION
 	string
 	option env="BACKPORTS_VERSION"
@@ -13,12 +10,38 @@
 	string
 	option env="BACKPORTED_KERNEL_NAME"
 
-# Packaging hacks
-source "$BACKPORT_DIR/Kconfig.package.hacks"
-
-# Code we backport
-source "$BACKPORT_DIR/Kconfig.sources"
-
 # these will be generated
-source "$BACKPORT_DIR/Kconfig.kernel"
-source "$BACKPORT_DIR/Kconfig.versions"
+source Kconfig.kernel
+source Kconfig.versions
+
+# some hacks ...
+config WIRELESS
+	def_bool y
+config NET_CORE
+	def_bool y
+config EXPERT
+	def_bool y
+
+# this has the configuration for the backport code
+source compat/Kconfig
+
+# these are copied from the kernel
+source net/wireless/Kconfig
+source net/mac80211/Kconfig
+source net/bluetooth/Kconfig
+source drivers/net/wireless/Kconfig
+source drivers/net/ethernet/Kconfig
+source drivers/net/usb/Kconfig
+
+source drivers/ssb/Kconfig
+source drivers/bcma/Kconfig
+
+source net/nfc/Kconfig
+
+source drivers/media/Kconfig
+
+source net/ieee802154/Kconfig
+source net/mac802154/Kconfig
+source drivers/net/ieee802154/Kconfig
+
+source drivers/usb/class/Kconfig
diff --git a/Kconfig.package.hacks b/Kconfig.package.hacks
deleted file mode 100644
index 6a429dd..0000000
--- a/Kconfig.package.hacks
+++ /dev/null
@@ -1,8 +0,0 @@
-# some hacks for when we use backports to generate a package
-# to build modules out of tree.
-config WIRELESS
-	def_bool y
-config NET_CORE
-	def_bool y
-config EXPERT
-	def_bool y
diff --git a/Kconfig.sources b/Kconfig.sources
deleted file mode 100644
index 5711433..0000000
--- a/Kconfig.sources
+++ /dev/null
@@ -1,24 +0,0 @@
-# this has the configuration for the backport code
-source "$BACKPORT_DIR/compat/Kconfig"
-
-# these are copied from the kernel
-source "$BACKPORT_DIR/net/wireless/Kconfig"
-source "$BACKPORT_DIR/net/mac80211/Kconfig"
-source "$BACKPORT_DIR/net/bluetooth/Kconfig"
-source "$BACKPORT_DIR/drivers/net/wireless/Kconfig"
-source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig"
-source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
-
-source "$BACKPORT_DIR/drivers/ssb/Kconfig"
-source "$BACKPORT_DIR/drivers/bcma/Kconfig"
-
-source "$BACKPORT_DIR/net/nfc/Kconfig"
-
-source "$BACKPORT_DIR/drivers/media/Kconfig"
-
-source "$BACKPORT_DIR/net/6lowpan/Kconfig"
-source "$BACKPORT_DIR/net/ieee802154/Kconfig"
-source "$BACKPORT_DIR/net/mac802154/Kconfig"
-source "$BACKPORT_DIR/drivers/net/ieee802154/Kconfig"
-
-source "$BACKPORT_DIR/drivers/usb/class/Kconfig"
diff --git a/MAINTAINERS b/MAINTAINERS
index ddb9ac8..a20df9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -618,16 +618,6 @@
 F:	drivers/iommu/amd_iommu*.[ch]
 F:	include/linux/amd-iommu.h
 
-AMD KFD
-M:      Oded Gabbay <oded.gabbay@amd.com>
-L:      dri-devel@lists.freedesktop.org
-T:      git git://people.freedesktop.org/~gabbayo/linux.git
-S:      Supported
-F:      drivers/gpu/drm/amd/amdkfd/
-F:      drivers/gpu/drm/radeon/radeon_kfd.c
-F:      drivers/gpu/drm/radeon/radeon_kfd.h
-F:      include/uapi/linux/kfd_ioctl.h
-
 AMD MICROCODE UPDATE SUPPORT
 M:	Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:	amd64-microcode@amd64.org
@@ -860,7 +850,6 @@
 M:	Carlo Caione <carlo@caione.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
-F:	drivers/media/rc/meson-ir.c
 N:	meson[x68]
 
 ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES
@@ -872,7 +861,6 @@
 W:	http://www.linux4sam.org
 S:	Supported
 F:	arch/arm/mach-at91/
-F:	include/soc/at91/
 F:	arch/arm/boot/dts/at91*.dts
 F:	arch/arm/boot/dts/at91*.dtsi
 F:	arch/arm/boot/dts/sama*.dts
@@ -930,15 +918,6 @@
 S:	Maintained
 F:	arch/arm/mach-ep93xx/micro9.c
 
-ARM/CORESIGHT FRAMEWORK AND DRIVERS
-M:	Mathieu Poirier <mathieu.poirier@linaro.org>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:	Maintained
-F:	drivers/coresight/*
-F:	Documentation/trace/coresight.txt
-F:	Documentation/devicetree/bindings/arm/coresight.txt
-F:	Documentation/ABI/testing/sysfs-bus-coresight-devices-*
-
 ARM/CORGI MACHINE SUPPORT
 M:	Richard Purdie <rpurdie@rpsys.net>
 S:	Maintained
@@ -1329,22 +1308,30 @@
 F:	drivers/*/*/*rockchip*
 F:	sound/soc/rockchip/
 
-ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
-M:	Kukjin Kim <kgene@kernel.org>
+ARM/SAMSUNG ARM ARCHITECTURES
+M:	Ben Dooks <ben-linux@fluff.org>
+M:	Kukjin Kim <kgene.kim@samsung.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:	linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+W:	http://www.fluff.org/ben/linux/
 S:	Maintained
 F:	arch/arm/boot/dts/s3c*
 F:	arch/arm/boot/dts/exynos*
 F:	arch/arm/plat-samsung/
 F:	arch/arm/mach-s3c24*/
 F:	arch/arm/mach-s3c64xx/
-F:	arch/arm/mach-s5p*/
-F:	arch/arm/mach-exynos*/
 F:	drivers/*/*s3c2410*
 F:	drivers/*/*/*s3c2410*
 F:	drivers/spi/spi-s3c*
 F:	sound/soc/samsung/*
+
+ARM/S5P EXYNOS ARM ARCHITECTURES
+M:	Kukjin Kim <kgene.kim@samsung.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:	linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-s5p*/
+F:	arch/arm/mach-exynos*/
 N:	exynos
 
 ARM/SAMSUNG MOBILE MACHINE SUPPORT
@@ -1394,12 +1381,12 @@
 F:	arch/arm/configs/ape6evm_defconfig
 F:	arch/arm/configs/armadillo800eva_defconfig
 F:	arch/arm/configs/bockw_defconfig
+F:	arch/arm/configs/koelsch_defconfig
 F:	arch/arm/configs/kzm9g_defconfig
 F:	arch/arm/configs/lager_defconfig
 F:	arch/arm/configs/mackerel_defconfig
 F:	arch/arm/configs/marzen_defconfig
 F:	arch/arm/configs/shmobile_defconfig
-F:	arch/arm/include/debug/renesas-scif.S
 F:	arch/arm/mach-shmobile/
 F:	drivers/sh/
 
@@ -1443,7 +1430,6 @@
 F:	drivers/usb/dwc3/dwc3-st.c
 F:	drivers/usb/host/ehci-st.c
 F:	drivers/usb/host/ohci-st.c
-F:	drivers/ata/ahci_st.c
 
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
@@ -1517,19 +1503,6 @@
 F:	drivers/clk/ux500/
 F:	include/linux/platform_data/clk-ux500.h
 
-ARM/VERSATILE EXPRESS PLATFORM
-M:	Liviu Dudau <liviu.dudau@arm.com>
-M:	Sudeep Holla <sudeep.holla@arm.com>
-M:	Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:	Maintained
-F:	arch/arm/boot/dts/vexpress*
-F:	arch/arm/mach-vexpress/
-F:	*/*/vexpress*
-F:	*/*/*/vexpress*
-F:	drivers/clk/versatile/clk-vexpress-osc.c
-F:	drivers/clocksource/versatile.c
-
 ARM/VFP SUPPORT
 M:	Russell King <linux@arm.linux.org.uk>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1570,7 +1543,6 @@
 
 ARM/ZYNQ ARCHITECTURE
 M:	Michal Simek <michal.simek@xilinx.com>
-R:	Sören Brinkmann <soren.brinkmann@xilinx.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:	http://wiki.xilinx.com
 T:	git git://git.xilinx.com/linux-xlnx.git
@@ -1741,13 +1713,6 @@
 F:	drivers/dma/at_hdmac_regs.h
 F:	include/linux/platform_data/dma-atmel.h
 
-ATMEL XDMA DRIVER
-M:	Ludovic Desroches <ludovic.desroches@atmel.com>
-L:	linux-arm-kernel@lists.infradead.org
-L:	dmaengine@vger.kernel.org
-S:	Supported
-F:	drivers/dma/at_xdmac.c
-
 ATMEL I2C DRIVER
 M:	Ludovic Desroches <ludovic.desroches@atmel.com>
 L:	linux-i2c@vger.kernel.org
@@ -1784,13 +1749,6 @@
 S:	Supported
 F:	drivers/spi/spi-atmel.*
 
-ATMEL SSC DRIVER
-M:	Bo Shen <voice.shen@atmel.com>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:	Supported
-F:	drivers/misc/atmel-ssc.c
-F:	include/linux/atmel-ssc.h
-
 ATMEL Timer Counter (TC) AND CLOCKSOURCE DRIVERS
 M:	Nicolas Ferre <nicolas.ferre@atmel.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1820,11 +1778,10 @@
 F:	drivers/scsi/esas2r
 
 AUDIT SUBSYSTEM
-M:	Paul Moore <paul@paul-moore.com>
 M:	Eric Paris <eparis@redhat.com>
-L:	linux-audit@redhat.com (moderated for non-subscribers)
+L:	linux-audit@redhat.com (subscribers-only)
 W:	http://people.redhat.com/sgrubb/audit/
-T:	git git://git.infradead.org/users/pcmoore/audit
+T:	git git://git.infradead.org/users/eparis/audit.git
 S:	Maintained
 F:	include/linux/audit.h
 F:	include/uapi/linux/audit.h
@@ -1863,7 +1820,7 @@
 F:	net/ax25/
 
 AZ6007 DVB DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -1897,6 +1854,7 @@
 
 BACKLIGHT CLASS/SUBSYSTEM
 M:	Jingoo Han <jg1.han@samsung.com>
+M:	Bryan Wu <cooloney@gmail.com>
 M:	Lee Jones <lee.jones@linaro.org>
 S:	Maintained
 F:	drivers/video/backlight/
@@ -1925,6 +1883,13 @@
 S:	Maintained:
 F:	drivers/md/bcache/
 
+BECEEM BCS200/BCS220-3/BCSM250 WIMAX SUPPORT
+M: Kevin McKinney <klmckinney1@gmail.com>
+M: Matthias Beyer <mail@beyermatthias.de>
+L: devel@driverdev.osuosl.org
+S: Maintained
+F: drivers/staging/bcm*
+
 BEFS FILE SYSTEM
 S:	Orphan
 F:	Documentation/filesystems/befs.txt
@@ -2099,20 +2064,11 @@
 
 BROADCOM BCM2835 ARM ARCHITECTURE
 M:	Stephen Warren <swarren@wwwdotorg.org>
-M:	Lee Jones <lee@kernel.org>
 L:	linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git
 S:	Maintained
 N:	bcm2835
 
-BROADCOM BCM33XX MIPS ARCHITECTURE
-M:	Kevin Cernekee <cernekee@gmail.com>
-L:	linux-mips@linux-mips.org
-S:	Maintained
-F:	arch/mips/bcm3384/*
-F:	arch/mips/include/asm/mach-bcm3384/*
-F:	arch/mips/kernel/*bmips*
-
 BROADCOM BCM5301X ARM ARCHITECTURE
 M:	Hauke Mehrtens <hauke@hauke-m.de>
 L:	linux-arm-kernel@lists.infradead.org
@@ -2129,34 +2085,13 @@
 F:	arch/arm/mach-bcm/bcm63xx.c
 F:	arch/arm/include/debug/bcm63xx.S
 
-BROADCOM BCM63XX/BCM33XX UDC DRIVER
-M:	Kevin Cernekee <cernekee@gmail.com>
-L:	linux-usb@vger.kernel.org
-S:	Maintained
-F:	drivers/usb/gadget/udc/bcm63xx_udc.*
-
 BROADCOM BCM7XXX ARM ARCHITECTURE
 M:	Marc Carino <marc.ceeeee@gmail.com>
 M:	Brian Norris <computersforpeace@gmail.com>
-M:	Gregory Fong <gregory.0xf0@gmail.com>
-M:	Florian Fainelli <f.fainelli@gmail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-bcm/*brcmstb*
 F:	arch/arm/boot/dts/bcm7*.dts*
-F:	drivers/bus/brcmstb_gisb.c
-
-BROADCOM BMIPS MIPS ARCHITECTURE
-M:	Kevin Cernekee <cernekee@gmail.com>
-M:	Florian Fainelli <f.fainelli@gmail.com>
-L:	linux-mips@linux-mips.org
-S:	Maintained
-F:	arch/mips/bmips/*
-F:	arch/mips/include/asm/mach-bmips/*
-F:	arch/mips/kernel/*bmips*
-F:	arch/mips/boot/dts/bcm*.dts*
-F:	drivers/irqchip/irq-bcm7*
-F:	drivers/irqchip/irq-brcmstb*
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M:	Prashant Sreedharan <prashant@broadcom.com>
@@ -2187,20 +2122,6 @@
 S:	Supported
 F:	drivers/scsi/bnx2i/
 
-BROADCOM CYGNUS/IPROC ARM ARCHITECTURE
-M:	Ray Jui <rjui@broadcom.com>
-M:	Scott Branden <sbranden@broadcom.com>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-L:	bcm-kernel-feedback-list@broadcom.com
-T:	git git://git.github.com/brcm/linux.git
-S:	Maintained
-N:	iproc
-N:	cygnus
-N:	bcm9113*
-N:	bcm9583*
-N:	bcm583*
-N:	bcm113*
-
 BROADCOM KONA GPIO DRIVER
 M:	Ray Jui <rjui@broadcom.com>
 L:	bcm-kernel-feedback-list@broadcom.com
@@ -2268,7 +2189,7 @@
 F:	fs/btrfs/
 
 BTTV VIDEO4LINUX DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -2378,14 +2299,6 @@
 F:	security/commoncap.c
 F:	kernel/capability.c
 
-CC2520 IEEE-802.15.4 RADIO DRIVER
-M:	Varka Bhadram <varkabhadram@gmail.com>
-L:	linux-wpan@vger.kernel.org
-S:	Maintained
-F:	drivers/net/ieee802154/cc2520.c
-F:	include/linux/spi/cc2520.h
-F:	Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
-
 CELL BROADBAND ENGINE ARCHITECTURE
 M:	Arnd Bergmann <arnd@arndb.de>
 L:	linuxppc-dev@lists.ozlabs.org
@@ -2567,18 +2480,10 @@
 F:	include/linux/coda*.h
 F:	include/uapi/linux/coda*.h
 
-CODA V4L2 MEM2MEM DRIVER
-M:	Philipp Zabel <p.zabel@pengutronix.de>
-L:	linux-media@vger.kernel.org
-S:	Maintained
-F:	Documentation/devicetree/bindings/media/coda.txt
-F:	drivers/media/platform/coda/
-
 COMMON CLK FRAMEWORK
 M:	Mike Turquette <mturquette@linaro.org>
-M:	Stephen Boyd <sboyd@codeaurora.org>
 L:	linux-kernel@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
+T:	git git://git.linaro.org/people/mturquette/linux.git
 S:	Maintained
 F:	drivers/clk/
 X:	drivers/clk/clkdev.c
@@ -2590,7 +2495,8 @@
 L:	linux-cifs@vger.kernel.org
 L:	samba-technical@lists.samba.org (moderated for non-subscribers)
 W:	http://linux-cifs.samba.org/
-T:	git git://git.samba.org/sfrench/cifs-2.6.git
+Q:	http://patchwork.ozlabs.org/project/linux-cifs-client/list/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
 S:	Supported
 F:	Documentation/filesystems/cifs/
 F:	fs/cifs/
@@ -2667,7 +2573,7 @@
 L:	linux-mm@kvack.org
 S:	Maintained
 F:	mm/memcontrol.c
-F:	mm/swap_cgroup.c
+F:	mm/page_cgroup.c
 
 CORETEMP HARDWARE MONITORING DRIVER
 M:	Fenghua Yu <fenghua.yu@intel.com>
@@ -2717,16 +2623,6 @@
 S:	Maintained
 F:	drivers/cpuidle/cpuidle-big_little.c
 
-CPUIDLE DRIVER - ARM EXYNOS
-M:	Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-M:	Daniel Lezcano <daniel.lezcano@linaro.org>
-M:	Kukjin Kim <kgene@kernel.org>
-L:	linux-pm@vger.kernel.org
-L:	linux-samsung-soc@vger.kernel.org
-S:	Supported
-F:	drivers/cpuidle/cpuidle-exynos.c
-F:	arch/arm/mach-exynos/pm.c
-
 CPUIDLE DRIVERS
 M:	Rafael J. Wysocki <rjw@rjwysocki.net>
 M:	Daniel Lezcano <daniel.lezcano@linaro.org>
@@ -2794,7 +2690,7 @@
 
 CX18 VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@md.metrocast.net>
-L:	ivtv-devel@ivtvdriver.org (subscribers-only)
+L:	ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
 L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 W:	http://linuxtv.org
@@ -2814,7 +2710,7 @@
 F:	include/media/cx2341x*
 
 CX88 VIDEO4LINUX DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -2839,13 +2735,6 @@
 S:	Supported
 F:	drivers/net/ethernet/chelsio/cxgb3/
 
-CXGB3 ISCSI DRIVER (CXGB3I)
-M:      Karen Xie <kxie@chelsio.com>
-L:      linux-scsi@vger.kernel.org
-W:      http://www.chelsio.com
-S:      Supported
-F:      drivers/scsi/cxgbi/cxgb3i
-
 CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
 M:	Steve Wise <swise@chelsio.com>
 L:	linux-rdma@vger.kernel.org
@@ -2860,13 +2749,6 @@
 S:	Supported
 F:	drivers/net/ethernet/chelsio/cxgb4/
 
-CXGB4 ISCSI DRIVER (CXGB4I)
-M:      Karen Xie <kxie@chelsio.com>
-L:      linux-scsi@vger.kernel.org
-W:      http://www.chelsio.com
-S:      Supported
-F:      drivers/scsi/cxgbi/cxgb4i
-
 CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
 M:	Steve Wise <swise@chelsio.com>
 L:	linux-rdma@vger.kernel.org
@@ -2957,10 +2839,11 @@
 F:	drivers/net/ethernet/dec/tulip/dmfe.c
 
 DC390/AM53C974 SCSI driver
-M:	Hannes Reinecke <hare@suse.de>
-L:	linux-scsi@vger.kernel.org
+M:	Kurt Garloff <garloff@suse.de>
+W:	http://www.garloff.de/kurt/linux/dc390/
+M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 S:	Maintained
-F:	drivers/scsi/am53c974.c
+F:	drivers/scsi/tmscsim.*
 
 DC395x SCSI driver
 M:	Oliver Neukum <oliver@neukum.org>
@@ -3183,8 +3066,7 @@
 S:	Maintained
 F:	drivers/dma/
 F:	include/linux/dma*
-F:	Documentation/dmaengine/
-T:	git git://git.infradead.org/users/vkoul/slave-dma.git
+T:	git git://git.infradead.org/users/vkoul/slave-dma.git (slave-dma)
 
 DME1737 HARDWARE MONITOR DRIVER
 M:	Juerg Haefliger <juergh@gmail.com>
@@ -3301,13 +3183,6 @@
 F:	include/drm/exynos*
 F:	include/uapi/drm/exynos*
 
-DRM DRIVERS FOR FREESCALE IMX
-M:	Philipp Zabel <p.zabel@pengutronix.de>
-L:	dri-devel@lists.freedesktop.org
-S:	Maintained
-F:	drivers/gpu/drm/imx/
-F:	Documentation/devicetree/bindings/drm/imx/
-
 DRM DRIVERS FOR NVIDIA TEGRA
 M:	Thierry Reding <thierry.reding@gmail.com>
 M:	Terje Bergström <tbergstrom@nvidia.com>
@@ -3504,7 +3379,7 @@
 EDAC-CORE
 M:	Doug Thompson <dougthompson@xmission.com>
 M:	Borislav Petkov <bp@alien8.de>
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Supported
@@ -3553,7 +3428,7 @@
 F:	drivers/edac/e7xxx_edac.c
 
 EDAC-GHES
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Maintained
@@ -3581,21 +3456,21 @@
 F:	drivers/edac/i5000_edac.c
 
 EDAC-I5400
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Maintained
 F:	drivers/edac/i5400_edac.c
 
 EDAC-I7300
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Maintained
 F:	drivers/edac/i7300_edac.c
 
 EDAC-I7CORE
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Maintained
@@ -3638,7 +3513,7 @@
 F:	drivers/edac/r82600_edac.c
 
 EDAC-SBRIDGE
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Maintained
@@ -3698,7 +3573,7 @@
 F:	drivers/net/ethernet/ibm/ehea/
 
 EM28XX VIDEO4LINUX DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -4066,7 +3941,7 @@
 FREESCALE SOC SOUND DRIVERS
 M:	Timur Tabi <timur@tabi.org>
 M:	Nicolin Chen <nicoleotsuka@gmail.com>
-M:	Xiubo Li <Xiubo.Lee@gmail.com>
+M:	Xiubo Li <Li.Xiubo@freescale.com>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:	linuxppc-dev@lists.ozlabs.org
 S:	Maintained
@@ -4256,12 +4131,6 @@
 S:	Maintained
 F:	drivers/media/usb/go7007/
 
-GOODIX TOUCHSCREEN
-M:	Bastien Nocera <hadess@hadess.net>
-L:	linux-input@vger.kernel.org
-S:	Maintained
-F:	drivers/input/touchscreen/goodix.c
-
 GPIO SUBSYSTEM
 M:	Linus Walleij <linus.walleij@linaro.org>
 M:	Alexandre Courbot <gnurou@gmail.com>
@@ -4436,10 +4305,8 @@
 F:	drivers/block/cpqarray.*
 
 HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
-M:	Don Brace <don.brace@pmcs.com>
+M:	"Stephen M. Cameron" <scameron@beardog.cce.hp.com>
 L:	iss_storagedev@hp.com
-L:	storagedev@pmcs.com
-L:	linux-scsi@vger.kernel.org
 S:	Supported
 F:	Documentation/scsi/hpsa.txt
 F:	drivers/scsi/hpsa*.[ch]
@@ -4447,10 +4314,8 @@
 F:	include/uapi/linux/cciss*.h
 
 HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
-M:	Don Brace <don.brace@pmcs.com>
+M:	Mike Miller <mike.miller@hp.com>
 L:	iss_storagedev@hp.com
-L:	storagedev@pmcs.com
-L:	linux-scsi@vger.kernel.org
 S:	Supported
 F:	Documentation/blockdev/cciss.txt
 F:	drivers/block/cciss*
@@ -4683,7 +4548,6 @@
 Q:	https://patchwork.ozlabs.org/project/linux-i2c/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
 S:	Maintained
-F:	Documentation/devicetree/bindings/i2c/
 F:	Documentation/i2c/
 F:	drivers/i2c/
 F:	include/linux/i2c.h
@@ -4737,7 +4601,7 @@
 F:	drivers/crypto/nx/
 
 IBM Power 842 compression accelerator
-M:	Dan Streetman <ddstreet@us.ibm.com>
+M:	Nathan Fontenot <nfont@linux.vnet.ibm.com>
 S:	Supported
 F:	drivers/crypto/nx/nx-842.c
 F:	include/linux/nx842.h
@@ -4822,21 +4686,8 @@
 F:	net/ieee802154/
 F:	net/mac802154/
 F:	drivers/net/ieee802154/
-F:	include/linux/nl802154.h
-F:	include/linux/ieee802154.h
-F:	include/net/nl802154.h
-F:	include/net/mac802154.h
-F:	include/net/af_ieee802154.h
-F:	include/net/cfg802154.h
-F:	include/net/ieee802154_netdev.h
 F:	Documentation/networking/ieee802154.txt
 
-IGORPLUG-USB IR RECEIVER
-M:	Sean Young <sean@mess.org>
-L:	linux-media@vger.kernel.org
-S:	Maintained
-F:	drivers/media/rc/igorplugusb.c
-
 IGUANAWORKS USB IR TRANSCEIVER
 M:	Sean Young <sean@mess.org>
 L:	linux-media@vger.kernel.org
@@ -4852,7 +4703,6 @@
 S:	Maintained
 F:	drivers/iio/
 F:	drivers/staging/iio/
-F:	include/linux/iio/
 
 IKANOS/ADI EAGLE ADSL USB DRIVER
 M:	Matthieu Castet <castet.matthieu@free.fr>
@@ -4894,11 +4744,6 @@
 S:	Supported
 F:	security/integrity/ima/
 
-IMGTEC IR DECODER DRIVER
-M:	James Hogan <james.hogan@imgtec.com>
-S:	Maintained
-F:	drivers/media/rc/img-ir/
-
 IMS TWINTURBO FRAMEBUFFER DRIVER
 L:	linux-fbdev@vger.kernel.org
 S:	Orphan
@@ -4964,12 +4809,6 @@
 S:	Supported
 F:	drivers/idle/intel_idle.c
 
-INTEL PSTATE DRIVER
-M:	Kristen Carlson Accardi <kristen@linux.intel.com>
-L:	linux-pm@vger.kernel.org
-S:	Supported
-F:	drivers/cpufreq/intel_pstate.c
-
 INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
 M:	Maik Broemme <mbroemme@plusserver.de>
 L:	linux-fbdev@vger.kernel.org
@@ -5319,7 +5158,7 @@
 
 IVTV VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@md.metrocast.net>
-L:	ivtv-devel@ivtvdriver.org (subscribers-only)
+L:	ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
 L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 W:	http://www.ivtvdriver.org
@@ -5502,6 +5341,15 @@
 F:	arch/powerpc/include/asm/kvm*
 F:	arch/powerpc/kvm/
 
+KERNEL VIRTUAL MACHINE For Itanium (KVM/IA64)
+M:	Xiantao Zhang <xiantao.zhang@intel.com>
+L:	kvm-ia64@vger.kernel.org
+W:	http://kvm.qumranet.com
+S:	Supported
+F:	Documentation/ia64/kvm.txt
+F:	arch/ia64/include/asm/kvm*
+F:	arch/ia64/kvm/
+
 KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
 M:	Christian Borntraeger <borntraeger@de.ibm.com>
 M:	Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -5986,14 +5834,6 @@
 F:	drivers/net/macvlan.c
 F:	include/linux/if_macvlan.h
 
-MAILBOX API
-M:	Jassi Brar <jassisinghbrar@gmail.com>
-L:	linux-kernel@vger.kernel.org
-S:	Maintained
-F:	drivers/mailbox/
-F:	include/linux/mailbox_client.h
-F:	include/linux/mailbox_controller.h
-
 MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
 M:	Michael Kerrisk <mtk.manpages@gmail.com>
 W:	http://www.kernel.org/doc/man-pages
@@ -6005,11 +5845,6 @@
 S:	Maintained
 F:	drivers/gpu/drm/armada/
 
-MARVELL 88E6352 DSA support
-M:	Guenter Roeck <linux@roeck-us.net>
-S:	Maintained
-F:	drivers/net/dsa/mv88e6352.c
-
 MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
 M:	Mirko Lindner <mlindner@marvell.com>
 M:	Stephen Hemminger <stephen@networkplumber.org>
@@ -6091,7 +5926,7 @@
 F:	drivers/media/radio/radio-maxiradio*
 
 MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 P:	LinuxTV.org Project
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
@@ -6120,13 +5955,10 @@
 S:	Odd Fixes
 F:	drivers/media/parport/pms*
 
-MEGARAID SCSI/SAS DRIVERS
-M:	Kashyap Desai <kashyap.desai@avagotech.com>
-M:	Sumit Saxena <sumit.saxena@avagotech.com>
-M:	Uday Lingala <uday.lingala@avagotech.com>
-L:	megaraidlinux.pdl@avagotech.com
+MEGARAID SCSI DRIVERS
+M:	Neela Syam Kolli <megaraidlinux@lsi.com>
 L:	linux-scsi@vger.kernel.org
-W:	http://www.lsi.com
+W:	http://megaraid.lsilogic.com
 S:	Maintained
 F:	Documentation/scsi/megaraid.txt
 F:	drivers/scsi/megaraid.*
@@ -6249,28 +6081,6 @@
 F:	include/linux/mlx5/
 F:	drivers/infiniband/hw/mlx5/
 
-MN88472 MEDIA DRIVER
-M:	Antti Palosaari <crope@iki.fi>
-L:	linux-media@vger.kernel.org
-W:	http://linuxtv.org/
-W:	http://palosaari.fi/linux/
-Q:	http://patchwork.linuxtv.org/project/linux-media/list/
-T:	git git://linuxtv.org/anttip/media_tree.git
-S:	Maintained
-F:	drivers/staging/media/mn88472/
-F:	drivers/media/dvb-frontends/mn88472.h
-
-MN88473 MEDIA DRIVER
-M:	Antti Palosaari <crope@iki.fi>
-L:	linux-media@vger.kernel.org
-W:	http://linuxtv.org/
-W:	http://palosaari.fi/linux/
-Q:	http://patchwork.linuxtv.org/project/linux-media/list/
-T:	git git://linuxtv.org/anttip/media_tree.git
-S:	Maintained
-F:	drivers/staging/media/mn88473/
-F:	drivers/media/dvb-frontends/mn88473.h
-
 MODULE SUPPORT
 M:	Rusty Russell <rusty@rustcorp.com.au>
 S:	Maintained
@@ -6459,6 +6269,7 @@
 F:	drivers/scsi/g_NCR5380_mmio.c
 F:	drivers/scsi/mac_scsi.*
 F:	drivers/scsi/pas16.*
+F:	drivers/scsi/sun3_NCR5380.c
 F:	drivers/scsi/sun3_scsi.*
 F:	drivers/scsi/sun3_scsi_vme.c
 F:	drivers/scsi/t128.*
@@ -6617,8 +6428,19 @@
 S:	Maintained
 
 NETWORKING [WIRELESS]
+M:	"John W. Linville" <linville@tuxdriver.com>
 L:	linux-wireless@vger.kernel.org
 Q:	http://patchwork.kernel.org/project/linux-wireless/list/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git
+S:	Maintained
+F:	net/mac80211/
+F:	net/rfkill/
+F:	net/wireless/
+F:	include/net/ieee80211*
+F:	include/linux/wireless.h
+F:	include/uapi/linux/wireless.h
+F:	include/net/iw_handler.h
+F:	drivers/net/wireless/
 
 NETWORKING DRIVERS
 L:	netdev@vger.kernel.org
@@ -6639,14 +6461,6 @@
 F:	include/uapi/linux/if_*
 F:	include/uapi/linux/netdevice.h
 
-NETWORKING DRIVERS (WIRELESS)
-M:	Kalle Valo <kvalo@codeaurora.org>
-L:	linux-wireless@vger.kernel.org
-Q:	http://patchwork.kernel.org/project/linux-wireless/list/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git/
-S:	Maintained
-F:	drivers/net/wireless/
-
 NETXEN (1/10) GbE SUPPORT
 M:	Manish Chopra <manish.chopra@qlogic.com>
 M:	Sony Chacko <sony.chacko@qlogic.com>
@@ -6711,13 +6525,6 @@
 F:	Documentation/scsi/NinjaSCSI.txt
 F:	drivers/scsi/nsp32*
 
-NIOS2 ARCHITECTURE
-M:	Ley Foon Tan <lftan@altera.com>
-L:	nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
-T:	git git://git.rocketboards.org/linux-socfpga.git
-S:	Maintained
-F:	arch/nios2/
-
 NTB DRIVER
 M:	Jon Mason <jdmason@kudzu.us>
 M:	Dave Jiang <dave.jiang@intel.com>
@@ -6758,12 +6565,6 @@
 F:	drivers/gpu/drm/i2c/tda998x_drv.c
 F:	include/drm/i2c/tda998x.h
 
-NXP TFA9879 DRIVER
-M:	Peter Rosin <peda@axentia.se>
-L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
-S:	Maintained
-F:	sound/soc/codecs/tfa9879*
-
 OMAP SUPPORT
 M:	Tony Lindgren <tony@atomide.com>
 L:	linux-omap@vger.kernel.org
@@ -6774,23 +6575,6 @@
 S:	Maintained
 F:	arch/arm/*omap*/
 F:	drivers/i2c/busses/i2c-omap.c
-F:	drivers/irqchip/irq-omap-intc.c
-F:	drivers/mfd/*omap*.c
-F:	drivers/mfd/menelaus.c
-F:	drivers/mfd/palmas.c
-F:	drivers/mfd/tps65217.c
-F:	drivers/mfd/tps65218.c
-F:	drivers/mfd/tps65910.c
-F:	drivers/mfd/twl-core.[ch]
-F:	drivers/mfd/twl4030*.c
-F:	drivers/mfd/twl6030*.c
-F:	drivers/mfd/twl6040*.c
-F:	drivers/regulator/palmas-regulator*.c
-F:	drivers/regulator/pbias-regulator.c
-F:	drivers/regulator/tps65217-regulator.c
-F:	drivers/regulator/tps65218-regulator.c
-F:	drivers/regulator/tps65910-regulator.c
-F:	drivers/regulator/twl-regulator.c
 F:	include/linux/i2c-omap.h
 
 OMAP DEVICE TREE SUPPORT
@@ -6801,9 +6585,6 @@
 S:	Maintained
 F:	arch/arm/boot/dts/*omap*
 F:	arch/arm/boot/dts/*am3*
-F:	arch/arm/boot/dts/*am4*
-F:	arch/arm/boot/dts/*am5*
-F:	arch/arm/boot/dts/*dra7*
 
 OMAP CLOCK FRAMEWORK SUPPORT
 M:	Paul Walmsley <paul@pwsan.com>
@@ -6833,14 +6614,6 @@
 S:	Maintained
 F:	sound/soc/omap/
 
-OMAP GENERAL PURPOSE MEMORY CONTROLLER SUPPORT
-M:	Roger Quadros <rogerq@ti.com>
-M:	Tony Lindgren <tony@atomide.com>
-L:	linux-omap@vger.kernel.org
-S:	Maintained
-F:	drivers/memory/omap-gpmc.c
-F:	arch/arm/mach-omap2/*gpmc*
-
 OMAP FRAMEBUFFER SUPPORT
 M:	Tomi Valkeinen <tomi.valkeinen@ti.com>
 L:	linux-fbdev@vger.kernel.org
@@ -7049,7 +6822,7 @@
 F:	drivers/net/wireless/orinoco/
 
 OSD LIBRARY and FILESYSTEM
-M:	Boaz Harrosh <ooo@electrozaur.com>
+M:	Boaz Harrosh <bharrosh@panasas.com>
 M:	Benny Halevy <bhalevy@primarydata.com>
 L:	osd-dev@open-osd.org
 W:	http://open-osd.org
@@ -7059,14 +6832,6 @@
 F:	include/scsi/osd_*
 F:	fs/exofs/
 
-OVERLAY FILESYSTEM
-M:	Miklos Szeredi <miklos@szeredi.hu>
-L:	linux-unionfs@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git
-S:	Supported
-F:	fs/overlayfs/
-F:	Documentation/filesystems/overlayfs.txt
-
 P54 WIRELESS DRIVER
 M:	Christian Lamparter <chunkeey@googlemail.com>
 L:	linux-wireless@vger.kernel.org
@@ -7218,16 +6983,6 @@
 F:	Documentation/devicetree/bindings/pci/xgene-pci.txt
 F:	drivers/pci/host/pci-xgene.c
 
-PCI DRIVER FOR FREESCALE LAYERSCAPE
-M:	Minghuan Lian <minghuan.Lian@freescale.com>
-M:	Mingkai Hu <mingkai.hu@freescale.com>
-M:	Roy Zang <tie-fei.zang@freescale.com>
-L:	linuxppc-dev@lists.ozlabs.org
-L:	linux-pci@vger.kernel.org
-L:	linux-arm-kernel@lists.infradead.org
-S:	Maintained
-F:	drivers/pci/host/*layerscape*
-
 PCI DRIVER FOR IMX6
 M:	Richard Zhu <r65037@freescale.com>
 M:	Lucas Stach <l.stach@pengutronix.de>
@@ -7398,7 +7153,6 @@
 
 PIN CONTROL SUBSYSTEM
 M:	Linus Walleij <linus.walleij@linaro.org>
-L:	linux-gpio@vger.kernel.org
 S:	Maintained
 F:	drivers/pinctrl/
 F:	include/linux/pinctrl/
@@ -7407,13 +7161,7 @@
 M:	Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
-F:	drivers/pinctrl/pinctrl-at91.*
-
-PIN CONTROLLER - INTEL
-M:	Mika Westerberg <mika.westerberg@linux.intel.com>
-M:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
-S:	Maintained
-F:	drivers/pinctrl/intel/
+F:	drivers/pinctrl/pinctrl-at91.c
 
 PIN CONTROLLER - RENESAS
 M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -8032,13 +7780,6 @@
 F:	include/linux/hid-roccat*
 F:	Documentation/ABI/*/sysfs-driver-hid-roccat*
 
-ROCKER DRIVER
-M:	Jiri Pirko <jiri@resnulli.us>
-M:	Scott Feldman <sfeldma@gmail.com>
-L:	netdev@vger.kernel.org
-S:	Supported
-F:	drivers/net/ethernet/rocker/
-
 ROCKETPORT DRIVER
 P:	Comtrol Corp.
 W:	http://www.comtrol.com
@@ -8046,12 +7787,6 @@
 F:	Documentation/serial/rocket.txt
 F:	drivers/tty/rocket*
 
-ROCKETPORT EXPRESS/INFINITY DRIVER
-M:	Kevin Cernekee <cernekee@gmail.com>
-L:	linux-serial@vger.kernel.org
-S:	Odd Fixes
-F:	drivers/tty/serial/rp2.*
-
 ROSE NETWORK LAYER
 M:	Ralf Baechle <ralf@linux-mips.org>
 L:	linux-hams@vger.kernel.org
@@ -8092,10 +7827,11 @@
 F:	drivers/media/dvb-frontends/rtl2832_sdr*
 
 RTL8180 WIRELESS DRIVER
+M:	"John W. Linville" <linville@tuxdriver.com>
 L:	linux-wireless@vger.kernel.org
 W:	http://wireless.kernel.org/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
-S:	Orphan
+S:	Maintained
 F:	drivers/net/wireless/rtl818x/rtl8180/
 
 RTL8187 WIRELESS DRIVER
@@ -8212,7 +7948,7 @@
 F:	drivers/media/i2c/saa6588*
 
 SAA7134 VIDEO4LINUX DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -8670,7 +8406,7 @@
 F:	drivers/media/radio/si4713/radio-usb-si4713.c
 
 SIANO DVB DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -8680,14 +8416,6 @@
 F:	drivers/media/usb/siano/
 F:	drivers/media/mmc/siano/
 
-SIMPLEFB FB DRIVER
-M:	Hans de Goede <hdegoede@redhat.com>
-L:	linux-fbdev@vger.kernel.org
-S:	Maintained
-F:	Documentation/devicetree/bindings/video/simple-framebuffer.txt
-F:	drivers/video/fbdev/simplefb.c
-F:	include/linux/platform_data/simplefb.h
-
 SH_VEU V4L2 MEM2MEM DRIVER
 L:	linux-media@vger.kernel.org
 S:	Orphan
@@ -8729,6 +8457,7 @@
 TI DAVINCI MACHINE SUPPORT
 M:	Sekhar Nori <nsekhar@ti.com>
 M:	Kevin Hilman <khilman@deeprootsystems.com>
+L:	davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
 T:	git git://gitorious.org/linux-davinci/linux-davinci.git
 Q:	http://patchwork.kernel.org/project/linux-davinci/list/
 S:	Supported
@@ -8738,6 +8467,7 @@
 TI DAVINCI SERIES MEDIA DRIVER
 M:	Lad, Prabhakar <prabhakar.csengg@gmail.com>
 L:	linux-media@vger.kernel.org
+L:	davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
 W:	http://linuxtv.org/
 Q:	http://patchwork.linuxtv.org/project/linux-media/list/
 T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
@@ -8889,9 +8619,7 @@
 F:	drivers/leds/leds-net48xx.c
 
 SOFTLOGIC 6x10 MPEG CODEC
-M:	Bluecherry Maintainers <maintainers@bluecherrydvr.com>
-M:	Andrey Utkin <andrey.utkin@corp.bluecherry.net>
-M:	Andrey Utkin <andrey.krieger.utkin@gmail.com>
+M:	Ismael Luceno <ismael.luceno@corp.bluecherry.net>
 L:	linux-media@vger.kernel.org
 S:	Supported
 F:	drivers/media/pci/solo6x10/
@@ -9248,13 +8976,6 @@
 F:	arch/*/kernel/pci-swiotlb.c
 F:	include/linux/swiotlb.h
 
-SWITCHDEV
-M:	Jiri Pirko <jiri@resnulli.us>
-L:	netdev@vger.kernel.org
-S:	Supported
-F:	net/switchdev/
-F:	include/net/switchdev.h
-
 SYNOPSYS ARC ARCHITECTURE
 M:	Vineet Gupta <vgupta@synopsys.com>
 S:	Supported
@@ -9372,7 +9093,7 @@
 F:	drivers/media/i2c/tda9840*
 
 TEA5761 TUNER DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -9380,7 +9101,7 @@
 F:	drivers/media/tuners/tea5761.*
 
 TEA5767 TUNER DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -9511,7 +9232,6 @@
 S:	Supported
 F:	drivers/thermal/
 F:	include/linux/thermal.h
-F:	include/uapi/linux/thermal.h
 F:	include/linux/cpu_cooling.h
 F:	Documentation/devicetree/bindings/thermal/
 
@@ -9616,7 +9336,7 @@
 F:	net/tipc/
 
 TILE ARCHITECTURE
-M:	Chris Metcalf <cmetcalf@ezchip.com>
+M:	Chris Metcalf <cmetcalf@tilera.com>
 W:	http://www.tilera.com/scm/
 S:	Supported
 F:	arch/tile/
@@ -9693,7 +9413,7 @@
 F:	mm/shmem.c
 
 TM6000 VIDEO4LINUX DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
@@ -9864,6 +9584,7 @@
 
 UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
 M:	Vinayak Holikatti <vinholikatti@gmail.com>
+M:	Santosh Y <santoshsy@gmail.com>
 L:	linux-scsi@vger.kernel.org
 S:	Supported
 F:	Documentation/scsi/ufs.txt
@@ -9957,6 +9678,11 @@
 F:	Documentation/hid/hiddev.txt
 F:	drivers/hid/usbhid/
 
+USB/IP DRIVERS
+L:	linux-usb@vger.kernel.org
+S:	Orphan
+F:	drivers/staging/usbip/
+
 USB ISP116X DRIVER
 M:	Olav Kongas <ok@artecdesign.ee>
 L:	linux-usb@vger.kernel.org
@@ -10244,13 +9970,13 @@
 S:	Maintained
 F:	drivers/net/ethernet/via/via-velocity.*
 
-VIVID VIRTUAL VIDEO DRIVER
+VIVI VIRTUAL VIDEO DRIVER
 M:	Hans Verkuil <hverkuil@xs4all.nl>
 L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 W:	http://linuxtv.org
 S:	Maintained
-F:	drivers/media/platform/vivid/*
+F:	drivers/media/platform/vivi*
 
 VLAN (802.1Q)
 M:	Patrick McHardy <kaber@trash.net>
@@ -10513,15 +10239,8 @@
 S:	Maintained
 F:	arch/x86/kernel/cpu/mcheck/*
 
-X86 VDSO
-M:	Andy Lutomirski <luto@amacapital.net>
-L:	linux-kernel@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/vdso
-S:	Maintained
-F:	arch/x86/vdso/
-
 XC2028/3028 TUNER DRIVER
-M:	Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:	Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
diff --git a/Makefile b/Makefile
index c21b813..ea3982b 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
 
 MAKEFLAGS += --no-print-directory
 SHELL := /bin/bash
-BACKPORT_DIR := $(shell pwd)
+BACKPORT_PWD := $(shell pwd)
 
 KMODDIR ?= updates
 ifneq ($(origin KLIB), undefined)
@@ -20,7 +20,7 @@
 KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
 CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
 
-export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
+export KLIB KLIB_BUILD BACKPORT_PWD KMODDIR KMODPATH_ARG
 
 # disable built-in rules for this file
 .SUFFIXES:
@@ -93,7 +93,7 @@
 		print=0									;\
 		for v in $$kvers ; do							\
 			if [ "$$print" = "1" ] ; then					\
-				echo config KERNEL_$$(echo $$v | tr . _)	;\
+				echo config BACKPORT_KERNEL_$$(echo $$v | tr . _)	;\
 				echo "    def_bool y"					;\
 			fi								;\
 			if [ "$$v" = "$$kver" ] ; then print=1 ; fi			;\
@@ -159,5 +159,5 @@
 	@echo ""
 	@echo "Execute "make" or "make all" to build all targets marked with [*]"
 else
-include $(BACKPORT_DIR)/Makefile.kernel
+include $(BACKPORT_PWD)/Makefile.kernel
 endif
diff --git a/Makefile.build b/Makefile.build
index a848b37..d209041 100644
--- a/Makefile.build
+++ b/Makefile.build
@@ -3,8 +3,8 @@
 
 .PHONY: modules
 modules:
-	@$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_DIR) modules
+	@$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_PWD) modules
 
 .PHONY: clean
 clean:
-	@$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_DIR) clean
+	@$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_PWD) clean
diff --git a/Makefile.kernel b/Makefile.kernel
index 42333ad..dcb2ba7 100644
--- a/Makefile.kernel
+++ b/Makefile.kernel
@@ -1,4 +1,3 @@
-ifeq ($(CONFIG_BACKPORT_INTEGRATE),)
 # Since 2.6.21, try-run is available, but cc-disable-warning
 # was only added later, so we add it here ourselves:
 backport-cc-disable-warning = $(call try-run,\
@@ -11,25 +10,13 @@
 	-I$(M)/include/uapi \
 	-include $(M)/backport-include/backport/backport.h \
 	$(call backport-cc-disable-warning, unused-but-set-variable) \
-	-DCPTCFG_VERSION=\"$(BACKPORTS_VERSION)\" \
-	-DCPTCFG_KERNEL_VERSION=\"$(BACKPORTED_KERNEL_VERSION)\" \
-	-DCPTCFG_KERNEL_NAME=\"$(BACKPORTED_KERNEL_NAME)\" \
+	-DBACKPORTS_VERSION=\"$(BACKPORTS_VERSION)\" \
+	-DBACKPORTED_KERNEL_VERSION=\"$(BACKPORTED_KERNEL_VERSION)\" \
+	-DBACKPORTED_KERNEL_NAME=\"$(BACKPORTED_KERNEL_NAME)\" \
 	$(BACKPORTS_GIT_TRACKER_DEF) \
 	$(CFLAGS)
 
 export backport_srctree = $(M)
-else
-export BACKPORT_DIR = backports/
-export backport_srctree = $(BACKPORT_DIR)
-NOSTDINC_FLAGS := \
-	-I$(BACKPORT_DIR)/backport-include/ \
-	-I$(BACKPORT_DIR)/backport-include/uapi \
-	-I$(BACKPORT_DIR)/include/ \
-	-I$(BACKPORT_DIR)/include/uapi \
-	-include $(BACKPORT_DIR)/backport-include/backport/backport.h \
-	$(CFLAGS)
-endif
-
 
 obj-y += compat/
 
@@ -46,7 +33,6 @@
 obj-$(CPTCFG_NFC) += drivers/nfc/
 obj-$(CPTCFG_MEDIA_SUPPORT) += drivers/media/
 
-obj-$(CPTCFG_6LOWPAN) += net/6lowpan/
 obj-$(CPTCFG_IEEE802154) += net/ieee802154/
 obj-$(CPTCFG_BT) += net/ieee802154/
 obj-$(CPTCFG_MAC802154) += net/mac802154/
diff --git a/Makefile.real b/Makefile.real
index a0f4916..f60d5ca 100644
--- a/Makefile.real
+++ b/Makefile.real
@@ -89,7 +89,7 @@
 
 .PHONY: install
 install: modules
-	@$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_DIR)			\
+	@$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_PWD)			\
 		INSTALL_MOD_DIR=$(KMODDIR) $(KMODPATH_ARG)		\
 		modules_install
 	@./scripts/blacklist.sh $(KLIB)/ $(KLIB)/$(KMODDIR)
diff --git a/backport-include/asm-generic/barrier.h b/backport-include/asm-generic/barrier.h
deleted file mode 100644
index 9169449..0000000
--- a/backport-include/asm-generic/barrier.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __BACKPORT_ASM_GENERIC_BARRIER_H
-#define __BACKPORT_ASM_GENERIC_BARRIER_H
-#include_next <asm-generic/barrier.h>
-
-#ifndef dma_rmb
-#define dma_rmb()	rmb()
-#endif
-
-#endif /* __BACKPORT_ASM_GENERIC_BARRIER_H */
diff --git a/backport-include/asm/barrier.h b/backport-include/asm/barrier.h
deleted file mode 100644
index b04bd33..0000000
--- a/backport-include/asm/barrier.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __BACKPORT_ASM_GENERIC_BARRIER_H
-#define __BACKPORT_ASM_GENERIC_BARRIER_H
-#include_next <asm/barrier.h>
-
-#ifndef dma_rmb
-#define dma_rmb()	rmb()
-#endif
-
-#endif /* __BACKPORT_ASM_GENERIC_BARRIER_H */
diff --git a/backport-include/asm/dma-mapping.h b/backport-include/asm/dma-mapping.h
index b73b7da..844fe3b 100644
--- a/backport-include/asm/dma-mapping.h
+++ b/backport-include/asm/dma-mapping.h
@@ -3,12 +3,12 @@
 #include_next <asm/dma-mapping.h>
 #include <linux/version.h>
 
-#if defined(CPTCFG_BPAUTO_BUILD_DMA_SHARED_HELPERS)
+#if defined(CPTCFG_BACKPORT_BUILD_DMA_SHARED_HELPERS)
 #define dma_common_get_sgtable LINUX_BACKPORT(dma_common_get_sgtable)
 int
 dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
 		       void *cpu_addr, dma_addr_t dma_addr, size_t size);
-#endif /* defined(CPTCFG_BPAUTO_BUILD_DMA_SHARED_HELPERS) */
+#endif /* defined(CPTCFG_BACKPORT_BUILD_DMA_SHARED_HELPERS) */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
 
diff --git a/backport-include/backport/backport.h b/backport-include/backport/backport.h
index d1d3b10..7cf21aa 100644
--- a/backport-include/backport/backport.h
+++ b/backport-include/backport/backport.h
@@ -1,16 +1,11 @@
 #ifndef __BACKPORT_H
 #define __BACKPORT_H
-#include <generated/autoconf.h>
-#ifndef CONFIG_BACKPORT_INTEGRATE
 #include <backport/autoconf.h>
-#endif
 #include <linux/kconfig.h>
 
 #ifndef __ASSEMBLY__
 #define LINUX_BACKPORT(__sym) backport_ ##__sym
-#ifndef CONFIG_BACKPORT_INTEGRATE
 #include <backport/checks.h>
 #endif
-#endif
 
 #endif /* __BACKPORT_H */
diff --git a/backport-include/backport/leds-disabled.h b/backport-include/backport/leds-disabled.h
index 156d7fa..501f2a0 100644
--- a/backport-include/backport/leds-disabled.h
+++ b/backport-include/backport/leds-disabled.h
@@ -8,7 +8,7 @@
  * allows compilation.
  */
 
-#ifdef CPTCFG_BPAUTO_BUILD_LEDS
+#ifdef CPTCFG_BACKPORT_BUILD_LEDS
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
diff --git a/backport-include/linux/bitops.h b/backport-include/linux/bitops.h
deleted file mode 100644
index b0e9283..0000000
--- a/backport-include/linux/bitops.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __BACKPORT_BITOPS_H
-#define __BACKPORT_BITOPS_H
-#include_next <linux/bitops.h>
-#include <linux/version.h>
-#include <generated/utsrelease.h>
-
-#ifndef GENMASK
-
-/*
- * Create a contiguous bitmask starting at bit position @l and ending at
- * position @h. For example
- * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
- */
-#define GENMASK(h, l)		(((U32_C(1) << ((h) - (l) + 1)) - 1) << (l))
-#define GENMASK_ULL(h, l)	(((U64_C(1) << ((h) - (l) + 1)) - 1) << (l))
-
-#endif
-
-#endif /* __BACKPORT_BITOPS_H */
diff --git a/backport-include/linux/debugfs.h b/backport-include/linux/debugfs.h
deleted file mode 100644
index 77b2e64..0000000
--- a/backport-include/linux/debugfs.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __BACKPORT_DEBUGFS_H_
-#define __BACKPORT_DEBUGFS_H_
-#include_next <linux/debugfs.h>
-#include <linux/version.h>
-#include <generated/utsrelease.h>
-
-#if defined(CONFIG_DEBUG_FS)
-struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
-					   struct dentry *parent,
-					   int (*read_fn)(struct seq_file *s,
-							  void *data));
-#else
-static inline struct dentry *debugfs_create_devm_seqfile(struct device *dev,
-							 const char *name,
-							 struct dentry *parent,
-					   int (*read_fn)(struct seq_file *s,
-							  void *data))
-{
-	return ERR_PTR(-ENODEV);
-}
-#endif /* CONFIG_DEBUG_FS */
-
-#endif /* __BACKPORT_DEBUGFS_H_ */
diff --git a/backport-include/linux/device.h b/backport-include/linux/device.h
index 29dc077..41f06c3 100644
--- a/backport-include/linux/device.h
+++ b/backport-include/linux/device.h
@@ -177,20 +177,4 @@
 }
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
-#define devm_kmemdup LINUX_BACKPORT(devm_kmemdup)
-static inline void *devm_kmemdup(struct device *dev, const void *src,
-				 size_t len, gfp_t gfp)
-{
-	void *p;
-
-	p = devm_kmalloc(dev, len, gfp);
-	if (p)
-		memcpy(p, src, len);
-
-	return p;
-}
-#endif
-
-
 #endif /* __BACKPORT_DEVICE_H */
diff --git a/backport-include/linux/dma-buf.h b/backport-include/linux/dma-buf.h
index 48c2ebf..13a225e 100644
--- a/backport-include/linux/dma-buf.h
+++ b/backport-include/linux/dma-buf.h
@@ -4,9 +4,6 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
 #include_next <linux/dma-buf.h>
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) */
-#include <linux/dma-direction.h>
-#include <linux/dma-attrs.h>
-#include <linux/dma-mapping.h>
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
 #define dma_buf_export(priv, ops, size, flags, resv)	\
diff --git a/backport-include/linux/etherdevice.h b/backport-include/linux/etherdevice.h
index 34dbf65..70decd2 100644
--- a/backport-include/linux/etherdevice.h
+++ b/backport-include/linux/etherdevice.h
@@ -178,19 +178,4 @@
 int eth_get_headlen(unsigned char *data, unsigned int max_len);
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) */
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#define eth_skb_pad LINUX_BACKPORT(eth_skb_pad)
-/**
- * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
- * @skb: Buffer to pad
- *
- * An Ethernet frame should have a minimum size of 60 bytes.  This function
- * takes short frames and pads them with zeros up to the 60 byte limit.
- */
-static inline int eth_skb_pad(struct sk_buff *skb)
-{
-	return skb_put_padto(skb, ETH_ZLEN);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
 #endif /* _BACKPORT_LINUX_ETHERDEVICE_H */
diff --git a/backport-include/linux/list.h b/backport-include/linux/list.h
index 3fbc10b..9042830 100644
--- a/backport-include/linux/list.h
+++ b/backport-include/linux/list.h
@@ -17,9 +17,7 @@
 
 #undef hlist_entry_safe
 #define hlist_entry_safe(ptr, type, member) \
-	({ typeof(ptr) ____ptr = (ptr); \
-	   ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
-	})
+	(ptr) ? hlist_entry(ptr, type, member) : NULL
 
 #define hlist_for_each_entry4(tpos, pos, head, member)			\
 	for (pos = (head)->first;					\
@@ -75,17 +73,4 @@
 	list_entry((pos)->member.next, typeof(*(pos)), member)
 #endif /* list_next_entry */
 
-#ifndef list_last_entry
-/**
- * list_last_entry - get the last element from a list
- * @ptr:	the list head to take the element from.
- * @type:	the type of the struct this is embedded in.
- * @member:	the name of the list_struct within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_last_entry(ptr, type, member) \
-	list_entry((ptr)->prev, type, member)
-#endif
-
 #endif /* __BACKPORT_LIST_H */
diff --git a/backport-include/linux/module.h b/backport-include/linux/module.h
index 8870abb..82c96bd 100644
--- a/backport-include/linux/module.h
+++ b/backport-include/linux/module.h
@@ -20,12 +20,11 @@
 #define BACKPORT_MOD_VERSIONS MODULE_VERSION(BACKPORTS_GIT_TRACKED);
 #else
 #define BACKPORT_MOD_VERSIONS						\
-	MODULE_VERSION("backported from " CPTCFG_KERNEL_NAME	\
-		       " (" CPTCFG_KERNEL_VERSION ")"		\
-		       " using backports " CPTCFG_VERSION);
+	MODULE_VERSION("backported from " BACKPORTED_KERNEL_NAME	\
+		       " (" BACKPORTED_KERNEL_VERSION ")"		\
+		       " using backports " BACKPORTS_VERSION);
 #endif
 
-#ifdef MODULE
 #undef module_init
 #define module_init(initfn)						\
 	static int __init __init_backport(void)				\
@@ -59,7 +58,6 @@
 		rcu_barrier();						\
 	}								\
 	void cleanup_module(void) __attribute__((alias("__exit_compat")));
-#endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
 #undef param_check_bool
diff --git a/backport-include/linux/netdevice.h b/backport-include/linux/netdevice.h
index 961450a..8826771 100644
--- a/backport-include/linux/netdevice.h
+++ b/backport-include/linux/netdevice.h
@@ -176,62 +176,4 @@
 			 count)
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) */
 
-/*
- * This backports this commit from upstream:
- * commit 87757a917b0b3c0787e0563c679762152be81312
- * net: force a list_del() in unregister_netdevice_many()
- */
-#if (!(LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,45) && \
-       LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)) && \
-     !(LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,23) && \
-       LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)) && \
-     !(LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,9) && \
-       LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) && \
-     !(LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,2) && \
-       LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) && \
-     (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)))
-static inline void backport_unregister_netdevice_many(struct list_head *head)
-{
-	unregister_netdevice_many(head);
-
-	if (!(head->next == LIST_POISON1 && head->prev == LIST_POISON2))
-		list_del(head);
-}
-#define unregister_netdevice_many LINUX_BACKPORT(unregister_netdevice_many)
-#endif
-
-/*
- * Complicated way of saying: We only backport netdev_rss_key stuff on kernels
- * that either already have net_get_random_once() (>= 3.13) or where we've been
- * brave enough to backport it due to static keys, refer to backports commit
- * 8cb8816d for details on difficulty to backport that further down.
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
-#define __BACKPORT_NETDEV_RSS_KEY_FILL 1
-#else
-#ifdef __BACKPORT_NET_GET_RANDOM_ONCE
-#define __BACKPORT_NETDEV_RSS_KEY_FILL 1
-#endif
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) */
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
-#ifdef __BACKPORT_NETDEV_RSS_KEY_FILL
-/* RSS keys are 40 or 52 bytes long */
-#define NETDEV_RSS_KEY_LEN 52
-#define netdev_rss_key LINUX_BACKPORT(netdev_rss_key)
-extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN];
-#define netdev_rss_key_fill LINUX_BACKPORT(netdev_rss_key_fill)
-void netdev_rss_key_fill(void *buffer, size_t len);
-#endif /* __BACKPORT_NETDEV_RSS_KEY_FILL */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#define napi_alloc_skb LINUX_BACKPORT(napi_alloc_skb)
-static inline struct sk_buff *napi_alloc_skb(struct napi_struct *napi,
-					     unsigned int length)
-{
-	return netdev_alloc_skb_ip_align(napi->dev, length);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
 #endif /* __BACKPORT_NETDEVICE_H */
diff --git a/backport-include/linux/of.h b/backport-include/linux/of.h
index b289bcb..f2a8ab4 100644
--- a/backport-include/linux/of.h
+++ b/backport-include/linux/of.h
@@ -29,7 +29,6 @@
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
-#define of_property_read_u8_array LINUX_BACKPORT(of_property_read_u8_array)
 #ifdef CONFIG_OF
 extern int of_property_read_u8_array(const struct device_node *np,
 			const char *propname, u8 *out_values, size_t sz);
@@ -40,31 +39,7 @@
 	return -ENOSYS;
 }
 #endif /* CONFIG_OF */
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
-#define of_property_read_u32_array LINUX_BACKPORT(of_property_read_u32_array)
-#ifdef CONFIG_OF
-extern int of_property_read_u32_array(const struct device_node *np,
-				      const char *propname,
-				      u32 *out_values,
-				      size_t sz);
-#else
-static inline int of_property_read_u32_array(const struct device_node *np,
-					     const char *propname,
-					     u32 *out_values, size_t sz)
-{
-	return -ENOSYS;
-}
-#endif /* CONFIG_OF */
-#define of_property_read_u32 LINUX_BACKPORT(of_property_read_u32)
-static inline int of_property_read_u32(const struct device_node *np,
-				       const char *propname,
-				       u32 *out_value)
-{
-	return of_property_read_u32_array(np, propname, out_value, 1);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
 #define of_property_read_u32_index LINUX_BACKPORT(of_property_read_u32_index)
@@ -139,22 +114,4 @@
 #endif /* CONFIG_OF */
 #endif /* of_match_ptr */
 
-#ifndef for_each_compatible_node
-#define for_each_compatible_node(dn, type, compatible) \
-	for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
-	     dn = of_find_compatible_node(dn, type, compatible))
-#endif /* for_each_compatible_node */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-#ifndef CONFIG_OF
-static inline struct device_node *of_find_compatible_node(
-						struct device_node *from,
-						const char *type,
-						const char *compat)
-{
-	return NULL;
-}
-#endif
-#endif
-
 #endif	/* _COMPAT_LINUX_OF_H */
diff --git a/backport-include/linux/pci.h b/backport-include/linux/pci.h
index f168bde..3dd2c7e 100644
--- a/backport-include/linux/pci.h
+++ b/backport-include/linux/pci.h
@@ -159,9 +159,4 @@
 #endif
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
-#define pci_device_is_present LINUX_BACKPORT(pci_device_is_present)
-bool pci_device_is_present(struct pci_dev *pdev);
-#endif
-
 #endif /* _BACKPORT_LINUX_PCI_H */
diff --git a/backport-include/linux/pci_regs.h b/backport-include/linux/pci_regs.h
new file mode 100644
index 0000000..b52c4a5
--- /dev/null
+++ b/backport-include/linux/pci_regs.h
@@ -0,0 +1,136 @@
+#ifndef __BACKPORT_UAPI_PCI_REGS_H
+#define __BACKPORT_UAPI_PCI_REGS_H
+#include_next <linux/pci_regs.h>
+
+#ifndef PCI_EXP_LNKCTL_ASPM_L0S
+#define  PCI_EXP_LNKCTL_ASPM_L0S  0x01 /* L0s Enable */
+#endif
+
+#ifndef PCI_EXP_LNKCTL_ASPM_L1
+#define  PCI_EXP_LNKCTL_ASPM_L1   0x02 /* L1 Enable */
+#endif
+
+/* This backports:
+ *
+ * commit 130f1b8f35f14d27c43da755f3c9226318c17f57
+ * Author: Bjorn Helgaas <bhelgaas@google.com>
+ * Date:   Wed Dec 26 10:39:23 2012 -0700
+ *
+ *     PCI: Add PCIe Link Capability link speed and width names
+ */
+#ifndef PCI_EXP_LNKCAP_SLS_2_5GB
+#define  PCI_EXP_LNKCAP_SLS_2_5GB 0x1	/* LNKCAP2 SLS Vector bit 0 (2.5GT/s) */
+#endif
+
+#ifndef PCI_EXP_LNKCAP_SLS_5_0GB
+#define  PCI_EXP_LNKCAP_SLS_5_0GB 0x2	/* LNKCAP2 SLS Vector bit 1 (5.0GT/s) */
+#endif
+
+#ifndef PCI_EXP_LNKSTA2
+#define PCI_EXP_LNKSTA2			50      /* Link Status 2 */
+#endif
+
+/**
+ * Backports
+ *
+ * commit cdcac9cd7741af2c2b9255cbf060f772596907bb
+ * Author: Dave Airlie <airlied@redhat.com>
+ * Date:   Wed Jun 27 08:35:52 2012 +0100
+ *
+ * 	pci_regs: define LNKSTA2 pcie cap + bits.
+ *
+ * 	We need these for detecting the max link speed for drm drivers.
+ *
+ * 	Acked-by: Bjorn Helgaas <bhelgass@google.com>
+ * 	Signed-off-by: Dave Airlie <airlied@redhat.com>
+ */
+#ifndef PCI_EXP_LNKCAP2
+#define  PCI_EXP_LNKCAP2 		44	/* Link Capability 2 */
+#endif
+
+#ifndef PCI_EXP_LNKCAP2_SLS_2_5GB
+#define  PCI_EXP_LNKCAP2_SLS_2_5GB 	0x01	/* Current Link Speed 2.5GT/s */
+#endif
+
+#ifndef PCI_EXP_LNKCAP2_SLS_5_0GB
+#define  PCI_EXP_LNKCAP2_SLS_5_0GB 	0x02	/* Current Link Speed 5.0GT/s */
+#endif
+
+#ifndef PCI_EXP_LNKCAP2_SLS_8_0GB
+#define  PCI_EXP_LNKCAP2_SLS_8_0GB 	0x04	/* Current Link Speed 8.0GT/s */
+#endif
+
+#ifndef PCI_EXP_LNKCAP2_CROSSLINK
+#define  PCI_EXP_LNKCAP2_CROSSLINK 	0x100 /* Crosslink supported */
+#endif
+
+/*
+ * PCI_EXP_TYPE_RC_EC was added via 1b6b8ce2 on v2.6.30-rc4~20 :
+ *
+ * mcgrof@frijol ~/linux-next (git::master)$ git describe --contains 1b6b8ce2
+ * v2.6.30-rc4~20^2
+ *
+ * but the fix for its definition was merged on v3.3-rc1~101^2~67
+ *
+ * mcgrof@frijol ~/linux-next (git::master)$ git describe --contains 1830ea91
+ * v3.3-rc1~101^2~67
+ *
+ * while we can assume it got merged and backported on v3.2.28 (which it did
+ * see c1c3cd9) we cannot assume every kernel has it fixed so lets just undef
+ * it here and redefine it.
+ */
+#undef PCI_EXP_TYPE_RC_EC
+#define  PCI_EXP_TYPE_RC_EC    0xa     /* Root Complex Event Collector */
+
+#ifndef PCI_MSIX_ENTRY_CTRL_MASKBIT
+#define PCI_MSIX_ENTRY_CTRL_MASKBIT  1
+#endif
+
+/* MSI-X entry's format */
+#ifndef PCI_MSIX_ENTRY_SIZE
+#define PCI_MSIX_ENTRY_SIZE            16
+#define  PCI_MSIX_ENTRY_LOWER_ADDR     0
+#define  PCI_MSIX_ENTRY_UPPER_ADDR     4
+#define  PCI_MSIX_ENTRY_DATA           8
+#define  PCI_MSIX_ENTRY_VECTOR_CTRL    12
+#endif
+
+#ifndef PCI_EXP_LNKCTL2
+#define PCI_EXP_LNKCTL2			48      /* Link Control 2 */
+#endif
+
+#ifndef PCI_EXP_SLTCTL2
+#define PCI_EXP_SLTCTL2			56      /* Slot Control 2 */
+#endif
+
+#ifndef PCI_EXP_LNKCTL_ES
+#define PCI_EXP_LNKCTL_ES     0x0080  /* Extended Synch */
+#endif
+
+#ifndef PCI_EXP_SLTSTA_PDS
+#define PCI_EXP_SLTSTA_PDS	0x0040  /* Presence Detect State */
+#endif
+
+#ifndef PCI_EXP_DEVCAP2
+#define PCI_EXP_DEVCAP2		36      /* Device Capabilities 2 */
+#define  PCI_EXP_DEVCAP2_ARI  	0x20    /* Alternative Routing-ID */
+#endif
+
+#ifndef PCI_EXP_DEVCTL2
+#define PCI_EXP_DEVCTL2		40      /* Device Control 2 */
+#define  PCI_EXP_DEVCTL2_ARI	0x20    /* Alternative Routing-ID */
+#endif
+
+#ifndef PCI_PM_CAP_PME_SHIFT
+#define PCI_PM_CAP_PME_SHIFT	11
+#endif
+
+#ifndef PCI_SRIOV_VF_DID
+#define PCI_SRIOV_VF_DID	0x1a	/* VF Device ID */
+#endif
+
+#ifndef PCI_SRIOV_CTRL_VFE
+#define PCI_SRIOV_CTRL_VFE	0x01	/* VF Enable */
+#endif
+
+#endif /* __BACKPORT_UAPI_PCI_REGS_H */
diff --git a/backport-include/linux/rculist.h b/backport-include/linux/rculist.h
index 74009ab..eb3bcfe 100644
--- a/backport-include/linux/rculist.h
+++ b/backport-include/linux/rculist.h
@@ -34,24 +34,4 @@
 	container_of(rcu_dereference(ptr), type, member)
 #endif
 
-#ifndef list_first_or_null_rcu
-/**
- * list_first_or_null_rcu - get the first element from a list
- * @ptr:        the list head to take the element from.
- * @type:       the type of the struct this is embedded in.
- * @member:     the name of the list_struct within the struct.
- *
- * Note that if the list is empty, it returns NULL.
- *
- * This primitive may safely run concurrently with the _rcu list-mutation
- * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
- */
-#define list_first_or_null_rcu(ptr, type, member) \
-({ \
-	struct list_head *__ptr = (ptr); \
-	struct list_head *__next = ACCESS_ONCE(__ptr->next); \
-	likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \
-})
-#endif /* list_first_or_null_rcu */
-
 #endif /* __BACKPORT_RCULIST_H */
diff --git a/backport-include/linux/skbuff.h b/backport-include/linux/skbuff.h
index 687297c..5a1725d 100644
--- a/backport-include/linux/skbuff.h
+++ b/backport-include/linux/skbuff.h
@@ -96,6 +96,52 @@
 }
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) */
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
+/**
+ *	__skb_alloc_pages - allocate pages for ps-rx on a skb and preserve pfmemalloc data
+ *	@gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX
+ *	@skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used
+ *	@order: size of the allocation
+ *
+ * 	Allocate a new page.
+ *
+ * 	%NULL is returned if there is no free memory.
+*/
+static inline struct page *__skb_alloc_pages(gfp_t gfp_mask,
+					      struct sk_buff *skb,
+					      unsigned int order)
+{
+	struct page *page;
+
+	gfp_mask |= __GFP_COLD;
+#if 0
+	if (!(gfp_mask & __GFP_NOMEMALLOC))
+		gfp_mask |= __GFP_MEMALLOC;
+#endif
+	page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
+#if 0
+	if (skb && page && page->pfmemalloc)
+		skb->pfmemalloc = true;
+#endif
+	return page;
+}
+
+/**
+ *	__skb_alloc_page - allocate a page for ps-rx for a given skb and preserve pfmemalloc data
+ *	@gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX
+ *	@skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used
+ *
+ * 	Allocate a new page.
+ *
+ * 	%NULL is returned if there is no free memory.
+ */
+static inline struct page *__skb_alloc_page(gfp_t gfp_mask,
+					     struct sk_buff *skb)
+{
+	return __skb_alloc_pages(gfp_mask, skb, 0);
+}
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
 #ifndef NETDEV_FRAG_PAGE_MAX_ORDER
 #define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768)
@@ -118,6 +164,129 @@
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
 
+#define skb_frag_size_set LINUX_BACKPORT(skb_frag_size_set)
+static inline void skb_frag_size_set(skb_frag_t *frag, unsigned int size)
+{
+	frag->size = size;
+}
+
+#define skb_frag_size_add LINUX_BACKPORT(skb_frag_size_add)
+static inline void skb_frag_size_add(skb_frag_t *frag, int delta)
+{
+	frag->size += delta;
+}
+
+#define __skb_fill_page_desc LINUX_BACKPORT(__skb_fill_page_desc)
+/**
+ * __skb_fill_page_desc - initialise a paged fragment in an skb
+ * @skb: buffer containing fragment to be initialised
+ * @i: paged fragment index to initialise
+ * @page: the page to use for this fragment
+ * @off: the offset to the data with @page
+ * @size: the length of the data
+ *
+ * Initialises the @i'th fragment of @skb to point to &size bytes at
+ * offset @off within @page.
+ *
+ * Does not take any additional reference on the fragment.
+ */
+static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
+					struct page *page, int off, int size)
+{
+	skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+	/*
+	 * Propagate page->pfmemalloc to the skb if we can. The problem is
+	 * that not all callers have unique ownership of the page. If
+	 * pfmemalloc is set, we check the mapping as a mapping implies
+	 * page->index is set (index and pfmemalloc share space).
+	 * If it's a valid mapping, we cannot use page->pfmemalloc but we
+	 * do not lose pfmemalloc information as the pages would not be
+	 * allocated using __GFP_MEMALLOC.
+	 */
+	frag->page		  = page;
+	frag->page_offset	  = off;
+	skb_frag_size_set(frag, size);
+
+#if 0 /* we can't backport this for older kernels */
+	page = compound_head(page);
+	if (page->pfmemalloc && !page->mapping)
+		skb->pfmemalloc	= true;
+#endif
+}
+
+#define skb_fill_page_desc LINUX_BACKPORT(skb_fill_page_desc)
+/**
+ * skb_fill_page_desc - initialise a paged fragment in an skb
+ * @skb: buffer containing fragment to be initialised
+ * @i: paged fragment index to initialise
+ * @page: the page to use for this fragment
+ * @off: the offset to the data with @page
+ * @size: the length of the data
+ *
+ * As per __skb_fill_page_desc() -- initialises the @i'th fragment of
+ * @skb to point to @size bytes at offset @off within @page. In
+ * addition updates @skb such that @i is the last fragment.
+ *
+ * Does not take any additional reference on the fragment.
+ */
+static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
+				      struct page *page, int off, int size)
+{
+	__skb_fill_page_desc(skb, i, page, off, size);
+	skb_shinfo(skb)->nr_frags = i + 1;
+}
+
+#define __skb_frag_ref LINUX_BACKPORT(__skb_frag_ref)
+/**
+ * __skb_frag_ref - take an addition reference on kb_frag_page paged fragment.
+ * @frag: the paged fragment
+ *
+ * Takes an additional reference on the paged fragment @frag.
+ */
+static inline void __skb_frag_ref(skb_frag_t *frag)
+{
+	get_page(skb_frag_page(frag));
+}
+
+#define skb_frag_ref LINUX_BACKPORT(skb_frag_ref)
+/**
+ * skb_frag_ref - take an addition reference on a paged fragment of an skb.
+ * @skb: the buffer
+ * @f: the fragment offset.
+ *
+ * Takes an additional reference on the @f'th paged fragment of @skb.
+ */
+static inline void skb_frag_ref(struct sk_buff *skb, int f)
+{
+	__skb_frag_ref(&skb_shinfo(skb)->frags[f]);
+}
+
+#define __skb_frag_unref LINUX_BACKPORT(__skb_frag_unref)
+/**
+ * __skb_frag_unref - release a reference on a paged fragment.
+ * @frag: the paged fragment
+ *
+ * Releases a reference on the paged fragment @frag.
+ */
+static inline void __skb_frag_unref(skb_frag_t *frag)
+{
+	put_page(skb_frag_page(frag));
+}
+
+#define skb_frag_unref LINUX_BACKPORT(skb_frag_unref)
+/**
+ * skb_frag_unref - release a reference on a paged fragment of an skb.
+ * @skb: the buffer
+ * @f: the fragment offset
+ *
+ * Releases a reference on the @f'th paged fragment of @skb.
+ */
+static inline void skb_frag_unref(struct sk_buff *skb, int f)
+{
+	__skb_frag_unref(&skb_shinfo(skb)->frags[f]);
+}
+
 #define skb_frag_address_safe LINUX_BACKPORT(skb_frag_address_safe)
 /**
  * skb_frag_address_safe - gets the address of the data contained in a paged fragment
@@ -134,6 +303,34 @@
 
 	return ptr + frag->page_offset;
 }
+
+#define __skb_frag_set_page LINUX_BACKPORT(__skb_frag_set_page)
+/**
+ * __skb_frag_set_page - sets the page contained in a paged fragment
+ * @frag: the paged fragment
+ * @page: the page to set
+ *
+ * Sets the fragment @frag to contain @page.
+ */
+static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page)
+{
+	frag->page = page;
+}
+
+#define skb_frag_set_page LINUX_BACKPORT(skb_frag_set_page)
+/**
+ * skb_frag_set_page - sets the page contained in a paged fragment of an skb
+ * @skb: the buffer
+ * @f: the fragment offset
+ * @page: the page to set
+ *
+ * Sets the @f'th fragment of @skb to contain @page.
+ */
+static inline void skb_frag_set_page(struct sk_buff *skb, int f,
+				     struct page *page)
+{
+	__skb_frag_set_page(&skb_shinfo(skb)->frags[f], page);
+}
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) && \
@@ -199,100 +396,4 @@
 struct sk_buff *skb_clone_sk(struct sk_buff *skb);
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-/**
- * __dev_alloc_pages - allocate page for network Rx
- * @gfp_mask: allocation priority. Set __GFP_NOMEMALLOC if not for network Rx
- * @order: size of the allocation
- *
- * Allocate a new page.
- *
- * %NULL is returned if there is no free memory.
-*/
-#define __dev_alloc_pages LINUX_BACKPORT(__dev_alloc_pages)
-static inline struct page *__dev_alloc_pages(gfp_t gfp_mask,
-					     unsigned int order)
-{
-	/* This piece of code contains several assumptions.
-	 * 1.  This is for device Rx, therefor a cold page is preferred.
-	 * 2.  The expectation is the user wants a compound page.
-	 * 3.  If requesting a order 0 page it will not be compound
-	 *     due to the check to see if order has a value in prep_new_page
-	 * 4.  __GFP_MEMALLOC is ignored if __GFP_NOMEMALLOC is set due to
-	 *     code in gfp_to_alloc_flags that should be enforcing this.
-	 */
-	gfp_mask |= __GFP_COLD | __GFP_COMP;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-	gfp_mask |= __GFP_MEMALLOC;
-#endif
-
-	return alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
-}
-
-#define dev_alloc_pages LINUX_BACKPORT(dev_alloc_pages)
-static inline struct page *dev_alloc_pages(unsigned int order)
-{
-	return __dev_alloc_pages(GFP_ATOMIC, order);
-}
-
-/**
- * __dev_alloc_page - allocate a page for network Rx
- * @gfp_mask: allocation priority. Set __GFP_NOMEMALLOC if not for network Rx
- *
- * Allocate a new page.
- *
- * %NULL is returned if there is no free memory.
- */
-#define __dev_alloc_page LINUX_BACKPORT(__dev_alloc_page)
-static inline struct page *__dev_alloc_page(gfp_t gfp_mask)
-{
-	return __dev_alloc_pages(gfp_mask, 0);
-}
-
-#define dev_alloc_page LINUX_BACKPORT(dev_alloc_page)
-static inline struct page *dev_alloc_page(void)
-{
-	return __dev_alloc_page(GFP_ATOMIC);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#define skb_copy_datagram_msg LINUX_BACKPORT(skb_copy_datagram_msg)
-static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset,
-					struct msghdr *msg, int size)
-{
-	return skb_copy_datagram_iovec(from, offset, msg->msg_iov, size);
-}
-
-#define memcpy_from_msg LINUX_BACKPORT(memcpy_from_msg)
-static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
-{
-	return memcpy_fromiovec(data, msg->msg_iov, len);
-}
-
-/**
- *	skb_put_padto - increase size and pad an skbuff up to a minimal size
- *	@skb: buffer to pad
- *	@len: minimal length
- *
- *	Pads up a buffer to ensure the trailing bytes exist and are
- *	blanked. If the buffer already contains sufficient data it
- *	is untouched. Otherwise it is extended. Returns zero on
- *	success. The skb is freed on error.
- */
-#define skb_put_padto LINUX_BACKPORT(skb_put_padto)
-static inline int skb_put_padto(struct sk_buff *skb, unsigned int len)
-{
-	unsigned int size = skb->len;
-
-	if (unlikely(size < len)) {
-		len -= size;
-		if (skb_pad(skb, len))
-			return -ENOMEM;
-		__skb_put(skb, len);
-	}
-	return 0;
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
 #endif /* __BACKPORT_SKBUFF_H */
diff --git a/backport-include/linux/wait.h b/backport-include/linux/wait.h
index 4057ff1..dfb111d 100644
--- a/backport-include/linux/wait.h
+++ b/backport-include/linux/wait.h
@@ -23,13 +23,4 @@
 
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#define WQ_FLAG_WOKEN		0x02
-
-#define wait_woken LINUX_BACKPORT(wait_woken)
-long wait_woken(wait_queue_t *wait, unsigned mode, long timeout);
-#define wait_woken LINUX_BACKPORT(wait_woken)
-int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
-#endif
-
 #endif /* __BACKPORT_LINUX_WAIT_H */
diff --git a/backport-include/linux/workqueue.h b/backport-include/linux/workqueue.h
index 078ed59..ec5c230 100644
--- a/backport-include/linux/workqueue.h
+++ b/backport-include/linux/workqueue.h
@@ -60,8 +60,4 @@
 #define system_freezable_power_efficient_wq system_freezable_wq
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
-#define drain_workqueue(wq) flush_workqueue(wq)
-#endif
-
 #endif /* __BACKPORT_LINUX_WORKQUEUE_H */
diff --git a/backport-include/net/genetlink.h b/backport-include/net/genetlink.h
index 0535b0f..fc7eff4 100644
--- a/backport-include/net/genetlink.h
+++ b/backport-include/net/genetlink.h
@@ -1,7 +1,6 @@
 #ifndef __BACKPORT_NET_GENETLINK_H
 #define __BACKPORT_NET_GENETLINK_H
 #include_next <net/genetlink.h>
-#include <linux/version.h>
 
 /* this is for patches we apply */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
@@ -86,10 +85,6 @@
 #define genl_unregister_family backport_genl_unregister_family
 int genl_unregister_family(struct genl_family *family);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-extern void genl_notify(struct sk_buff *skb, struct net *net, u32 pid,
-			u32 group, struct nlmsghdr *nlh, gfp_t flags);
-#endif
 #define genl_notify(_fam, _skb, _net, _portid, _group, _nlh, _flags)	\
 	genl_notify(_skb, _net, _portid, (_fam)->mcgrps[_group].id,	\
 		    _nlh, _flags)
diff --git a/backport-include/net/ip6_fib.h b/backport-include/net/ip6_fib.h
deleted file mode 100644
index 8c5d8ff..0000000
--- a/backport-include/net/ip6_fib.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __BACKPORT_NET_IP6_ROUTE_H
-#define __BACKPORT_NET_IP6_ROUTE_H
-#include_next <net/ip6_fib.h>
-#include <net/ip6_route.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-#define rt6_nexthop LINUX_BACKPORT(rt6_nexthop)
-static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt)
-{
-	return &rt->rt6i_gateway;
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) */
-
-#endif /* __BACKPORT_NET_IP6_ROUTE_H */
diff --git a/backport-include/sound/pcm.h b/backport-include/sound/pcm.h
deleted file mode 100644
index 469e871..0000000
--- a/backport-include/sound/pcm.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __BACKPORT_SOUND_PCM_H
-#define __BACKPORT_SOUND_PCM_H
-#include_next <sound/pcm.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-/**
- * snd_pcm_stop_xrun - stop the running streams as XRUN
- * @substream: the PCM substream instance
- *
- * This stops the given running substream (and all linked substreams) as XRUN.
- * Unlike snd_pcm_stop(), this function takes the substream lock by itself.
- *
- * Return: Zero if successful, or a negative error code.
- */
-static inline int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	snd_pcm_stream_lock_irqsave(substream, flags);
-	if (snd_pcm_running(substream))
-		ret = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-	snd_pcm_stream_unlock_irqrestore(substream, flags);
-	return ret;
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
-#endif /* __BACKPORT_SOUND_PCM_H */
diff --git a/compat/Kconfig b/compat/Kconfig
index a5ae300..d501092 100644
--- a/compat/Kconfig
+++ b/compat/Kconfig
@@ -1,37 +1,37 @@
 #
 # backport Kconfig
 #
-# Some options are user-selectable ("BPAUTO_USERSEL_*")
+# Some options are user-selectable ("BACKPORT_USERSEL_*")
 #
 # Most options, however, follow a few different schemes:
 #
 # A) An option that is selected by drivers ("select FOO") will be
-#    changed to "select BPAUTO_FOO" (if the option BPAUTO_FOO
-#    exists). The option BPAUTO_FOO then controls setting of the
-#    BPAUTO_BUILD_FOO option, which is a module, like this:
+#    changed to "select BACKPORT_FOO" (if the option BACKPORT_FOO
+#    exists). The option BACKPORT_FOO then controls setting of the
+#    BACKPORT_BUILD_FOO option, which is a module, like this:
 #
-# config BPAUTO_BUILD_FOO
+# config BACKPORT_BUILD_FOO
 #	tristate
 #	# or bool
 #
 #	# not possible on kernel < X.Y, build will fail if any
 #	# drivers are allowed to build on kernels < X.Y
-#	depends on KERNEL_X_Y
+#	depends on BACKPORT_KERNEL_X_Y
 #
 #	# don't build the backport code if FOO is in the kernel
 #	# already, but only if the kernel version is also >= X.Z;
 #	# this is an example of backporting where the version of
 #	# the FOO subsystem that we need is only available from
 #	# kernel version X.Z
-#	depends on !FOO || KERNEL_X_Z
+#	depends on !FOO || BACKPORT_KERNEL_X_Z
 #
-#	# build if driver needs it (it selects BPAUTO_FOO)
-#	default m if BPAUTO_FOO
+#	# build if driver needs it (it selects BACKPORT_FOO)
+#	default m if BACKPORT_FOO
 #
-#	# or for build-testing (BPAUTO_USERSEL_BUILD_ALL is enabled)
-#	default m if BPAUTO_USERSEL_BUILD_ALL
+#	# or for build-testing (BACKPORT_USERSEL_BUILD_ALL is enabled)
+#	default m if BACKPORT_USERSEL_BUILD_ALL
 #
-# config BPAUTO_FOO
+# config BACKPORT_FOO
 #	bool
 #
 # This only works as-is if the kernel code is usable on any version,
@@ -41,72 +41,72 @@
 # B) An option for code always present on some kernels (e.g. KFIFO).
 #    This simply depends on/sets the default based on the version:
 #
-# config BPAUTO_BUILD_KFIFO
+# config BACKPORT_BUILD_KFIFO
 #	def_bool y
-#	depends on KERNEL_2_6_36
+#	depends on BACKPORT_KERNEL_2_6_36
 #
 #
 # C) similarly, a kconfig symbol for an option, e.g.
-#    BPAUTO_OPTION_SOME_FIX (no examples provided) check git log
+#    BACKPORT_OPTION_SOME_FIX (no examples provided) check git log
 #
 #
 # Variations are obviously possible.
 #
 
-config BPAUTO_BUILD_CORDIC
+config BACKPORT_BUILD_CORDIC
 	tristate
 	depends on m
 	depends on !CORDIC
-	default m if BPAUTO_CORDIC
-	default m if BPAUTO_USERSEL_BUILD_ALL
+	default m if BACKPORT_CORDIC
+	default m if BACKPORT_USERSEL_BUILD_ALL
 	#module-name cordic
 	#c-file lib/cordic.c
 
-config BPAUTO_CORDIC
+config BACKPORT_CORDIC
 	bool
 
-config BPAUTO_BUILD_AVERAGE
+config BACKPORT_BUILD_AVERAGE
 	bool
 	depends on !AVERAGE
-	default y if BPAUTO_USERSEL_BUILD_ALL
-	default y if BPAUTO_AVERAGE
+	default y if BACKPORT_USERSEL_BUILD_ALL
+	default y if BACKPORT_AVERAGE
 	#h-file linux/average.h
 	#c-file lib/average.c
 
-config BPAUTO_AVERAGE
+config BACKPORT_AVERAGE
 	bool
 
-config BPAUTO_MII
+config BACKPORT_MII
 	bool
 
-config BPAUTO_BUILD_DMA_SHARED_HELPERS
+config BACKPORT_BUILD_DMA_SHARED_HELPERS
 	bool
 	depends on HAS_DMA
 	# Build on other kernels kernels < 3.9 if HAVE_GENERIC_DMA_COHERENT is
 	# not set. Kernels >= 3.8 have this if HAS_DMA is set.
-	depends on (!HAVE_GENERIC_DMA_COHERENT || KERNEL_3_9)
+	depends on (!HAVE_GENERIC_DMA_COHERENT || BACKPORT_KERNEL_3_9)
 	# Always build if on 3.3 - 3.5
-	default y if (KERNEL_3_4 || KERNEL_3_5 || KERNEL_3_6)
+	default y if (BACKPORT_KERNEL_3_4 || BACKPORT_KERNEL_3_5 || BACKPORT_KERNEL_3_6)
 	# build for testing
-	default y if BPAUTO_USERSEL_BUILD_ALL
+	default y if BACKPORT_USERSEL_BUILD_ALL
 
-config BPAUTO_BUILD_LEDS
+config BACKPORT_BUILD_LEDS
 	bool
 	depends on !NEW_LEDS || LEDS_CLASS=n || !LEDS_TRIGGERS
-	default y if BPAUTO_NEW_LEDS
-	default y if BPAUTO_LEDS_CLASS
-	default y if BPAUTO_LEDS_TRIGGERS
+	default y if BACKPORT_NEW_LEDS
+	default y if BACKPORT_LEDS_CLASS
+	default y if BACKPORT_LEDS_TRIGGERS
 
-config BPAUTO_NEW_LEDS
+config BACKPORT_NEW_LEDS
 	bool
 
-config BPAUTO_LEDS_CLASS
+config BACKPORT_LEDS_CLASS
 	bool
 
-config BPAUTO_LEDS_TRIGGERS
+config BACKPORT_LEDS_TRIGGERS
 	bool
 
-config BPAUTO_USERSEL_BUILD_ALL
+config BACKPORT_USERSEL_BUILD_ALL
 	bool "Build all compat code"
 	help
 	  This option selects all the compat code options
@@ -115,24 +115,25 @@
 	  It's only really useful for compat testing, so
 	  you probably shouldn't enable it.
 
-config BPAUTO_CRYPTO_CCM
+config BACKPORT_CRYPTO_CCM
 	depends on CRYPTO_AEAD
 	depends on CRYPTO_CTR
 	bool
 
-config BPAUTO_BUILD_CRYPTO_CCM
+config BACKPORT_BUILD_CRYPTO_CCM
 	bool
 	default n if CRYPTO_CCM
-	default y if BPAUTO_CRYPTO_CCM
+	default y if BACKPORT_CRYPTO_CCM
 	#c-file crypto/ccm.c
 
-config BPAUTO_WANT_DEV_COREDUMP
+config BACKPORT_WANT_DEV_COREDUMP
 	bool
 
-config BPAUTO_BUILD_WANT_DEV_COREDUMP
+config BACKPORT_BUILD_WANT_DEV_COREDUMP
+	depends on n
 	bool
 	default n if DEV_COREDUMP
 	default n if DISABLE_DEV_COREDUMP
-	default y if BPAUTO_WANT_DEV_COREDUMP
+	default y if BACKPORT_WANT_DEV_COREDUMP
 	#h-file linux/devcoredump.h
 	#c-file drivers/base/devcoredump.c
diff --git a/compat/Makefile b/compat/Makefile
index 36c4377..1df6225 100644
--- a/compat/Makefile
+++ b/compat/Makefile
@@ -1,35 +1,29 @@
 ccflags-y += -I$(src)
-ifeq ($(CONFIG_BACKPORT_INTEGRATE),)
 obj-m += compat.o
-else
-obj-y += compat.o
-endif
 compat-y += main.o
 
 # Kernel backport compatibility code
-compat-$(CPTCFG_KERNEL_3_0) += compat-3.0.o
-compat-$(CPTCFG_KERNEL_3_1) += compat-3.1.o
-compat-$(CPTCFG_KERNEL_3_2) += backport-3.2.o
-compat-$(CPTCFG_KERNEL_3_3) += compat-3.3.o
-compat-$(CPTCFG_KERNEL_3_4) += compat-3.4.o
-compat-$(CPTCFG_KERNEL_3_5) += compat-3.5.o user_namespace.o
-compat-$(CPTCFG_KERNEL_3_6) += compat-3.6.o
-compat-$(CPTCFG_KERNEL_3_7) += compat-3.7.o
-compat-$(CPTCFG_KERNEL_3_8) += compat-3.8.o
-compat-$(CPTCFG_KERNEL_3_9) += compat-3.9.o
-compat-$(CPTCFG_KERNEL_3_10) += backport-3.10.o
-compat-$(CPTCFG_KERNEL_3_12) += backport-3.12.o
-compat-$(CPTCFG_KERNEL_3_13) += backport-3.13.o
-compat-$(CPTCFG_KERNEL_3_14) += backport-3.14.o
-compat-$(CPTCFG_KERNEL_3_15) += backport-3.15.o
-compat-$(CPTCFG_KERNEL_3_17) += backport-3.17.o
-compat-$(CPTCFG_KERNEL_3_18) += backport-3.18.o
-compat-$(CPTCFG_KERNEL_3_19) += backport-3.19.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_0) += compat-3.0.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_1) += compat-3.1.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_2) += backport-3.2.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_3) += compat-3.3.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_4) += compat-3.4.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_5) += compat-3.5.o user_namespace.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_6) += compat-3.6.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_7) += compat-3.7.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_8) += compat-3.8.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_9) += compat-3.9.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_10) += backport-3.10.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_12) += backport-3.12.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_13) += backport-3.13.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_14) += backport-3.14.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_15) += backport-3.15.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_17) += backport-3.17.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_18) += backport-3.18.o
 
-compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o
-compat-$(CPTCFG_BPAUTO_BUILD_DMA_SHARED_HELPERS) += dma-shared-helpers.o
-compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o
-compat-$(CPTCFG_BPAUTO_BUILD_AVERAGE) += lib-average.o
+compat-$(CPTCFG_BACKPORT_BUILD_CRYPTO_CCM) += crypto-ccm.o
+compat-$(CPTCFG_BACKPORT_BUILD_DMA_SHARED_HELPERS) += dma-shared-helpers.o
 cordic-objs += lib-cordic.o
-obj-$(CPTCFG_BPAUTO_BUILD_CORDIC) += cordic.o
-compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o
+obj-$(CPTCFG_BACKPORT_BUILD_CORDIC) += cordic.o
+compat-$(CPTCFG_BACKPORT_BUILD_AVERAGE) += lib-average.o
+compat-$(CPTCFG_BACKPORT_BUILD_CRYPTO_CCM) += crypto-ccm.o
diff --git a/compat/backport-3.13.c b/compat/backport-3.13.c
index 553ed8f..fd562bb 100644
--- a/compat/backport-3.13.c
+++ b/compat/backport-3.13.c
@@ -12,8 +12,6 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <net/genetlink.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
 #ifdef CONFIG_REGULATOR
@@ -202,53 +200,3 @@
 }
 EXPORT_SYMBOL_GPL(__net_get_random_once);
 #endif /* __BACKPORT_NET_GET_RANDOM_ONCE */
-
-#ifdef CONFIG_PCI
-#define pci_bus_read_dev_vendor_id LINUX_BACKPORT(pci_bus_read_dev_vendor_id)
-static bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
-				int crs_timeout)
-{
-	int delay = 1;
-
-	if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
-		return false;
-
-	/* some broken boards return 0 or ~0 if a slot is empty: */
-	if (*l == 0xffffffff || *l == 0x00000000 ||
-	    *l == 0x0000ffff || *l == 0xffff0000)
-		return false;
-
-	/*
-	 * Configuration Request Retry Status.  Some root ports return the
-	 * actual device ID instead of the synthetic ID (0xFFFF) required
-	 * by the PCIe spec.  Ignore the device ID and only check for
-	 * (vendor id == 1).
-	 */
-	while ((*l & 0xffff) == 0x0001) {
-		if (!crs_timeout)
-			return false;
-
-		msleep(delay);
-		delay *= 2;
-		if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
-			return false;
-		/* Card hasn't responded in 60 seconds?  Must be stuck. */
-		if (delay > crs_timeout) {
-			printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not responding\n",
-			       pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
-			       PCI_FUNC(devfn));
-			return false;
-		}
-	}
-
-	return true;
-}
-
-bool pci_device_is_present(struct pci_dev *pdev)
-{
-	u32 v;
-
-	return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0);
-}
-EXPORT_SYMBOL_GPL(pci_device_is_present);
-#endif /* CONFIG_PCI */
diff --git a/compat/backport-3.19.c b/compat/backport-3.19.c
deleted file mode 100644
index c633f38..0000000
--- a/compat/backport-3.19.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2014  Hauke Mehrtens <hauke@hauke-m.de>
- *
- * Backport functionality introduced in Linux 3.18.
- *
- * 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/wait.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <linux/export.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/debugfs.h>
-
-static inline bool is_kthread_should_stop(void)
-{
-	return (current->flags & PF_KTHREAD) && kthread_should_stop();
-}
-
-/*
- * DEFINE_WAIT_FUNC(wait, woken_wake_func);
- *
- * add_wait_queue(&wq, &wait);
- * for (;;) {
- *     if (condition)
- *         break;
- *
- *     p->state = mode;				condition = true;
- *     smp_mb(); // A				smp_wmb(); // C
- *     if (!wait->flags & WQ_FLAG_WOKEN)	wait->flags |= WQ_FLAG_WOKEN;
- *         schedule()				try_to_wake_up();
- *     p->state = TASK_RUNNING;		    ~~~~~~~~~~~~~~~~~~
- *     wait->flags &= ~WQ_FLAG_WOKEN;		condition = true;
- *     smp_mb() // B				smp_wmb(); // C
- *						wait->flags |= WQ_FLAG_WOKEN;
- * }
- * remove_wait_queue(&wq, &wait);
- *
- */
-long wait_woken(wait_queue_t *wait, unsigned mode, long timeout)
-{
-	set_current_state(mode); /* A */
-	/*
-	 * The above implies an smp_mb(), which matches with the smp_wmb() from
-	 * woken_wake_function() such that if we observe WQ_FLAG_WOKEN we must
-	 * also observe all state before the wakeup.
-	 */
-	if (!(wait->flags & WQ_FLAG_WOKEN) && !is_kthread_should_stop())
-		timeout = schedule_timeout(timeout);
-	__set_current_state(TASK_RUNNING);
-
-	/*
-	 * The below implies an smp_mb(), it too pairs with the smp_wmb() from
-	 * woken_wake_function() such that we must either observe the wait
-	 * condition being true _OR_ WQ_FLAG_WOKEN such that we will not miss
-	 * an event.
-	 */
-	set_mb(wait->flags, wait->flags & ~WQ_FLAG_WOKEN); /* B */
-
-	return timeout;
-}
-EXPORT_SYMBOL(wait_woken);
-
-int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
-	/*
-	 * Although this function is called under waitqueue lock, LOCK
-	 * doesn't imply write barrier and the users expects write
-	 * barrier semantics on wakeup functions.  The following
-	 * smp_wmb() is equivalent to smp_wmb() in try_to_wake_up()
-	 * and is paired with set_mb() in wait_woken().
-	 */
-	smp_wmb(); /* C */
-	wait->flags |= WQ_FLAG_WOKEN;
-
-	return default_wake_function(wait, mode, sync, key);
-}
-EXPORT_SYMBOL(woken_wake_function);
-
-#ifdef __BACKPORT_NETDEV_RSS_KEY_FILL
-u8 netdev_rss_key[NETDEV_RSS_KEY_LEN];
-
-void netdev_rss_key_fill(void *buffer, size_t len)
-{
-	BUG_ON(len > sizeof(netdev_rss_key));
-	net_get_random_once(netdev_rss_key, sizeof(netdev_rss_key));
-	memcpy(buffer, netdev_rss_key, len);
-}
-EXPORT_SYMBOL_GPL(netdev_rss_key_fill);
-#endif /* __BACKPORT_NETDEV_RSS_KEY_FILL */
-
-#if defined(CONFIG_DEBUG_FS)
-struct debugfs_devm_entry {
-	int (*read)(struct seq_file *seq, void *data);
-	struct device *dev;
-};
-
-static int debugfs_devm_entry_open(struct inode *inode, struct file *f)
-{
-	struct debugfs_devm_entry *entry = inode->i_private;
-
-	return single_open(f, entry->read, entry->dev);
-}
-
-static const struct file_operations debugfs_devm_entry_ops = {
-	.owner = THIS_MODULE,
-	.open = debugfs_devm_entry_open,
-	.release = single_release,
-	.read = seq_read,
-	.llseek = seq_lseek
-};
-
-/**
- * debugfs_create_devm_seqfile - create a debugfs file that is bound to device.
- *
- * @dev: device related to this debugfs file.
- * @name: name of the debugfs file.
- * @parent: a pointer to the parent dentry for this file.  This should be a
- *	directory dentry if set.  If this parameter is %NULL, then the
- *	file will be created in the root of the debugfs filesystem.
- * @read_fn: function pointer called to print the seq_file content.
- */
-struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
-					   struct dentry *parent,
-					   int (*read_fn)(struct seq_file *s,
-							  void *data))
-{
-	struct debugfs_devm_entry *entry;
-
-	if (IS_ERR(parent))
-		return ERR_PTR(-ENOENT);
-
-	entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
-	if (!entry)
-		return ERR_PTR(-ENOMEM);
-
-	entry->read = read_fn;
-	entry->dev = dev;
-
-	return debugfs_create_file(name, S_IRUGO, parent, entry,
-				   &debugfs_devm_entry_ops);
-}
-EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile);
-
-#endif /* CONFIG_DEBUG_FS */
diff --git a/compat/backports.h b/compat/backports.h
index ccc8972..c9094ac 100644
--- a/compat/backports.h
+++ b/compat/backports.h
@@ -3,7 +3,7 @@
 
 #include <linux/version.h>
 
-#ifdef CPTCFG_BPAUTO_BUILD_CRYPTO_CCM
+#ifdef CPTCFG_BACKPORT_BUILD_CRYPTO_CCM
 int crypto_ccm_module_init(void);
 void crypto_ccm_module_exit(void);
 #else
@@ -13,7 +13,7 @@
 {}
 #endif
 
-#ifdef CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP
+#ifdef CPTCFG_BACKPORT_BUILD_WANT_DEV_COREDUMP
 int devcoredump_init(void);
 void devcoredump_exit(void);
 #else
diff --git a/compat/compat-3.1.c b/compat/compat-3.1.c
index 2618780..0d9c3a2 100644
--- a/compat/compat-3.1.c
+++ b/compat/compat-3.1.c
@@ -10,7 +10,6 @@
 
 #include <linux/idr.h>
 #include <linux/cpufreq.h>
-#include <linux/of.h>
 
 static DEFINE_SPINLOCK(compat_simple_ida_lock);
 
@@ -83,36 +82,3 @@
 EXPORT_SYMBOL_GPL(ida_simple_remove);
 /* source lib/idr.c */
 
-#ifdef CONFIG_OF
-/**
- * of_property_read_u32_array - Find and read an array of 32 bit integers
- * from a property.
- *
- * @np:		device node from which the property value is to be read.
- * @propname:	name of the property to be searched.
- * @out_values:	pointer to return value, modified only if return value is 0.
- * @sz:		number of array elements to read
- *
- * Search for a property in a device node and read 32-bit value(s) from
- * it. Returns 0 on success, -EINVAL if the property does not exist,
- * -ENODATA if property does not have a value, and -EOVERFLOW if the
- * property data isn't large enough.
- *
- * The out_values is modified only if a valid u32 value can be decoded.
- */
-int of_property_read_u32_array(const struct device_node *np,
-			       const char *propname, u32 *out_values,
-			       size_t sz)
-{
-	const __be32 *val = of_find_property_value_of_size(np, propname,
-						(sz * sizeof(*out_values)));
-
-	if (IS_ERR(val))
-		return PTR_ERR(val);
-
-	while (sz--)
-		*out_values++ = be32_to_cpup(val++);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(of_property_read_u32_array);
-#endif
diff --git a/compat/compat-3.3.c b/compat/compat-3.3.c
index 490c29b..7ddc2bd 100644
--- a/compat/compat-3.3.c
+++ b/compat/compat-3.3.c
@@ -224,16 +224,3 @@
 	spin_unlock(&wq_name_lock);
 }
 EXPORT_SYMBOL_GPL(backport_destroy_workqueue);
-
-void genl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
-		 struct nlmsghdr *nlh, gfp_t flags)
-{
-	struct sock *sk = net->genl_sock;
-	int report = 0;
-
-	if (nlh)
-		report = nlmsg_report(nlh);
-
-	nlmsg_notify(sk, skb, pid, group, report, flags);
-}
-EXPORT_SYMBOL_GPL(genl_notify);
diff --git a/compat/drivers-base-devcoredump.c b/compat/drivers-base-devcoredump.c
deleted file mode 100644
index f15c830..0000000
--- a/compat/drivers-base-devcoredump.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * This file is provided under the GPLv2 license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2014 Intel Mobile Communications GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * Author: Johannes Berg <johannes@sipsolutions.net>
- */
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/devcoredump.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/workqueue.h>
-#include "backports.h"
-
-static struct class devcd_class;
-
-/* global disable flag, for security purposes */
-static bool devcd_disabled;
-
-/* if data isn't read by userspace after 5 minutes then delete it */
-#define DEVCD_TIMEOUT	(HZ * 60 * 5)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
-static struct bin_attribute devcd_attr_data;
-#endif
-
-struct devcd_entry {
-	struct device devcd_dev;
-	const void *data;
-	size_t datalen;
-	struct module *owner;
-	ssize_t (*read)(char *buffer, loff_t offset, size_t count,
-			const void *data, size_t datalen);
-	void (*free)(const void *data);
-	struct delayed_work del_wk;
-	struct device *failing_dev;
-};
-
-static struct devcd_entry *dev_to_devcd(struct device *dev)
-{
-	return container_of(dev, struct devcd_entry, devcd_dev);
-}
-
-static void devcd_dev_release(struct device *dev)
-{
-	struct devcd_entry *devcd = dev_to_devcd(dev);
-
-	devcd->free(devcd->data);
-	module_put(devcd->owner);
-
-	/*
-	 * this seems racy, but I don't see a notifier or such on
-	 * a struct device to know when it goes away?
-	 */
-	if (devcd->failing_dev->kobj.sd)
-		sysfs_remove_link(&devcd->failing_dev->kobj, "devcoredump");
-
-	put_device(devcd->failing_dev);
-	kfree(devcd);
-}
-
-static void devcd_del(struct work_struct *wk)
-{
-	struct devcd_entry *devcd;
-
-	devcd = container_of(wk, struct devcd_entry, del_wk.work);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
-	device_remove_bin_file(&devcd->devcd_dev, &devcd_attr_data);
-#endif
-	device_del(&devcd->devcd_dev);
-	put_device(&devcd->devcd_dev);
-}
-
-static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj,
-			       struct bin_attribute *bin_attr,
-			       char *buffer, loff_t offset, size_t count)
-{
-	struct device *dev = kobj_to_dev(kobj);
-	struct devcd_entry *devcd = dev_to_devcd(dev);
-
-	return devcd->read(buffer, offset, count, devcd->data, devcd->datalen);
-}
-
-static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj,
-				struct bin_attribute *bin_attr,
-				char *buffer, loff_t offset, size_t count)
-{
-	struct device *dev = kobj_to_dev(kobj);
-	struct devcd_entry *devcd = dev_to_devcd(dev);
-
-	mod_delayed_work(system_wq, &devcd->del_wk, 0);
-
-	return count;
-}
-
-static struct bin_attribute devcd_attr_data = {
-	.attr = { .name = "data", .mode = S_IRUSR | S_IWUSR, },
-	.size = 0,
-	.read = devcd_data_read,
-	.write = devcd_data_write,
-};
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
-static struct bin_attribute *devcd_dev_bin_attrs[] = {
-	&devcd_attr_data, NULL,
-};
-
-static const struct attribute_group devcd_dev_group = {
-	.bin_attrs = devcd_dev_bin_attrs,
-};
-
-static const struct attribute_group *devcd_dev_groups[] = {
-	&devcd_dev_group, NULL,
-};
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) */
-
-static int devcd_free(struct device *dev, void *data)
-{
-	struct devcd_entry *devcd = dev_to_devcd(dev);
-
-	flush_delayed_work(&devcd->del_wk);
-	return 0;
-}
-
-static ssize_t disabled_show(struct class *class, struct class_attribute *attr,
-			     char *buf)
-{
-	return sprintf(buf, "%d\n", devcd_disabled);
-}
-
-static ssize_t disabled_store(struct class *class, struct class_attribute *attr,
-			      const char *buf, size_t count)
-{
-	long tmp = simple_strtol(buf, NULL, 10);
-
-	/*
-	 * This essentially makes the attribute write-once, since you can't
-	 * go back to not having it disabled. This is intentional, it serves
-	 * as a system lockdown feature.
-	 */
-	if (tmp != 1)
-		return -EINVAL;
-
-	devcd_disabled = true;
-
-	class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
-
-	return count;
-}
-
-static struct class_attribute devcd_class_attrs[] = {
-	__ATTR_RW(disabled),
-	__ATTR_NULL
-};
-
-static struct class devcd_class = {
-	.name		= "devcoredump",
-	.owner		= THIS_MODULE,
-	.dev_release	= devcd_dev_release,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
-	.dev_groups	= devcd_dev_groups,
-#endif
-	.class_attrs	= devcd_class_attrs,
-};
-
-static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count,
-			   const void *data, size_t datalen)
-{
-	if (offset > datalen)
-		return -EINVAL;
-
-	if (offset + count > datalen)
-		count = datalen - offset;
-
-	if (count)
-		memcpy(buffer, ((u8 *)data) + offset, count);
-
-	return count;
-}
-
-/**
- * dev_coredumpv - create device coredump with vmalloc data
- * @dev: the struct device for the crashed device
- * @data: vmalloc data containing the device coredump
- * @datalen: length of the data
- * @gfp: allocation flags
- *
- * This function takes ownership of the vmalloc'ed data and will free
- * it when it is no longer used. See dev_coredumpm() for more information.
- */
-void dev_coredumpv(struct device *dev, const void *data, size_t datalen,
-		   gfp_t gfp)
-{
-	dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, vfree);
-}
-EXPORT_SYMBOL_GPL(dev_coredumpv);
-
-static int devcd_match_failing(struct device *dev, const void *failing)
-{
-	struct devcd_entry *devcd = dev_to_devcd(dev);
-
-	return devcd->failing_dev == failing;
-}
-
-/**
- * dev_coredumpm - create device coredump with read/free methods
- * @dev: the struct device for the crashed device
- * @owner: the module that contains the read/free functions, use %THIS_MODULE
- * @data: data cookie for the @read/@free functions
- * @datalen: length of the data
- * @gfp: allocation flags
- * @read: function to read from the given buffer
- * @free: function to free the given buffer
- *
- * Creates a new device coredump for the given device. If a previous one hasn't
- * been read yet, the new coredump is discarded. The data lifetime is determined
- * by the device coredump framework and when it is no longer needed the @free
- * function will be called to free the data.
- */
-void dev_coredumpm(struct device *dev, struct module *owner,
-		   const void *data, size_t datalen, gfp_t gfp,
-		   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
-				   const void *data, size_t datalen),
-		   void (*free)(const void *data))
-{
-	static atomic_t devcd_count = ATOMIC_INIT(0);
-	struct devcd_entry *devcd;
-	struct device *existing;
-
-	if (devcd_disabled)
-		goto free;
-
-	existing = class_find_device(&devcd_class, NULL, dev,
-				     devcd_match_failing);
-	if (existing) {
-		put_device(existing);
-		goto free;
-	}
-
-	if (!try_module_get(owner))
-		goto free;
-
-	devcd = kzalloc(sizeof(*devcd), gfp);
-	if (!devcd)
-		goto put_module;
-
-	devcd->owner = owner;
-	devcd->data = data;
-	devcd->datalen = datalen;
-	devcd->read = read;
-	devcd->free = free;
-	devcd->failing_dev = get_device(dev);
-
-	device_initialize(&devcd->devcd_dev);
-
-	dev_set_name(&devcd->devcd_dev, "devcd%d",
-		     atomic_inc_return(&devcd_count));
-	devcd->devcd_dev.class = &devcd_class;
-
-	if (device_add(&devcd->devcd_dev))
-		goto put_device;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
-	if (device_create_bin_file(&devcd->devcd_dev, &devcd_attr_data))
-		goto put_device;
-#endif
-
-	if (sysfs_create_link(&devcd->devcd_dev.kobj, &dev->kobj,
-			      "failing_device"))
-		/* nothing - symlink will be missing */;
-
-	if (sysfs_create_link(&dev->kobj, &devcd->devcd_dev.kobj,
-			      "devcoredump"))
-		/* nothing - symlink will be missing */;
-
-	INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
-	schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
-
-	return;
- put_device:
-	put_device(&devcd->devcd_dev);
- put_module:
-	module_put(owner);
- free:
-	free(data);
-}
-EXPORT_SYMBOL_GPL(dev_coredumpm);
-
-int __init devcoredump_init(void)
-{
-	return class_register(&devcd_class);
-}
-
-void __exit devcoredump_exit(void)
-{
-	class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
-	class_unregister(&devcd_class);
-}
diff --git a/compat/main.c b/compat/main.c
index 5d45e3d..d3f8944 100644
--- a/compat/main.c
+++ b/compat/main.c
@@ -8,40 +8,40 @@
 MODULE_DESCRIPTION("Kernel backport module");
 MODULE_LICENSE("GPL");
 
-#ifndef CPTCFG_KERNEL_NAME
-#error "You need a CPTCFG_KERNEL_NAME"
+#ifndef BACKPORTED_KERNEL_NAME
+#error "You need a BACKPORTED_KERNEL_NAME"
 #endif
 
-#ifndef CPTCFG_KERNEL_VERSION
-#error "You need a CPTCFG_KERNEL_VERSION"
+#ifndef BACKPORTED_KERNEL_VERSION
+#error "You need a BACKPORTED_KERNEL_VERSION"
 #endif
 
-#ifndef CPTCFG_VERSION
-#error "You need a CPTCFG_VERSION"
+#ifndef BACKPORTS_VERSION
+#error "You need a BACKPORTS_VERSION"
 #endif
 
-static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
+static char *backported_kernel_name = BACKPORTED_KERNEL_NAME;
 
 module_param(backported_kernel_name, charp, 0400);
 MODULE_PARM_DESC(backported_kernel_name,
-		 "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
+		 "The kernel tree name that was used for this backport (" BACKPORTED_KERNEL_NAME ")");
 
-#ifdef BACKPORTS_GIT_TRACKED
+#ifdef BACKPORTS_GIT_TRACKED 
 static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
 module_param(backports_tracker_id, charp, 0400);
 MODULE_PARM_DESC(backports_tracker_id,
 		 "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
 #else
-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
-static char *backports_version = CPTCFG_VERSION;
+static char *backported_kernel_version = BACKPORTED_KERNEL_VERSION;
+static char *backports_version = BACKPORTS_VERSION;
 
 module_param(backported_kernel_version, charp, 0400);
 MODULE_PARM_DESC(backported_kernel_version,
-		 "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
+		 "The kernel version that was used for this backport (" BACKPORTED_KERNEL_VERSION ")");
 
 module_param(backports_version, charp, 0400);
 MODULE_PARM_DESC(backports_version,
-		 "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
+		 "The git version of the backports tree used to generate this backport (" BACKPORTS_VERSION ")");
 
 #endif
 
@@ -63,22 +63,16 @@
 		return ret;
 	}
 
-	printk(KERN_INFO "Loading modules backported from " CPTCFG_KERNEL_NAME
+	printk(KERN_INFO "Loading modules backported from " BACKPORTED_KERNEL_NAME
 #ifndef BACKPORTS_GIT_TRACKED
-		" version " CPTCFG_KERNEL_VERSION
+		" version " BACKPORTED_KERNEL_VERSION
 #endif
 		"\n");
 #ifdef BACKPORTS_GIT_TRACKED
 	printk(KERN_INFO BACKPORTS_GIT_TRACKED "\n");
 #else
-
-#ifdef CONFIG_BACKPORT_INTEGRATE
-	printk(KERN_INFO "Backport integrated by backports.git " CPTCFG_VERSION "\n");
-#else
-	printk(KERN_INFO "Backport generated by backports.git " CPTCFG_VERSION "\n");
-#endif /* CONFIG_BACKPORT_INTEGRATE */
-
-#endif /* BACKPORTS_GIT_TRACKED */
+	printk(KERN_INFO "Backport generated by backports.git " BACKPORTS_VERSION "\n");
+#endif
 
         return 0;
 }
diff --git a/defconfigs/ieee802154 b/defconfigs/ieee802154
new file mode 100644
index 0000000..2c6730a
--- /dev/null
+++ b/defconfigs/ieee802154
@@ -0,0 +1,8 @@
+CPTCFG_IEEE802154_DRIVERS=m
+CPTCFG_IEEE802154_FAKEHARD=m
+CPTCFG_IEEE802154_FAKELB=m
+CPTCFG_IEEE802154_AT86RF230=m
+CPTCFG_IEEE802154_MRF24J40=m
+CPTCFG_IEEE802154=m
+CPTCFG_IEEE802154_6LOWPAN=m
+CPTCFG_MAC802154=m
diff --git a/defconfigs/media b/defconfigs/media
new file mode 100644
index 0000000..7b1bfa9
--- /dev/null
+++ b/defconfigs/media
@@ -0,0 +1,513 @@
+CPTCFG_DVB_A8293=m
+CPTCFG_DVB_AF9013=m
+CPTCFG_DVB_AF9033=m
+CPTCFG_DVB_AS102=m
+CPTCFG_DVB_AS102_FE=m
+CPTCFG_DVB_ATBM8830=m
+CPTCFG_DVB_AU8522=m
+CPTCFG_DVB_AU8522_DTV=m
+CPTCFG_DVB_AU8522_V4L=m
+CPTCFG_DVB_AV7110=m
+CPTCFG_DVB_B2C2_FLEXCOP=m
+CPTCFG_DVB_B2C2_FLEXCOP_PCI=m
+CPTCFG_DVB_B2C2_FLEXCOP_USB=m
+CPTCFG_DVB_BCM3510=m
+CPTCFG_DVB_BT8XX=m
+CPTCFG_DVB_BUDGET=m
+CPTCFG_DVB_BUDGET_AV=m
+CPTCFG_DVB_BUDGET_CI=m
+CPTCFG_DVB_BUDGET_CORE=m
+CPTCFG_DVB_BUDGET_PATCH=m
+CPTCFG_DVB_CORE=m
+CPTCFG_DVB_CX22700=m
+CPTCFG_DVB_CX22702=m
+CPTCFG_DVB_CX24110=m
+CPTCFG_DVB_CX24116=m
+CPTCFG_DVB_CX24123=m
+CPTCFG_DVB_CXD2820R=m
+CPTCFG_DVB_DDBRIDGE=m
+CPTCFG_DVB_DIB3000MB=m
+CPTCFG_DVB_DIB3000MC=m
+CPTCFG_DVB_DIB7000M=m
+CPTCFG_DVB_DIB7000P=m
+CPTCFG_DVB_DIB8000=m
+CPTCFG_DVB_DIB9000=m
+CPTCFG_DVB_DM1105=m
+CPTCFG_DVB_DRXD=m
+CPTCFG_DVB_DRXK=m
+CPTCFG_DVB_DS3000=m
+CPTCFG_DVB_DUMMY_FE=m
+CPTCFG_DVB_EC100=m
+CPTCFG_DVB_FIREDTV=m
+CPTCFG_DVB_FIREDTV_INPUT=y
+CPTCFG_DVB_HD29L2=m
+CPTCFG_DVB_HOPPER=m
+CPTCFG_DVB_ISL6405=m
+CPTCFG_DVB_ISL6421=m
+CPTCFG_DVB_ISL6423=m
+CPTCFG_DVB_IX2505V=m
+CPTCFG_DVB_L64781=m
+CPTCFG_DVB_LG2160=m
+CPTCFG_DVB_LGDT3305=m
+CPTCFG_DVB_LGDT330X=m
+CPTCFG_DVB_LGS8GL5=m
+CPTCFG_DVB_LGS8GXX=m
+CPTCFG_DVB_LNBP21=m
+CPTCFG_DVB_LNBP22=m
+CPTCFG_DVB_M88RS2000=m
+CPTCFG_DVB_MANTIS=m
+CPTCFG_DVB_MB86A16=m
+CPTCFG_DVB_MB86A20S=m
+CPTCFG_DVB_MT312=m
+CPTCFG_DVB_MT352=m
+CPTCFG_DVB_NGENE=m
+CPTCFG_DVB_NXT200X=m
+CPTCFG_DVB_NXT6000=m
+CPTCFG_DVB_OR51132=m
+CPTCFG_DVB_OR51211=m
+CPTCFG_DVB_PLL=m
+CPTCFG_DVB_PLUTO2=m
+CPTCFG_DVB_PT1=m
+CPTCFG_DVB_PT3=m
+CPTCFG_DVB_RTL2830=m
+CPTCFG_DVB_RTL2832=m
+CPTCFG_DVB_S5H1409=m
+CPTCFG_DVB_S5H1411=m
+CPTCFG_DVB_S5H1420=m
+CPTCFG_DVB_S5H1432=m
+CPTCFG_DVB_S921=m
+CPTCFG_DVB_SI21XX=m
+CPTCFG_DVB_SP8870=m
+CPTCFG_DVB_SP887X=m
+CPTCFG_DVB_STB0899=m
+CPTCFG_DVB_STB6000=m
+CPTCFG_DVB_STB6100=m
+CPTCFG_DVB_STV0288=m
+CPTCFG_DVB_STV0297=m
+CPTCFG_DVB_STV0299=m
+CPTCFG_DVB_STV0367=m
+CPTCFG_DVB_STV0900=m
+CPTCFG_DVB_STV090x=m
+CPTCFG_DVB_STV6110=m
+CPTCFG_DVB_STV6110x=m
+CPTCFG_DVB_TDA10021=m
+CPTCFG_DVB_TDA10023=m
+CPTCFG_DVB_TDA10048=m
+CPTCFG_DVB_TDA1004X=m
+CPTCFG_DVB_TDA10071=m
+CPTCFG_DVB_TDA10086=m
+CPTCFG_DVB_TDA18271C2DD=m
+CPTCFG_DVB_TDA665x=m
+CPTCFG_DVB_TDA8083=m
+CPTCFG_DVB_TDA8261=m
+CPTCFG_DVB_TDA826X=m
+CPTCFG_DVB_TS2020=m
+CPTCFG_DVB_TTUSB_BUDGET=m
+CPTCFG_DVB_TTUSB_DEC=m
+CPTCFG_DVB_TUA6100=m
+CPTCFG_DVB_TUNER_CX24113=m
+CPTCFG_DVB_TUNER_DIB0070=m
+CPTCFG_DVB_TUNER_DIB0090=m
+CPTCFG_DVB_TUNER_ITD1000=m
+CPTCFG_DVB_USB=m
+CPTCFG_DVB_USB_A800=m
+CPTCFG_DVB_USB_AF9005=m
+CPTCFG_DVB_USB_AF9005_REMOTE=m
+CPTCFG_DVB_USB_AF9015=m
+CPTCFG_DVB_USB_AF9035=m
+CPTCFG_DVB_USB_ANYSEE=m
+CPTCFG_DVB_USB_AU6610=m
+CPTCFG_DVB_USB_AZ6007=m
+CPTCFG_DVB_USB_AZ6027=m
+CPTCFG_DVB_USB_CE6230=m
+CPTCFG_DVB_USB_CINERGY_T2=m
+CPTCFG_DVB_USB_CXUSB=m
+CPTCFG_DVB_USB_CYPRESS_FIRMWARE=m
+CPTCFG_DVB_USB_DIB0700=m
+CPTCFG_DVB_USB_DIBUSB_MB=m
+CPTCFG_DVB_USB_DIBUSB_MC=m
+CPTCFG_DVB_USB_DIGITV=m
+CPTCFG_DVB_USB_DTT200U=m
+CPTCFG_DVB_USB_DTV5100=m
+CPTCFG_DVB_USB_DVBSKY=m
+CPTCFG_DVB_USB_DW2102=m
+CPTCFG_DVB_USB_EC168=m
+CPTCFG_DVB_USB_FRIIO=m
+CPTCFG_DVB_USB_GL861=m
+CPTCFG_DVB_USB_GP8PSK=m
+CPTCFG_DVB_USB_LME2510=m
+CPTCFG_DVB_USB_M920X=m
+CPTCFG_DVB_USB_MXL111SF=m
+CPTCFG_DVB_USB_NOVA_T_USB2=m
+CPTCFG_DVB_USB_OPERA1=m
+CPTCFG_DVB_USB_PCTV452E=m
+CPTCFG_DVB_USB_RTL28XXU=m
+CPTCFG_DVB_USB_TECHNISAT_USB2=m
+CPTCFG_DVB_USB_TTUSB2=m
+CPTCFG_DVB_USB_UMT_010=m
+CPTCFG_DVB_USB_V2=m
+CPTCFG_DVB_USB_VP702X=m
+CPTCFG_DVB_USB_VP7045=m
+CPTCFG_DVB_VES1820=m
+CPTCFG_DVB_VES1X93=m
+CPTCFG_DVB_ZL10036=m
+CPTCFG_DVB_ZL10039=m
+CPTCFG_DVB_ZL10353=m
+CPTCFG_I2C_SI470X=m
+CPTCFG_I2C_SI4713=m
+CPTCFG_IR_ENE=m
+CPTCFG_IR_FINTEK=m
+CPTCFG_IR_GPIO_CIR=m
+CPTCFG_IR_IGUANA=m
+CPTCFG_IR_IMG=m
+CPTCFG_IR_IMG_HW=y
+CPTCFG_IR_IMG_JVC=y
+CPTCFG_IR_IMG_NEC=y
+CPTCFG_IR_IMG_RAW=y
+CPTCFG_IR_IMG_SANYO=y
+CPTCFG_IR_IMG_SHARP=y
+CPTCFG_IR_IMG_SONY=y
+CPTCFG_IR_IMON=m
+CPTCFG_IR_ITE_CIR=m
+CPTCFG_IR_JVC_DECODER=m
+CPTCFG_IR_LIRC_CODEC=m
+CPTCFG_IR_MCEUSB=m
+CPTCFG_IR_MCE_KBD_DECODER=m
+CPTCFG_IR_NEC_DECODER=m
+CPTCFG_IR_NUVOTON=m
+CPTCFG_IR_RC5_DECODER=m
+CPTCFG_IR_RC6_DECODER=m
+CPTCFG_IR_REDRAT3=m
+CPTCFG_IR_RX51=m
+CPTCFG_IR_SANYO_DECODER=m
+CPTCFG_IR_SONY_DECODER=m
+CPTCFG_IR_STREAMZAP=m
+CPTCFG_IR_TTUSBIR=m
+CPTCFG_IR_WINBOND_CIR=m
+CPTCFG_LIRC=m
+CPTCFG_MANTIS_CORE=m
+CPTCFG_MEDIA_ALTERA_CI=m
+CPTCFG_MEDIA_ANALOG_TV_SUPPORT=y
+CPTCFG_MEDIA_CAMERA_SUPPORT=y
+CPTCFG_MEDIA_CONTROLLER=y
+CPTCFG_MEDIA_DIGITAL_TV_SUPPORT=y
+CPTCFG_MEDIA_PARPORT_SUPPORT=y
+CPTCFG_MEDIA_PCI_SUPPORT=y
+CPTCFG_MEDIA_RADIO_SUPPORT=y
+CPTCFG_MEDIA_RC_SUPPORT=y
+CPTCFG_MEDIA_SDR_SUPPORT=y
+CPTCFG_MEDIA_SUPPORT=m
+CPTCFG_MEDIA_USB_SUPPORT=y
+CPTCFG_PLATFORM_SI4713=m
+CPTCFG_RADIO_AZTECH=m
+CPTCFG_RADIO_CADET=m
+CPTCFG_RADIO_GEMTEK=m
+CPTCFG_RADIO_ISA=m
+CPTCFG_RADIO_MAXIRADIO=m
+CPTCFG_RADIO_MIROPCM20=m
+CPTCFG_RADIO_RTRACK2=m
+CPTCFG_RADIO_RTRACK=m
+CPTCFG_RADIO_SAA7706H=m
+CPTCFG_RADIO_SF16FMI=m
+CPTCFG_RADIO_SF16FMR2=m
+CPTCFG_RADIO_SHARK2=m
+CPTCFG_RADIO_SHARK=m
+CPTCFG_RADIO_SI470X=y
+CPTCFG_RADIO_SI4713=m
+CPTCFG_RADIO_SI476X=m
+CPTCFG_RADIO_TEA5764=m
+CPTCFG_RADIO_TEF6862=m
+CPTCFG_RADIO_TERRATEC=m
+CPTCFG_RADIO_TIMBERDALE=m
+CPTCFG_RADIO_TRUST=m
+CPTCFG_RADIO_TYPHOON=m
+CPTCFG_RADIO_WL1273=m
+CPTCFG_RADIO_WL128X=m
+CPTCFG_RADIO_ZOLTRIX=m
+CPTCFG_RC_ATI_REMOTE=m
+CPTCFG_RC_CORE=m
+CPTCFG_RC_DEVICES=y
+CPTCFG_RC_LOOPBACK=m
+CPTCFG_RC_MAP=m
+CPTCFG_SMS_SDIO_DRV=m
+CPTCFG_SMS_SIANO_MDTV=m
+CPTCFG_SMS_USB_DRV=m
+CPTCFG_SOC_CAMERA=m
+CPTCFG_SOC_CAMERA_IMX074=m
+CPTCFG_SOC_CAMERA_MT9M001=m
+CPTCFG_SOC_CAMERA_MT9M111=m
+CPTCFG_SOC_CAMERA_MT9T031=m
+CPTCFG_SOC_CAMERA_MT9T112=m
+CPTCFG_SOC_CAMERA_MT9V022=m
+CPTCFG_SOC_CAMERA_OV2640=m
+CPTCFG_SOC_CAMERA_OV5642=m
+CPTCFG_SOC_CAMERA_OV6650=m
+CPTCFG_SOC_CAMERA_OV772X=m
+CPTCFG_SOC_CAMERA_OV9640=m
+CPTCFG_SOC_CAMERA_OV9740=m
+CPTCFG_SOC_CAMERA_PLATFORM=m
+CPTCFG_SOC_CAMERA_RJ54N1=m
+CPTCFG_SOC_CAMERA_TW9910=m
+CPTCFG_STA2X11_VIP=m
+CPTCFG_TTPCI_EEPROM=m
+CPTCFG_USB_AIRSPY=m
+CPTCFG_USB_DSBR=m
+CPTCFG_USB_GL860=m
+CPTCFG_USB_GSPCA=m
+CPTCFG_USB_GSPCA_BENQ=m
+CPTCFG_USB_GSPCA_CONEX=m
+CPTCFG_USB_GSPCA_CPIA1=m
+CPTCFG_USB_GSPCA_DTCS033=m
+CPTCFG_USB_GSPCA_ETOMS=m
+CPTCFG_USB_GSPCA_FINEPIX=m
+CPTCFG_USB_GSPCA_JEILINJ=m
+CPTCFG_USB_GSPCA_JL2005BCD=m
+CPTCFG_USB_GSPCA_KINECT=m
+CPTCFG_USB_GSPCA_KONICA=m
+CPTCFG_USB_GSPCA_MARS=m
+CPTCFG_USB_GSPCA_MR97310A=m
+CPTCFG_USB_GSPCA_NW80X=m
+CPTCFG_USB_GSPCA_OV519=m
+CPTCFG_USB_GSPCA_OV534=m
+CPTCFG_USB_GSPCA_OV534_9=m
+CPTCFG_USB_GSPCA_PAC207=m
+CPTCFG_USB_GSPCA_PAC7302=m
+CPTCFG_USB_GSPCA_PAC7311=m
+CPTCFG_USB_GSPCA_SE401=m
+CPTCFG_USB_GSPCA_SN9C2028=m
+CPTCFG_USB_GSPCA_SN9C20X=m
+CPTCFG_USB_GSPCA_SONIXB=m
+CPTCFG_USB_GSPCA_SONIXJ=m
+CPTCFG_USB_GSPCA_SPCA1528=m
+CPTCFG_USB_GSPCA_SPCA500=m
+CPTCFG_USB_GSPCA_SPCA501=m
+CPTCFG_USB_GSPCA_SPCA505=m
+CPTCFG_USB_GSPCA_SPCA506=m
+CPTCFG_USB_GSPCA_SPCA508=m
+CPTCFG_USB_GSPCA_SPCA561=m
+CPTCFG_USB_GSPCA_SQ905=m
+CPTCFG_USB_GSPCA_SQ905C=m
+CPTCFG_USB_GSPCA_SQ930X=m
+CPTCFG_USB_GSPCA_STK014=m
+CPTCFG_USB_GSPCA_STK1135=m
+CPTCFG_USB_GSPCA_STV0680=m
+CPTCFG_USB_GSPCA_SUNPLUS=m
+CPTCFG_USB_GSPCA_T613=m
+CPTCFG_USB_GSPCA_TOPRO=m
+CPTCFG_USB_GSPCA_TV8532=m
+CPTCFG_USB_GSPCA_VC032X=m
+CPTCFG_USB_GSPCA_VICAM=m
+CPTCFG_USB_GSPCA_XIRLINK_CIT=m
+CPTCFG_USB_GSPCA_ZC3XX=m
+CPTCFG_USB_HACKRF=m
+CPTCFG_USB_KEENE=m
+CPTCFG_USB_M5602=m
+CPTCFG_USB_MA901=m
+CPTCFG_USB_MR800=m
+CPTCFG_USB_MSI2500=m
+CPTCFG_USB_PWC=m
+CPTCFG_USB_RAREMONO=m
+CPTCFG_USB_S2255=m
+CPTCFG_USB_SI470X=m
+CPTCFG_USB_SI4713=m
+CPTCFG_USB_STKWEBCAM=m
+CPTCFG_USB_STV06XX=m
+CPTCFG_USB_VIDEO_CLASS=m
+CPTCFG_USB_ZR364XX=m
+CPTCFG_V4L2_MEM2MEM_DEV=m
+CPTCFG_V4L_MEM2MEM_DRIVERS=y
+CPTCFG_V4L_PLATFORM_DRIVERS=y
+CPTCFG_VIDEOBUF2_CORE=m
+CPTCFG_VIDEOBUF2_DMA_CONTIG=m
+CPTCFG_VIDEOBUF2_DMA_SG=m
+CPTCFG_VIDEOBUF2_MEMOPS=m
+CPTCFG_VIDEOBUF2_VMALLOC=m
+CPTCFG_VIDEOBUF_DMA_CONTIG=m
+CPTCFG_VIDEOBUF_DMA_SG=m
+CPTCFG_VIDEOBUF_DVB=m
+CPTCFG_VIDEOBUF_GEN=m
+CPTCFG_VIDEOBUF_VMALLOC=m
+CPTCFG_VIDEO_AD9389B=m
+CPTCFG_VIDEO_ADP1653=m
+CPTCFG_VIDEO_ADV7170=m
+CPTCFG_VIDEO_ADV7175=m
+CPTCFG_VIDEO_ADV7180=m
+CPTCFG_VIDEO_ADV7183=m
+CPTCFG_VIDEO_ADV7343=m
+CPTCFG_VIDEO_ADV7393=m
+CPTCFG_VIDEO_ADV7604=m
+CPTCFG_VIDEO_AK881X=m
+CPTCFG_VIDEO_APTINA_PLL=m
+CPTCFG_VIDEO_AS3645A=m
+CPTCFG_VIDEO_ATMEL_ISI=m
+CPTCFG_VIDEO_AU0828=m
+CPTCFG_VIDEO_AU0828_RC=y
+CPTCFG_VIDEO_BLACKFIN_CAPTURE=m
+CPTCFG_VIDEO_BLACKFIN_PPI=m
+CPTCFG_VIDEO_BT819=m
+CPTCFG_VIDEO_BT848=m
+CPTCFG_VIDEO_BT856=m
+CPTCFG_VIDEO_BT866=m
+CPTCFG_VIDEO_BTCX=m
+CPTCFG_VIDEO_BWQCAM=m
+CPTCFG_VIDEO_CAFE_CCIC=m
+CPTCFG_VIDEO_CODA=m
+CPTCFG_VIDEO_CPIA2=m
+CPTCFG_VIDEO_CQCAM=m
+CPTCFG_VIDEO_CS5345=m
+CPTCFG_VIDEO_CS53L32A=m
+CPTCFG_VIDEO_CX18=m
+CPTCFG_VIDEO_CX18_ALSA=m
+CPTCFG_VIDEO_CX231XX=m
+CPTCFG_VIDEO_CX231XX_ALSA=m
+CPTCFG_VIDEO_CX231XX_DVB=m
+CPTCFG_VIDEO_CX231XX_RC=y
+CPTCFG_VIDEO_CX2341X=m
+CPTCFG_VIDEO_CX23885=m
+CPTCFG_VIDEO_CX25821=m
+CPTCFG_VIDEO_CX25821_ALSA=m
+CPTCFG_VIDEO_CX25840=m
+CPTCFG_VIDEO_CX88=m
+CPTCFG_VIDEO_CX88_ALSA=m
+CPTCFG_VIDEO_CX88_BLACKBIRD=m
+CPTCFG_VIDEO_CX88_DVB=m
+CPTCFG_VIDEO_CX88_MPEG=m
+CPTCFG_VIDEO_CX88_VP3054=m
+CPTCFG_VIDEO_DAVINCI_VPBE_DISPLAY=m
+CPTCFG_VIDEO_DAVINCI_VPIF_CAPTURE=m
+CPTCFG_VIDEO_DAVINCI_VPIF_DISPLAY=m
+CPTCFG_VIDEO_DEV=m
+CPTCFG_VIDEO_DM355_CCDC=m
+CPTCFG_VIDEO_DM6446_CCDC=m
+CPTCFG_VIDEO_EM28XX=m
+CPTCFG_VIDEO_EM28XX_ALSA=m
+CPTCFG_VIDEO_EM28XX_DVB=m
+CPTCFG_VIDEO_EM28XX_RC=m
+CPTCFG_VIDEO_EM28XX_V4L2=m
+CPTCFG_VIDEO_EXYNOS_FIMC_LITE=m
+CPTCFG_VIDEO_FB_IVTV=m
+CPTCFG_VIDEO_GO7007=m
+CPTCFG_VIDEO_GO7007_USB=m
+CPTCFG_VIDEO_GO7007_USB_S2250_BOARD=m
+CPTCFG_VIDEO_HDPVR=m
+CPTCFG_VIDEO_HEXIUM_GEMINI=m
+CPTCFG_VIDEO_HEXIUM_ORION=m
+CPTCFG_VIDEO_IR_I2C=m
+CPTCFG_VIDEO_IVTV=m
+CPTCFG_VIDEO_IVTV_ALSA=m
+CPTCFG_VIDEO_KS0127=m
+CPTCFG_VIDEO_M32R_AR_M64278=m
+CPTCFG_VIDEO_M52790=m
+CPTCFG_VIDEO_M5MOLS=m
+CPTCFG_VIDEO_MEM2MEM_DEINTERLACE=m
+CPTCFG_VIDEO_MEM2MEM_TESTDEV=m
+CPTCFG_VIDEO_MEYE=m
+CPTCFG_VIDEO_MMP_CAMERA=m
+CPTCFG_VIDEO_MSP3400=m
+CPTCFG_VIDEO_MT9M032=m
+CPTCFG_VIDEO_MT9P031=m
+CPTCFG_VIDEO_MT9T001=m
+CPTCFG_VIDEO_MT9V011=m
+CPTCFG_VIDEO_MT9V032=m
+CPTCFG_VIDEO_MX2=m
+CPTCFG_VIDEO_MX2_EMMAPRP=m
+CPTCFG_VIDEO_MX3=m
+CPTCFG_VIDEO_MXB=m
+CPTCFG_VIDEO_NOON010PC30=m
+CPTCFG_VIDEO_OMAP1=m
+CPTCFG_VIDEO_OMAP2_VOUT=m
+CPTCFG_VIDEO_OMAP3=m
+CPTCFG_VIDEO_OV7640=m
+CPTCFG_VIDEO_OV7670=m
+CPTCFG_VIDEO_OV9650=m
+CPTCFG_VIDEO_PMS=m
+CPTCFG_VIDEO_PVRUSB2=m
+CPTCFG_VIDEO_PXA27x=m
+CPTCFG_VIDEO_S3C_CAMIF=m
+CPTCFG_VIDEO_S5C73M3=m
+CPTCFG_VIDEO_S5K4ECGX=m
+CPTCFG_VIDEO_S5K6AA=m
+CPTCFG_VIDEO_S5P_FIMC=m
+CPTCFG_VIDEO_S5P_MIPI_CSIS=m
+CPTCFG_VIDEO_SAA6588=m
+CPTCFG_VIDEO_SAA7110=m
+CPTCFG_VIDEO_SAA711X=m
+CPTCFG_VIDEO_SAA7127=m
+CPTCFG_VIDEO_SAA7134=m
+CPTCFG_VIDEO_SAA7134_ALSA=m
+CPTCFG_VIDEO_SAA7134_DVB=m
+CPTCFG_VIDEO_SAA7134_GO7007=m
+CPTCFG_VIDEO_SAA7134_RC=y
+CPTCFG_VIDEO_SAA7146=m
+CPTCFG_VIDEO_SAA7146_VV=m
+CPTCFG_VIDEO_SAA7164=m
+CPTCFG_VIDEO_SAA717X=m
+CPTCFG_VIDEO_SAA7185=m
+CPTCFG_VIDEO_SAA7191=m
+CPTCFG_VIDEO_SAMSUNG_EXYNOS_GSC=m
+CPTCFG_VIDEO_SAMSUNG_S5P_G2D=m
+CPTCFG_VIDEO_SAMSUNG_S5P_HDMI=m
+CPTCFG_VIDEO_SAMSUNG_S5P_HDMIPHY=m
+CPTCFG_VIDEO_SAMSUNG_S5P_JPEG=m
+CPTCFG_VIDEO_SAMSUNG_S5P_MFC=m
+CPTCFG_VIDEO_SAMSUNG_S5P_MIXER=m
+CPTCFG_VIDEO_SAMSUNG_S5P_SDO=m
+CPTCFG_VIDEO_SAMSUNG_S5P_SII9234=m
+CPTCFG_VIDEO_SAMSUNG_S5P_TV=y
+CPTCFG_VIDEO_SH_MOBILE_CEU=m
+CPTCFG_VIDEO_SH_MOBILE_CSI2=m
+CPTCFG_VIDEO_SH_VEU=m
+CPTCFG_VIDEO_SH_VOU=m
+CPTCFG_VIDEO_SMIAPP=m
+CPTCFG_VIDEO_SMIAPP_PLL=m
+CPTCFG_VIDEO_SOLO6X10=m
+CPTCFG_VIDEO_SONY_BTF_MPX=m
+CPTCFG_VIDEO_SR030PC30=m
+CPTCFG_VIDEO_STK1160=m
+CPTCFG_VIDEO_STK1160_AC97=y
+CPTCFG_VIDEO_STK1160_COMMON=m
+CPTCFG_VIDEO_TDA7432=m
+CPTCFG_VIDEO_TDA9840=m
+CPTCFG_VIDEO_TEA6415C=m
+CPTCFG_VIDEO_TEA6420=m
+CPTCFG_VIDEO_THS7303=m
+CPTCFG_VIDEO_TIMBERDALE=m
+CPTCFG_VIDEO_TLG2300=m
+CPTCFG_VIDEO_TLV320AIC23B=m
+CPTCFG_VIDEO_TM6000=m
+CPTCFG_VIDEO_TM6000_ALSA=m
+CPTCFG_VIDEO_TM6000_DVB=m
+CPTCFG_VIDEO_TUNER=m
+CPTCFG_VIDEO_TVAUDIO=m
+CPTCFG_VIDEO_TVEEPROM=m
+CPTCFG_VIDEO_TVP514X=m
+CPTCFG_VIDEO_TVP5150=m
+CPTCFG_VIDEO_TVP7002=m
+CPTCFG_VIDEO_TW2804=m
+CPTCFG_VIDEO_TW68=m
+CPTCFG_VIDEO_TW9903=m
+CPTCFG_VIDEO_TW9906=m
+CPTCFG_VIDEO_UDA1342=m
+CPTCFG_VIDEO_UPD64031A=m
+CPTCFG_VIDEO_UPD64083=m
+CPTCFG_VIDEO_USBTV=m
+CPTCFG_VIDEO_USBVISION=m
+CPTCFG_VIDEO_V4L2=m
+CPTCFG_VIDEO_V4L2_SUBDEV_API=y
+CPTCFG_VIDEO_VIA_CAMERA=m
+CPTCFG_VIDEO_VINO=m
+CPTCFG_VIDEO_VIU=m
+CPTCFG_VIDEO_VP27SMPX=m
+CPTCFG_VIDEO_VPX3220=m
+CPTCFG_VIDEO_VS6624=m
+CPTCFG_VIDEO_W9966=m
+CPTCFG_VIDEO_WM8739=m
+CPTCFG_VIDEO_WM8775=m
+CPTCFG_VIDEO_ZORAN=m
+CPTCFG_VIDEO_ZORAN_AVS6EYES=m
+CPTCFG_VIDEO_ZORAN_BUZ=m
+CPTCFG_VIDEO_ZORAN_DC10=m
+CPTCFG_VIDEO_ZORAN_DC30=m
+CPTCFG_VIDEO_ZORAN_LML33=m
+CPTCFG_VIDEO_ZORAN_LML33R10=m
+CPTCFG_VIDEO_ZORAN_ZR36060=m
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index b9686bb..c5180b8 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -36,7 +36,7 @@
 	  PCI core hostmode operation (external PCI bus).
 
 config BCMA_HOST_SOC
-	depends on !KERNEL_3_7
+	depends on !BACKPORT_KERNEL_3_7
 	bool "Support for BCMA in a SoC"
 	depends on BCMA
 	help
@@ -47,7 +47,7 @@
 	  If unsure, say N
 
 config BCMA_DRIVER_MIPS
-	depends on !KERNEL_3_3
+	depends on !BACKPORT_KERNEL_3_3
 	bool "BCMA Broadcom MIPS core driver"
 	depends on BCMA && MIPS
 	help
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index cb91beb..16fc849 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -24,7 +24,6 @@
 /* main.c */
 bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
 		     int timeout);
-void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core);
 int bcma_bus_register(struct bcma_bus *bus);
 void bcma_bus_unregister(struct bcma_bus *bus);
 int __init bcma_bus_early_register(struct bcma_bus *bus,
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index 368c24c..9ff6cdf 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -339,7 +339,7 @@
 		return;
 	}
 
-	irq = bcma_core_irq(cc->core, 0);
+	irq = bcma_core_irq(cc->core);
 
 	/* Determine the registers of the UARTs */
 	cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 598a6cd..706b9ae 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -152,7 +152,7 @@
 					 handle_simple_irq);
 	}
 
-	hwirq = bcma_core_irq(cc->core, 0);
+	hwirq = bcma_core_irq(cc->core);
 	err = request_irq(hwirq, bcma_gpio_irq_handler, IRQF_SHARED, "gpio",
 			  cc);
 	if (err)
@@ -183,7 +183,7 @@
 		return;
 
 	bcma_cc_mask32(cc, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO);
-	free_irq(bcma_core_irq(cc->core, 0), cc);
+	free_irq(bcma_core_irq(cc->core), cc);
 	for (gpio = 0; gpio < chip->ngpio; gpio++) {
 		int irq = irq_find_mapping(cc->irq_domain, gpio);
 
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index 04faf6d..004d6aa 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -20,9 +20,6 @@
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/time.h>
-#ifdef CONFIG_BCM47XX
-#include <bcm47xx_nvram.h>
-#endif
 
 enum bcma_boot_dev {
 	BCMA_BOOT_DEV_UNK = 0,
@@ -118,7 +115,7 @@
  * If disabled, 5 is returned.
  * If not supported, 6 is returned.
  */
-unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
 {
 	struct bcma_device *mdev = dev->bus->drv_mips.core;
 	u32 irqflag;
@@ -136,6 +133,13 @@
 	return 5;
 }
 
+unsigned int bcma_core_irq(struct bcma_device *dev)
+{
+	unsigned int mips_irq = bcma_core_mips_irq(dev);
+	return mips_irq <= 4 ? mips_irq + 2 : 0;
+}
+EXPORT_SYMBOL(bcma_core_irq);
+
 static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
 {
 	unsigned int oldirq = bcma_core_mips_irq(dev);
@@ -319,16 +323,10 @@
 	switch (boot_dev) {
 	case BCMA_BOOT_DEV_PARALLEL:
 	case BCMA_BOOT_DEV_SERIAL:
-#ifdef CONFIG_BCM47XX
-		bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH2,
-					    BCMA_SOC_FLASH2_SZ);
-#endif
+		/* TODO: Init NVRAM using BCMA_SOC_FLASH2 window */
 		break;
 	case BCMA_BOOT_DEV_NAND:
-#ifdef CONFIG_BCM47XX
-		bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH1,
-					    BCMA_SOC_FLASH1_SZ);
-#endif
+		/* TODO: Init NVRAM using BCMA_SOC_FLASH1 window */
 		break;
 	default:
 		break;
@@ -425,7 +423,7 @@
 		break;
 	default:
 		list_for_each_entry(core, &bus->cores, list) {
-			core->irq = bcma_core_irq(core, 0);
+			core->irq = bcma_core_irq(core);
 		}
 		bcma_err(bus,
 			 "Unknown device (0x%x) found, can not configure IRQs\n",
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index c8a6b74..c3d7b03 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -593,7 +593,7 @@
 	pr_info("PCI: Fixing up device %s\n", pci_name(dev));
 
 	/* Fix up interrupt lines */
-	dev->irq = bcma_core_irq(pc_host->pdev->core, 0);
+	dev->irq = bcma_core_irq(pc_host->pdev->core);
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 
 	readrq = pcie_get_readrq(dev);
@@ -617,6 +617,6 @@
 
 	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
 			       pci_ops);
-	return bcma_core_irq(pc_host->pdev->core, 0);
+	return bcma_core_irq(pc_host->pdev->core);
 }
 EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 34b40bb..6a76e68 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -275,7 +275,7 @@
 static const struct pci_device_id bcma_pci_bridge_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },	/* 0xa8d8 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
@@ -285,8 +285,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },	/* 0xa8db, BCM43217 (sic!) */
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43228) },	/* 0xa8dc */
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },	/* 0xA8DB */
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 17fcf56..5379919 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -11,7 +11,6 @@
 #include <linux/bcma/bcma.h>
 #include <linux/slab.h>
 #include <linux/of_address.h>
-#include <linux/of_irq.h>
 
 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
 MODULE_LICENSE("GPL");
@@ -142,7 +141,7 @@
 	return false;
 }
 
-#if defined(CONFIG_OF) && defined(CONFIG_OF_ADDRESS)
+#ifdef CONFIG_OF
 static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
 						     struct bcma_device *core)
 {
@@ -163,46 +162,6 @@
 	return NULL;
 }
 
-static int bcma_of_irq_parse(struct platform_device *parent,
-			     struct bcma_device *core,
-			     struct of_phandle_args *out_irq, int num)
-{
-	__be32 laddr[1];
-	int rc;
-
-	if (core->dev.of_node) {
-		rc = of_irq_parse_one(core->dev.of_node, num, out_irq);
-		if (!rc)
-			return rc;
-	}
-
-	out_irq->np = parent->dev.of_node;
-	out_irq->args_count = 1;
-	out_irq->args[0] = num;
-
-	laddr[0] = cpu_to_be32(core->addr);
-	return of_irq_parse_raw(laddr, out_irq);
-}
-
-static unsigned int bcma_of_get_irq(struct platform_device *parent,
-				    struct bcma_device *core, int num)
-{
-	struct of_phandle_args out_irq;
-	int ret;
-
-	if (!parent || !parent->dev.of_node)
-		return 0;
-
-	ret = bcma_of_irq_parse(parent, core, &out_irq, num);
-	if (ret) {
-		bcma_debug(core->bus, "bcma_of_get_irq() failed with rc=%d\n",
-			   ret);
-		return 0;
-	}
-
-	return irq_create_of_mapping(&out_irq);
-}
-
 static void bcma_of_fill_device(struct platform_device *parent,
 				struct bcma_device *core)
 {
@@ -211,47 +170,18 @@
 	node = bcma_of_find_child_device(parent, core);
 	if (node)
 		core->dev.of_node = node;
-
-	core->irq = bcma_of_get_irq(parent, core, 0);
 }
 #else
 static void bcma_of_fill_device(struct platform_device *parent,
 				struct bcma_device *core)
 {
 }
-static inline unsigned int bcma_of_get_irq(struct platform_device *parent,
-					   struct bcma_device *core, int num)
-{
-	return 0;
-}
 #endif /* CONFIG_OF */
 
-unsigned int bcma_core_irq(struct bcma_device *core, int num)
+static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
 {
-	struct bcma_bus *bus = core->bus;
-	unsigned int mips_irq;
+	int err;
 
-	switch (bus->hosttype) {
-	case BCMA_HOSTTYPE_PCI:
-		return bus->host_pci->irq;
-	case BCMA_HOSTTYPE_SOC:
-		if (bus->drv_mips.core && num == 0) {
-			mips_irq = bcma_core_mips_irq(core);
-			return mips_irq <= 4 ? mips_irq + 2 : 0;
-		}
-		if (bus->host_pdev)
-			return bcma_of_get_irq(bus->host_pdev, core, num);
-		return 0;
-	case BCMA_HOSTTYPE_SDIO:
-		return 0;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(bcma_core_irq);
-
-void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
-{
 	core->dev.release = bcma_release_core_dev;
 	core->dev.bus = &bcma_bus_type;
 	dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index);
@@ -275,11 +205,6 @@
 	case BCMA_HOSTTYPE_SDIO:
 		break;
 	}
-}
-
-static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
-{
-	int err;
 
 	err = device_register(&core->dev);
 	if (err) {
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 9175207..14b5656 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -505,7 +505,6 @@
 		bus->nr_cores++;
 		other_core = bcma_find_core_reverse(bus, core->id.id);
 		core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
-		bcma_prepare_core(bus, core);
 
 		bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
 			  core->core_index, bcma_device_name(&core->id),
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index c30744e..dcc4d71 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -223,7 +223,6 @@
 	depends on m
 	depends on BT_MRVL && MMC
 	depends on FW_LOADER
-	select BPAUTO_WANT_DEV_COREDUMP
 	help
 	  The driver for Marvell Bluetooth chipsets with SDIO interface.
 
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 544feb3..1723b6e 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -79,7 +79,6 @@
 	{ USB_DEVICE(0x0489, 0xe057) },
 	{ USB_DEVICE(0x0489, 0xe056) },
 	{ USB_DEVICE(0x0489, 0xe05f) },
-	{ USB_DEVICE(0x0489, 0xe078) },
 	{ USB_DEVICE(0x04c5, 0x1330) },
 	{ USB_DEVICE(0x04CA, 0x3004) },
 	{ USB_DEVICE(0x04CA, 0x3005) },
@@ -87,7 +86,6 @@
 	{ USB_DEVICE(0x04CA, 0x3007) },
 	{ USB_DEVICE(0x04CA, 0x3008) },
 	{ USB_DEVICE(0x04CA, 0x300b) },
-	{ USB_DEVICE(0x04CA, 0x3010) },
 	{ USB_DEVICE(0x0930, 0x0219) },
 	{ USB_DEVICE(0x0930, 0x0220) },
 	{ USB_DEVICE(0x0930, 0x0227) },
@@ -107,7 +105,6 @@
 	{ USB_DEVICE(0x13d3, 0x3375) },
 	{ USB_DEVICE(0x13d3, 0x3393) },
 	{ USB_DEVICE(0x13d3, 0x3402) },
-	{ USB_DEVICE(0x13d3, 0x3408) },
 	{ USB_DEVICE(0x13d3, 0x3432) },
 
 	/* Atheros AR5BBU12 with sflash firmware */
@@ -133,7 +130,6 @@
 	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
@@ -141,7 +137,6 @@
 	{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
@@ -161,7 +156,6 @@
 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU22 with sflash firmware */
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index 1828ed8..023d35e 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -167,35 +167,6 @@
 	.llseek = default_llseek,
 };
 
-static ssize_t btmrvl_fwdump_write(struct file *file, const char __user *ubuf,
-				   size_t count, loff_t *ppos)
-{
-	struct btmrvl_private *priv = file->private_data;
-	char buf[16];
-	bool result;
-
-	memset(buf, 0, sizeof(buf));
-
-	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
-		return -EFAULT;
-
-	if (strtobool(buf, &result))
-		return -EINVAL;
-
-	if (!result)
-		return -EINVAL;
-
-	btmrvl_firmware_dump(priv);
-
-	return count;
-}
-
-static const struct file_operations btmrvl_fwdump_fops = {
-	.write	= btmrvl_fwdump_write,
-	.open	= simple_open,
-	.llseek = default_llseek,
-};
-
 void btmrvl_debugfs_init(struct hci_dev *hdev)
 {
 	struct btmrvl_private *priv = hci_get_drvdata(hdev);
@@ -226,8 +197,6 @@
 			    priv, &btmrvl_hscmd_fops);
 	debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
 			    priv, &btmrvl_hscfgcmd_fops);
-	debugfs_create_file("fw_dump", 0200, dbg->config_dir,
-			    priv, &btmrvl_fwdump_fops);
 
 	dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
 	debugfs_create_u8("curpsmode", 0444, dbg->status_dir,
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 330f8f8..38ad662 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -32,24 +32,6 @@
 /* Time to wait for command response in millisecond */
 #define WAIT_UNTIL_CMD_RESP		5000
 
-enum rdwr_status {
-	RDWR_STATUS_SUCCESS = 0,
-	RDWR_STATUS_FAILURE = 1,
-	RDWR_STATUS_DONE = 2
-};
-
-#define FW_DUMP_MAX_NAME_LEN    8
-#define FW_DUMP_HOST_READY      0xEE
-#define FW_DUMP_DONE            0xFF
-#define FW_DUMP_READ_DONE       0xFE
-
-struct memory_type_mapping {
-	u8 mem_name[FW_DUMP_MAX_NAME_LEN];
-	u8 *mem_ptr;
-	u32 mem_size;
-	u8 done_flag;
-};
-
 struct btmrvl_thread {
 	struct task_struct *task;
 	wait_queue_head_t wait_q;
@@ -99,7 +81,6 @@
 				u8 *payload, u16 nb);
 	int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
 	int (*hw_process_int_status) (struct btmrvl_private *priv);
-	void (*firmware_dump)(struct btmrvl_private *priv);
 	spinlock_t driver_lock;		/* spinlock used by driver */
 #ifdef CONFIG_DEBUG_FS
 	void *debugfs_data;
@@ -170,7 +151,6 @@
 int btmrvl_enable_ps(struct btmrvl_private *priv);
 int btmrvl_prepare_command(struct btmrvl_private *priv);
 int btmrvl_enable_hs(struct btmrvl_private *priv);
-void btmrvl_firmware_dump(struct btmrvl_private *priv);
 
 #ifdef CONFIG_DEBUG_FS
 void btmrvl_debugfs_init(struct hci_dev *hdev);
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 30939c9..1d7db20 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -22,7 +22,6 @@
 #include <linux/of.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
-#include <linux/mmc/sdio_func.h>
 
 #include "btmrvl_drv.h"
 #include "btmrvl_sdio.h"
@@ -42,11 +41,6 @@
 
 	priv->adapter->int_count++;
 
-	if (priv->adapter->hs_state == HS_ACTIVATED) {
-		BT_DBG("BT: HS DEACTIVATED in ISR!");
-		priv->adapter->hs_state = HS_DEACTIVATED;
-	}
-
 	wake_up_interruptible(&priv->main_thread.wait_q);
 }
 EXPORT_SYMBOL_GPL(btmrvl_interrupt);
@@ -215,7 +209,7 @@
 
 	ret = btmrvl_send_sync_cmd(priv, BT_CMD_MODULE_CFG_REQ, &subcmd, 1);
 	if (ret)
-		BT_ERR("module_cfg_cmd(%x) failed", subcmd);
+		BT_ERR("module_cfg_cmd(%x) failed\n", subcmd);
 
 	return ret;
 }
@@ -251,7 +245,7 @@
 
 	ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, 2);
 	if (ret)
-		BT_ERR("HSCFG command failed");
+		BT_ERR("HSCFG command failed\n");
 
 	return ret;
 }
@@ -269,7 +263,7 @@
 
 	ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, &param, 1);
 	if (ret)
-		BT_ERR("PSMODE command failed");
+		BT_ERR("PSMODE command failed\n");
 
 	return 0;
 }
@@ -282,7 +276,7 @@
 
 	ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
 	if (ret) {
-		BT_ERR("Host sleep enable command failed");
+		BT_ERR("Host sleep enable command failed\n");
 		return ret;
 	}
 
@@ -329,19 +323,12 @@
 		} else {
 			ret = priv->hw_wakeup_firmware(priv);
 			priv->adapter->hs_state = HS_DEACTIVATED;
-			BT_DBG("BT: HS DEACTIVATED due to host activity!");
 		}
 	}
 
 	return ret;
 }
 
-void btmrvl_firmware_dump(struct btmrvl_private *priv)
-{
-	if (priv->firmware_dump)
-		priv->firmware_dump(priv);
-}
-
 static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
 {
 	int ret = 0;
@@ -500,36 +487,34 @@
 	ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
 				   BT_CAL_HDR_LEN + len);
 	if (ret)
-		BT_ERR("Failed to download caibration data");
+		BT_ERR("Failed to download caibration data\n");
 
 	return 0;
 }
 
-static int btmrvl_check_device_tree(struct btmrvl_private *priv)
+static int btmrvl_cal_data_dt(struct btmrvl_private *priv)
 {
 	struct device_node *dt_node;
 	u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE];
+	const char name[] = "btmrvl_caldata";
+	const char property[] = "btmrvl,caldata";
 	int ret;
-	u32 val;
 
-	for_each_compatible_node(dt_node, NULL, "btmrvl,cfgdata") {
-		ret = of_property_read_u32(dt_node, "btmrvl,gpio-gap", &val);
-		if (!ret)
-			priv->btmrvl_dev.gpio_gap = val;
+	dt_node = of_find_node_by_name(NULL, name);
+	if (!dt_node)
+		return -ENODEV;
 
-		ret = of_property_read_u8_array(dt_node, "btmrvl,cal-data",
-						cal_data + BT_CAL_HDR_LEN,
-						BT_CAL_DATA_SIZE);
-		if (ret)
-			return ret;
+	ret = of_property_read_u8_array(dt_node, property,
+					cal_data + BT_CAL_HDR_LEN,
+					BT_CAL_DATA_SIZE);
+	if (ret)
+		return ret;
 
-		BT_DBG("Use cal data from device tree");
-		ret = btmrvl_download_cal_data(priv, cal_data,
-					       BT_CAL_DATA_SIZE);
-		if (ret) {
-			BT_ERR("Fail to download calibrate data");
-			return ret;
-		}
+	BT_DBG("Use cal data from device tree");
+	ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE);
+	if (ret) {
+		BT_ERR("Fail to download calibrate data");
+		return ret;
 	}
 
 	return 0;
@@ -541,15 +526,14 @@
 
 	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
 
-	priv->btmrvl_dev.gpio_gap = 0xffff;
-
-	btmrvl_check_device_tree(priv);
+	btmrvl_cal_data_dt(priv);
 
 	btmrvl_pscan_window_reporting(priv, 0x01);
 
 	priv->btmrvl_dev.psmode = 1;
 	btmrvl_enable_ps(priv);
 
+	priv->btmrvl_dev.gpio_gap = 0xffff;
 	btmrvl_send_hscfg_cmd(priv);
 
 	return 0;
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 0057c0b..550bce0 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -24,7 +24,6 @@
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/module.h>
-#include <linux/devcoredump.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -34,24 +33,6 @@
 
 #define VERSION "1.0"
 
-static struct memory_type_mapping mem_type_mapping_tbl[] = {
-	{"ITCM", NULL, 0, 0xF0},
-	{"DTCM", NULL, 0, 0xF1},
-	{"SQRAM", NULL, 0, 0xF2},
-	{"APU", NULL, 0, 0xF3},
-	{"CIU", NULL, 0, 0xF4},
-	{"ICU", NULL, 0, 0xF5},
-	{"MAC", NULL, 0, 0xF6},
-	{"EXT7", NULL, 0, 0xF7},
-	{"EXT8", NULL, 0, 0xF8},
-	{"EXT9", NULL, 0, 0xF9},
-	{"EXT10", NULL, 0, 0xFA},
-	{"EXT11", NULL, 0, 0xFB},
-	{"EXT12", NULL, 0, 0xFC},
-	{"EXT13", NULL, 0, 0xFD},
-	{"EXTLAST", NULL, 0, 0xFE},
-};
-
 /* The btmrvl_sdio_remove() callback function is called
  * when user removes this module from kernel space or ejects
  * the card from the slot. The driver handles these 2 cases
@@ -141,9 +122,6 @@
 	.int_read_to_clear = true,
 	.host_int_rsr = 0x01,
 	.card_misc_cfg = 0xcc,
-	.fw_dump_ctrl = 0xe2,
-	.fw_dump_start = 0xe3,
-	.fw_dump_end = 0xea,
 };
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
@@ -152,7 +130,6 @@
 	.reg		= &btmrvl_reg_8688,
 	.support_pscan_win_report = false,
 	.sd_blksz_fw_dl	= 64,
-	.supports_fw_dump = false,
 };
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
@@ -161,7 +138,6 @@
 	.reg		= &btmrvl_reg_87xx,
 	.support_pscan_win_report = false,
 	.sd_blksz_fw_dl	= 256,
-	.supports_fw_dump = false,
 };
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
@@ -170,7 +146,6 @@
 	.reg		= &btmrvl_reg_87xx,
 	.support_pscan_win_report = false,
 	.sd_blksz_fw_dl	= 256,
-	.supports_fw_dump = false,
 };
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
@@ -179,7 +154,6 @@
 	.reg		= &btmrvl_reg_8887,
 	.support_pscan_win_report = true,
 	.sd_blksz_fw_dl	= 256,
-	.supports_fw_dump = false,
 };
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
@@ -188,7 +162,6 @@
 	.reg		= &btmrvl_reg_8897,
 	.support_pscan_win_report = true,
 	.sd_blksz_fw_dl	= 256,
-	.supports_fw_dump = true,
 };
 
 static const struct sdio_device_id btmrvl_sdio_ids[] = {
@@ -791,8 +764,8 @@
 
 	card = sdio_get_drvdata(func);
 	if (!card || !card->priv) {
-		BT_ERR("sbi_interrupt(%p) card or priv is NULL, card=%p",
-		       func, card);
+		BT_ERR("sbi_interrupt(%p) card or priv is "
+				"NULL, card=%p\n", func, card);
 		return;
 	}
 
@@ -1107,277 +1080,6 @@
 	return ret;
 }
 
-static void btmrvl_sdio_dump_regs(struct btmrvl_private *priv)
-{
-	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
-	int ret = 0;
-	unsigned int reg, reg_start, reg_end;
-	char buf[256], *ptr;
-	u8 loop, func, data;
-	int MAX_LOOP = 2;
-
-	btmrvl_sdio_wakeup_fw(priv);
-	sdio_claim_host(card->func);
-
-	for (loop = 0; loop < MAX_LOOP; loop++) {
-		memset(buf, 0, sizeof(buf));
-		ptr = buf;
-
-		if (loop == 0) {
-			/* Read the registers of SDIO function0 */
-			func = loop;
-			reg_start = 0;
-			reg_end = 9;
-		} else {
-			func = 2;
-			reg_start = 0;
-			reg_end = 0x09;
-		}
-
-		ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ",
-			       func, reg_start, reg_end);
-		for (reg = reg_start; reg <= reg_end; reg++) {
-			if (func == 0)
-				data = sdio_f0_readb(card->func, reg, &ret);
-			else
-				data = sdio_readb(card->func, reg, &ret);
-
-			if (!ret) {
-				ptr += sprintf(ptr, "%02x ", data);
-			} else {
-				ptr += sprintf(ptr, "ERR");
-				break;
-			}
-		}
-
-		BT_INFO("%s", buf);
-	}
-
-	sdio_release_host(card->func);
-}
-
-/* This function read/write firmware */
-static enum
-rdwr_status btmrvl_sdio_rdwr_firmware(struct btmrvl_private *priv,
-				      u8 doneflag)
-{
-	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
-	int ret, tries;
-	u8 ctrl_data = 0;
-
-	sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
-		    &ret);
-
-	if (ret) {
-		BT_ERR("SDIO write err");
-		return RDWR_STATUS_FAILURE;
-	}
-
-	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-		ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
-				       &ret);
-
-		if (ret) {
-			BT_ERR("SDIO read err");
-			return RDWR_STATUS_FAILURE;
-		}
-
-		if (ctrl_data == FW_DUMP_DONE)
-			break;
-		if (doneflag && ctrl_data == doneflag)
-			return RDWR_STATUS_DONE;
-		if (ctrl_data != FW_DUMP_HOST_READY) {
-			BT_INFO("The ctrl reg was changed, re-try again!");
-			sdio_writeb(card->func, FW_DUMP_HOST_READY,
-				    card->reg->fw_dump_ctrl, &ret);
-			if (ret) {
-				BT_ERR("SDIO write err");
-				return RDWR_STATUS_FAILURE;
-			}
-		}
-		usleep_range(100, 200);
-	}
-
-	if (ctrl_data == FW_DUMP_HOST_READY) {
-		BT_ERR("Fail to pull ctrl_data");
-		return RDWR_STATUS_FAILURE;
-	}
-
-	return RDWR_STATUS_SUCCESS;
-}
-
-/* This function dump sdio register and memory data */
-static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
-{
-	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
-	int ret = 0;
-	unsigned int reg, reg_start, reg_end;
-	enum rdwr_status stat;
-	u8 *dbg_ptr, *end_ptr, *fw_dump_data, *fw_dump_ptr;
-	u8 dump_num, idx, i, read_reg, doneflag = 0;
-	u32 memory_size, fw_dump_len = 0;
-
-	/* dump sdio register first */
-	btmrvl_sdio_dump_regs(priv);
-
-	if (!card->supports_fw_dump) {
-		BT_ERR("Firmware dump not supported for this card!");
-		return;
-	}
-
-	for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
-		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
-		if (entry->mem_ptr) {
-			vfree(entry->mem_ptr);
-			entry->mem_ptr = NULL;
-		}
-		entry->mem_size = 0;
-	}
-
-	btmrvl_sdio_wakeup_fw(priv);
-	sdio_claim_host(card->func);
-
-	BT_INFO("== btmrvl firmware dump start ==");
-
-	stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
-	if (stat == RDWR_STATUS_FAILURE)
-		goto done;
-
-	reg = card->reg->fw_dump_start;
-	/* Read the number of the memories which will dump */
-	dump_num = sdio_readb(card->func, reg, &ret);
-
-	if (ret) {
-		BT_ERR("SDIO read memory length err");
-		goto done;
-	}
-
-	/* Read the length of every memory which will dump */
-	for (idx = 0; idx < dump_num; idx++) {
-		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
-		stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
-		if (stat == RDWR_STATUS_FAILURE)
-			goto done;
-
-		memory_size = 0;
-		reg = card->reg->fw_dump_start;
-		for (i = 0; i < 4; i++) {
-			read_reg = sdio_readb(card->func, reg, &ret);
-			if (ret) {
-				BT_ERR("SDIO read err");
-				goto done;
-			}
-			memory_size |= (read_reg << i*8);
-			reg++;
-		}
-
-		if (memory_size == 0) {
-			BT_INFO("Firmware dump finished!");
-			break;
-		}
-
-		BT_INFO("%s_SIZE=0x%x", entry->mem_name, memory_size);
-		entry->mem_ptr = vzalloc(memory_size + 1);
-		entry->mem_size = memory_size;
-		if (!entry->mem_ptr) {
-			BT_ERR("Vzalloc %s failed", entry->mem_name);
-			goto done;
-		}
-
-		fw_dump_len += (strlen("========Start dump ") +
-				strlen(entry->mem_name) +
-				strlen("========\n") +
-				(memory_size + 1) +
-				strlen("\n========End dump========\n"));
-
-		dbg_ptr = entry->mem_ptr;
-		end_ptr = dbg_ptr + memory_size;
-
-		doneflag = entry->done_flag;
-		BT_INFO("Start %s output, please wait...",
-			entry->mem_name);
-
-		do {
-			stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
-			if (stat == RDWR_STATUS_FAILURE)
-				goto done;
-
-			reg_start = card->reg->fw_dump_start;
-			reg_end = card->reg->fw_dump_end;
-			for (reg = reg_start; reg <= reg_end; reg++) {
-				*dbg_ptr = sdio_readb(card->func, reg, &ret);
-				if (ret) {
-					BT_ERR("SDIO read err");
-					goto done;
-				}
-				if (dbg_ptr < end_ptr)
-					dbg_ptr++;
-				else
-					BT_ERR("Allocated buffer not enough");
-			}
-
-			if (stat != RDWR_STATUS_DONE) {
-				continue;
-			} else {
-				BT_INFO("%s done: size=0x%tx",
-					entry->mem_name,
-					dbg_ptr - entry->mem_ptr);
-				break;
-			}
-		} while (1);
-	}
-
-	BT_INFO("== btmrvl firmware dump end ==");
-
-done:
-	sdio_release_host(card->func);
-
-	if (fw_dump_len == 0)
-		return;
-
-	fw_dump_data = vzalloc(fw_dump_len+1);
-	if (!fw_dump_data) {
-		BT_ERR("Vzalloc fw_dump_data fail!");
-		return;
-	}
-	fw_dump_ptr = fw_dump_data;
-
-	/* Dump all the memory data into single file, a userspace script will
-	   be used to split all the memory data to multiple files*/
-	BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump start");
-	for (idx = 0; idx < dump_num; idx++) {
-		struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
-		if (entry->mem_ptr) {
-			strcpy(fw_dump_ptr, "========Start dump ");
-			fw_dump_ptr += strlen("========Start dump ");
-
-			strcpy(fw_dump_ptr, entry->mem_name);
-			fw_dump_ptr += strlen(entry->mem_name);
-
-			strcpy(fw_dump_ptr, "========\n");
-			fw_dump_ptr += strlen("========\n");
-
-			memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
-			fw_dump_ptr += entry->mem_size;
-
-			strcpy(fw_dump_ptr, "\n========End dump========\n");
-			fw_dump_ptr += strlen("\n========End dump========\n");
-
-			vfree(mem_type_mapping_tbl[idx].mem_ptr);
-			mem_type_mapping_tbl[idx].mem_ptr = NULL;
-		}
-	}
-
-	/* fw_dump_data will be free in device coredump release function
-	   after 5 min*/
-	dev_coredumpv(&priv->btmrvl_dev.hcidev->dev, fw_dump_data,
-		      fw_dump_len, GFP_KERNEL);
-	BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end");
-}
-
 static int btmrvl_sdio_probe(struct sdio_func *func,
 					const struct sdio_device_id *id)
 {
@@ -1401,7 +1103,6 @@
 		card->reg = data->reg;
 		card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
 		card->support_pscan_win_report = data->support_pscan_win_report;
-		card->supports_fw_dump = data->supports_fw_dump;
 	}
 
 	if (btmrvl_sdio_register_dev(card) < 0) {
@@ -1433,7 +1134,6 @@
 	priv->hw_host_to_card = btmrvl_sdio_host_to_card;
 	priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
 	priv->hw_process_int_status = btmrvl_sdio_process_int_status;
-	priv->firmware_dump = btmrvl_sdio_dump_firmware;
 
 	if (btmrvl_register_hdev(priv)) {
 		BT_ERR("Register hdev failed!");
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index 1a3bd06..453559f 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -81,9 +81,6 @@
 	bool int_read_to_clear;
 	u8 host_int_rsr;
 	u8 card_misc_cfg;
-	u8 fw_dump_ctrl;
-	u8 fw_dump_start;
-	u8 fw_dump_end;
 };
 
 struct btmrvl_sdio_card {
@@ -93,7 +90,6 @@
 	const char *firmware;
 	const struct btmrvl_sdio_card_reg *reg;
 	bool support_pscan_win_report;
-	bool supports_fw_dump;
 	u16 sd_blksz_fw_dl;
 	u8 rx_unit;
 	struct btmrvl_private *priv;
@@ -105,7 +101,6 @@
 	const struct btmrvl_sdio_card_reg *reg;
 	const bool support_pscan_win_report;
 	u16 sd_blksz_fw_dl;
-	bool supports_fw_dump;
 };
 
 
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 61d9c77..f9db709 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -106,12 +106,9 @@
 	{ USB_DEVICE(0x0b05, 0x17b5) },
 	{ USB_DEVICE(0x0b05, 0x17cb) },
 	{ USB_DEVICE(0x413c, 0x8197) },
-	{ USB_DEVICE(0x13d3, 0x3404),
-	  .driver_info = BTUSB_BCM_PATCHRAM },
 
 	/* Foxconn - Hon Hai */
-	{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
-	  .driver_info = BTUSB_BCM_PATCHRAM },
+	{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
 
 	/* Broadcom devices with vendor specific id */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
@@ -159,7 +156,6 @@
 	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
@@ -167,7 +163,6 @@
 	{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
@@ -187,7 +182,6 @@
 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
-	{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU12 with sflash firmware */
@@ -304,8 +298,6 @@
 	unsigned int sco_num;
 	int isoc_altsetting;
 	int suspend_count;
-
-	int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
 };
 
 static inline void btusb_free_frags(struct btusb_data *data)
@@ -597,7 +589,7 @@
 	if (urb->status == 0) {
 		hdev->stat.byte_rx += urb->actual_length;
 
-		if (data->recv_bulk(data, urb->transfer_buffer,
+		if (btusb_recv_bulk(data, urb->transfer_buffer,
 				    urb->actual_length) < 0) {
 			BT_ERR("%s corrupted ACL packet", hdev->name);
 			hdev->stat.err_rx++;
@@ -2019,8 +2011,6 @@
 	init_usb_anchor(&data->isoc_anchor);
 	spin_lock_init(&data->rxlock);
 
-	data->recv_bulk = btusb_recv_bulk;
-
 	hdev = hci_alloc_dev();
 	if (!hdev)
 		return -ENOMEM;
@@ -2044,7 +2034,6 @@
 	if (id->driver_info & BTUSB_BCM_PATCHRAM) {
 		hdev->setup = btusb_setup_bcm_patchram;
 		hdev->set_bdaddr = btusb_set_bdaddr_bcm;
-		set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
 	}
 
 	if (id->driver_info & BTUSB_INTEL) {
diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c
index 55c135b..f038dba 100644
--- a/drivers/bluetooth/btwilink.c
+++ b/drivers/bluetooth/btwilink.c
@@ -349,6 +349,7 @@
 	.remove = bt_ti_remove,
 	.driver = {
 		.name = "btwilink",
+		.owner = THIS_MODULE,
 	},
 };
 
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 326eb27..b6d639e 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -78,7 +78,7 @@
 
 	status = tty->driver->ops->tiocmget(tty);
 
-	/* Enable Automatic RTSCTS */
+	/* Disable Automatic RTSCTS */
 	ktermios.c_cflag |= CRTSCTS;
 	status = tty_set_termios(tty, &ktermios);
 
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index ec0fa77..a228386 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -168,27 +168,6 @@
 	hci_uart_tx_wakeup(hu);
 }
 
-static void h5_peer_reset(struct hci_uart *hu)
-{
-	struct h5 *h5 = hu->priv;
-
-	BT_ERR("Peer device has reset");
-
-	h5->state = H5_UNINITIALIZED;
-
-	del_timer(&h5->timer);
-
-	skb_queue_purge(&h5->rel);
-	skb_queue_purge(&h5->unrel);
-	skb_queue_purge(&h5->unack);
-
-	h5->tx_seq = 0;
-	h5->tx_ack = 0;
-
-	/* Send reset request to upper stack */
-	hci_reset_dev(hu->hdev);
-}
-
 static int h5_open(struct hci_uart *hu)
 {
 	struct h5 *h5;
@@ -304,12 +283,8 @@
 	conf_req[2] = h5_cfg_field(h5);
 
 	if (memcmp(data, sync_req, 2) == 0) {
-		if (h5->state == H5_ACTIVE)
-			h5_peer_reset(hu);
 		h5_link_control(hu, sync_rsp, 2);
 	} else if (memcmp(data, sync_rsp, 2) == 0) {
-		if (h5->state == H5_ACTIVE)
-			h5_peer_reset(hu);
 		h5->state = H5_INITIALIZED;
 		h5_link_control(hu, conf_req, 3);
 	} else if (memcmp(data, conf_req, 2) == 0) {
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index ac7a704..fda0983 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menuconfig MEDIA_SUPPORT
-	depends on !KERNEL_3_2
+	depends on !BACKPORT_KERNEL_3_2
 	tristate "Multimedia support"
 	depends on m
 	depends on HAS_IOMEM
@@ -165,6 +165,7 @@
 source "drivers/media/pci/Kconfig"
 source "drivers/media/platform/Kconfig"
 source "drivers/media/mmc/Kconfig"
+source "drivers/media/parport/Kconfig"
 source "drivers/media/radio/Kconfig"
 
 comment "Supported FireWire (IEEE 1394) Adapters"
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 9f5d0bc..6219093 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -28,6 +28,6 @@
 # Finally, merge the drivers that require the core
 #
 
-obj-y += common/ platform/ pci/ usb/ mmc/ firewire/
+obj-y += common/ platform/ pci/ usb/ mmc/ firewire/ parport/
 obj-$(CPTCFG_VIDEO_DEV) += radio/
 
diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c
index c07b9db..be76315 100644
--- a/drivers/media/common/cx2341x.c
+++ b/drivers/media/common/cx2341x.c
@@ -931,35 +931,6 @@
 	}
 }
 
-/* Check for correctness of the ctrl's value based on the data from
-   struct v4l2_queryctrl and the available menu items. Note that
-   menu_items may be NULL, in that case it is ignored. */
-static int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
-		const char * const *menu_items)
-{
-	if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
-		return -EINVAL;
-	if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
-		return -EBUSY;
-	if (qctrl->type == V4L2_CTRL_TYPE_STRING)
-		return 0;
-	if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
-	    qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
-	    qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
-		return 0;
-	if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
-		return -ERANGE;
-	if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
-		if (menu_items[ctrl->value] == NULL ||
-		    menu_items[ctrl->value][0] == '\0')
-			return -EINVAL;
-	}
-	if (qctrl->type == V4L2_CTRL_TYPE_BITMASK &&
-			(ctrl->value & ~qctrl->maximum))
-		return -ERANGE;
-	return 0;
-}
-
 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
 		  struct v4l2_ext_controls *ctrls, unsigned int cmd)
 {
diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c
index 1ff9f53..97afee6 100644
--- a/drivers/media/common/saa7146/saa7146_core.c
+++ b/drivers/media/common/saa7146/saa7146_core.c
@@ -71,7 +71,7 @@
 		if (saa7146_read(dev, MC2) & 2)
 			break;
 		if (err) {
-			pr_debug("%s: %s timed out while waiting for registers getting programmed\n",
+			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
 			       dev->name, __func__);
 			return -ETIMEDOUT;
 		}
@@ -364,9 +364,6 @@
 		goto out;
 	}
 
-	/* create a nice device name */
-	sprintf(dev->name, "saa7146 (%d)", saa7146_num);
-
 	DEB_EE("pci:%p\n", pci);
 
 	err = pci_enable_device(pci);
@@ -441,6 +438,9 @@
 
 	/* the rest + print status message */
 
+	/* create a nice device name */
+	sprintf(dev->name, "saa7146 (%d)", saa7146_num);
+
 	pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n",
 		dev->mem, dev->revision, pci->irq,
 		pci->subsystem_vendor, pci->subsystem_device);
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index 35d0e88..273043e 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -107,7 +107,8 @@
 
 void sms_ir_exit(struct smscore_device_t *coredev)
 {
-	rc_unregister_device(coredev->ir.dev);
+	if (coredev->ir.dev)
+		rc_unregister_device(coredev->ir.dev);
 
 	sms_log("");
 }
diff --git a/drivers/media/common/tveeprom.c b/drivers/media/common/tveeprom.c
index 47da037..c7dace6 100644
--- a/drivers/media/common/tveeprom.c
+++ b/drivers/media/common/tveeprom.c
@@ -286,17 +286,9 @@
 	{ TUNER_ABSENT,                 "Xceive XC5200C"},
 	{ TUNER_ABSENT,                 "NXP 18273"},
 	{ TUNER_ABSENT,                 "Montage M88TS2022"},
-	/* 180-188 */
+	/* 180-189 */
 	{ TUNER_ABSENT,                 "NXP 18272M"},
 	{ TUNER_ABSENT,                 "NXP 18272S"},
-
-	{ TUNER_ABSENT,                 "Mirics MSi003"},
-	{ TUNER_ABSENT,                 "MaxLinear MxL256"},
-	{ TUNER_ABSENT,                 "SiLabs Si2158"},
-	{ TUNER_ABSENT,                 "SiLabs Si2178"},
-	{ TUNER_ABSENT,                 "SiLabs Si2157"},
-	{ TUNER_ABSENT,                 "SiLabs Si2177"},
-	{ TUNER_ABSENT,                 "ITE IT9137FN"},
 };
 
 /* Use TVEEPROM_AUDPROC_INTERNAL for those audio 'chips' that are
@@ -359,16 +351,6 @@
 	{ TVEEPROM_AUDPROC_INTERNAL, "CX23887"   },
 	{ TVEEPROM_AUDPROC_INTERNAL, "SAA7164"   },
 	{ TVEEPROM_AUDPROC_INTERNAL, "AU8522"    },
-	/* 45-49 */
-	{ TVEEPROM_AUDPROC_INTERNAL, "AVF4910B"  },
-	{ TVEEPROM_AUDPROC_INTERNAL, "SAA7231"   },
-	{ TVEEPROM_AUDPROC_INTERNAL, "CX23102"   },
-	{ TVEEPROM_AUDPROC_INTERNAL, "SAA7163"   },
-	{ TVEEPROM_AUDPROC_OTHER,    "AK4113"    },
-	/* 50-52 */
-	{ TVEEPROM_AUDPROC_OTHER,    "CS5340"    },
-	{ TVEEPROM_AUDPROC_OTHER,    "CS8416"    },
-	{ TVEEPROM_AUDPROC_OTHER,    "CX20810"   },
 };
 
 /* This list is supplied by Hauppauge. Thanks! */
@@ -389,12 +371,8 @@
 	"CX25843", "CX23418", "NEC61153", "CX23885", "CX23888",
 	/* 35-39 */
 	"SAA7131", "CX25837", "CX23887", "CX23885A", "CX23887A",
-	/* 40-44 */
-	"SAA7164", "CX23885B", "AU8522", "ADV7401", "AVF4910B",
-	/* 45-49 */
-	"SAA7231", "CX23102", "SAA7163", "ADV7441A", "ADV7181C",
-	/* 50-53 */
-	"CX25836", "TDA9955", "TDA19977", "ADV7842"
+	/* 40-42 */
+	"SAA7164", "CX23885B", "AU8522"
 };
 
 static int hasRadioTuner(int tunerType)
@@ -570,10 +548,10 @@
 			tvee->serial_number =
 				eeprom_data[i+5] +
 				(eeprom_data[i+6] << 8) +
-				(eeprom_data[i+7] << 16)+
-				(eeprom_data[i+8] << 24);
+				(eeprom_data[i+7] << 16);
 
-			if (eeprom_data[i + 8] == 0xf0) {
+			if ((eeprom_data[i + 8] & 0xf0) &&
+					(tvee->serial_number < 0xffffff)) {
 				tvee->MAC_address[0] = 0x00;
 				tvee->MAC_address[1] = 0x0D;
 				tvee->MAC_address[2] = 0xFE;
@@ -718,7 +696,7 @@
 		}
 	}
 
-	tveeprom_info("Hauppauge model %d, rev %s, serial# %u\n",
+	tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",
 		tvee->model, tvee->rev_str, tvee->serial_number);
 	if (tvee->has_MAC_address == 1)
 		tveeprom_info("MAC address is %pM\n", tvee->MAC_address);
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
index 80ab8d0..e07a84e 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -356,7 +356,6 @@
 #define USB_PID_MSI_DIGI_VOX_MINI_III                   0x8807
 #define USB_PID_SONY_PLAYTV				0x0003
 #define USB_PID_MYGICA_D689				0xd811
-#define USB_PID_MYGICA_T230				0xc688
 #define USB_PID_ELGATO_EYETV_DIVERSITY			0x0011
 #define USB_PID_ELGATO_EYETV_DTT			0x0021
 #define USB_PID_ELGATO_EYETV_DTT_2			0x003f
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index c29531e..7e9b079 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -962,11 +962,6 @@
 	case SYS_ATSC:
 		c->modulation = VSB_8;
 		break;
-	case SYS_ISDBS:
-		c->symbol_rate = 28860000;
-		c->rolloff = ROLLOFF_35;
-		c->bandwidth_hz = c->symbol_rate / 100 * 135;
-		break;
 	default:
 		c->modulation = QAM_AUTO;
 		break;
@@ -2077,7 +2072,6 @@
 		break;
 	case SYS_DVBS:
 	case SYS_TURBO:
-	case SYS_ISDBS:
 		rolloff = 135;
 		break;
 	case SYS_DVBS2:
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index e4041f0..059e611 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -379,9 +379,7 @@
 			/* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */
 			if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) {
 				printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n",
-				       priv->ts_count, ts[0],
-				       (ts[1] & TS_TEI) >> 7,
-				       (ts[3] & TS_SC) >> 6);
+				       priv->ts_count, ts[0], ts[1] & TS_TEI >> 7, ts[3] & 0xC0 >> 6);
 
 				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
 				if (priv->ule_skb) {
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index bafccf7..8971120 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -728,16 +728,13 @@
 	  A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
 	  Say Y when you want to support this frontend.
 
-comment "ISDB-S (satellite) & ISDB-T (terrestrial) frontends"
-	depends on DVB_CORE
-
 config DVB_TC90522
 	tristate "Toshiba TC90522"
 	depends on m
 	depends on DVB_CORE && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
-	  Toshiba TC90522 2xISDB-S 8PSK + 2xISDB-T OFDM demodulator.
+	  A Toshiba TC90522 2xISDB-T + 2xISDB-S demodulator.
 	  Say Y when you want to support this frontend.
 
 comment "Digital terrestrial only tuners/PLL"
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
index 82ce47b..63a89c1 100644
--- a/drivers/media/dvb-frontends/af9033.c
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -291,12 +291,6 @@
 		if (clock_adc_lut[i].clock == dev->cfg.clock)
 			break;
 	}
-	if (i == ARRAY_SIZE(clock_adc_lut)) {
-		dev_err(&dev->client->dev,
-			"Couldn't find ADC config for clock=%d\n",
-			dev->cfg.clock);
-		goto err;
-	}
 
 	adc_cw = af9033_div(dev, clock_adc_lut[i].adc, 1000000ul, 19ul);
 	buf[0] = (adc_cw >>  0) & 0xff;
@@ -586,15 +580,7 @@
 				break;
 			}
 		}
-		if (i == ARRAY_SIZE(coeff_lut)) {
-			dev_err(&dev->client->dev,
-				"Couldn't find LUT config for clock=%d\n",
-				dev->cfg.clock);
-			ret = -EINVAL;
-			goto err;
-		}
-
-		ret = af9033_wr_regs(dev, 0x800001,
+		ret =  af9033_wr_regs(dev, 0x800001,
 				coeff_lut[i].val, sizeof(coeff_lut[i].val));
 	}
 
@@ -606,13 +592,6 @@
 			if (clock_adc_lut[i].clock == dev->cfg.clock)
 				break;
 		}
-		if (i == ARRAY_SIZE(clock_adc_lut)) {
-			dev_err(&dev->client->dev,
-				"Couldn't find ADC clock for clock=%d\n",
-				dev->cfg.clock);
-			ret = -EINVAL;
-			goto err;
-		}
 		adc_freq = clock_adc_lut[i].adc;
 
 		/* get used IF frequency */
@@ -870,97 +849,29 @@
 {
 	struct af9033_dev *dev = fe->demodulator_priv;
 	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
-	int ret;
-	u8 u8tmp;
 
 	/* use DVBv5 CNR */
-	if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) {
-		/* Return 0.1 dB for AF9030 and 0-0xffff for IT9130. */
-		if (dev->is_af9035) {
-			/* 1000x => 10x (0.1 dB) */
-			*snr = div_s64(c->cnr.stat[0].svalue, 100);
-		} else {
-			/* 1000x => 1x (1 dB) */
-			*snr = div_s64(c->cnr.stat[0].svalue, 1000);
-
-			/* read current modulation */
-			ret = af9033_rd_reg(dev, 0x80f903, &u8tmp);
-			if (ret)
-				goto err;
-
-			/* scale value to 0x0000-0xffff */
-			switch ((u8tmp >> 0) & 3) {
-			case 0:
-				*snr = *snr * 0xffff / 23;
-				break;
-			case 1:
-				*snr = *snr * 0xffff / 26;
-				break;
-			case 2:
-				*snr = *snr * 0xffff / 32;
-				break;
-			default:
-				goto err;
-			}
-		}
-	} else {
+	if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
+		*snr = div_s64(c->cnr.stat[0].svalue, 100); /* 1000x => 10x */
+	else
 		*snr = 0;
-	}
 
 	return 0;
-
-err:
-	dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-
-	return ret;
 }
 
 static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
 	struct af9033_dev *dev = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
-	int ret, tmp, power_real;
-	u8 u8tmp, gain_offset, buf[7];
+	int ret;
+	u8 strength2;
 
-	if (dev->is_af9035) {
-		/* read signal strength of 0-100 scale */
-		ret = af9033_rd_reg(dev, 0x800048, &u8tmp);
-		if (ret < 0)
-			goto err;
+	/* read signal strength of 0-100 scale */
+	ret = af9033_rd_reg(dev, 0x800048, &strength2);
+	if (ret < 0)
+		goto err;
 
-		/* scale value to 0x0000-0xffff */
-		*strength = u8tmp * 0xffff / 100;
-	} else {
-		ret = af9033_rd_reg(dev, 0x8000f7, &u8tmp);
-		if (ret < 0)
-			goto err;
-
-		ret = af9033_rd_regs(dev, 0x80f900, buf, 7);
-		if (ret < 0)
-			goto err;
-
-		if (c->frequency <= 300000000)
-			gain_offset = 7; /* VHF */
-		else
-			gain_offset = 4; /* UHF */
-
-		power_real = (u8tmp - 100 - gain_offset) -
-			power_reference[((buf[3] >> 0) & 3)][((buf[6] >> 0) & 7)];
-
-		if (power_real < -15)
-			tmp = 0;
-		else if ((power_real >= -15) && (power_real < 0))
-			tmp = (2 * (power_real + 15)) / 3;
-		else if ((power_real >= 0) && (power_real < 20))
-			tmp = 4 * power_real + 10;
-		else if ((power_real >= 20) && (power_real < 35))
-			tmp = (2 * (power_real - 20)) / 3 + 90;
-		else
-			tmp = 100;
-
-		/* scale value to 0x0000-0xffff */
-		*strength = tmp * 0xffff / 100;
-	}
+	/* scale value to 0x0000-0xffff */
+	*strength = strength2 * 0xffff / 100;
 
 	return 0;
 
@@ -1100,33 +1011,6 @@
 
 		snr_val = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
 
-		/* read superframe number */
-		ret = af9033_rd_reg(dev, 0x80f78b, &u8tmp);
-		if (ret)
-			goto err;
-
-		if (u8tmp)
-			snr_val /= u8tmp;
-
-		/* read current transmission mode */
-		ret = af9033_rd_reg(dev, 0x80f900, &u8tmp);
-		if (ret)
-			goto err;
-
-		switch ((u8tmp >> 0) & 3) {
-		case 0:
-			snr_val *= 4;
-			break;
-		case 1:
-			snr_val *= 1;
-			break;
-		case 2:
-			snr_val *= 2;
-			break;
-		default:
-			goto err_schedule_delayed_work;
-		}
-
 		/* read current modulation */
 		ret = af9033_rd_reg(dev, 0x80f903, &u8tmp);
 		if (ret)
diff --git a/drivers/media/dvb-frontends/af9033_priv.h b/drivers/media/dvb-frontends/af9033_priv.h
index 8e23275..c12c92c 100644
--- a/drivers/media/dvb-frontends/af9033_priv.h
+++ b/drivers/media/dvb-frontends/af9033_priv.h
@@ -181,10 +181,7 @@
 	{ 0x05570d, 26 },
 	{ 0x059feb, 27 },
 	{ 0x05bf38, 28 },
-	{ 0x05f78f, 29 },
-	{ 0x0612c3, 30 },
-	{ 0x0626be, 31 },
-	{ 0xffffff, 32 },
+	{ 0xffffff, 29 },
 };
 
 static const struct reg_val ofsm_init[] = {
@@ -2054,10 +2051,4 @@
 	{ 0x80fd8b, 0x00 },
 };
 
-/* NorDig power reference table */
-static const int power_reference[][5] = {
-	{-93, -91, -90, -89, -88}, /* QPSK 1/2 ~ 7/8 */
-	{-87, -85, -84, -83, -82}, /* 16QAM 1/2 ~ 7/8 */
-	{-82, -80, -78, -77, -76}, /* 64QAM 1/2 ~ 7/8 */
-};
 #endif /* AF9033_PRIV_H */
diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c
index 5d06c99..a68974f 100644
--- a/drivers/media/dvb-frontends/au8522_dig.c
+++ b/drivers/media/dvb-frontends/au8522_dig.c
@@ -29,7 +29,6 @@
 #include "au8522_priv.h"
 
 static int debug;
-static int zv_mode = 1; /* default to on */
 
 #define dprintk(arg...)\
 	do { if (debug)\
@@ -470,87 +469,6 @@
 	{ 0x8526, 0x01 },
 };
 
-static struct {
-	u16 reg;
-	u16 data;
-} QAM256_mod_tab_zv_mode[] = {
-	{ 0x80a3, 0x09 },
-	{ 0x80a4, 0x00 },
-	{ 0x8081, 0xc4 },
-	{ 0x80a5, 0x40 },
-	{ 0x80b5, 0xfb },
-	{ 0x80b6, 0x8e },
-	{ 0x80b7, 0x39 },
-	{ 0x80aa, 0x77 },
-	{ 0x80ad, 0x77 },
-	{ 0x80a6, 0x67 },
-	{ 0x8262, 0x20 },
-	{ 0x821c, 0x30 },
-	{ 0x80b8, 0x3e },
-	{ 0x80b9, 0xf0 },
-	{ 0x80ba, 0x01 },
-	{ 0x80bb, 0x18 },
-	{ 0x80bc, 0x50 },
-	{ 0x80bd, 0x00 },
-	{ 0x80be, 0xea },
-	{ 0x80bf, 0xef },
-	{ 0x80c0, 0xfc },
-	{ 0x80c1, 0xbd },
-	{ 0x80c2, 0x1f },
-	{ 0x80c3, 0xfc },
-	{ 0x80c4, 0xdd },
-	{ 0x80c5, 0xaf },
-	{ 0x80c6, 0x00 },
-	{ 0x80c7, 0x38 },
-	{ 0x80c8, 0x30 },
-	{ 0x80c9, 0x05 },
-	{ 0x80ca, 0x4a },
-	{ 0x80cb, 0xd0 },
-	{ 0x80cc, 0x01 },
-	{ 0x80cd, 0xd9 },
-	{ 0x80ce, 0x6f },
-	{ 0x80cf, 0xf9 },
-	{ 0x80d0, 0x70 },
-	{ 0x80d1, 0xdf },
-	{ 0x80d2, 0xf7 },
-	{ 0x80d3, 0xc2 },
-	{ 0x80d4, 0xdf },
-	{ 0x80d5, 0x02 },
-	{ 0x80d6, 0x9a },
-	{ 0x80d7, 0xd0 },
-	{ 0x8250, 0x0d },
-	{ 0x8251, 0xcd },
-	{ 0x8252, 0xe0 },
-	{ 0x8253, 0x05 },
-	{ 0x8254, 0xa7 },
-	{ 0x8255, 0xff },
-	{ 0x8256, 0xed },
-	{ 0x8257, 0x5b },
-	{ 0x8258, 0xae },
-	{ 0x8259, 0xe6 },
-	{ 0x825a, 0x3d },
-	{ 0x825b, 0x0f },
-	{ 0x825c, 0x0d },
-	{ 0x825d, 0xea },
-	{ 0x825e, 0xf2 },
-	{ 0x825f, 0x51 },
-	{ 0x8260, 0xf5 },
-	{ 0x8261, 0x06 },
-	{ 0x821a, 0x01 },
-	{ 0x8546, 0x40 },
-	{ 0x8210, 0x26 },
-	{ 0x8211, 0xf6 },
-	{ 0x8212, 0x84 },
-	{ 0x8213, 0x02 },
-	{ 0x8502, 0x01 },
-	{ 0x8121, 0x04 },
-	{ 0x8122, 0x04 },
-	{ 0x852e, 0x10 },
-	{ 0x80a4, 0xca },
-	{ 0x80a7, 0x40 },
-	{ 0x8526, 0x01 },
-};
-
 static int au8522_enable_modulation(struct dvb_frontend *fe,
 				    fe_modulation_t m)
 {
@@ -577,23 +495,12 @@
 		au8522_set_if(fe, state->config->qam_if);
 		break;
 	case QAM_256:
-		if (zv_mode) {
-			dprintk("%s() QAM 256 (zv_mode)\n", __func__);
-			for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab_zv_mode); i++)
-				au8522_writereg(state,
-					QAM256_mod_tab_zv_mode[i].reg,
-					QAM256_mod_tab_zv_mode[i].data);
-			au8522_set_if(fe, state->config->qam_if);
-			msleep(100);
-			au8522_writereg(state, 0x821a, 0x00);
-		} else {
-			dprintk("%s() QAM 256\n", __func__);
-			for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
-				au8522_writereg(state,
-					QAM256_mod_tab[i].reg,
-					QAM256_mod_tab[i].data);
-			au8522_set_if(fe, state->config->qam_if);
-		}
+		dprintk("%s() QAM 256\n", __func__);
+		for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
+			au8522_writereg(state,
+				QAM256_mod_tab[i].reg,
+				QAM256_mod_tab[i].data);
+		au8522_set_if(fe, state->config->qam_if);
 		break;
 	default:
 		dprintk("%s() Invalid modulation\n", __func__);
@@ -630,12 +537,7 @@
 		return ret;
 
 	/* Allow the tuner to settle */
-	if (zv_mode) {
-		dprintk("%s() increase tuner settling time for zv_mode\n",
-			__func__);
-		msleep(250);
-	} else
-		msleep(100);
+	msleep(100);
 
 	au8522_enable_modulation(fe, c->modulation);
 
@@ -921,11 +823,6 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Enable verbose debug messages");
 
-module_param(zv_mode, int, 0644);
-MODULE_PARM_DESC(zv_mode, "Turn on/off ZeeVee modulator compatability mode (default:on).\n"
-	"\t\ton - modified AU8522 QAM256 initialization.\n"
-	"\t\tProvides faster lock when using ZeeVee modulator based sources");
-
 MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
 MODULE_AUTHOR("Steven Toth");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c
index 8656326..3d399d9 100644
--- a/drivers/media/dvb-frontends/cx22700.c
+++ b/drivers/media/dvb-frontends/cx22700.c
@@ -169,9 +169,6 @@
 
 	cx22700_writereg (state, 0x04, val);
 
-	if (p->code_rate_HP - FEC_1_2 >= sizeof(fec_tab) ||
-	    p->code_rate_LP - FEC_1_2 >= sizeof(fec_tab))
-		return -EINVAL;
 	val = fec_tab[p->code_rate_HP - FEC_1_2] << 3;
 	val |= fec_tab[p->code_rate_LP - FEC_1_2];
 
diff --git a/drivers/media/dvb-frontends/cx24110.c b/drivers/media/dvb-frontends/cx24110.c
index 7b510f2..95b981c 100644
--- a/drivers/media/dvb-frontends/cx24110.c
+++ b/drivers/media/dvb-frontends/cx24110.c
@@ -177,45 +177,47 @@
 	return 0;
 }
 
-static int cx24110_set_fec(struct cx24110_state* state, fe_code_rate_t fec)
+static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
 {
-	static const int rate[FEC_AUTO] = {-1,    1,    2,    3,    5,    7, -1};
-	static const int g1[FEC_AUTO]   = {-1, 0x01, 0x02, 0x05, 0x15, 0x45, -1};
-	static const int g2[FEC_AUTO]   = {-1, 0x01, 0x03, 0x06, 0x1a, 0x7a, -1};
+/* fixme (low): error handling */
+
+	static const int rate[]={-1,1,2,3,5,7,-1};
+	static const int g1[]={-1,0x01,0x02,0x05,0x15,0x45,-1};
+	static const int g2[]={-1,0x01,0x03,0x06,0x1a,0x7a,-1};
 
 	/* Well, the AutoAcq engine of the cx24106 and 24110 automatically
 	   searches all enabled viterbi rates, and can handle non-standard
 	   rates as well. */
 
-	if (fec > FEC_AUTO)
-		fec = FEC_AUTO;
+	if (fec>FEC_AUTO)
+		fec=FEC_AUTO;
 
-	if (fec == FEC_AUTO) { /* (re-)establish AutoAcq behaviour */
-		cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) & 0xdf);
+	if (fec==FEC_AUTO) { /* (re-)establish AutoAcq behaviour */
+		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xdf);
 		/* clear AcqVitDis bit */
-		cx24110_writereg(state, 0x18, 0xae);
+		cx24110_writereg(state,0x18,0xae);
 		/* allow all DVB standard code rates */
-		cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 0x3);
+		cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|0x3);
 		/* set nominal Viterbi rate 3/4 */
-		cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 0x3);
+		cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|0x3);
 		/* set current Viterbi rate 3/4 */
-		cx24110_writereg(state, 0x1a, 0x05);
-		cx24110_writereg(state, 0x1b, 0x06);
+		cx24110_writereg(state,0x1a,0x05); cx24110_writereg(state,0x1b,0x06);
 		/* set the puncture registers for code rate 3/4 */
 		return 0;
 	} else {
-		cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20);
+		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x20);
 		/* set AcqVitDis bit */
-		if (rate[fec] < 0)
-			return -EINVAL;
-
-		cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | rate[fec]);
-		/* set nominal Viterbi rate */
-		cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | rate[fec]);
-		/* set current Viterbi rate */
-		cx24110_writereg(state, 0x1a, g1[fec]);
-		cx24110_writereg(state, 0x1b, g2[fec]);
-		/* not sure if this is the right way: I always used AutoAcq mode */
+		if(rate[fec]>0) {
+			cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|rate[fec]);
+			/* set nominal Viterbi rate */
+			cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|rate[fec]);
+			/* set current Viterbi rate */
+			cx24110_writereg(state,0x1a,g1[fec]);
+			cx24110_writereg(state,0x1b,g2[fec]);
+			/* not sure if this is the right way: I always used AutoAcq mode */
+	   } else
+		   return -EOPNOTSUPP;
+/* fixme (low): which is the correct return code? */
 	}
 	return 0;
 }
diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c
index acb965c..a6c3c9e 100644
--- a/drivers/media/dvb-frontends/cx24117.c
+++ b/drivers/media/dvb-frontends/cx24117.c
@@ -459,7 +459,7 @@
 	if (state->priv->skip_fw_load)
 		return 0;
 
-	/* check if firmware is already running */
+	/* check if firmware if already running */
 	if (cx24117_readreg(state, 0xeb) != 0xa) {
 		/* Load firmware */
 		/* request the firmware, this will block until loaded */
diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c
index c505d69..589134e 100644
--- a/drivers/media/dvb-frontends/dib7000p.c
+++ b/drivers/media/dvb-frontends/dib7000p.c
@@ -1780,7 +1780,7 @@
 }
 
 /* FIXME: may require changes - this one was borrowed from dib8000 */
-static u32 dib7000p_get_time_us(struct dvb_frontend *demod)
+static u32 dib7000p_get_time_us(struct dvb_frontend *demod, int layer)
 {
 	struct dtv_frontend_properties *c = &demod->dtv_property_cache;
 	u64 time_us, tmp64;
@@ -1881,6 +1881,7 @@
 {
 	struct dib7000p_state *state = demod->demodulator_priv;
 	struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+	int i;
 	int show_per_stats = 0;
 	u32 time_us = 0, val, snr;
 	u64 blocks, ucb;
@@ -1934,7 +1935,7 @@
 
 		/* Estimate the number of packets based on bitrate */
 		if (!time_us)
-			time_us = dib7000p_get_time_us(demod);
+			time_us = dib7000p_get_time_us(demod, -1);
 
 		if (time_us) {
 			blocks = 1250000ULL * 1000000ULL;
@@ -1948,7 +1949,7 @@
 
 	/* Get post-BER measures */
 	if (time_after(jiffies, state->ber_jiffies_stats)) {
-		time_us = dib7000p_get_time_us(demod);
+		time_us = dib7000p_get_time_us(demod, -1);
 		state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
 
 		dprintk("Next all layers stats available in %u us.", time_us);
@@ -1968,7 +1969,7 @@
 		c->block_error.stat[0].scale = FE_SCALE_COUNTER;
 		c->block_error.stat[0].uvalue += val;
 
-		time_us = dib7000p_get_time_us(demod);
+		time_us = dib7000p_get_time_us(demod, i);
 		if (time_us) {
 			blocks = 1250000ULL * 1000000ULL;
 			do_div(blocks, time_us * 8 * 204);
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c
index 2bfa7a4..5ec221f 100644
--- a/drivers/media/dvb-frontends/drx39xyj/drxj.c
+++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -12255,7 +12255,8 @@
 	kfree(demod->my_ext_attr);
 	kfree(demod->my_common_attr);
 	kfree(demod->my_i2c_dev_addr);
-	release_firmware(demod->firmware);
+	if (demod->firmware)
+		release_firmware(demod->firmware);
 	kfree(demod);
 	kfree(state);
 }
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index d46cf5f..6721951 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -166,9 +166,9 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable debug messages");
 
-#define dprintk(level, fmt, arg...) do {				\
-if (debug >= level)							\
-	printk(KERN_DEBUG KBUILD_MODNAME ": %s " fmt, __func__, ##arg);	\
+#define dprintk(level, fmt, arg...) do {			\
+if (debug >= level)						\
+	pr_debug(fmt, ##arg);					\
 } while (0)
 
 
@@ -6310,7 +6310,8 @@
 	struct drxk_state *state = fe->demodulator_priv;
 
 	dprintk(1, "\n");
-	release_firmware(state->fw);
+	if (state->fw)
+		release_firmware(state->fw);
 
 	kfree(state);
 }
diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c
index 9d0d034..335daef 100644
--- a/drivers/media/dvb-frontends/ds3000.c
+++ b/drivers/media/dvb-frontends/ds3000.c
@@ -864,13 +864,6 @@
 	memcpy(&state->frontend.ops, &ds3000_ops,
 			sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
-
-	/*
-	 * Some devices like T480 starts with voltage on. Be sure
-	 * to turn voltage off during init, as this can otherwise
-	 * interfere with Unicable SCR systems.
-	 */
-	ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF);
 	return &state->frontend;
 
 error3:
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index ba4ee0b..81657e9 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -1,5 +1,5 @@
 /*
- * Montage M88DS3103/M88RS6000 demodulator driver
+ * Montage M88DS3103 demodulator driver
  *
  * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
  *
@@ -162,7 +162,7 @@
 
 	dev_dbg(&priv->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
 
-	if (tab_len > 86) {
+	if (tab_len > 83) {
 		ret = -EINVAL;
 		goto err;
 	}
@@ -245,9 +245,9 @@
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, len;
 	const struct m88ds3103_reg_val *init;
-	u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */
-	u8 buf[3];
-	u16 u16tmp, divide_ratio = 0;
+	u8 u8tmp, u8tmp1, u8tmp2;
+	u8 buf[2];
+	u16 u16tmp, divide_ratio;
 	u32 tuner_frequency, target_mclk;
 	s32 s32tmp;
 
@@ -262,22 +262,6 @@
 		goto err;
 	}
 
-	/* reset */
-	ret = m88ds3103_wr_reg(priv, 0x07, 0x80);
-	if (ret)
-		goto err;
-
-	ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
-	if (ret)
-		goto err;
-
-	/* Disable demod clock path */
-	if (priv->chip_id == M88RS6000_CHIP_ID) {
-		ret = m88ds3103_wr_reg(priv, 0x06, 0xe0);
-		if (ret)
-			goto err;
-	}
-
 	/* program tuner */
 	if (fe->ops.tuner_ops.set_params) {
 		ret = fe->ops.tuner_ops.set_params(fe);
@@ -298,73 +282,14 @@
 		tuner_frequency = c->frequency;
 	}
 
-	/* select M88RS6000 demod main mclk and ts mclk from tuner die. */
-	if (priv->chip_id == M88RS6000_CHIP_ID) {
-		if (c->symbol_rate > 45010000)
-			priv->mclk_khz = 110250;
-		else
-			priv->mclk_khz = 96000;
+	/* reset */
+	ret = m88ds3103_wr_reg(priv, 0x07, 0x80);
+	if (ret)
+		goto err;
 
-		if (c->delivery_system == SYS_DVBS)
-			target_mclk = 96000;
-		else
-			target_mclk = 144000;
-
-		/* Enable demod clock path */
-		ret = m88ds3103_wr_reg(priv, 0x06, 0x00);
-		if (ret)
-			goto err;
-		usleep_range(10000, 20000);
-	} else {
-	/* set M88DS3103 mclk and ts mclk. */
-		priv->mclk_khz = 96000;
-
-		switch (priv->cfg->ts_mode) {
-		case M88DS3103_TS_SERIAL:
-		case M88DS3103_TS_SERIAL_D7:
-			target_mclk = priv->cfg->ts_clk;
-			break;
-		case M88DS3103_TS_PARALLEL:
-		case M88DS3103_TS_CI:
-			if (c->delivery_system == SYS_DVBS)
-				target_mclk = 96000;
-			else {
-				if (c->symbol_rate < 18000000)
-					target_mclk = 96000;
-				else if (c->symbol_rate < 28000000)
-					target_mclk = 144000;
-				else
-					target_mclk = 192000;
-			}
-			break;
-		default:
-			dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n",
-					__func__);
-			ret = -EINVAL;
-			goto err;
-		}
-
-		switch (target_mclk) {
-		case 96000:
-			u8tmp1 = 0x02; /* 0b10 */
-			u8tmp2 = 0x01; /* 0b01 */
-			break;
-		case 144000:
-			u8tmp1 = 0x00; /* 0b00 */
-			u8tmp2 = 0x01; /* 0b01 */
-			break;
-		case 192000:
-			u8tmp1 = 0x03; /* 0b11 */
-			u8tmp2 = 0x00; /* 0b00 */
-			break;
-		}
-		ret = m88ds3103_wr_reg_mask(priv, 0x22, u8tmp1 << 6, 0xc0);
-		if (ret)
-			goto err;
-		ret = m88ds3103_wr_reg_mask(priv, 0x24, u8tmp2 << 6, 0xc0);
-		if (ret)
-			goto err;
-	}
+	ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
+	if (ret)
+		goto err;
 
 	ret = m88ds3103_wr_reg(priv, 0xb2, 0x01);
 	if (ret)
@@ -376,21 +301,36 @@
 
 	switch (c->delivery_system) {
 	case SYS_DVBS:
-		if (priv->chip_id == M88RS6000_CHIP_ID) {
-			len = ARRAY_SIZE(m88rs6000_dvbs_init_reg_vals);
-			init = m88rs6000_dvbs_init_reg_vals;
-		} else {
-			len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals);
-			init = m88ds3103_dvbs_init_reg_vals;
-		}
+		len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals);
+		init = m88ds3103_dvbs_init_reg_vals;
+		target_mclk = 96000;
 		break;
 	case SYS_DVBS2:
-		if (priv->chip_id == M88RS6000_CHIP_ID) {
-			len = ARRAY_SIZE(m88rs6000_dvbs2_init_reg_vals);
-			init = m88rs6000_dvbs2_init_reg_vals;
-		} else {
-			len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals);
-			init = m88ds3103_dvbs2_init_reg_vals;
+		len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals);
+		init = m88ds3103_dvbs2_init_reg_vals;
+
+		switch (priv->cfg->ts_mode) {
+		case M88DS3103_TS_SERIAL:
+		case M88DS3103_TS_SERIAL_D7:
+			if (c->symbol_rate < 18000000)
+				target_mclk = 96000;
+			else
+				target_mclk = 144000;
+			break;
+		case M88DS3103_TS_PARALLEL:
+		case M88DS3103_TS_CI:
+			if (c->symbol_rate < 18000000)
+				target_mclk = 96000;
+			else if (c->symbol_rate < 28000000)
+				target_mclk = 144000;
+			else
+				target_mclk = 192000;
+			break;
+		default:
+			dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n",
+					__func__);
+			ret = -EINVAL;
+			goto err;
 		}
 		break;
 	default:
@@ -407,30 +347,7 @@
 			goto err;
 	}
 
-	if (priv->chip_id == M88RS6000_CHIP_ID) {
-		if ((c->delivery_system == SYS_DVBS2)
-			&& ((c->symbol_rate / 1000) <= 5000)) {
-			ret = m88ds3103_wr_reg(priv, 0xc0, 0x04);
-			if (ret)
-				goto err;
-			buf[0] = 0x09;
-			buf[1] = 0x22;
-			buf[2] = 0x88;
-			ret = m88ds3103_wr_regs(priv, 0x8a, buf, 3);
-			if (ret)
-				goto err;
-		}
-		ret = m88ds3103_wr_reg_mask(priv, 0x9d, 0x08, 0x08);
-		if (ret)
-			goto err;
-		ret = m88ds3103_wr_reg(priv, 0xf1, 0x01);
-		if (ret)
-			goto err;
-		ret = m88ds3103_wr_reg_mask(priv, 0x30, 0x80, 0x80);
-		if (ret)
-			goto err;
-	}
-
+	u8tmp1 = 0; /* silence compiler warning */
 	switch (priv->cfg->ts_mode) {
 	case M88DS3103_TS_SERIAL:
 		u8tmp1 = 0x00;
@@ -466,15 +383,16 @@
 		ret = m88ds3103_wr_reg_mask(priv, 0x29, u8tmp1, 0x20);
 		if (ret)
 			goto err;
+	}
+
+	if (priv->cfg->ts_clk) {
+		divide_ratio = DIV_ROUND_UP(target_mclk, priv->cfg->ts_clk);
+		u8tmp1 = divide_ratio / 2;
+		u8tmp2 = DIV_ROUND_UP(divide_ratio, 2);
+	} else {
+		divide_ratio = 0;
 		u8tmp1 = 0;
 		u8tmp2 = 0;
-		break;
-	default:
-		if (priv->cfg->ts_clk) {
-			divide_ratio = DIV_ROUND_UP(target_mclk, priv->cfg->ts_clk);
-			u8tmp1 = divide_ratio / 2;
-			u8tmp2 = DIV_ROUND_UP(divide_ratio, 2);
-		}
 	}
 
 	dev_dbg(&priv->i2c->dev,
@@ -502,6 +420,29 @@
 	if (ret)
 		goto err;
 
+	switch (target_mclk) {
+	case 96000:
+		u8tmp1 = 0x02; /* 0b10 */
+		u8tmp2 = 0x01; /* 0b01 */
+		break;
+	case 144000:
+		u8tmp1 = 0x00; /* 0b00 */
+		u8tmp2 = 0x01; /* 0b01 */
+		break;
+	case 192000:
+		u8tmp1 = 0x03; /* 0b11 */
+		u8tmp2 = 0x00; /* 0b00 */
+		break;
+	}
+
+	ret = m88ds3103_wr_reg_mask(priv, 0x22, u8tmp1 << 6, 0xc0);
+	if (ret)
+		goto err;
+
+	ret = m88ds3103_wr_reg_mask(priv, 0x24, u8tmp2 << 6, 0xc0);
+	if (ret)
+		goto err;
+
 	if (c->symbol_rate <= 3000000)
 		u8tmp = 0x20;
 	else if (c->symbol_rate <= 10000000)
@@ -525,7 +466,7 @@
 	if (ret)
 		goto err;
 
-	u16tmp = DIV_ROUND_CLOSEST((c->symbol_rate / 1000) << 15, priv->mclk_khz / 2);
+	u16tmp = DIV_ROUND_CLOSEST((c->symbol_rate / 1000) << 15, M88DS3103_MCLK_KHZ / 2);
 	buf[0] = (u16tmp >> 0) & 0xff;
 	buf[1] = (u16tmp >> 8) & 0xff;
 	ret = m88ds3103_wr_regs(priv, 0x61, buf, 2);
@@ -548,7 +489,7 @@
 			(tuner_frequency - c->frequency));
 
 	s32tmp = 0x10000 * (tuner_frequency - c->frequency);
-	s32tmp = DIV_ROUND_CLOSEST(s32tmp, priv->mclk_khz);
+	s32tmp = DIV_ROUND_CLOSEST(s32tmp, M88DS3103_MCLK_KHZ);
 	if (s32tmp < 0)
 		s32tmp += 0x10000;
 
@@ -579,7 +520,7 @@
 	struct m88ds3103_priv *priv = fe->demodulator_priv;
 	int ret, len, remaining;
 	const struct firmware *fw = NULL;
-	u8 *fw_file;
+	u8 *fw_file = M88DS3103_FIRMWARE;
 	u8 u8tmp;
 
 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
@@ -600,6 +541,15 @@
 	if (ret)
 		goto err;
 
+	/* reset */
+	ret = m88ds3103_wr_reg(priv, 0x07, 0x60);
+	if (ret)
+		goto err;
+
+	ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
+	if (ret)
+		goto err;
+
 	/* firmware status */
 	ret = m88ds3103_rd_reg(priv, 0xb9, &u8tmp);
 	if (ret)
@@ -610,23 +560,10 @@
 	if (u8tmp)
 		goto skip_fw_download;
 
-	/* global reset, global diseqc reset, golbal fec reset */
-	ret = m88ds3103_wr_reg(priv, 0x07, 0xe0);
-	if (ret)
-		goto err;
-
-	ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
-	if (ret)
-		goto err;
-
 	/* cold state - try to download firmware */
 	dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state\n",
 			KBUILD_MODNAME, m88ds3103_ops.info.name);
 
-	if (priv->chip_id == M88RS6000_CHIP_ID)
-		fw_file = M88RS6000_FIRMWARE;
-	else
-		fw_file = M88DS3103_FIRMWARE;
 	/* request the firmware, this will block and timeout */
 	ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
 	if (ret) {
@@ -640,7 +577,7 @@
 
 	ret = m88ds3103_wr_reg(priv, 0xb2, 0x01);
 	if (ret)
-		goto error_fw_release;
+		goto err;
 
 	for (remaining = fw->size; remaining > 0;
 			remaining -= (priv->cfg->i2c_wr_max - 1)) {
@@ -654,13 +591,13 @@
 			dev_err(&priv->i2c->dev,
 					"%s: firmware download failed=%d\n",
 					KBUILD_MODNAME, ret);
-			goto error_fw_release;
+			goto err;
 		}
 	}
 
 	ret = m88ds3103_wr_reg(priv, 0xb2, 0x00);
 	if (ret)
-		goto error_fw_release;
+		goto err;
 
 	release_firmware(fw);
 	fw = NULL;
@@ -686,10 +623,10 @@
 	priv->warm = true;
 
 	return 0;
-
-error_fw_release:
-	release_firmware(fw);
 err:
+	if (fw)
+		release_firmware(fw);
+
 	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
 }
@@ -698,18 +635,13 @@
 {
 	struct m88ds3103_priv *priv = fe->demodulator_priv;
 	int ret;
-	u8 u8tmp;
 
 	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
 
 	priv->delivery_system = SYS_UNDEFINED;
 
 	/* TS Hi-Z */
-	if (priv->chip_id == M88RS6000_CHIP_ID)
-		u8tmp = 0x29;
-	else
-		u8tmp = 0x27;
-	ret = m88ds3103_wr_reg_mask(priv, u8tmp, 0x00, 0x01);
+	ret = m88ds3103_wr_reg_mask(priv, 0x27, 0x00, 0x01);
 	if (ret)
 		goto err;
 
@@ -898,7 +830,7 @@
 		goto err;
 
 	c->symbol_rate = 1ull * ((buf[1] << 8) | (buf[0] << 0)) *
-			priv->mclk_khz * 1000 / 0x10000;
+			M88DS3103_MCLK_KHZ * 1000 / 0x10000;
 
 	return 0;
 err:
@@ -1378,22 +1310,18 @@
 	priv->i2c = i2c;
 	mutex_init(&priv->i2c_mutex);
 
-	/* 0x00: chip id[6:0], 0x01: chip ver[7:0], 0x02: chip ver[15:8] */
-	ret = m88ds3103_rd_reg(priv, 0x00, &chip_id);
+	ret = m88ds3103_rd_reg(priv, 0x01, &chip_id);
 	if (ret)
 		goto err;
 
-	chip_id >>= 1;
-	dev_info(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
+	dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
 
 	switch (chip_id) {
-	case M88RS6000_CHIP_ID:
-	case M88DS3103_CHIP_ID:
+	case 0xd0:
 		break;
 	default:
 		goto err;
 	}
-	priv->chip_id = chip_id;
 
 	switch (priv->cfg->clock_out) {
 	case M88DS3103_CLOCK_OUT_DISABLED:
@@ -1409,11 +1337,6 @@
 		goto err;
 	}
 
-	/* 0x29 register is defined differently for m88rs6000. */
-	/* set internal tuner address to 0x21 */
-	if (chip_id == M88RS6000_CHIP_ID)
-		u8tmp = 0x00;
-
 	ret = m88ds3103_wr_reg(priv, 0x29, u8tmp);
 	if (ret)
 		goto err;
@@ -1441,9 +1364,6 @@
 
 	/* create dvb_frontend */
 	memcpy(&priv->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops));
-	if (priv->chip_id == M88RS6000_CHIP_ID)
-		strncpy(priv->fe.ops.info.name,
-			"Montage M88RS6000", sizeof(priv->fe.ops.info.name));
 	priv->fe.demodulator_priv = priv;
 
 	return &priv->fe;
@@ -1503,4 +1423,3 @@
 MODULE_DESCRIPTION("Montage M88DS3103 DVB-S/S2 demodulator driver");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(M88DS3103_FIRMWARE);
-MODULE_FIRMWARE(M88RS6000_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h
index a2c0958..9169fdd 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -25,10 +25,7 @@
 #include <linux/math64.h>
 
 #define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw"
-#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw"
 #define M88DS3103_MCLK_KHZ 96000
-#define M88RS6000_CHIP_ID 0x74
-#define M88DS3103_CHIP_ID 0x70
 
 struct m88ds3103_priv {
 	struct i2c_adapter *i2c;
@@ -41,10 +38,6 @@
 	u32 ber;
 	bool warm; /* FW running */
 	struct i2c_adapter *i2c_adapter;
-	/* auto detect chip id to do different config */
-	u8 chip_id;
-	/* main mclk is calculated for M88RS6000 dynamically */
-	u32 mclk_khz;
 };
 
 struct m88ds3103_reg_val {
@@ -221,178 +214,4 @@
 	{0xb8, 0x00},
 };
 
-static const struct m88ds3103_reg_val m88rs6000_dvbs_init_reg_vals[] = {
-	{0x23, 0x07},
-	{0x08, 0x03},
-	{0x0c, 0x02},
-	{0x20, 0x00},
-	{0x21, 0x54},
-	{0x25, 0x82},
-	{0x27, 0x31},
-	{0x30, 0x08},
-	{0x31, 0x40},
-	{0x32, 0x32},
-	{0x33, 0x35},
-	{0x35, 0xff},
-	{0x3a, 0x00},
-	{0x37, 0x10},
-	{0x38, 0x10},
-	{0x39, 0x02},
-	{0x42, 0x60},
-	{0x4a, 0x80},
-	{0x4b, 0x04},
-	{0x4d, 0x91},
-	{0x5d, 0xc8},
-	{0x50, 0x36},
-	{0x51, 0x36},
-	{0x52, 0x36},
-	{0x53, 0x36},
-	{0x63, 0x0f},
-	{0x64, 0x30},
-	{0x65, 0x40},
-	{0x68, 0x26},
-	{0x69, 0x4c},
-	{0x70, 0x20},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0x40},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0x60},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0x80},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0xa0},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0x1f},
-	{0x76, 0x38},
-	{0x77, 0xa6},
-	{0x78, 0x0c},
-	{0x79, 0x80},
-	{0x7f, 0x14},
-	{0x7c, 0x00},
-	{0xae, 0x82},
-	{0x80, 0x64},
-	{0x81, 0x66},
-	{0x82, 0x44},
-	{0x85, 0x04},
-	{0xcd, 0xf4},
-	{0x90, 0x33},
-	{0xa0, 0x44},
-	{0xbe, 0x00},
-	{0xc0, 0x08},
-	{0xc3, 0x10},
-	{0xc4, 0x08},
-	{0xc5, 0xf0},
-	{0xc6, 0xff},
-	{0xc7, 0x00},
-	{0xc8, 0x1a},
-	{0xc9, 0x80},
-	{0xe0, 0xf8},
-	{0xe6, 0x8b},
-	{0xd0, 0x40},
-	{0xf8, 0x20},
-	{0xfa, 0x0f},
-	{0x00, 0x00},
-	{0xbd, 0x01},
-	{0xb8, 0x00},
-	{0x29, 0x11},
-};
-
-static const struct m88ds3103_reg_val m88rs6000_dvbs2_init_reg_vals[] = {
-	{0x23, 0x07},
-	{0x08, 0x07},
-	{0x0c, 0x02},
-	{0x20, 0x00},
-	{0x21, 0x54},
-	{0x25, 0x82},
-	{0x27, 0x31},
-	{0x30, 0x08},
-	{0x32, 0x32},
-	{0x33, 0x35},
-	{0x35, 0xff},
-	{0x3a, 0x00},
-	{0x37, 0x10},
-	{0x38, 0x10},
-	{0x39, 0x02},
-	{0x42, 0x60},
-	{0x4a, 0x80},
-	{0x4b, 0x04},
-	{0x4d, 0x91},
-	{0x5d, 0xc8},
-	{0x50, 0x36},
-	{0x51, 0x36},
-	{0x52, 0x36},
-	{0x53, 0x36},
-	{0x63, 0x0f},
-	{0x64, 0x10},
-	{0x65, 0x20},
-	{0x68, 0x46},
-	{0x69, 0xcd},
-	{0x70, 0x20},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0x40},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0x60},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0x80},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0xa0},
-	{0x71, 0x70},
-	{0x72, 0x04},
-	{0x73, 0x00},
-	{0x70, 0x1f},
-	{0x76, 0x38},
-	{0x77, 0xa6},
-	{0x78, 0x0c},
-	{0x79, 0x80},
-	{0x7f, 0x14},
-	{0x85, 0x08},
-	{0xcd, 0xf4},
-	{0x90, 0x33},
-	{0x86, 0x00},
-	{0x87, 0x0f},
-	{0x89, 0x00},
-	{0x8b, 0x44},
-	{0x8c, 0x66},
-	{0x9d, 0xc1},
-	{0x8a, 0x10},
-	{0xad, 0x40},
-	{0xa0, 0x44},
-	{0xbe, 0x00},
-	{0xc0, 0x08},
-	{0xc1, 0x10},
-	{0xc2, 0x08},
-	{0xc3, 0x10},
-	{0xc4, 0x08},
-	{0xc5, 0xf0},
-	{0xc6, 0xff},
-	{0xc7, 0x00},
-	{0xc8, 0x1a},
-	{0xc9, 0x80},
-	{0xca, 0x23},
-	{0xcb, 0x24},
-	{0xcc, 0xf4},
-	{0xce, 0x74},
-	{0x00, 0x00},
-	{0xbd, 0x01},
-	{0xb8, 0x00},
-	{0x29, 0x01},
-};
 #endif
diff --git a/drivers/media/dvb-frontends/mn88472.h b/drivers/media/dvb-frontends/mn88472.h
deleted file mode 100644
index da4558b..0000000
--- a/drivers/media/dvb-frontends/mn88472.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Panasonic MN88472 DVB-T/T2/C demodulator driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
- *
- *    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 MN88472_H
-#define MN88472_H
-
-#include <linux/dvb/frontend.h>
-
-struct mn88472_config {
-	/*
-	 * Max num of bytes given I2C adapter could write at once.
-	 * Default: none
-	 */
-	u16 i2c_wr_max;
-
-
-	/* Everything after that is returned by the driver. */
-
-	/*
-	 * DVB frontend.
-	 */
-	struct dvb_frontend **fe;
-};
-
-#endif
diff --git a/drivers/media/dvb-frontends/mn88473.h b/drivers/media/dvb-frontends/mn88473.h
deleted file mode 100644
index a373ec9..0000000
--- a/drivers/media/dvb-frontends/mn88473.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Panasonic MN88473 DVB-T/T2/C demodulator driver
- *
- * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
- *
- *    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 MN88473_H
-#define MN88473_H
-
-#include <linux/dvb/frontend.h>
-
-struct mn88473_config {
-	/*
-	 * Max num of bytes given I2C adapter could write at once.
-	 * Default: none
-	 */
-	u16 i2c_wr_max;
-
-
-	/* Everything after that is returned by the driver. */
-
-	/*
-	 * DVB frontend.
-	 */
-	struct dvb_frontend **fe;
-};
-
-#endif
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 9026e1a..eb737cf 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -258,11 +258,13 @@
 	return rtl2832_rd(priv, reg, val, len);
 }
 
+#if 0 /* currently not used */
 /* write single register */
 static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val)
 {
 	return rtl2832_wr_regs(priv, reg, page, &val, 1);
 }
+#endif
 
 /* read single register */
 static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
@@ -597,11 +599,6 @@
 	if (fe->ops.tuner_ops.set_params)
 		fe->ops.tuner_ops.set_params(fe);
 
-	/* PIP mode related */
-	ret = rtl2832_wr_regs(priv, 0x92, 1, "\x00\x0f\xff", 3);
-	if (ret)
-		goto err;
-
 	/* If the frontend has get_if_frequency(), use it */
 	if (fe->ops.tuner_ops.get_if_frequency) {
 		u32 if_freq;
@@ -664,6 +661,7 @@
 	if (ret)
 		goto err;
 
+
 	/* soft reset */
 	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
 	if (ret)
@@ -1022,58 +1020,6 @@
 	return 0;
 }
 
-int rtl2832_enable_external_ts_if(struct dvb_frontend *fe)
-{
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-	int ret;
-
-	dev_dbg(&priv->i2c->dev, "%s: setting PIP mode\n", __func__);
-
-	ret = rtl2832_wr_regs(priv, 0x0c, 1, "\x5f\xff", 2);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_demod_reg(priv, DVBT_PIP_ON, 0x1);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_reg(priv, 0xbc, 0, 0x18);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_reg(priv, 0x22, 0, 0x01);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_reg(priv, 0x26, 0, 0x1f);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_reg(priv, 0x27, 0, 0xff);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_regs(priv, 0x92, 1, "\x7f\xf7\xff", 3);
-	if (ret)
-		goto err;
-
-	/* soft reset */
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
-	if (ret)
-		goto err;
-
-	return 0;
-err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-
-}
-EXPORT_SYMBOL(rtl2832_enable_external_ts_if);
-
 struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
 {
 	struct rtl2832_priv *priv = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index 5e72630..f32b09c 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -64,10 +64,6 @@
 	struct dvb_frontend *fe
 );
 
-extern int rtl2832_enable_external_ts_if(
-	struct dvb_frontend *fe
-);
-
 #else
 
 static inline struct dvb_frontend *rtl2832_attach(
@@ -93,13 +89,6 @@
 	return NULL;
 }
 
-static inline int rtl2832_enable_external_ts_if(
-	struct dvb_frontend *fe
-)
-{
-	return -ENODEV;
-}
-
 #endif
 
 
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 2896b47..7bf98cf 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -1013,10 +1013,6 @@
 	if (s->d->props->power_ctrl)
 		s->d->props->power_ctrl(s->d, 1);
 
-	/* enable ADC */
-	if (s->d->props->frontend_ctrl)
-		s->d->props->frontend_ctrl(s->fe, 1);
-
 	set_bit(POWER_ON, &s->flags);
 
 	ret = rtl2832_sdr_set_tuner(s);
@@ -1068,10 +1064,6 @@
 
 	clear_bit(POWER_ON, &s->flags);
 
-	/* disable ADC */
-	if (s->d->props->frontend_ctrl)
-		s->d->props->frontend_ctrl(s->fe, 0);
-
 	if (s->d->props->power_ctrl)
 		s->d->props->power_ctrl(s->d, 0);
 
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index ce9ab44..1cd93be 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -308,16 +308,14 @@
 	if (ret)
 		goto err;
 
-	memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x08", 6);
-	cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10;
+	memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
 	if (ret)
 		goto err;
 
-	memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6);
-	cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10;
+	memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
 	ret = si2168_cmd_execute(s, &cmd);
@@ -455,45 +453,27 @@
 			dev_err(&s->client->dev,
 					"firmware file '%s' not found\n",
 					fw_file);
-			goto error_fw_release;
+			goto err;
 		}
 	}
 
 	dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
 			fw_file);
 
-	if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {
-		/* firmware is in the new format */
-		for (remaining = fw->size; remaining > 0; remaining -= 17) {
-			len = fw->data[fw->size - remaining];
-			memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
-			cmd.wlen = len;
-			cmd.rlen = 1;
-			ret = si2168_cmd_execute(s, &cmd);
-			if (ret) {
-				dev_err(&s->client->dev,
-						"firmware download failed=%d\n",
-						ret);
-				goto error_fw_release;
-			}
-		}
-	} else {
-		/* firmware is in the old format */
-		for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
-			len = remaining;
-			if (len > i2c_wr_max)
-				len = i2c_wr_max;
+	for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
+		len = remaining;
+		if (len > i2c_wr_max)
+			len = i2c_wr_max;
 
-			memcpy(cmd.args, &fw->data[fw->size - remaining], len);
-			cmd.wlen = len;
-			cmd.rlen = 1;
-			ret = si2168_cmd_execute(s, &cmd);
-			if (ret) {
-				dev_err(&s->client->dev,
-						"firmware download failed=%d\n",
-						ret);
-				goto error_fw_release;
-			}
+		memcpy(cmd.args, &fw->data[fw->size - remaining], len);
+		cmd.wlen = len;
+		cmd.rlen = 1;
+		ret = si2168_cmd_execute(s, &cmd);
+		if (ret) {
+			dev_err(&s->client->dev,
+					"firmware download failed=%d\n",
+					ret);
+			goto err;
 		}
 	}
 
@@ -507,17 +487,6 @@
 	if (ret)
 		goto err;
 
-	/* query firmware version */
-	memcpy(cmd.args, "\x11", 1);
-	cmd.wlen = 1;
-	cmd.rlen = 10;
-	ret = si2168_cmd_execute(s, &cmd);
-	if (ret)
-		goto err;
-
-	dev_dbg(&s->client->dev, "firmware version: %c.%c.%d\n",
-			cmd.args[6], cmd.args[7], cmd.args[8]);
-
 	/* set ts mode */
 	memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
 	cmd.args[4] |= s->ts_mode;
@@ -529,16 +498,17 @@
 
 	s->fw_loaded = true;
 
+warm:
 	dev_info(&s->client->dev, "found a '%s' in warm state\n",
 			si2168_ops.info.name);
-warm:
+
 	s->active = true;
 
 	return 0;
-
-error_fw_release:
-	release_firmware(fw);
 err:
+	if (fw)
+		release_firmware(fw);
+
 	dev_dbg(&s->client->dev, "failed=%d\n", ret);
 	return ret;
 }
@@ -700,7 +670,6 @@
 	*config->i2c_adapter = s->adapter;
 	*config->fe = &s->fe;
 	s->ts_mode = config->ts_mode;
-	s->ts_clock_inv = config->ts_clock_inv;
 	s->fw_loaded = false;
 
 	i2c_set_clientdata(client, s);
diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h
index 87bc121..e086d67 100644
--- a/drivers/media/dvb-frontends/si2168.h
+++ b/drivers/media/dvb-frontends/si2168.h
@@ -37,10 +37,6 @@
 
 	/* TS mode */
 	u8 ts_mode;
-
-	/* TS clock inverted */
-	bool ts_clock_inv;
-
 };
 
 #define SI2168_TS_PARALLEL	0x06
diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h
index 60bc334..e13983e 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -38,7 +38,6 @@
 	bool active;
 	bool fw_loaded;
 	u8 ts_mode;
-	bool ts_clock_inv;
 };
 
 /* firmare command struct */
diff --git a/drivers/media/dvb-frontends/sp2.c b/drivers/media/dvb-frontends/sp2.c
index cc1ef96..9b684d5 100644
--- a/drivers/media/dvb-frontends/sp2.c
+++ b/drivers/media/dvb-frontends/sp2.c
@@ -92,9 +92,6 @@
 			return -EIO;
 	}
 
-	dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %*ph\n",
-				client->addr, reg, len, buf);
-
 	return 0;
 }
 
@@ -106,6 +103,9 @@
 	int mem, ret;
 	int (*ci_op_cam)(void*, u8, int, u8, int*) = s->ci_control;
 
+	dev_dbg(&s->client->dev, "slot=%d, acs=0x%02x, addr=0x%04x, data = 0x%02x",
+			slot, acs, addr, data);
+
 	if (slot != 0)
 		return -EINVAL;
 
@@ -140,16 +140,13 @@
 	if (ret)
 		return ret;
 
-	dev_dbg(&s->client->dev, "%s: slot=%d, addr=0x%04x, %s, data=%x",
-			(read) ? "read" : "write", slot, addr,
-			(acs == SP2_CI_ATTR_ACS) ? "attr" : "io",
-			(read) ? mem : data);
-
-	if (read)
+	if (read) {
+		dev_dbg(&s->client->dev, "cam read, addr=0x%04x, data = 0x%04x",
+				addr, mem);
 		return mem;
-	else
+	} else {
 		return 0;
-
+	}
 }
 
 int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
@@ -269,7 +266,7 @@
 	return s->status;
 }
 
-static int sp2_init(struct sp2 *s)
+int sp2_init(struct sp2 *s)
 {
 	int ret = 0;
 	u8 buf;
@@ -351,7 +348,7 @@
 	return ret;
 }
 
-static int sp2_exit(struct i2c_client *client)
+int sp2_exit(struct i2c_client *client)
 {
 	struct sp2 *s;
 
@@ -410,7 +407,7 @@
 
 static int sp2_remove(struct i2c_client *client)
 {
-	struct sp2 *s = i2c_get_clientdata(client);
+	struct si2157 *s = i2c_get_clientdata(client);
 
 	dev_dbg(&client->dev, "\n");
 
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
index 19646fb..07cd5ea 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -705,7 +705,7 @@
 	struct stb0899_state *state = fe->demodulator_priv;
 	u8 reg, i;
 
-	if (cmd->msg_len > sizeof(cmd->msg))
+	if (cmd->msg_len > 8)
 		return -EINVAL;
 
 	/* enable FIFO precharge	*/
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
index 0b2a934..23e872f 100644
--- a/drivers/media/dvb-frontends/stv090x.c
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -2146,7 +2146,7 @@
 
 	u32 reg;
 	s32 car_step, steps, cur_step, dir, freq, timeout_lock;
-	int lock;
+	int lock = 0;
 
 	if (state->srate >= 10000000)
 		timeout_lock = timeout_dmd / 3;
@@ -2154,96 +2154,98 @@
 		timeout_lock = timeout_dmd / 2;
 
 	lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */
-	if (lock)
-		return lock;
+	if (!lock) {
+		if (state->srate >= 10000000) {
+			if (stv090x_chk_tmg(state)) {
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+					goto err;
+				lock = stv090x_get_dmdlock(state, timeout_dmd);
+			} else {
+				lock = 0;
+			}
+		} else {
+			if (state->srate <= 4000000)
+				car_step = 1000;
+			else if (state->srate <= 7000000)
+				car_step = 2000;
+			else if (state->srate <= 10000000)
+				car_step = 3000;
+			else
+				car_step = 5000;
 
-	if (state->srate >= 10000000) {
-		if (stv090x_chk_tmg(state)) {
-			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
-				goto err;
-			return stv090x_get_dmdlock(state, timeout_dmd);
+			steps  = (state->search_range / 1000) / car_step;
+			steps /= 2;
+			steps  = 2 * (steps + 1);
+			if (steps < 0)
+				steps = 2;
+			else if (steps > 12)
+				steps = 12;
+
+			cur_step = 1;
+			dir = 1;
+
+			if (!lock) {
+				freq = state->frequency;
+				state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
+				while ((cur_step <= steps) && (!lock)) {
+					if (dir > 0)
+						freq += cur_step * car_step;
+					else
+						freq -= cur_step * car_step;
+
+					/* Setup tuner */
+					if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+						goto err;
+
+					if (state->config->tuner_set_frequency) {
+						if (state->config->tuner_set_frequency(fe, freq) < 0)
+							goto err_gateoff;
+					}
+
+					if (state->config->tuner_set_bandwidth) {
+						if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+							goto err_gateoff;
+					}
+
+					if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+						goto err;
+
+					msleep(50);
+
+					if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+						goto err;
+
+					if (state->config->tuner_get_status) {
+						if (state->config->tuner_get_status(fe, &reg) < 0)
+							goto err_gateoff;
+					}
+
+					if (reg)
+						dprintk(FE_DEBUG, 1, "Tuner phase locked");
+					else
+						dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+					if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+						goto err;
+
+					STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
+					if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+						goto err;
+					lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
+
+					dir *= -1;
+					cur_step++;
+				}
+			}
 		}
-		return 0;
-	}
-
-	if (state->srate <= 4000000)
-		car_step = 1000;
-	else if (state->srate <= 7000000)
-		car_step = 2000;
-	else if (state->srate <= 10000000)
-		car_step = 3000;
-	else
-		car_step = 5000;
-
-	steps  = (state->search_range / 1000) / car_step;
-	steps /= 2;
-	steps  = 2 * (steps + 1);
-	if (steps < 0)
-		steps = 2;
-	else if (steps > 12)
-		steps = 12;
-
-	cur_step = 1;
-	dir = 1;
-
-	freq = state->frequency;
-	state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
-	while ((cur_step <= steps) && (!lock)) {
-		if (dir > 0)
-			freq += cur_step * car_step;
-		else
-			freq -= cur_step * car_step;
-
-		/* Setup tuner */
-		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-			goto err;
-
-		if (state->config->tuner_set_frequency) {
-			if (state->config->tuner_set_frequency(fe, freq) < 0)
-				goto err_gateoff;
-		}
-
-		if (state->config->tuner_set_bandwidth) {
-			if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
-				goto err_gateoff;
-		}
-
-		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-			goto err;
-
-		msleep(50);
-
-		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-			goto err;
-
-		if (state->config->tuner_get_status) {
-			if (state->config->tuner_get_status(fe, &reg) < 0)
-				goto err_gateoff;
-		}
-
-		if (reg)
-			dprintk(FE_DEBUG, 1, "Tuner phase locked");
-		else
-			dprintk(FE_DEBUG, 1, "Tuner unlocked");
-
-		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-			goto err;
-
-		STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
-		if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
-			goto err;
-		lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
-
-		dir *= -1;
-		cur_step++;
 	}
 
 	return lock;
@@ -2661,9 +2663,13 @@
 			return STV090x_RANGEOK;
 		else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
 			return STV090x_RANGEOK;
+		else
+			return STV090x_OUTOFRANGE; /* Out of Range */
 	} else {
 		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
 			return STV090x_RANGEOK;
+		else
+			return STV090x_OUTOFRANGE;
 	}
 
 	return STV090x_OUTOFRANGE;
@@ -2783,12 +2789,6 @@
 				aclc = car_loop[i].crl_pilots_off_30;
 		}
 	} else { /* 16APSK and 32APSK */
-		/*
-		 * This should never happen in practice, except if
-		 * something is really wrong at the car_loop table.
-		 */
-		if (i >= 11)
-			i = 10;
 		if (state->srate <= 3000000)
 			aclc = car_loop_apsk_low[i].crl_pilots_on_2;
 		else if (state->srate <= 7000000)
@@ -3470,20 +3470,7 @@
 	if (props->frequency == 0)
 		return DVBFE_ALGO_SEARCH_INVALID;
 
-	switch (props->delivery_system) {
-	case SYS_DSS:
-		state->delsys = STV090x_DSS;
-		break;
-	case SYS_DVBS:
-		state->delsys = STV090x_DVBS1;
-		break;
-	case SYS_DVBS2:
-		state->delsys = STV090x_DVBS2;
-		break;
-	default:
-		return DVBFE_ALGO_SEARCH_INVALID;
-	}
-
+	state->delsys = props->delivery_system;
 	state->frequency = props->frequency;
 	state->srate = props->symbol_rate;
 	state->search_mode = STV090x_SEARCH_AUTO;
@@ -4872,8 +4859,8 @@
 	return -1;
 }
 
-static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir,
-			    u8 value, u8 xor_value)
+int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
+		u8 xor_value)
 {
 	struct stv090x_state *state = fe->demodulator_priv;
 	u8 reg = 0;
@@ -4884,6 +4871,7 @@
 
 	return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
 }
+EXPORT_SYMBOL(stv090x_set_gpio);
 
 static struct dvb_frontend_ops stv090x_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
@@ -4920,7 +4908,7 @@
 };
 
 
-struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
+struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
 				    struct i2c_adapter *i2c,
 				    enum stv090x_demodulator demod)
 {
@@ -4981,8 +4969,6 @@
 	if (config->diseqc_envelope_mode)
 		stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
 
-	config->set_gpio = stv090x_set_gpio;
-
 	dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
 	       state->device == STV0900 ? "STV0900" : "STV0903",
 	       demod,
diff --git a/drivers/media/dvb-frontends/stv090x.h b/drivers/media/dvb-frontends/stv090x.h
index 9a3ca6f..86ef794 100644
--- a/drivers/media/dvb-frontends/stv090x.h
+++ b/drivers/media/dvb-frontends/stv090x.h
@@ -89,29 +89,29 @@
 
 	bool diseqc_envelope_mode;
 
-	int (*tuner_init)(struct dvb_frontend *fe);
-	int (*tuner_sleep)(struct dvb_frontend *fe);
-	int (*tuner_set_mode)(struct dvb_frontend *fe, enum tuner_mode mode);
-	int (*tuner_set_frequency)(struct dvb_frontend *fe, u32 frequency);
-	int (*tuner_get_frequency)(struct dvb_frontend *fe, u32 *frequency);
-	int (*tuner_set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
-	int (*tuner_get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
-	int (*tuner_set_bbgain)(struct dvb_frontend *fe, u32 gain);
-	int (*tuner_get_bbgain)(struct dvb_frontend *fe, u32 *gain);
-	int (*tuner_set_refclk)(struct dvb_frontend *fe, u32 refclk);
-	int (*tuner_get_status)(struct dvb_frontend *fe, u32 *status);
-	void (*tuner_i2c_lock)(struct dvb_frontend *fe, int lock);
-
-	/* dir = 0 -> output, dir = 1 -> input/open-drain */
-	int (*set_gpio)(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
-			u8 xor_value);
+	int (*tuner_init) (struct dvb_frontend *fe);
+	int (*tuner_sleep) (struct dvb_frontend *fe);
+	int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
+	int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
+	int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
+	int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
+	int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
+	int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
+	int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
+	int (*tuner_set_refclk)  (struct dvb_frontend *fe, u32 refclk);
+	int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
+	void (*tuner_i2c_lock) (struct dvb_frontend *fe, int lock);
 };
 
 #if IS_ENABLED(CPTCFG_DVB_STV090x)
 
-struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
-				    struct i2c_adapter *i2c,
-				    enum stv090x_demodulator demod);
+extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+					   struct i2c_adapter *i2c,
+					   enum stv090x_demodulator demod);
+
+/* dir = 0 -> output, dir = 1 -> input/open-drain */
+extern int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
+		u8 dir, u8 value, u8 xor_value);
 
 #else
 
@@ -123,6 +123,12 @@
 	return NULL;
 }
 
+static inline int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
+		u8 opd, u8 value, u8 xor_value)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
 #endif /* CPTCFG_DVB_STV090x */
 
 #endif /* __STV090x_H */
diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c
index b35d65c..d9905fb 100644
--- a/drivers/media/dvb-frontends/tc90522.c
+++ b/drivers/media/dvb-frontends/tc90522.c
@@ -216,30 +216,32 @@
 	c->delivery_system = SYS_ISDBS;
 
 	layers = 0;
-	ret = reg_read(state, 0xe6, val, 5);
+	ret = reg_read(state, 0xe8, val, 3);
 	if (ret == 0) {
+		int slots;
 		u8 v;
 
-		c->stream_id = val[0] << 8 | val[1];
-
 		/* high/single layer */
-		v = (val[2] & 0x70) >> 4;
+		v = (val[0] & 0x70) >> 4;
 		c->modulation = (v == 7) ? PSK_8 : QPSK;
 		c->fec_inner = fec_conv_sat[v];
 		c->layer[0].fec = c->fec_inner;
 		c->layer[0].modulation = c->modulation;
-		c->layer[0].segment_count = val[3] & 0x3f; /* slots */
+		c->layer[0].segment_count = val[1] & 0x3f; /* slots */
 
 		/* low layer */
-		v = (val[2] & 0x07);
+		v = (val[0] & 0x07);
 		c->layer[1].fec = fec_conv_sat[v];
 		if (v == 0)  /* no low layer */
 			c->layer[1].segment_count = 0;
 		else
-			c->layer[1].segment_count = val[4] & 0x3f; /* slots */
+			c->layer[1].segment_count = val[2] & 0x3f; /* slots */
 		/* actually, BPSK if v==1, but not defined in fe_modulation_t */
 		c->layer[1].modulation = QPSK;
 		layers = (v > 0) ? 2 : 1;
+
+		slots =  c->layer[0].segment_count +  c->layer[1].segment_count;
+		c->symbol_rate = 28860000 * slots / 48;
 	}
 
 	/* statistics */
@@ -361,7 +363,7 @@
 		u8 v;
 
 		c->isdbt_partial_reception = val[0] & 0x01;
-		c->isdbt_sb_mode = (val[0] & 0xc0) == 0x40;
+		c->isdbt_sb_mode = (val[0] & 0xc0) == 0x01;
 
 		/* layer A */
 		v = (val[2] & 0x78) >> 3;
diff --git a/drivers/media/firewire/Kconfig b/drivers/media/firewire/Kconfig
index 0a173ac..eea1e1d 100644
--- a/drivers/media/firewire/Kconfig
+++ b/drivers/media/firewire/Kconfig
@@ -1,5 +1,5 @@
 config DVB_FIREDTV
-	depends on !KERNEL_3_11
+	depends on !BACKPORT_KERNEL_3_11
 	tristate "FireDTV and FloppyDTV"
 	depends on m
 	depends on DVB_CORE && FIREWIRE
diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c
index e63f582..e5ebdbf 100644
--- a/drivers/media/firewire/firedtv-ci.c
+++ b/drivers/media/firewire/firedtv-ci.c
@@ -253,5 +253,6 @@
 
 void fdtv_ca_release(struct firedtv *fdtv)
 {
-	dvb_unregister_device(fdtv->cadev);
+	if (fdtv->cadev)
+		dvb_unregister_device(fdtv->cadev);
 }
diff --git a/drivers/media/firewire/firedtv.h b/drivers/media/firewire/firedtv.h
index 23972d2..0d79513 100644
--- a/drivers/media/firewire/firedtv.h
+++ b/drivers/media/firewire/firedtv.h
@@ -96,7 +96,7 @@
 
 	enum model_type		type;
 	char			subunit;
-	s8			isochannel;
+	char			isochannel;
 	struct fdtv_ir_context	*ir_context;
 
 	fe_sec_voltage_t	voltage;
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index bd78e2f..1482285 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -213,7 +213,7 @@
 	  module will be called adv7183.
 
 config VIDEO_ADV7604
-	depends on !KERNEL_3_13
+	depends on !BACKPORT_KERNEL_3_13
 	tristate "Analog Devices ADV7604 decoder"
 	depends on m
 	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
@@ -312,6 +312,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called saa7115.
 
+config VIDEO_SAA7191
+	tristate "Philips SAA7191 video decoder"
+	depends on m
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Philips SAA7191 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7191.
+
 config VIDEO_TVP514X
 	tristate "Texas Instruments TVP514x video decoder"
 	depends on m
@@ -443,7 +453,6 @@
 	  module will be called adv7175.
 
 config VIDEO_ADV7343
-	depends on !KERNEL_3_4
 	tristate "ADV7343 video encoder"
 	depends on m
 	depends on I2C
@@ -567,7 +576,7 @@
 	  models only.
 
 config VIDEO_MT9P031
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Aptina MT9P031 support"
 	depends on m
 	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -578,7 +587,7 @@
 	  (Micron) mt9p031 5 Mpixel camera.
 
 config VIDEO_MT9T001
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Aptina MT9T001 support"
 	depends on m
 	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -598,7 +607,7 @@
 	  em28xx driver.
 
 config VIDEO_MT9V032
-	depends on !KERNEL_3_3
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Micron MT9V032 sensor support"
 	depends on m
 	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -617,7 +626,7 @@
 	  This driver supports SR030PC30 VGA camera from Siliconfile
 
 config VIDEO_NOON010PC30
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Siliconfile NOON010PC30 sensor support"
 	depends on m
 	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -628,8 +637,7 @@
 source "drivers/media/i2c/m5mols/Kconfig"
 
 config VIDEO_S5K6AA
-	depends on !KERNEL_3_3
-	depends on !KERNEL_3_13
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Samsung S5K6AAFX sensor support"
 	depends on m
 	depends on MEDIA_CAMERA_SUPPORT
@@ -639,7 +647,7 @@
 	  camera sensor with an embedded SoC image signal processor.
 
 config VIDEO_S5K6A3
-	depends on !KERNEL_3_13
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Samsung S5K6A3 sensor support"
 	depends on m
 	depends on MEDIA_CAMERA_SUPPORT
@@ -649,7 +657,7 @@
 	  camera sensor.
 
 config VIDEO_S5K4ECGX
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_3
         tristate "Samsung S5K4ECGX sensor support"
         depends on m
         depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -658,7 +666,7 @@
           camera sensor with an embedded SoC image signal processor.
 
 config VIDEO_S5K5BAF
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Samsung S5K5BAF sensor support"
 	depends on m
 	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -669,7 +677,7 @@
 source "drivers/media/i2c/smiapp/Kconfig"
 
 config VIDEO_S5C73M3
-	depends on !KERNEL_3_6
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Samsung S5C73M3 sensor support"
 	depends on m
 	depends on I2C && SPI && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -698,7 +706,7 @@
 	  build in control for flash, torch and indicator LEDs.
 
 config VIDEO_LM3560
-	depends on !KERNEL_3_3
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "LM3560 dual flash driver support"
 	depends on m
 	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
@@ -709,7 +717,7 @@
 	  flash, torch LEDs.
 
 config VIDEO_LM3646
-	depends on !KERNEL_3_3
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "LM3646 dual flash driver support"
 	depends on m
 	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 61f289c..6345c00 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -18,6 +18,7 @@
 obj-$(CPTCFG_VIDEO_SAA717X) += saa717x.o
 obj-$(CPTCFG_VIDEO_SAA7127) += saa7127.o
 obj-$(CPTCFG_VIDEO_SAA7185) += saa7185.o
+obj-$(CPTCFG_VIDEO_SAA7191) += saa7191.o
 obj-$(CPTCFG_VIDEO_SAA6752HS) += saa6752hs.o
 obj-$(CPTCFG_VIDEO_ADV7170) += adv7170.o
 obj-$(CPTCFG_VIDEO_ADV7175) += adv7175.o
diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c
index 40a1a95..04bb297 100644
--- a/drivers/media/i2c/adv7170.c
+++ b/drivers/media/i2c/adv7170.c
@@ -63,9 +63,9 @@
 
 static char *inputs[] = { "pass_through", "play_back" };
 
-static u32 adv7170_codes[] = {
-	MEDIA_BUS_FMT_UYVY8_2X8,
-	MEDIA_BUS_FMT_UYVY8_1X16,
+static enum v4l2_mbus_pixelcode adv7170_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_UYVY8_1X16,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -263,7 +263,7 @@
 }
 
 static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-				u32 *code)
+				enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(adv7170_codes))
 		return -EINVAL;
@@ -278,9 +278,9 @@
 	u8 val = adv7170_read(sd, 0x7);
 
 	if ((val & 0x40) == (1 << 6))
-		mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
+		mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
 	else
-		mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
 
 	mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
 	mf->width       = 0;
@@ -297,11 +297,11 @@
 	int ret;
 
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		val &= ~0x40;
 		break;
 
-	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case V4L2_MBUS_FMT_UYVY8_1X16:
 		val |= 0x40;
 		break;
 
diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c
index d220af5..b88f3b3 100644
--- a/drivers/media/i2c/adv7175.c
+++ b/drivers/media/i2c/adv7175.c
@@ -60,9 +60,9 @@
 
 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
 
-static u32 adv7175_codes[] = {
-	MEDIA_BUS_FMT_UYVY8_2X8,
-	MEDIA_BUS_FMT_UYVY8_1X16,
+static enum v4l2_mbus_pixelcode adv7175_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_UYVY8_1X16,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -301,7 +301,7 @@
 }
 
 static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-				u32 *code)
+				enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(adv7175_codes))
 		return -EINVAL;
@@ -316,9 +316,9 @@
 	u8 val = adv7175_read(sd, 0x7);
 
 	if ((val & 0x40) == (1 << 6))
-		mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
+		mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
 	else
-		mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
 
 	mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
 	mf->width       = 0;
@@ -335,11 +335,11 @@
 	int ret;
 
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		val &= ~0x40;
 		break;
 
-	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case V4L2_MBUS_FMT_UYVY8_1X16:
 		val |= 0x40;
 		break;
 
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index bffe6eb..821178d 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -422,12 +422,12 @@
 }
 
 static int adv7180_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
-				 u32 *code)
+				 enum v4l2_mbus_pixelcode *code)
 {
 	if (index > 0)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_YUYV8_2X8;
+	*code = V4L2_MBUS_FMT_YUYV8_2X8;
 
 	return 0;
 }
@@ -437,7 +437,7 @@
 {
 	struct adv7180_state *state = to_state(sd);
 
-	fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
+	fmt->code = V4L2_MBUS_FMT_YUYV8_2X8;
 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	fmt->field = V4L2_FIELD_INTERLACED;
 	fmt->width = 720;
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
index 905890a..3222c79 100644
--- a/drivers/media/i2c/adv7183.c
+++ b/drivers/media/i2c/adv7183.c
@@ -421,12 +421,12 @@
 }
 
 static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
-				u32 *code)
+				enum v4l2_mbus_pixelcode *code)
 {
 	if (index > 0)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_UYVY8_2X8;
+	*code = V4L2_MBUS_FMT_UYVY8_2X8;
 	return 0;
 }
 
@@ -435,7 +435,7 @@
 {
 	struct adv7183 *decoder = to_adv7183(sd);
 
-	fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
+	fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	if (decoder->std & V4L2_STD_525_60) {
 		fmt->field = V4L2_FIELD_SEQ_TB;
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index 3a943c6..7b2d7ce 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -26,7 +26,6 @@
 #include <linux/videodev2.h>
 #include <linux/gpio.h>
 #include <linux/workqueue.h>
-#include <linux/hdmi.h>
 #include <linux/v4l2-dv-timings.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-common.h>
@@ -97,10 +96,6 @@
 	bool have_monitor;
 	/* timings from s_dv_timings */
 	struct v4l2_dv_timings dv_timings;
-	u32 fmt_code;
-	u32 colorspace;
-	u32 ycbcr_enc;
-	u32 quantization;
 	/* controls */
 	struct v4l2_ctrl *hdmi_mode_ctrl;
 	struct v4l2_ctrl *hotplug_ctrl;
@@ -784,234 +779,26 @@
 {
 	struct adv7511_state *state = get_adv7511_state(sd);
 
-	memset(edid->reserved, 0, sizeof(edid->reserved));
-
 	if (edid->pad != 0)
 		return -EINVAL;
-
-	if (edid->start_block == 0 && edid->blocks == 0) {
-		edid->blocks = state->edid.segments * 2;
-		return 0;
-	}
-
-	if (state->edid.segments == 0)
-		return -ENODATA;
-
-	if (edid->start_block >= state->edid.segments * 2)
+	if ((edid->blocks == 0) || (edid->blocks > 256))
 		return -EINVAL;
-
-	if (edid->start_block + edid->blocks > state->edid.segments * 2)
+	if (!state->edid.segments) {
+		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
+		return -ENODATA;
+	}
+	if (edid->start_block >= state->edid.segments * 2)
+		return -E2BIG;
+	if ((edid->blocks + edid->start_block) >= state->edid.segments * 2)
 		edid->blocks = state->edid.segments * 2 - edid->start_block;
 
 	memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
 			128 * edid->blocks);
-
-	return 0;
-}
-
-static int adv7511_enum_mbus_code(struct v4l2_subdev *sd,
-				  struct v4l2_subdev_fh *fh,
-				  struct v4l2_subdev_mbus_code_enum *code)
-{
-	if (code->pad != 0)
-		return -EINVAL;
-
-	switch (code->index) {
-	case 0:
-		code->code = MEDIA_BUS_FMT_RGB888_1X24;
-		break;
-	case 1:
-		code->code = MEDIA_BUS_FMT_YUYV8_1X16;
-		break;
-	case 2:
-		code->code = MEDIA_BUS_FMT_UYVY8_1X16;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void adv7511_fill_format(struct adv7511_state *state,
-				struct v4l2_mbus_framefmt *format)
-{
-	memset(format, 0, sizeof(*format));
-
-	format->width = state->dv_timings.bt.width;
-	format->height = state->dv_timings.bt.height;
-	format->field = V4L2_FIELD_NONE;
-}
-
-static int adv7511_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-			      struct v4l2_subdev_format *format)
-{
-	struct adv7511_state *state = get_adv7511_state(sd);
-
-	if (format->pad != 0)
-		return -EINVAL;
-
-	adv7511_fill_format(state, &format->format);
-
-	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
-		struct v4l2_mbus_framefmt *fmt;
-
-		fmt = v4l2_subdev_get_try_format(fh, format->pad);
-		format->format.code = fmt->code;
-		format->format.colorspace = fmt->colorspace;
-		format->format.ycbcr_enc = fmt->ycbcr_enc;
-		format->format.quantization = fmt->quantization;
-	} else {
-		format->format.code = state->fmt_code;
-		format->format.colorspace = state->colorspace;
-		format->format.ycbcr_enc = state->ycbcr_enc;
-		format->format.quantization = state->quantization;
-	}
-
-	return 0;
-}
-
-static int adv7511_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-		       struct v4l2_subdev_format *format)
-{
-	struct adv7511_state *state = get_adv7511_state(sd);
-	/*
-	 * Bitfield namings come the CEA-861-F standard, table 8 "Auxiliary
-	 * Video Information (AVI) InfoFrame Format"
-	 *
-	 * c = Colorimetry
-	 * ec = Extended Colorimetry
-	 * y = RGB or YCbCr
-	 * q = RGB Quantization Range
-	 * yq = YCC Quantization Range
-	 */
-	u8 c = HDMI_COLORIMETRY_NONE;
-	u8 ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-	u8 y = HDMI_COLORSPACE_RGB;
-	u8 q = HDMI_QUANTIZATION_RANGE_DEFAULT;
-	u8 yq = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
-
-	if (format->pad != 0)
-		return -EINVAL;
-	switch (format->format.code) {
-	case MEDIA_BUS_FMT_UYVY8_1X16:
-	case MEDIA_BUS_FMT_YUYV8_1X16:
-	case MEDIA_BUS_FMT_RGB888_1X24:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	adv7511_fill_format(state, &format->format);
-	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
-		struct v4l2_mbus_framefmt *fmt;
-
-		fmt = v4l2_subdev_get_try_format(fh, format->pad);
-		fmt->code = format->format.code;
-		fmt->colorspace = format->format.colorspace;
-		fmt->ycbcr_enc = format->format.ycbcr_enc;
-		fmt->quantization = format->format.quantization;
-		return 0;
-	}
-
-	switch (format->format.code) {
-	case MEDIA_BUS_FMT_UYVY8_1X16:
-		adv7511_wr_and_or(sd, 0x15, 0xf0, 0x01);
-		adv7511_wr_and_or(sd, 0x16, 0x03, 0xb8);
-		y = HDMI_COLORSPACE_YUV422;
-		break;
-	case MEDIA_BUS_FMT_YUYV8_1X16:
-		adv7511_wr_and_or(sd, 0x15, 0xf0, 0x01);
-		adv7511_wr_and_or(sd, 0x16, 0x03, 0xbc);
-		y = HDMI_COLORSPACE_YUV422;
-		break;
-	case MEDIA_BUS_FMT_RGB888_1X24:
-	default:
-		adv7511_wr_and_or(sd, 0x15, 0xf0, 0x00);
-		adv7511_wr_and_or(sd, 0x16, 0x03, 0x00);
-		break;
-	}
-	state->fmt_code = format->format.code;
-	state->colorspace = format->format.colorspace;
-	state->ycbcr_enc = format->format.ycbcr_enc;
-	state->quantization = format->format.quantization;
-
-	switch (format->format.colorspace) {
-	case V4L2_COLORSPACE_ADOBERGB:
-		c = HDMI_COLORIMETRY_EXTENDED;
-		ec = y ? HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601 :
-			 HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB;
-		break;
-	case V4L2_COLORSPACE_SMPTE170M:
-		c = y ? HDMI_COLORIMETRY_ITU_601 : HDMI_COLORIMETRY_NONE;
-		if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_XV601) {
-			c = HDMI_COLORIMETRY_EXTENDED;
-			ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-		}
-		break;
-	case V4L2_COLORSPACE_REC709:
-		c = y ? HDMI_COLORIMETRY_ITU_709 : HDMI_COLORIMETRY_NONE;
-		if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_XV709) {
-			c = HDMI_COLORIMETRY_EXTENDED;
-			ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
-		}
-		break;
-	case V4L2_COLORSPACE_SRGB:
-		c = y ? HDMI_COLORIMETRY_EXTENDED : HDMI_COLORIMETRY_NONE;
-		ec = y ? HDMI_EXTENDED_COLORIMETRY_S_YCC_601 :
-			 HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-		break;
-	case V4L2_COLORSPACE_BT2020:
-		c = HDMI_COLORIMETRY_EXTENDED;
-		if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_BT2020_CONST_LUM)
-			ec = 5; /* Not yet available in hdmi.h */
-		else
-			ec = 6; /* Not yet available in hdmi.h */
-		break;
-	default:
-		break;
-	}
-
-	/*
-	 * CEA-861-F says that for RGB formats the YCC range must match the
-	 * RGB range, although sources should ignore the YCC range.
-	 *
-	 * The RGB quantization range shouldn't be non-zero if the EDID doesn't
-	 * have the Q bit set in the Video Capabilities Data Block, however this
-	 * isn't checked at the moment. The assumption is that the application
-	 * knows the EDID and can detect this.
-	 *
-	 * The same is true for the YCC quantization range: non-standard YCC
-	 * quantization ranges should only be sent if the EDID has the YQ bit
-	 * set in the Video Capabilities Data Block.
-	 */
-	switch (format->format.quantization) {
-	case V4L2_QUANTIZATION_FULL_RANGE:
-		q = y ? HDMI_QUANTIZATION_RANGE_DEFAULT :
-			HDMI_QUANTIZATION_RANGE_FULL;
-		yq = q ? q - 1 : HDMI_YCC_QUANTIZATION_RANGE_FULL;
-		break;
-	case V4L2_QUANTIZATION_LIM_RANGE:
-		q = y ? HDMI_QUANTIZATION_RANGE_DEFAULT :
-			HDMI_QUANTIZATION_RANGE_LIMITED;
-		yq = q ? q - 1 : HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
-		break;
-	}
-
-	adv7511_wr_and_or(sd, 0x4a, 0xbf, 0);
-	adv7511_wr_and_or(sd, 0x55, 0x9f, y << 5);
-	adv7511_wr_and_or(sd, 0x56, 0x3f, c << 6);
-	adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2));
-	adv7511_wr_and_or(sd, 0x59, 0x0f, yq << 4);
-	adv7511_wr_and_or(sd, 0x4a, 0xff, 1);
-
 	return 0;
 }
 
 static const struct v4l2_subdev_pad_ops adv7511_pad_ops = {
 	.get_edid = adv7511_get_edid,
-	.enum_mbus_code = adv7511_enum_mbus_code,
-	.get_fmt = adv7511_get_fmt,
-	.set_fmt = adv7511_set_fmt,
 	.enum_dv_timings = adv7511_enum_dv_timings,
 	.dv_timings_cap = adv7511_dv_timings_cap,
 };
@@ -1329,8 +1116,6 @@
 		return -ENODEV;
 	}
 	memcpy(&state->pdata, pdata, sizeof(state->pdata));
-	state->fmt_code = MEDIA_BUS_FMT_RGB888_1X24;
-	state->colorspace = V4L2_COLORSPACE_SRGB;
 
 	sd = &state->sd;
 
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 764b2b7..bb6c3a4 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -88,7 +88,7 @@
 };
 
 struct adv7604_format_info {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	u8 op_ch_sel;
 	bool rgb_out;
 	bool swap_cb_cr;
@@ -749,77 +749,77 @@
  */
 
 static const struct adv7604_format_info adv7604_formats[] = {
-	{ MEDIA_BUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
 	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
-	{ MEDIA_BUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
-	{ MEDIA_BUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
+	{ V4L2_MBUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
-	{ MEDIA_BUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
+	{ V4L2_MBUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
-	{ MEDIA_BUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
-	{ MEDIA_BUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
-	{ MEDIA_BUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
 };
 
 static const struct adv7604_format_info adv7611_formats[] = {
-	{ MEDIA_BUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
 	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-	{ MEDIA_BUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-	{ MEDIA_BUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
 	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
 };
 
 static const struct adv7604_format_info *
-adv7604_format_info(struct adv7604_state *state, u32 code)
+adv7604_format_info(struct adv7604_state *state, enum v4l2_mbus_pixelcode code)
 {
 	unsigned int i;
 
@@ -1917,7 +1917,7 @@
 
 	info = adv7604_format_info(state, format->format.code);
 	if (info == NULL)
-		info = adv7604_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
+		info = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
 
 	adv7604_fill_format(state, &format->format);
 	format->format.code = info->code;
@@ -1997,7 +1997,19 @@
 	struct adv7604_state *state = to_state(sd);
 	u8 *data = NULL;
 
-	memset(edid->reserved, 0, sizeof(edid->reserved));
+	if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
+		return -EINVAL;
+	if (edid->blocks == 0)
+		return -EINVAL;
+	if (edid->blocks > 2)
+		return -EINVAL;
+	if (edid->start_block > 1)
+		return -EINVAL;
+	if (edid->start_block == 1)
+		edid->blocks = 1;
+
+	if (edid->blocks > state->edid.blocks)
+		edid->blocks = state->edid.blocks;
 
 	switch (edid->pad) {
 	case ADV7604_PAD_HDMI_PORT_A:
@@ -2009,24 +2021,14 @@
 		break;
 	default:
 		return -EINVAL;
+		break;
 	}
-
-	if (edid->start_block == 0 && edid->blocks == 0) {
-		edid->blocks = data ? state->edid.blocks : 0;
-		return 0;
-	}
-
-	if (data == NULL)
+	if (!data)
 		return -ENODATA;
 
-	if (edid->start_block >= state->edid.blocks)
-		return -EINVAL;
-
-	if (edid->start_block + edid->blocks > state->edid.blocks)
-		edid->blocks = state->edid.blocks - edid->start_block;
-
-	memcpy(edid->edid, data + edid->start_block * 128, edid->blocks * 128);
-
+	memcpy(edid->edid,
+	       data + edid->start_block * 128,
+	       edid->blocks * 128);
 	return 0;
 }
 
@@ -2066,8 +2068,6 @@
 	int err;
 	int i;
 
-	memset(edid->reserved, 0, sizeof(edid->reserved));
-
 	if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
 		return -EINVAL;
 	if (edid->start_block != 0)
@@ -2164,6 +2164,7 @@
 		return -EIO;
 	}
 
+
 	/* enable hotplug after 100 ms */
 	queue_delayed_work(state->work_queues,
 			&state->delayed_work_enable_hotplug, HZ / 10);
@@ -2806,7 +2807,7 @@
 	}
 
 	state->timings = cea640x480;
-	state->format = adv7604_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
+	state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
 
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 9af02d3..ba8e833 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -1877,12 +1877,12 @@
 }
 
 static int adv7842_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
-				 u32 *code)
+				 enum v4l2_mbus_pixelcode *code)
 {
 	if (index)
 		return -EINVAL;
 	/* Good enough for now */
-	*code = MEDIA_BUS_FMT_FIXED;
+	*code = V4L2_MBUS_FMT_FIXED;
 	return 0;
 }
 
@@ -1893,7 +1893,7 @@
 
 	fmt->width = state->timings.bt.width;
 	fmt->height = state->timings.bt.height;
-	fmt->code = MEDIA_BUS_FMT_FIXED;
+	fmt->code = V4L2_MBUS_FMT_FIXED;
 	fmt->field = V4L2_FIELD_NONE;
 
 	if (state->mode == ADV7842_MODE_SDP) {
@@ -2028,7 +2028,16 @@
 	struct adv7842_state *state = to_state(sd);
 	u8 *data = NULL;
 
-	memset(edid->reserved, 0, sizeof(edid->reserved));
+	if (edid->pad > ADV7842_EDID_PORT_VGA)
+		return -EINVAL;
+	if (edid->blocks == 0)
+		return -EINVAL;
+	if (edid->blocks > 2)
+		return -EINVAL;
+	if (edid->start_block > 1)
+		return -EINVAL;
+	if (edid->start_block == 1)
+		edid->blocks = 1;
 
 	switch (edid->pad) {
 	case ADV7842_EDID_PORT_A:
@@ -2043,23 +2052,12 @@
 	default:
 		return -EINVAL;
 	}
-
-	if (edid->start_block == 0 && edid->blocks == 0) {
-		edid->blocks = data ? 2 : 0;
-		return 0;
-	}
-
 	if (!data)
 		return -ENODATA;
 
-	if (edid->start_block >= 2)
-		return -EINVAL;
-
-	if (edid->start_block + edid->blocks > 2)
-		edid->blocks = 2 - edid->start_block;
-
-	memcpy(edid->edid, data + edid->start_block * 128, edid->blocks * 128);
-
+	memcpy(edid->edid,
+	       data + edid->start_block * 128,
+	       edid->blocks * 128);
 	return 0;
 }
 
@@ -2068,16 +2066,12 @@
 	struct adv7842_state *state = to_state(sd);
 	int err = 0;
 
-	memset(e->reserved, 0, sizeof(e->reserved));
-
 	if (e->pad > ADV7842_EDID_PORT_VGA)
 		return -EINVAL;
 	if (e->start_block != 0)
 		return -EINVAL;
-	if (e->blocks > 2) {
-		e->blocks = 2;
+	if (e->blocks > 2)
 		return -E2BIG;
-	}
 
 	/* todo, per edid */
 	state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15],
diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c
index c8076f2..b480759 100644
--- a/drivers/media/i2c/ak881x.c
+++ b/drivers/media/i2c/ak881x.c
@@ -102,7 +102,7 @@
 	v4l_bound_align_image(&mf->width, 0, 720, 2,
 			      &mf->height, 0, ak881x->lines, 1, 0);
 	mf->field	= V4L2_FIELD_INTERLACED;
-	mf->code	= MEDIA_BUS_FMT_YUYV8_2X8;
+	mf->code	= V4L2_MBUS_FMT_YUYV8_2X8;
 	mf->colorspace	= V4L2_COLORSPACE_SMPTE170M;
 
 	return 0;
@@ -112,19 +112,19 @@
 			     struct v4l2_mbus_framefmt *mf)
 {
 	if (mf->field != V4L2_FIELD_INTERLACED ||
-	    mf->code != MEDIA_BUS_FMT_YUYV8_2X8)
+	    mf->code != V4L2_MBUS_FMT_YUYV8_2X8)
 		return -EINVAL;
 
 	return ak881x_try_g_mbus_fmt(sd, mf);
 }
 
 static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
-				u32 *code)
+				enum v4l2_mbus_pixelcode *code)
 {
 	if (index)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_YUYV8_2X8;
+	*code = V4L2_MBUS_FMT_YUYV8_2X8;
 	return 0;
 }
 
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c
index 05b7cd6..f460ce0 100644
--- a/drivers/media/i2c/cx25840/cx25840-core.c
+++ b/drivers/media/i2c/cx25840/cx25840-core.c
@@ -879,7 +879,7 @@
 	/* Sets horizontal blanking delay and active lines */
 	cx25840_write(client, 0x470, hblank);
 	cx25840_write(client, 0x471,
-		      (((hblank >> 8) & 0x3) | (hactive << 4)) & 0xff);
+			0xff & (((hblank >> 8) & 0x3) | (hactive << 4)));
 	cx25840_write(client, 0x472, hactive >> 4);
 
 	/* Sets burst gate delay */
@@ -888,13 +888,13 @@
 	/* Sets vertical blanking delay and active duration */
 	cx25840_write(client, 0x474, vblank);
 	cx25840_write(client, 0x475,
-		      (((vblank >> 8) & 0x3) | (vactive << 4)) & 0xff);
+			0xff & (((vblank >> 8) & 0x3) | (vactive << 4)));
 	cx25840_write(client, 0x476, vactive >> 4);
 	cx25840_write(client, 0x477, vblank656);
 
 	/* Sets src decimation rate */
-	cx25840_write(client, 0x478, src_decimation & 0xff);
-	cx25840_write(client, 0x479, (src_decimation >> 8) & 0xff);
+	cx25840_write(client, 0x478, 0xff & src_decimation);
+	cx25840_write(client, 0x479, 0xff & (src_decimation >> 8));
 
 	/* Sets Luma and UV Low pass filters */
 	cx25840_write(client, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
@@ -904,8 +904,8 @@
 
 	/* Sets SC Step*/
 	cx25840_write(client, 0x47c, sc);
-	cx25840_write(client, 0x47d, (sc >> 8) & 0xff);
-	cx25840_write(client, 0x47e, (sc >> 16) & 0xff);
+	cx25840_write(client, 0x47d, 0xff & sc >> 8);
+	cx25840_write(client, 0x47e, 0xff & sc >> 16);
 
 	/* Sets VBI parameters */
 	if (std & V4L2_STD_625_50) {
@@ -1373,7 +1373,7 @@
 	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
 	int is_50Hz = !(state->std & V4L2_STD_525_60);
 
-	if (fmt->code != MEDIA_BUS_FMT_FIXED)
+	if (fmt->code != V4L2_MBUS_FMT_FIXED)
 		return -EINVAL;
 
 	fmt->field = V4L2_FIELD_INTERLACED;
diff --git a/drivers/media/i2c/cx25840/cx25840-firmware.c b/drivers/media/i2c/cx25840/cx25840-firmware.c
index 9bbb31a..b3169f9 100644
--- a/drivers/media/i2c/cx25840/cx25840-firmware.c
+++ b/drivers/media/i2c/cx25840/cx25840-firmware.c
@@ -113,7 +113,7 @@
 	const u8 *ptr;
 	const char *fwname = get_fw_name(client);
 	int size, retval;
-	int max_buf_size = FWSEND;
+	int MAX_BUF_SIZE = FWSEND;
 	u32 gpio_oe = 0, gpio_da = 0;
 
 	if (is_cx2388x(state)) {
@@ -122,9 +122,10 @@
 		gpio_da = cx25840_read(client, 0x164);
 	}
 
-	/* cx231xx cannot accept more than 16 bytes at a time */
-	if (is_cx231xx(state) && max_buf_size > 16)
-		max_buf_size = 16;
+	if (is_cx231xx(state) && MAX_BUF_SIZE > 16) {
+		v4l_err(client, " Firmware download size changed to 16 bytes max length\n");
+		MAX_BUF_SIZE = 16;  /* cx231xx cannot accept more than 16 bytes at a time */
+	}
 
 	if (request_firmware(&fw, fwname, FWDEV(client)) != 0) {
 		v4l_err(client, "unable to open firmware %s\n", fwname);
@@ -139,7 +140,7 @@
 	size = fw->size;
 	ptr = fw->data;
 	while (size > 0) {
-		int len = min(max_buf_size - 2, size);
+		int len = min(MAX_BUF_SIZE - 2, size);
 
 		memcpy(buffer + 2, ptr, len);
 
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 175a761..8311f1a 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -464,7 +464,8 @@
 	cancel_delayed_work_sync(&ir->work);
 
 	/* unregister device */
-	rc_unregister_device(ir->rc);
+	if (ir->rc)
+		rc_unregister_device(ir->rc);
 
 	/* free memory */
 	return 0;
diff --git a/drivers/media/i2c/m5mols/Kconfig b/drivers/media/i2c/m5mols/Kconfig
index 4ed0509..c858c2f 100644
--- a/drivers/media/i2c/m5mols/Kconfig
+++ b/drivers/media/i2c/m5mols/Kconfig
@@ -1,5 +1,5 @@
 config VIDEO_M5MOLS
-	depends on !KERNEL_3_6
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Fujitsu M-5MOLS 8MP sensor support"
 	depends on m
 	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c
index 2820f7c..8d870b7 100644
--- a/drivers/media/i2c/m5mols/m5mols_core.c
+++ b/drivers/media/i2c/m5mols/m5mols_core.c
@@ -57,14 +57,14 @@
 	[M5MOLS_RESTYPE_MONITOR] = {
 		.width		= 1920,
 		.height		= 1080,
-		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
 		.field		= V4L2_FIELD_NONE,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 	},
 	[M5MOLS_RESTYPE_CAPTURE] = {
 		.width		= 1920,
 		.height		= 1080,
-		.code		= MEDIA_BUS_FMT_JPEG_1X8,
+		.code		= V4L2_MBUS_FMT_JPEG_1X8,
 		.field		= V4L2_FIELD_NONE,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 	},
@@ -479,7 +479,7 @@
  * __find_restype - Lookup M-5MOLS resolution type according to pixel code
  * @code: pixel code
  */
-static enum m5mols_restype __find_restype(u32 code)
+static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code)
 {
 	enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
 
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c
index f6ed2a4..c629b33 100644
--- a/drivers/media/i2c/ml86v7667.c
+++ b/drivers/media/i2c/ml86v7667.c
@@ -192,12 +192,12 @@
 }
 
 static int ml86v7667_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
-				   u32 *code)
+				   enum v4l2_mbus_pixelcode *code)
 {
 	if (index > 0)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_YUYV8_2X8;
+	*code = V4L2_MBUS_FMT_YUYV8_2X8;
 
 	return 0;
 }
@@ -207,7 +207,7 @@
 {
 	struct ml86v7667_priv *priv = to_ml86v7667(sd);
 
-	fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
+	fmt->code = V4L2_MBUS_FMT_YUYV8_2X8;
 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	/* The top field is always transferred first by the chip */
 	fmt->field = V4L2_FIELD_INTERLACED_TB;
diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c
index 7a2b628..fe9d820 100644
--- a/drivers/media/i2c/mt9m032.c
+++ b/drivers/media/i2c/mt9m032.c
@@ -323,7 +323,7 @@
 	if (code->index != 0)
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_Y8_1X8;
+	code->code = V4L2_MBUS_FMT_Y8_1X8;
 	return 0;
 }
 
@@ -331,7 +331,7 @@
 				   struct v4l2_subdev_fh *fh,
 				   struct v4l2_subdev_frame_size_enum *fse)
 {
-	if (fse->index != 0 || fse->code != MEDIA_BUS_FMT_Y8_1X8)
+	if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8)
 		return -EINVAL;
 
 	fse->min_width = MT9M032_COLUMN_SIZE_DEF;
@@ -759,7 +759,7 @@
 
 	sensor->format.width = sensor->crop.width;
 	sensor->format.height = sensor->crop.height;
-	sensor->format.code = MEDIA_BUS_FMT_Y8_1X8;
+	sensor->format.code = V4L2_MBUS_FMT_Y8_1X8;
 	sensor->format.field = V4L2_FIELD_NONE;
 	sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
 
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
index edb76bd..e18797f 100644
--- a/drivers/media/i2c/mt9p031.c
+++ b/drivers/media/i2c/mt9p031.c
@@ -950,9 +950,9 @@
 	format = v4l2_subdev_get_try_format(fh, 0);
 
 	if (mt9p031->model == MT9P031_MODEL_MONOCHROME)
-		format->code = MEDIA_BUS_FMT_Y12_1X12;
+		format->code = V4L2_MBUS_FMT_Y12_1X12;
 	else
-		format->code = MEDIA_BUS_FMT_SGRBG12_1X12;
+		format->code = V4L2_MBUS_FMT_SGRBG12_1X12;
 
 	format->width = MT9P031_WINDOW_WIDTH_DEF;
 	format->height = MT9P031_WINDOW_HEIGHT_DEF;
@@ -1120,9 +1120,9 @@
 	mt9p031->crop.top = MT9P031_ROW_START_DEF;
 
 	if (mt9p031->model == MT9P031_MODEL_MONOCHROME)
-		mt9p031->format.code = MEDIA_BUS_FMT_Y12_1X12;
+		mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12;
 	else
-		mt9p031->format.code = MEDIA_BUS_FMT_SGRBG12_1X12;
+		mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
 
 	mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF;
 	mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF;
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c
index d9e9889..422e068 100644
--- a/drivers/media/i2c/mt9t001.c
+++ b/drivers/media/i2c/mt9t001.c
@@ -333,7 +333,7 @@
 	if (code->index > 0)
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	return 0;
 }
 
@@ -341,7 +341,7 @@
 				   struct v4l2_subdev_fh *fh,
 				   struct v4l2_subdev_frame_size_enum *fse)
 {
-	if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
+	if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
 		return -EINVAL;
 
 	fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
@@ -792,7 +792,7 @@
 	crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
 
 	format = v4l2_subdev_get_try_format(fh, 0);
-	format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
 	format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
 	format->field = V4L2_FIELD_NONE;
@@ -917,7 +917,7 @@
 	mt9t001->crop.width = MT9T001_WINDOW_WIDTH_DEF + 1;
 	mt9t001->crop.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
 
-	mt9t001->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	mt9t001->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	mt9t001->format.width = MT9T001_WINDOW_WIDTH_DEF + 1;
 	mt9t001->format.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
 	mt9t001->format.field = V4L2_FIELD_NONE;
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
index d56bd47..355646c 100644
--- a/drivers/media/i2c/mt9v011.c
+++ b/drivers/media/i2c/mt9v011.c
@@ -325,18 +325,18 @@
 }
 
 static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
-					u32 *code)
+					enum v4l2_mbus_pixelcode *code)
 {
 	if (index > 0)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_SGRBG8_1X8;
+	*code = V4L2_MBUS_FMT_SGRBG8_1X8;
 	return 0;
 }
 
 static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
-	if (fmt->code != MEDIA_BUS_FMT_SGRBG8_1X8)
+	if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8)
 		return -EINVAL;
 
 	v4l_bound_align_image(&fmt->width, 48, 639, 1,
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 93687c1..d044bce 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -454,7 +454,7 @@
 	if (code->index > 0)
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	return 0;
 }
 
@@ -462,7 +462,7 @@
 				   struct v4l2_subdev_fh *fh,
 				   struct v4l2_subdev_frame_size_enum *fse)
 {
-	if (fse->index >= 3 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
+	if (fse->index >= 3 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
 		return -EINVAL;
 
 	fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index);
@@ -814,9 +814,9 @@
 	format = v4l2_subdev_get_try_format(fh, 0);
 
 	if (mt9v032->model->color)
-		format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+		format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	else
-		format->code = MEDIA_BUS_FMT_Y10_1X10;
+		format->code = V4L2_MBUS_FMT_Y10_1X10;
 
 	format->width = MT9V032_WINDOW_WIDTH_DEF;
 	format->height = MT9V032_WINDOW_HEIGHT_DEF;
@@ -966,9 +966,9 @@
 	mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF;
 
 	if (mt9v032->model->color)
-		mt9v032->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+		mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	else
-		mt9v032->format.code = MEDIA_BUS_FMT_Y10_1X10;
+		mt9v032->format.code = V4L2_MBUS_FMT_Y10_1X10;
 
 	mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF;
 	mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF;
diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c
index 00c7b26..7eae487 100644
--- a/drivers/media/i2c/noon010pc30.c
+++ b/drivers/media/i2c/noon010pc30.c
@@ -112,7 +112,7 @@
 #define REG_TERM		0xFFFF
 
 struct noon010_format {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	enum v4l2_colorspace colorspace;
 	u16 ispctl1_reg;
 };
@@ -175,23 +175,23 @@
 /* Supported pixel formats. */
 static const struct noon010_format noon010_formats[] = {
 	{
-		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0x03,
 	}, {
-		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0x02,
 	}, {
-		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0,
 	}, {
-		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0x01,
 	}, {
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_BE,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0x40,
 	},
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index 48eeb6a..ad8795f 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -632,31 +632,31 @@
  * The magic matrix numbers come from OmniVision.
  */
 static struct ov7670_format_struct {
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 	enum v4l2_colorspace colorspace;
 	struct regval_list *regs;
 	int cmatrix[CMATRIX_LEN];
 } ov7670_formats[] = {
 	{
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.regs 		= ov7670_fmt_yuv422,
 		.cmatrix	= { 128, -128, 0, -34, -94, 128 },
 	},
 	{
-		.mbus_code	= MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE,
+		.mbus_code	= V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.regs		= ov7670_fmt_rgb444,
 		.cmatrix	= { 179, -179, 0, -61, -176, 228 },
 	},
 	{
-		.mbus_code	= MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.mbus_code	= V4L2_MBUS_FMT_RGB565_2X8_LE,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.regs		= ov7670_fmt_rgb565,
 		.cmatrix	= { 179, -179, 0, -61, -176, 228 },
 	},
 	{
-		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.mbus_code	= V4L2_MBUS_FMT_SBGGR8_1X8,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.regs 		= ov7670_fmt_raw,
 		.cmatrix	= { 0, 0, 0, 0, 0, 0 },
@@ -772,7 +772,7 @@
 		pll_factor = PLL_FACTOR;
 
 	clkrc++;
-	if (info->fmt->mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8)
+	if (info->fmt->mbus_code == V4L2_MBUS_FMT_SBGGR8_1X8)
 		clkrc = (clkrc >> 1);
 
 	tpf->numerator = 1;
@@ -810,7 +810,7 @@
 	} else {
 		clkrc = (5 * pll_factor * info->clock_speed * tpf->numerator) /
 			(4 * tpf->denominator);
-		if (info->fmt->mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8)
+		if (info->fmt->mbus_code == V4L2_MBUS_FMT_SBGGR8_1X8)
 			clkrc = (clkrc << 1);
 		clkrc--;
 	}
@@ -900,7 +900,7 @@
 
 
 static int ov7670_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
-					u32 *code)
+					enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= N_OV7670_FMTS)
 		return -EINVAL;
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c
index 2246bd5..4da90c6 100644
--- a/drivers/media/i2c/ov9650.c
+++ b/drivers/media/i2c/ov9650.c
@@ -384,17 +384,17 @@
 };
 
 struct ov965x_pixfmt {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	u32 colorspace;
 	/* REG_TSLB value, only bits [3:2] may be set. */
 	u8 tslb_reg;
 };
 
 static const struct ov965x_pixfmt ov965x_formats[] = {
-	{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 0x00},
-	{ MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG, 0x04},
-	{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG, 0x0c},
-	{ MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG, 0x08},
+	{ V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 0x00},
+	{ V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG, 0x04},
+	{ V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG, 0x0c},
+	{ V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG, 0x08},
 };
 
 /*
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h
index 13aed59..9656b67 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3.h
+++ b/drivers/media/i2c/s5c73m3/s5c73m3.h
@@ -27,8 +27,8 @@
 
 #define DRIVER_NAME			"S5C73M3"
 
-#define S5C73M3_ISP_FMT			MEDIA_BUS_FMT_VYUY8_2X8
-#define S5C73M3_JPEG_FMT		MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8
+#define S5C73M3_ISP_FMT			V4L2_MBUS_FMT_VYUY8_2X8
+#define S5C73M3_JPEG_FMT		V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8
 
 /* Subdevs pad index definitions */
 enum s5c73m3_pads {
@@ -402,7 +402,7 @@
 
 	const struct s5c73m3_frame_size *sensor_pix_size[2];
 	const struct s5c73m3_frame_size *oif_pix_size[2];
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 
 	const struct s5c73m3_interval *fiv;
 
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
index d1c50c9..1fcc76f 100644
--- a/drivers/media/i2c/s5k4ecgx.c
+++ b/drivers/media/i2c/s5k4ecgx.c
@@ -151,7 +151,7 @@
 #define S5K4ECGX_NUM_PREV ARRAY_SIZE(s5k4ecgx_prev_sizes)
 
 struct s5k4ecgx_pixfmt {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	u32 colorspace;
 	/* REG_TC_PCFG_Format register value */
 	u16 reg_p_format;
@@ -159,7 +159,7 @@
 
 /* By default value, output from sensor will be YUV422 0-255 */
 static const struct s5k4ecgx_pixfmt s5k4ecgx_formats[] = {
-	{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
+	{ V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
 };
 
 static const char * const s5k4ecgx_supply_names[] = {
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 60a74d8..0e461a6 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -248,7 +248,7 @@
 #define NUM_ISP_PADS 2
 
 struct s5k5baf_pixfmt {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	u32 colorspace;
 	/* REG_P_FMT(x) register value */
 	u16 reg_p_fmt;
@@ -331,10 +331,10 @@
 };
 
 static const struct s5k5baf_pixfmt s5k5baf_formats[] = {
-	{ MEDIA_BUS_FMT_VYUY8_2X8,	V4L2_COLORSPACE_JPEG,	5 },
+	{ V4L2_MBUS_FMT_VYUY8_2X8,	V4L2_COLORSPACE_JPEG,	5 },
 	/* range 16-240 */
-	{ MEDIA_BUS_FMT_VYUY8_2X8,	V4L2_COLORSPACE_REC709,	6 },
-	{ MEDIA_BUS_FMT_RGB565_2X8_BE,	V4L2_COLORSPACE_JPEG,	0 },
+	{ V4L2_MBUS_FMT_VYUY8_2X8,	V4L2_COLORSPACE_REC709,	6 },
+	{ V4L2_MBUS_FMT_RGB565_2X8_BE,	V4L2_COLORSPACE_JPEG,	0 },
 };
 
 static struct v4l2_rect s5k5baf_cis_rect = {
@@ -1206,7 +1206,7 @@
 	if (code->pad == PAD_CIS) {
 		if (code->index > 0)
 			return -EINVAL;
-		code->code = MEDIA_BUS_FMT_FIXED;
+		code->code = V4L2_MBUS_FMT_FIXED;
 		return 0;
 	}
 
@@ -1227,7 +1227,7 @@
 		return -EINVAL;
 
 	if (fse->pad == PAD_CIS) {
-		fse->code = MEDIA_BUS_FMT_FIXED;
+		fse->code = V4L2_MBUS_FMT_FIXED;
 		fse->min_width = S5K5BAF_CIS_WIDTH;
 		fse->max_width = S5K5BAF_CIS_WIDTH;
 		fse->min_height = S5K5BAF_CIS_HEIGHT;
@@ -1252,7 +1252,7 @@
 {
 	mf->width = S5K5BAF_CIS_WIDTH;
 	mf->height = S5K5BAF_CIS_HEIGHT;
-	mf->code = MEDIA_BUS_FMT_FIXED;
+	mf->code = V4L2_MBUS_FMT_FIXED;
 	mf->colorspace = V4L2_COLORSPACE_JPEG;
 	mf->field = V4L2_FIELD_NONE;
 }
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
index 91b841a..c11a408 100644
--- a/drivers/media/i2c/s5k6a3.c
+++ b/drivers/media/i2c/s5k6a3.c
@@ -80,7 +80,7 @@
 
 static const struct v4l2_mbus_framefmt s5k6a3_formats[] = {
 	{
-		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.code = V4L2_MBUS_FMT_SGRBG10_1X10,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.field = V4L2_FIELD_NONE,
 	}
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c
index 2851581..629a5cd 100644
--- a/drivers/media/i2c/s5k6aa.c
+++ b/drivers/media/i2c/s5k6aa.c
@@ -191,7 +191,7 @@
 };
 
 struct s5k6aa_pixfmt {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	u32 colorspace;
 	/* REG_P_FMT(x) register value */
 	u16 reg_p_fmt;
@@ -285,10 +285,10 @@
 
 /* TODO: Add RGB888 and Bayer format */
 static const struct s5k6aa_pixfmt s5k6aa_formats[] = {
-	{ MEDIA_BUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_JPEG,	5 },
+	{ V4L2_MBUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_JPEG,	5 },
 	/* range 16-240 */
-	{ MEDIA_BUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_REC709,	6 },
-	{ MEDIA_BUS_FMT_RGB565_2X8_BE,	V4L2_COLORSPACE_JPEG,	0 },
+	{ V4L2_MBUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_REC709,	6 },
+	{ V4L2_MBUS_FMT_RGB565_2X8_BE,	V4L2_COLORSPACE_JPEG,	0 },
 };
 
 static const struct s5k6aa_interval s5k6aa_intervals[] = {
diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c
index f14c0e6..4024ea6 100644
--- a/drivers/media/i2c/saa6752hs.c
+++ b/drivers/media/i2c/saa6752hs.c
@@ -562,7 +562,7 @@
 		h->video_format = SAA6752HS_VF_D1;
 	f->width = v4l2_format_table[h->video_format].fmt.pix.width;
 	f->height = v4l2_format_table[h->video_format].fmt.pix.height;
-	f->code = MEDIA_BUS_FMT_FIXED;
+	f->code = V4L2_MBUS_FMT_FIXED;
 	f->field = V4L2_FIELD_INTERLACED;
 	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	return 0;
@@ -572,7 +572,7 @@
 {
 	int dist_352, dist_480, dist_720;
 
-	f->code = MEDIA_BUS_FMT_FIXED;
+	f->code = V4L2_MBUS_FMT_FIXED;
 
 	dist_352 = abs(f->width - 352);
 	dist_480 = abs(f->width - 480);
@@ -599,7 +599,7 @@
 {
 	struct saa6752hs_state *h = to_state(sd);
 
-	if (f->code != MEDIA_BUS_FMT_FIXED)
+	if (f->code != V4L2_MBUS_FMT_FIXED)
 		return -EINVAL;
 
 	/*
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index 80a106b..bdbac44 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -1172,7 +1172,7 @@
 
 static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
-	if (fmt->code != MEDIA_BUS_FMT_FIXED)
+	if (fmt->code != V4L2_MBUS_FMT_FIXED)
 		return -EINVAL;
 	fmt->field = V4L2_FIELD_INTERLACED;
 	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c
index 5ef14b2..4aef84a 100644
--- a/drivers/media/i2c/saa717x.c
+++ b/drivers/media/i2c/saa717x.c
@@ -998,7 +998,7 @@
 
 	v4l2_dbg(1, debug, sd, "decoder set size\n");
 
-	if (fmt->code != MEDIA_BUS_FMT_FIXED)
+	if (fmt->code != V4L2_MBUS_FMT_FIXED)
 		return -EINVAL;
 
 	/* FIXME need better bounds checking here */
diff --git a/drivers/media/i2c/saa7191.c b/drivers/media/i2c/saa7191.c
new file mode 100644
index 0000000..8e96992
--- /dev/null
+++ b/drivers/media/i2c/saa7191.c
@@ -0,0 +1,649 @@
+/*
+ *  saa7191.c - Philips SAA7191 video decoder driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  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/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+
+#include "saa7191.h"
+
+#define SAA7191_MODULE_VERSION	"0.0.5"
+
+MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
+MODULE_VERSION(SAA7191_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+
+// #define SAA7191_DEBUG
+
+#ifdef SAA7191_DEBUG
+#define dprintk(x...) printk("SAA7191: " x);
+#else
+#define dprintk(x...)
+#endif
+
+#define SAA7191_SYNC_COUNT	30
+#define SAA7191_SYNC_DELAY	100	/* milliseconds */
+
+struct saa7191 {
+	struct v4l2_subdev sd;
+
+	/* the register values are stored here as the actual
+	 * I2C-registers are write-only */
+	u8 reg[25];
+
+	int input;
+	v4l2_std_id norm;
+};
+
+static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa7191, sd);
+}
+
+static const u8 initseq[] = {
+	0,	/* Subaddress */
+
+	0x50,	/* (0x50) SAA7191_REG_IDEL */
+
+	/* 50 Hz signal timing */
+	0x30,	/* (0x30) SAA7191_REG_HSYB */
+	0x00,	/* (0x00) SAA7191_REG_HSYS */
+	0xe8,	/* (0xe8) SAA7191_REG_HCLB */
+	0xb6,	/* (0xb6) SAA7191_REG_HCLS */
+	0xf4,	/* (0xf4) SAA7191_REG_HPHI */
+
+	/* control */
+	SAA7191_LUMA_APER_1,	/* (0x01) SAA7191_REG_LUMA - CVBS mode */
+	0x00,	/* (0x00) SAA7191_REG_HUEC */
+	0xf8,	/* (0xf8) SAA7191_REG_CKTQ */
+	0xf8,	/* (0xf8) SAA7191_REG_CKTS */
+	0x90,	/* (0x90) SAA7191_REG_PLSE */
+	0x90,	/* (0x90) SAA7191_REG_SESE */
+	0x00,	/* (0x00) SAA7191_REG_GAIN */
+	SAA7191_STDC_NFEN | SAA7191_STDC_HRMV,	/* (0x0c) SAA7191_REG_STDC
+						 * - not SECAM,
+						 * slow time constant */
+	SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS
+	| SAA7191_IOCK_OEDY,	/* (0x78) SAA7191_REG_IOCK
+				 * - chroma from CVBS, GPSW1 & 2 off */
+	SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS
+	| SAA7191_CTL3_YDEL0,	/* (0x99) SAA7191_REG_CTL3
+				 * - automatic field detection */
+	0x00,	/* (0x00) SAA7191_REG_CTL4 */
+	0x2c,	/* (0x2c) SAA7191_REG_CHCV - PAL nominal value */
+	0x00,	/* unused */
+	0x00,	/* unused */
+
+	/* 60 Hz signal timing */
+	0x34,	/* (0x34) SAA7191_REG_HS6B */
+	0x0a,	/* (0x0a) SAA7191_REG_HS6S */
+	0xf4,	/* (0xf4) SAA7191_REG_HC6B */
+	0xce,	/* (0xce) SAA7191_REG_HC6S */
+	0xf4,	/* (0xf4) SAA7191_REG_HP6I */
+};
+
+/* SAA7191 register handling */
+
+static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg)
+{
+	return to_saa7191(sd)->reg[reg];
+}
+
+static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	ret = i2c_master_recv(client, value, 1);
+	if (ret < 0) {
+		printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+
+static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	to_saa7191(sd)->reg[reg] = value;
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* the first byte of data must be the first subaddress number (register) */
+static int saa7191_write_block(struct v4l2_subdev *sd,
+			       u8 length, const u8 *data)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa7191 *decoder = to_saa7191(sd);
+	int i;
+	int ret;
+
+	for (i = 0; i < (length - 1); i++) {
+		decoder->reg[data[0] + i] = data[i + 1];
+	}
+
+	ret = i2c_master_send(client, data, length);
+	if (ret < 0) {
+		printk(KERN_ERR "SAA7191: saa7191_write_block(): "
+		       "write failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/* Helper functions */
+
+static int saa7191_s_routing(struct v4l2_subdev *sd,
+			     u32 input, u32 output, u32 config)
+{
+	struct saa7191 *decoder = to_saa7191(sd);
+	u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+	u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK);
+	int err;
+
+	switch (input) {
+	case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
+		iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
+			  | SAA7191_IOCK_GPSW2);
+		/* Chrominance trap active */
+		luma &= ~SAA7191_LUMA_BYPS;
+		break;
+	case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
+		iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
+		/* Chrominance trap bypassed */
+		luma |= SAA7191_LUMA_BYPS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma);
+	if (err)
+		return -EIO;
+	err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock);
+	if (err)
+		return -EIO;
+
+	decoder->input = input;
+
+	return 0;
+}
+
+static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct saa7191 *decoder = to_saa7191(sd);
+	u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
+	u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+	u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV);
+	int err;
+
+	if (norm & V4L2_STD_PAL) {
+		stdc &= ~SAA7191_STDC_SECS;
+		ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+		chcv = SAA7191_CHCV_PAL;
+	} else if (norm & V4L2_STD_NTSC) {
+		stdc &= ~SAA7191_STDC_SECS;
+		ctl3 &= ~SAA7191_CTL3_AUFD;
+		ctl3 |= SAA7191_CTL3_FSEL;
+		chcv = SAA7191_CHCV_NTSC;
+	} else if (norm & V4L2_STD_SECAM) {
+		stdc |= SAA7191_STDC_SECS;
+		ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+		chcv = SAA7191_CHCV_PAL;
+	} else {
+		return -EINVAL;
+	}
+
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+	if (err)
+		return -EIO;
+	err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
+	if (err)
+		return -EIO;
+	err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv);
+	if (err)
+		return -EIO;
+
+	decoder->norm = norm;
+
+	dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3,
+		stdc, chcv);
+	dprintk("norm: %llx\n", norm);
+
+	return 0;
+}
+
+static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status)
+{
+	int i = 0;
+
+	dprintk("Checking for signal...\n");
+
+	for (i = 0; i < SAA7191_SYNC_COUNT; i++) {
+		if (saa7191_read_status(sd, status))
+			return -EIO;
+
+		if (((*status) & SAA7191_STATUS_HLCK) == 0) {
+			dprintk("Signal found\n");
+			return 0;
+		}
+
+		msleep(SAA7191_SYNC_DELAY);
+	}
+
+	dprintk("No signal\n");
+
+	return -EBUSY;
+}
+
+static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm)
+{
+	struct saa7191 *decoder = to_saa7191(sd);
+	u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
+	u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+	u8 status;
+	v4l2_std_id old_norm = decoder->norm;
+	int err = 0;
+
+	dprintk("SAA7191 extended signal auto-detection...\n");
+
+	*norm &= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
+	stdc &= ~SAA7191_STDC_SECS;
+	ctl3 &= ~(SAA7191_CTL3_FSEL);
+
+	err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
+	if (err) {
+		err = -EIO;
+		goto out;
+	}
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+	if (err) {
+		err = -EIO;
+		goto out;
+	}
+
+	ctl3 |= SAA7191_CTL3_AUFD;
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+	if (err) {
+		err = -EIO;
+		goto out;
+	}
+
+	msleep(SAA7191_SYNC_DELAY);
+
+	err = saa7191_wait_for_signal(sd, &status);
+	if (err)
+		goto out;
+
+	if (status & SAA7191_STATUS_FIDT) {
+		/* 60Hz signal -> NTSC */
+		dprintk("60Hz signal: NTSC\n");
+		*norm &= V4L2_STD_NTSC;
+		return 0;
+	}
+
+	/* 50Hz signal */
+	dprintk("50Hz signal: Trying PAL...\n");
+
+	/* try PAL first */
+	err = saa7191_s_std(sd, V4L2_STD_PAL);
+	if (err)
+		goto out;
+
+	msleep(SAA7191_SYNC_DELAY);
+
+	err = saa7191_wait_for_signal(sd, &status);
+	if (err)
+		goto out;
+
+	/* not 50Hz ? */
+	if (status & SAA7191_STATUS_FIDT) {
+		dprintk("No 50Hz signal\n");
+		saa7191_s_std(sd, old_norm);
+		*norm = V4L2_STD_UNKNOWN;
+		return 0;
+	}
+
+	if (status & SAA7191_STATUS_CODE) {
+		dprintk("PAL\n");
+		*norm &= V4L2_STD_PAL;
+		return saa7191_s_std(sd, old_norm);
+	}
+
+	dprintk("No color detected with PAL - Trying SECAM...\n");
+
+	/* no color detected ? -> try SECAM */
+	err = saa7191_s_std(sd, V4L2_STD_SECAM);
+	if (err)
+		goto out;
+
+	msleep(SAA7191_SYNC_DELAY);
+
+	err = saa7191_wait_for_signal(sd, &status);
+	if (err)
+		goto out;
+
+	/* not 50Hz ? */
+	if (status & SAA7191_STATUS_FIDT) {
+		dprintk("No 50Hz signal\n");
+		*norm = V4L2_STD_UNKNOWN;
+		goto out;
+	}
+
+	if (status & SAA7191_STATUS_CODE) {
+		/* Color detected -> SECAM */
+		dprintk("SECAM\n");
+		*norm &= V4L2_STD_SECAM;
+		return saa7191_s_std(sd, old_norm);
+	}
+
+	dprintk("No color detected with SECAM - Going back to PAL.\n");
+	*norm = V4L2_STD_UNKNOWN;
+
+out:
+	return saa7191_s_std(sd, old_norm);
+}
+
+static int saa7191_autodetect_norm(struct v4l2_subdev *sd)
+{
+	u8 status;
+
+	dprintk("SAA7191 signal auto-detection...\n");
+
+	dprintk("Reading status...\n");
+
+	if (saa7191_read_status(sd, &status))
+		return -EIO;
+
+	dprintk("Checking for signal...\n");
+
+	/* no signal ? */
+	if (status & SAA7191_STATUS_HLCK) {
+		dprintk("No signal\n");
+		return -EBUSY;
+	}
+
+	dprintk("Signal found\n");
+
+	if (status & SAA7191_STATUS_FIDT) {
+		/* 60hz signal -> NTSC */
+		dprintk("NTSC\n");
+		return saa7191_s_std(sd, V4L2_STD_NTSC);
+	} else {
+		/* 50hz signal -> PAL */
+		dprintk("PAL\n");
+		return saa7191_s_std(sd, V4L2_STD_PAL);
+	}
+}
+
+static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	u8 reg;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case SAA7191_CONTROL_BANDPASS:
+	case SAA7191_CONTROL_BANDPASS_WEIGHT:
+	case SAA7191_CONTROL_CORING:
+		reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+		switch (ctrl->id) {
+		case SAA7191_CONTROL_BANDPASS:
+			ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK)
+				>> SAA7191_LUMA_BPSS_SHIFT;
+			break;
+		case SAA7191_CONTROL_BANDPASS_WEIGHT:
+			ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK)
+				>> SAA7191_LUMA_APER_SHIFT;
+			break;
+		case SAA7191_CONTROL_CORING:
+			ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK)
+				>> SAA7191_LUMA_CORI_SHIFT;
+			break;
+		}
+		break;
+	case SAA7191_CONTROL_FORCE_COLOUR:
+	case SAA7191_CONTROL_CHROMA_GAIN:
+		reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+		if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR)
+			ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0;
+		else
+			ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK)
+				>> SAA7191_GAIN_LFIS_SHIFT;
+		break;
+	case V4L2_CID_HUE:
+		reg = saa7191_read_reg(sd, SAA7191_REG_HUEC);
+		if (reg < 0x80)
+			reg += 0x80;
+		else
+			reg -= 0x80;
+		ctrl->value = (s32)reg;
+		break;
+	case SAA7191_CONTROL_VTRC:
+		reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
+		ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0;
+		break;
+	case SAA7191_CONTROL_LUMA_DELAY:
+		reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+		ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK)
+			>> SAA7191_CTL3_YDEL_SHIFT;
+		if (ctrl->value >= 4)
+			ctrl->value -= 8;
+		break;
+	case SAA7191_CONTROL_VNR:
+		reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
+		ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK)
+			>> SAA7191_CTL4_VNOI_SHIFT;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	u8 reg;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case SAA7191_CONTROL_BANDPASS:
+	case SAA7191_CONTROL_BANDPASS_WEIGHT:
+	case SAA7191_CONTROL_CORING:
+		reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+		switch (ctrl->id) {
+		case SAA7191_CONTROL_BANDPASS:
+			reg &= ~SAA7191_LUMA_BPSS_MASK;
+			reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT)
+				& SAA7191_LUMA_BPSS_MASK;
+			break;
+		case SAA7191_CONTROL_BANDPASS_WEIGHT:
+			reg &= ~SAA7191_LUMA_APER_MASK;
+			reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT)
+				& SAA7191_LUMA_APER_MASK;
+			break;
+		case SAA7191_CONTROL_CORING:
+			reg &= ~SAA7191_LUMA_CORI_MASK;
+			reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT)
+				& SAA7191_LUMA_CORI_MASK;
+			break;
+		}
+		ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg);
+		break;
+	case SAA7191_CONTROL_FORCE_COLOUR:
+	case SAA7191_CONTROL_CHROMA_GAIN:
+		reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+		if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) {
+			if (ctrl->value)
+				reg |= SAA7191_GAIN_COLO;
+			else
+				reg &= ~SAA7191_GAIN_COLO;
+		} else {
+			reg &= ~SAA7191_GAIN_LFIS_MASK;
+			reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT)
+				& SAA7191_GAIN_LFIS_MASK;
+		}
+		ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg);
+		break;
+	case V4L2_CID_HUE:
+		reg = ctrl->value & 0xff;
+		if (reg < 0x80)
+			reg += 0x80;
+		else
+			reg -= 0x80;
+		ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg);
+		break;
+	case SAA7191_CONTROL_VTRC:
+		reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
+		if (ctrl->value)
+			reg |= SAA7191_STDC_VTRC;
+		else
+			reg &= ~SAA7191_STDC_VTRC;
+		ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg);
+		break;
+	case SAA7191_CONTROL_LUMA_DELAY: {
+		s32 value = ctrl->value;
+		if (value < 0)
+			value += 8;
+		reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+		reg &= ~SAA7191_CTL3_YDEL_MASK;
+		reg |= (value << SAA7191_CTL3_YDEL_SHIFT)
+			& SAA7191_CTL3_YDEL_MASK;
+		ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg);
+		break;
+	}
+	case SAA7191_CONTROL_VNR:
+		reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
+		reg &= ~SAA7191_CTL4_VNOI_MASK;
+		reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT)
+			& SAA7191_CTL4_VNOI_MASK;
+		ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/* I2C-interface */
+
+static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	u8 status_reg;
+	int res = V4L2_IN_ST_NO_SIGNAL;
+
+	if (saa7191_read_status(sd, &status_reg))
+		return -EIO;
+	if ((status_reg & SAA7191_STATUS_HLCK) == 0)
+		res = 0;
+	if (!(status_reg & SAA7191_STATUS_CODE))
+		res |= V4L2_IN_ST_NO_COLOR;
+	*status = res;
+	return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops saa7191_core_ops = {
+	.g_ctrl = saa7191_g_ctrl,
+	.s_ctrl = saa7191_s_ctrl,
+};
+
+static const struct v4l2_subdev_video_ops saa7191_video_ops = {
+	.s_std = saa7191_s_std,
+	.s_routing = saa7191_s_routing,
+	.querystd = saa7191_querystd,
+	.g_input_status = saa7191_g_input_status,
+};
+
+static const struct v4l2_subdev_ops saa7191_ops = {
+	.core = &saa7191_core_ops,
+	.video = &saa7191_video_ops,
+};
+
+static int saa7191_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	int err = 0;
+	struct saa7191 *decoder;
+	struct v4l2_subdev *sd;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
+	if (!decoder)
+		return -ENOMEM;
+
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa7191_ops);
+
+	err = saa7191_write_block(sd, sizeof(initseq), initseq);
+	if (err) {
+		printk(KERN_ERR "SAA7191 initialization failed\n");
+		return err;
+	}
+
+	printk(KERN_INFO "SAA7191 initialized\n");
+
+	decoder->input = SAA7191_INPUT_COMPOSITE;
+	decoder->norm = V4L2_STD_PAL;
+
+	err = saa7191_autodetect_norm(sd);
+	if (err && (err != -EBUSY))
+		printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");
+
+	return 0;
+}
+
+static int saa7191_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	return 0;
+}
+
+static const struct i2c_device_id saa7191_id[] = {
+	{ "saa7191", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa7191_id);
+
+static struct i2c_driver saa7191_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa7191",
+	},
+	.probe		= saa7191_probe,
+	.remove		= saa7191_remove,
+	.id_table	= saa7191_id,
+};
+
+module_i2c_driver(saa7191_driver);
diff --git a/drivers/media/i2c/saa7191.h b/drivers/media/i2c/saa7191.h
new file mode 100644
index 0000000..803c74d
--- /dev/null
+++ b/drivers/media/i2c/saa7191.h
@@ -0,0 +1,245 @@
+/*
+ *  saa7191.h - Philips SAA7191 video decoder driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  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 _SAA7191_H_
+#define _SAA7191_H_
+
+/* Philips SAA7191 DMSD I2C bus address */
+#define SAA7191_ADDR		0x8a
+
+/* Register subaddresses. */
+#define SAA7191_REG_IDEL	0x00
+#define SAA7191_REG_HSYB	0x01
+#define SAA7191_REG_HSYS	0x02
+#define SAA7191_REG_HCLB	0x03
+#define SAA7191_REG_HCLS	0x04
+#define SAA7191_REG_HPHI	0x05
+#define SAA7191_REG_LUMA	0x06
+#define SAA7191_REG_HUEC	0x07
+#define SAA7191_REG_CKTQ	0x08 /* bits 3-7 */
+#define SAA7191_REG_CKTS	0x09 /* bits 3-7 */
+#define SAA7191_REG_PLSE	0x0a
+#define SAA7191_REG_SESE	0x0b
+#define SAA7191_REG_GAIN	0x0c
+#define SAA7191_REG_STDC	0x0d
+#define SAA7191_REG_IOCK	0x0e
+#define SAA7191_REG_CTL3	0x0f
+#define SAA7191_REG_CTL4	0x10
+#define SAA7191_REG_CHCV	0x11
+#define SAA7191_REG_HS6B	0x14
+#define SAA7191_REG_HS6S	0x15
+#define SAA7191_REG_HC6B	0x16
+#define SAA7191_REG_HC6S	0x17
+#define SAA7191_REG_HP6I	0x18
+#define SAA7191_REG_STATUS	0xff	/* not really a subaddress */
+
+/* Status Register definitions */
+#define SAA7191_STATUS_CODE	0x01	/* color detected flag */
+#define SAA7191_STATUS_FIDT	0x20	/* signal type 50/60 Hz */
+#define SAA7191_STATUS_HLCK	0x40	/* PLL unlocked(1)/locked(0) */
+#define SAA7191_STATUS_STTC	0x80	/* tv/vtr time constant */
+
+/* Luminance Control Register definitions */
+/* input mode select bit:
+ * 0=CVBS (chrominance trap active), 1=S-Video (trap bypassed) */
+#define SAA7191_LUMA_BYPS	0x80
+/* pre-filter (only when chrominance trap is active) */
+#define SAA7191_LUMA_PREF	0x40
+/* aperture bandpass to select different characteristics with maximums
+ * (bits 4-5) */
+#define SAA7191_LUMA_BPSS_MASK	0x30
+#define SAA7191_LUMA_BPSS_SHIFT	4
+#define SAA7191_LUMA_BPSS_3	0x30
+#define SAA7191_LUMA_BPSS_2	0x20
+#define SAA7191_LUMA_BPSS_1	0x10
+#define SAA7191_LUMA_BPSS_0	0x00
+/* coring range for high frequency components according to 8-bit luminance
+ * (bits 2-3)
+ * 0=coring off, n= (+-)n LSB */
+#define SAA7191_LUMA_CORI_MASK	0x0c
+#define SAA7191_LUMA_CORI_SHIFT	2
+#define SAA7191_LUMA_CORI_3	0x0c
+#define SAA7191_LUMA_CORI_2	0x08
+#define SAA7191_LUMA_CORI_1	0x04
+#define SAA7191_LUMA_CORI_0	0x00
+/* aperture bandpass filter weights high frequency components of luminance
+ * signal (bits 0-1)
+ * 0=factor 0, 1=0.25, 2=0.5, 3=1 */
+#define SAA7191_LUMA_APER_MASK	0x03
+#define SAA7191_LUMA_APER_SHIFT	0
+#define SAA7191_LUMA_APER_3	0x03
+#define SAA7191_LUMA_APER_2	0x02
+#define SAA7191_LUMA_APER_1	0x01
+#define SAA7191_LUMA_APER_0	0x00
+
+/* Chrominance Gain Control Settings Register definitions */
+/* colour on: 0=automatic colour-killer enabled, 1=forced colour on */
+#define SAA7191_GAIN_COLO	0x80
+/* chrominance gain control (AGC filter)
+ * 0=loop filter time constant slow, 1=medium, 2=fast, 3=actual gain */
+#define SAA7191_GAIN_LFIS_MASK	0x60
+#define SAA7191_GAIN_LFIS_SHIFT	5
+#define SAA7191_GAIN_LFIS_3	0x60
+#define SAA7191_GAIN_LFIS_2	0x40
+#define SAA7191_GAIN_LFIS_1	0x20
+#define SAA7191_GAIN_LFIS_0	0x00
+
+/* Standard/Mode Control Register definitions */
+/* tv/vtr mode bit: 0=TV mode (slow time constant),
+ * 1=VTR mode (fast time constant) */
+#define SAA7191_STDC_VTRC	0x80
+/* SAA7191B-specific functions enable (RTCO, ODD and GPSW0 outputs)
+ * 0=outputs set to high-impedance (circuit equals SAA7191), 1=enabled */
+#define SAA7191_STDC_NFEN	0x08
+/* HREF generation: 0=like SAA7191, 1=HREF is 8xLLC2 clocks earlier */
+#define SAA7191_STDC_HRMV	0x04
+/* general purpose switch 0
+ * (not used with VINO afaik) */
+#define SAA7191_STDC_GPSW0	0x02
+/* SECAM mode bit: 0=other standards, 1=SECAM */
+#define SAA7191_STDC_SECS	0x01
+
+/* I/O and Clock Control Register definitions */
+/* horizontal clock PLL: 0=PLL closed,
+ * 1=PLL circuit open and horizontal freq fixed */
+#define SAA7191_IOCK_HPLL	0x80
+/* colour-difference output enable (outputs UV0-UV7) */
+#define SAA7191_IOCK_OEDC	0x40
+/* H-sync output enable */
+#define SAA7191_IOCK_OEHS	0x20
+/* V-sync output enable */
+#define SAA7191_IOCK_OEVS	0x10
+/* luminance output enable (outputs Y0-Y7) */
+#define SAA7191_IOCK_OEDY	0x08
+/* S-VHS bit (chrominance from CVBS or from chrominance input):
+ * 0=controlled by BYPS-bit, 1=from chrominance input */
+#define SAA7191_IOCK_CHRS	0x04
+/* general purpose switch 2
+ * VINO-specific: 0=used with CVBS, 1=used with S-Video */
+#define SAA7191_IOCK_GPSW2	0x02
+/* general purpose switch 1 */
+/* VINO-specific: 0=always, 1=not used!*/
+#define SAA7191_IOCK_GPSW1	0x01
+
+/* Miscellaneous Control #1 Register definitions */
+/* automatic field detection (50/60Hz standard) */
+#define SAA7191_CTL3_AUFD	0x80
+/* field select: (if AUFD=0)
+ * 0=50Hz (625 lines), 1=60Hz (525 lines) */
+#define SAA7191_CTL3_FSEL	0x40
+/* SECAM cross-colour reduction enable */
+#define SAA7191_CTL3_SXCR	0x20
+/* sync and clamping pulse enable (HCL and HSY outputs) */
+#define SAA7191_CTL3_SCEN	0x10
+/* output format: 0=4:1:1, 1=4:2:2 (4:2:2 for VINO) */
+#define SAA7191_CTL3_OFTS	0x08
+/* luminance delay compensation
+ * 0=0*2/LLC,  1=+1*2/LLC, 2=+2*2/LLC, 3=+3*2/LLC,
+ * 4=-4*2/LLC, 5=-3*2/LLC, 6=-2*2/LLC, 7=-1*2/LLC
+ * step size = 2/LLC = 67.8ns for 50Hz, 81.5ns for 60Hz */
+#define SAA7191_CTL3_YDEL_MASK	0x07
+#define SAA7191_CTL3_YDEL_SHIFT	0
+#define SAA7191_CTL3_YDEL2	0x04
+#define SAA7191_CTL3_YDEL1	0x02
+#define SAA7191_CTL3_YDEL0	0x01
+
+/* Miscellaneous Control #2 Register definitions */
+/* select HREF position
+ * 0=normal, HREF is matched to YUV output port,
+ * 1=HREF is matched to CVBS input port */
+#define SAA7191_CTL4_HRFS	0x04
+/* vertical noise reduction
+ * 0=normal, 1=searching window, 2=auto-deflection, 3=reduction bypassed */
+#define SAA7191_CTL4_VNOI_MASK	0x03
+#define SAA7191_CTL4_VNOI_SHIFT	0
+#define SAA7191_CTL4_VNOI_3	0x03
+#define SAA7191_CTL4_VNOI_2	0x02
+#define SAA7191_CTL4_VNOI_1	0x01
+#define SAA7191_CTL4_VNOI_0	0x00
+
+/* Chrominance Gain Control Register definitions
+ * - for QAM-modulated input signals, effects output amplitude
+ * (SECAM gain fixed)
+ * (nominal values for UV CCIR level) */
+#define SAA7191_CHCV_NTSC	0x2c
+#define SAA7191_CHCV_PAL	0x59
+
+/* Driver interface definitions */
+#define SAA7191_INPUT_COMPOSITE	0
+#define SAA7191_INPUT_SVIDEO	1
+
+#define SAA7191_NORM_PAL	1
+#define SAA7191_NORM_NTSC	2
+#define SAA7191_NORM_SECAM	3
+
+struct saa7191_status {
+	/* 0=no signal, 1=signal detected */
+	int signal;
+	/* 0=50hz (pal) signal, 1=60hz (ntsc) signal */
+	int signal_60hz;
+	/* 0=no color detected, 1=color detected */
+	int color;
+
+	/* current SAA7191_INPUT_ */
+	int input;
+	/* current SAA7191_NORM_ */
+	int norm;
+};
+
+#define SAA7191_BANDPASS_MIN		0x00
+#define SAA7191_BANDPASS_MAX		0x03
+#define SAA7191_BANDPASS_DEFAULT	0x00
+
+#define SAA7191_BANDPASS_WEIGHT_MIN	0x00
+#define SAA7191_BANDPASS_WEIGHT_MAX	0x03
+#define SAA7191_BANDPASS_WEIGHT_DEFAULT	0x01
+
+#define SAA7191_CORING_MIN		0x00
+#define SAA7191_CORING_MAX		0x03
+#define SAA7191_CORING_DEFAULT		0x00
+
+#define SAA7191_HUE_MIN			0x00
+#define SAA7191_HUE_MAX			0xff
+#define SAA7191_HUE_DEFAULT		0x80
+
+#define SAA7191_VTRC_MIN		0x00
+#define SAA7191_VTRC_MAX		0x01
+#define SAA7191_VTRC_DEFAULT		0x00
+
+#define SAA7191_FORCE_COLOUR_MIN	0x00
+#define SAA7191_FORCE_COLOUR_MAX	0x01
+#define SAA7191_FORCE_COLOUR_DEFAULT	0x00
+
+#define SAA7191_CHROMA_GAIN_MIN		0x00
+#define SAA7191_CHROMA_GAIN_MAX		0x03
+#define SAA7191_CHROMA_GAIN_DEFAULT	0x00
+
+#define SAA7191_LUMA_DELAY_MIN		-0x04
+#define SAA7191_LUMA_DELAY_MAX		0x03
+#define SAA7191_LUMA_DELAY_DEFAULT	0x01
+
+#define SAA7191_VNR_MIN			0x00
+#define SAA7191_VNR_MAX			0x03
+#define SAA7191_VNR_DEFAULT		0x00
+
+#define SAA7191_CONTROL_BANDPASS	(V4L2_CID_PRIVATE_BASE + 0)
+#define SAA7191_CONTROL_BANDPASS_WEIGHT	(V4L2_CID_PRIVATE_BASE + 1)
+#define SAA7191_CONTROL_CORING		(V4L2_CID_PRIVATE_BASE + 2)
+#define SAA7191_CONTROL_FORCE_COLOUR	(V4L2_CID_PRIVATE_BASE + 3)
+#define SAA7191_CONTROL_CHROMA_GAIN	(V4L2_CID_PRIVATE_BASE + 4)
+#define SAA7191_CONTROL_VTRC		(V4L2_CID_PRIVATE_BASE + 5)
+#define SAA7191_CONTROL_LUMA_DELAY	(V4L2_CID_PRIVATE_BASE + 6)
+#define SAA7191_CONTROL_VNR		(V4L2_CID_PRIVATE_BASE + 7)
+
+#define	DECODER_SAA7191_GET_STATUS	_IOR('d', 195, struct saa7191_status)
+#define	DECODER_SAA7191_SET_NORM	_IOW('d', 196, int)
+
+#endif
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index e40d902..2335529 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -65,36 +65,264 @@
 
 static void print_pll(struct device *dev, struct smiapp_pll *pll)
 {
-	dev_dbg(dev, "pre_pll_clk_div\t%u\n",  pll->pre_pll_clk_div);
-	dev_dbg(dev, "pll_multiplier \t%u\n",  pll->pll_multiplier);
-	if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
-		dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op.sys_clk_div);
-		dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op.pix_clk_div);
+	dev_dbg(dev, "pre_pll_clk_div\t%d\n",  pll->pre_pll_clk_div);
+	dev_dbg(dev, "pll_multiplier \t%d\n",  pll->pll_multiplier);
+	if (pll->flags != SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+		dev_dbg(dev, "op_sys_clk_div \t%d\n", pll->op_sys_clk_div);
+		dev_dbg(dev, "op_pix_clk_div \t%d\n", pll->op_pix_clk_div);
 	}
-	dev_dbg(dev, "vt_sys_clk_div \t%u\n",  pll->vt.sys_clk_div);
-	dev_dbg(dev, "vt_pix_clk_div \t%u\n",  pll->vt.pix_clk_div);
+	dev_dbg(dev, "vt_sys_clk_div \t%d\n",  pll->vt_sys_clk_div);
+	dev_dbg(dev, "vt_pix_clk_div \t%d\n",  pll->vt_pix_clk_div);
 
-	dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz);
-	dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->pll_ip_clk_freq_hz);
-	dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->pll_op_clk_freq_hz);
-	if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
-		dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n",
-			pll->op.sys_clk_freq_hz);
-		dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n",
-			pll->op.pix_clk_freq_hz);
+	dev_dbg(dev, "ext_clk_freq_hz \t%d\n", pll->ext_clk_freq_hz);
+	dev_dbg(dev, "pll_ip_clk_freq_hz \t%d\n", pll->pll_ip_clk_freq_hz);
+	dev_dbg(dev, "pll_op_clk_freq_hz \t%d\n", pll->pll_op_clk_freq_hz);
+	if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+		dev_dbg(dev, "op_sys_clk_freq_hz \t%d\n",
+			pll->op_sys_clk_freq_hz);
+		dev_dbg(dev, "op_pix_clk_freq_hz \t%d\n",
+			pll->op_pix_clk_freq_hz);
 	}
-	dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt.sys_clk_freq_hz);
-	dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt.pix_clk_freq_hz);
+	dev_dbg(dev, "vt_sys_clk_freq_hz \t%d\n", pll->vt_sys_clk_freq_hz);
+	dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
 }
 
-static int check_all_bounds(struct device *dev,
-			    const struct smiapp_pll_limits *limits,
-			    const struct smiapp_pll_branch_limits *op_limits,
-			    struct smiapp_pll *pll,
-			    struct smiapp_pll_branch *op_pll)
+/*
+ * Heuristically guess the PLL tree for a given common multiplier and
+ * divisor. Begin with the operational timing and continue to video
+ * timing once operational timing has been verified.
+ *
+ * @mul is the PLL multiplier and @div is the common divisor
+ * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL
+ * multiplier will be a multiple of @mul.
+ *
+ * @return Zero on success, error code on error.
+ */
+static int __smiapp_pll_calculate(struct device *dev,
+				  const struct smiapp_pll_limits *limits,
+				  struct smiapp_pll *pll, uint32_t mul,
+				  uint32_t div, uint32_t lane_op_clock_ratio)
 {
+	uint32_t sys_div;
+	uint32_t best_pix_div = INT_MAX >> 1;
+	uint32_t vt_op_binning_div;
+	/*
+	 * Higher multipliers (and divisors) are often required than
+	 * necessitated by the external clock and the output clocks.
+	 * There are limits for all values in the clock tree. These
+	 * are the minimum and maximum multiplier for mul.
+	 */
+	uint32_t more_mul_min, more_mul_max;
+	uint32_t more_mul_factor;
+	uint32_t min_vt_div, max_vt_div, vt_div;
+	uint32_t min_sys_div, max_sys_div;
+	unsigned int i;
 	int rval;
 
+	/*
+	 * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
+	 * too high.
+	 */
+	dev_dbg(dev, "pre_pll_clk_div %d\n", pll->pre_pll_clk_div);
+
+	/* Don't go above max pll multiplier. */
+	more_mul_max = limits->max_pll_multiplier / mul;
+	dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %d\n",
+		more_mul_max);
+	/* Don't go above max pll op frequency. */
+	more_mul_max =
+		min_t(uint32_t,
+		      more_mul_max,
+		      limits->max_pll_op_freq_hz
+		      / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
+	dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %d\n",
+		more_mul_max);
+	/* Don't go above the division capability of op sys clock divider. */
+	more_mul_max = min(more_mul_max,
+			   limits->op.max_sys_clk_div * pll->pre_pll_clk_div
+			   / div);
+	dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n",
+		more_mul_max);
+	/* Ensure we won't go above min_pll_multiplier. */
+	more_mul_max = min(more_mul_max,
+			   DIV_ROUND_UP(limits->max_pll_multiplier, mul));
+	dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %d\n",
+		more_mul_max);
+
+	/* Ensure we won't go below min_pll_op_freq_hz. */
+	more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz,
+				    pll->ext_clk_freq_hz / pll->pre_pll_clk_div
+				    * mul);
+	dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %d\n",
+		more_mul_min);
+	/* Ensure we won't go below min_pll_multiplier. */
+	more_mul_min = max(more_mul_min,
+			   DIV_ROUND_UP(limits->min_pll_multiplier, mul));
+	dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %d\n",
+		more_mul_min);
+
+	if (more_mul_min > more_mul_max) {
+		dev_dbg(dev,
+			"unable to compute more_mul_min and more_mul_max\n");
+		return -EINVAL;
+	}
+
+	more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
+	dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor);
+	more_mul_factor = lcm(more_mul_factor, limits->op.min_sys_clk_div);
+	dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
+		more_mul_factor);
+	i = roundup(more_mul_min, more_mul_factor);
+	if (!is_one_or_even(i))
+		i <<= 1;
+
+	dev_dbg(dev, "final more_mul: %d\n", i);
+	if (i > more_mul_max) {
+		dev_dbg(dev, "final more_mul is bad, max %d\n", more_mul_max);
+		return -EINVAL;
+	}
+
+	pll->pll_multiplier = mul * i;
+	pll->op_sys_clk_div = div * i / pll->pre_pll_clk_div;
+	dev_dbg(dev, "op_sys_clk_div: %d\n", pll->op_sys_clk_div);
+
+	pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz
+		/ pll->pre_pll_clk_div;
+
+	pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz
+		* pll->pll_multiplier;
+
+	/* Derive pll_op_clk_freq_hz. */
+	pll->op_sys_clk_freq_hz =
+		pll->pll_op_clk_freq_hz / pll->op_sys_clk_div;
+
+	pll->op_pix_clk_div = pll->bits_per_pixel;
+	dev_dbg(dev, "op_pix_clk_div: %d\n", pll->op_pix_clk_div);
+
+	pll->op_pix_clk_freq_hz =
+		pll->op_sys_clk_freq_hz / pll->op_pix_clk_div;
+
+	/*
+	 * Some sensors perform analogue binning and some do this
+	 * digitally. The ones doing this digitally can be roughly be
+	 * found out using this formula. The ones doing this digitally
+	 * should run at higher clock rate, so smaller divisor is used
+	 * on video timing side.
+	 */
+	if (limits->min_line_length_pck_bin > limits->min_line_length_pck
+	    / pll->binning_horizontal)
+		vt_op_binning_div = pll->binning_horizontal;
+	else
+		vt_op_binning_div = 1;
+	dev_dbg(dev, "vt_op_binning_div: %d\n", vt_op_binning_div);
+
+	/*
+	 * Profile 2 supports vt_pix_clk_div E [4, 10]
+	 *
+	 * Horizontal binning can be used as a base for difference in
+	 * divisors. One must make sure that horizontal blanking is
+	 * enough to accommodate the CSI-2 sync codes.
+	 *
+	 * Take scaling factor into account as well.
+	 *
+	 * Find absolute limits for the factor of vt divider.
+	 */
+	dev_dbg(dev, "scale_m: %d\n", pll->scale_m);
+	min_vt_div = DIV_ROUND_UP(pll->op_pix_clk_div * pll->op_sys_clk_div
+				  * pll->scale_n,
+				  lane_op_clock_ratio * vt_op_binning_div
+				  * pll->scale_m);
+
+	/* Find smallest and biggest allowed vt divisor. */
+	dev_dbg(dev, "min_vt_div: %d\n", min_vt_div);
+	min_vt_div = max(min_vt_div,
+			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+				      limits->vt.max_pix_clk_freq_hz));
+	dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n",
+		min_vt_div);
+	min_vt_div = max_t(uint32_t, min_vt_div,
+			   limits->vt.min_pix_clk_div
+			   * limits->vt.min_sys_clk_div);
+	dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div);
+
+	max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
+	dev_dbg(dev, "max_vt_div: %d\n", max_vt_div);
+	max_vt_div = min(max_vt_div,
+			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+				      limits->vt.min_pix_clk_freq_hz));
+	dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n",
+		max_vt_div);
+
+	/*
+	 * Find limitsits for sys_clk_div. Not all values are possible
+	 * with all values of pix_clk_div.
+	 */
+	min_sys_div = limits->vt.min_sys_clk_div;
+	dev_dbg(dev, "min_sys_div: %d\n", min_sys_div);
+	min_sys_div = max(min_sys_div,
+			  DIV_ROUND_UP(min_vt_div,
+				       limits->vt.max_pix_clk_div));
+	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div);
+	min_sys_div = max(min_sys_div,
+			  pll->pll_op_clk_freq_hz
+			  / limits->vt.max_sys_clk_freq_hz);
+	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div);
+	min_sys_div = clk_div_even_up(min_sys_div);
+	dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div);
+
+	max_sys_div = limits->vt.max_sys_clk_div;
+	dev_dbg(dev, "max_sys_div: %d\n", max_sys_div);
+	max_sys_div = min(max_sys_div,
+			  DIV_ROUND_UP(max_vt_div,
+				       limits->vt.min_pix_clk_div));
+	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div);
+	max_sys_div = min(max_sys_div,
+			  DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+				       limits->vt.min_pix_clk_freq_hz));
+	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div);
+
+	/*
+	 * Find pix_div such that a legal pix_div * sys_div results
+	 * into a value which is not smaller than div, the desired
+	 * divisor.
+	 */
+	for (vt_div = min_vt_div; vt_div <= max_vt_div;
+	     vt_div += 2 - (vt_div & 1)) {
+		for (sys_div = min_sys_div;
+		     sys_div <= max_sys_div;
+		     sys_div += 2 - (sys_div & 1)) {
+			uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div);
+
+			if (pix_div < limits->vt.min_pix_clk_div
+			    || pix_div > limits->vt.max_pix_clk_div) {
+				dev_dbg(dev,
+					"pix_div %d too small or too big (%d--%d)\n",
+					pix_div,
+					limits->vt.min_pix_clk_div,
+					limits->vt.max_pix_clk_div);
+				continue;
+			}
+
+			/* Check if this one is better. */
+			if (pix_div * sys_div
+			    <= roundup(min_vt_div, best_pix_div))
+				best_pix_div = pix_div;
+		}
+		if (best_pix_div < INT_MAX >> 1)
+			break;
+	}
+
+	pll->vt_sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div);
+	pll->vt_pix_clk_div = best_pix_div;
+
+	pll->vt_sys_clk_freq_hz =
+		pll->pll_op_clk_freq_hz / pll->vt_sys_clk_div;
+	pll->vt_pix_clk_freq_hz =
+		pll->vt_sys_clk_freq_hz / pll->vt_pix_clk_div;
+
+	pll->pixel_rate_csi =
+		pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
+
 	rval = bounds_check(dev, pll->pll_ip_clk_freq_hz,
 			    limits->min_pll_ip_freq_hz,
 			    limits->max_pll_ip_freq_hz,
@@ -111,38 +339,35 @@
 			"pll_op_clk_freq_hz");
 	if (!rval)
 		rval = bounds_check(
-			dev, op_pll->sys_clk_div,
-			op_limits->min_sys_clk_div, op_limits->max_sys_clk_div,
+			dev, pll->op_sys_clk_div,
+			limits->op.min_sys_clk_div, limits->op.max_sys_clk_div,
 			"op_sys_clk_div");
 	if (!rval)
 		rval = bounds_check(
-			dev, op_pll->sys_clk_freq_hz,
-			op_limits->min_sys_clk_freq_hz,
-			op_limits->max_sys_clk_freq_hz,
+			dev, pll->op_pix_clk_div,
+			limits->op.min_pix_clk_div, limits->op.max_pix_clk_div,
+			"op_pix_clk_div");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->op_sys_clk_freq_hz,
+			limits->op.min_sys_clk_freq_hz,
+			limits->op.max_sys_clk_freq_hz,
 			"op_sys_clk_freq_hz");
 	if (!rval)
 		rval = bounds_check(
-			dev, op_pll->pix_clk_freq_hz,
-			op_limits->min_pix_clk_freq_hz,
-			op_limits->max_pix_clk_freq_hz,
+			dev, pll->op_pix_clk_freq_hz,
+			limits->op.min_pix_clk_freq_hz,
+			limits->op.max_pix_clk_freq_hz,
 			"op_pix_clk_freq_hz");
-
-	/*
-	 * If there are no OP clocks, the VT clocks are contained in
-	 * the OP clock struct.
-	 */
-	if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)
-		return rval;
-
 	if (!rval)
 		rval = bounds_check(
-			dev, pll->vt.sys_clk_freq_hz,
+			dev, pll->vt_sys_clk_freq_hz,
 			limits->vt.min_sys_clk_freq_hz,
 			limits->vt.max_sys_clk_freq_hz,
 			"vt_sys_clk_freq_hz");
 	if (!rval)
 		rval = bounds_check(
-			dev, pll->vt.pix_clk_freq_hz,
+			dev, pll->vt_pix_clk_freq_hz,
 			limits->vt.min_pix_clk_freq_hz,
 			limits->vt.max_pix_clk_freq_hz,
 			"vt_pix_clk_freq_hz");
@@ -150,258 +375,10 @@
 	return rval;
 }
 
-/*
- * Heuristically guess the PLL tree for a given common multiplier and
- * divisor. Begin with the operational timing and continue to video
- * timing once operational timing has been verified.
- *
- * @mul is the PLL multiplier and @div is the common divisor
- * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL
- * multiplier will be a multiple of @mul.
- *
- * @return Zero on success, error code on error.
- */
-static int __smiapp_pll_calculate(
-	struct device *dev, const struct smiapp_pll_limits *limits,
-	const struct smiapp_pll_branch_limits *op_limits,
-	struct smiapp_pll *pll, struct smiapp_pll_branch *op_pll, uint32_t mul,
-	uint32_t div, uint32_t lane_op_clock_ratio)
-{
-	uint32_t sys_div;
-	uint32_t best_pix_div = INT_MAX >> 1;
-	uint32_t vt_op_binning_div;
-	/*
-	 * Higher multipliers (and divisors) are often required than
-	 * necessitated by the external clock and the output clocks.
-	 * There are limits for all values in the clock tree. These
-	 * are the minimum and maximum multiplier for mul.
-	 */
-	uint32_t more_mul_min, more_mul_max;
-	uint32_t more_mul_factor;
-	uint32_t min_vt_div, max_vt_div, vt_div;
-	uint32_t min_sys_div, max_sys_div;
-	unsigned int i;
-
-	/*
-	 * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
-	 * too high.
-	 */
-	dev_dbg(dev, "pre_pll_clk_div %u\n", pll->pre_pll_clk_div);
-
-	/* Don't go above max pll multiplier. */
-	more_mul_max = limits->max_pll_multiplier / mul;
-	dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %u\n",
-		more_mul_max);
-	/* Don't go above max pll op frequency. */
-	more_mul_max =
-		min_t(uint32_t,
-		      more_mul_max,
-		      limits->max_pll_op_freq_hz
-		      / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
-	dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %u\n",
-		more_mul_max);
-	/* Don't go above the division capability of op sys clock divider. */
-	more_mul_max = min(more_mul_max,
-			   op_limits->max_sys_clk_div * pll->pre_pll_clk_div
-			   / div);
-	dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n",
-		more_mul_max);
-	/* Ensure we won't go above min_pll_multiplier. */
-	more_mul_max = min(more_mul_max,
-			   DIV_ROUND_UP(limits->max_pll_multiplier, mul));
-	dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n",
-		more_mul_max);
-
-	/* Ensure we won't go below min_pll_op_freq_hz. */
-	more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz,
-				    pll->ext_clk_freq_hz / pll->pre_pll_clk_div
-				    * mul);
-	dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %u\n",
-		more_mul_min);
-	/* Ensure we won't go below min_pll_multiplier. */
-	more_mul_min = max(more_mul_min,
-			   DIV_ROUND_UP(limits->min_pll_multiplier, mul));
-	dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %u\n",
-		more_mul_min);
-
-	if (more_mul_min > more_mul_max) {
-		dev_dbg(dev,
-			"unable to compute more_mul_min and more_mul_max\n");
-		return -EINVAL;
-	}
-
-	more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
-	dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor);
-	more_mul_factor = lcm(more_mul_factor, op_limits->min_sys_clk_div);
-	dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
-		more_mul_factor);
-	i = roundup(more_mul_min, more_mul_factor);
-	if (!is_one_or_even(i))
-		i <<= 1;
-
-	dev_dbg(dev, "final more_mul: %u\n", i);
-	if (i > more_mul_max) {
-		dev_dbg(dev, "final more_mul is bad, max %u\n", more_mul_max);
-		return -EINVAL;
-	}
-
-	pll->pll_multiplier = mul * i;
-	op_pll->sys_clk_div = div * i / pll->pre_pll_clk_div;
-	dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll->sys_clk_div);
-
-	pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz
-		/ pll->pre_pll_clk_div;
-
-	pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz
-		* pll->pll_multiplier;
-
-	/* Derive pll_op_clk_freq_hz. */
-	op_pll->sys_clk_freq_hz =
-		pll->pll_op_clk_freq_hz / op_pll->sys_clk_div;
-
-	op_pll->pix_clk_div = pll->bits_per_pixel;
-	dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll->pix_clk_div);
-
-	op_pll->pix_clk_freq_hz =
-		op_pll->sys_clk_freq_hz / op_pll->pix_clk_div;
-
-	if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
-		/* No OP clocks --- VT clocks are used instead. */
-		goto out_skip_vt_calc;
-	}
-
-	/*
-	 * Some sensors perform analogue binning and some do this
-	 * digitally. The ones doing this digitally can be roughly be
-	 * found out using this formula. The ones doing this digitally
-	 * should run at higher clock rate, so smaller divisor is used
-	 * on video timing side.
-	 */
-	if (limits->min_line_length_pck_bin > limits->min_line_length_pck
-	    / pll->binning_horizontal)
-		vt_op_binning_div = pll->binning_horizontal;
-	else
-		vt_op_binning_div = 1;
-	dev_dbg(dev, "vt_op_binning_div: %u\n", vt_op_binning_div);
-
-	/*
-	 * Profile 2 supports vt_pix_clk_div E [4, 10]
-	 *
-	 * Horizontal binning can be used as a base for difference in
-	 * divisors. One must make sure that horizontal blanking is
-	 * enough to accommodate the CSI-2 sync codes.
-	 *
-	 * Take scaling factor into account as well.
-	 *
-	 * Find absolute limits for the factor of vt divider.
-	 */
-	dev_dbg(dev, "scale_m: %u\n", pll->scale_m);
-	min_vt_div = DIV_ROUND_UP(op_pll->pix_clk_div * op_pll->sys_clk_div
-				  * pll->scale_n,
-				  lane_op_clock_ratio * vt_op_binning_div
-				  * pll->scale_m);
-
-	/* Find smallest and biggest allowed vt divisor. */
-	dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);
-	min_vt_div = max(min_vt_div,
-			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				      limits->vt.max_pix_clk_freq_hz));
-	dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n",
-		min_vt_div);
-	min_vt_div = max_t(uint32_t, min_vt_div,
-			   limits->vt.min_pix_clk_div
-			   * limits->vt.min_sys_clk_div);
-	dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div);
-
-	max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
-	dev_dbg(dev, "max_vt_div: %u\n", max_vt_div);
-	max_vt_div = min(max_vt_div,
-			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				      limits->vt.min_pix_clk_freq_hz));
-	dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n",
-		max_vt_div);
-
-	/*
-	 * Find limitsits for sys_clk_div. Not all values are possible
-	 * with all values of pix_clk_div.
-	 */
-	min_sys_div = limits->vt.min_sys_clk_div;
-	dev_dbg(dev, "min_sys_div: %u\n", min_sys_div);
-	min_sys_div = max(min_sys_div,
-			  DIV_ROUND_UP(min_vt_div,
-				       limits->vt.max_pix_clk_div));
-	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div);
-	min_sys_div = max(min_sys_div,
-			  pll->pll_op_clk_freq_hz
-			  / limits->vt.max_sys_clk_freq_hz);
-	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div);
-	min_sys_div = clk_div_even_up(min_sys_div);
-	dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div);
-
-	max_sys_div = limits->vt.max_sys_clk_div;
-	dev_dbg(dev, "max_sys_div: %u\n", max_sys_div);
-	max_sys_div = min(max_sys_div,
-			  DIV_ROUND_UP(max_vt_div,
-				       limits->vt.min_pix_clk_div));
-	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div);
-	max_sys_div = min(max_sys_div,
-			  DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				       limits->vt.min_pix_clk_freq_hz));
-	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div);
-
-	/*
-	 * Find pix_div such that a legal pix_div * sys_div results
-	 * into a value which is not smaller than div, the desired
-	 * divisor.
-	 */
-	for (vt_div = min_vt_div; vt_div <= max_vt_div;
-	     vt_div += 2 - (vt_div & 1)) {
-		for (sys_div = min_sys_div;
-		     sys_div <= max_sys_div;
-		     sys_div += 2 - (sys_div & 1)) {
-			uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div);
-
-			if (pix_div < limits->vt.min_pix_clk_div
-			    || pix_div > limits->vt.max_pix_clk_div) {
-				dev_dbg(dev,
-					"pix_div %u too small or too big (%u--%u)\n",
-					pix_div,
-					limits->vt.min_pix_clk_div,
-					limits->vt.max_pix_clk_div);
-				continue;
-			}
-
-			/* Check if this one is better. */
-			if (pix_div * sys_div
-			    <= roundup(min_vt_div, best_pix_div))
-				best_pix_div = pix_div;
-		}
-		if (best_pix_div < INT_MAX >> 1)
-			break;
-	}
-
-	pll->vt.sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div);
-	pll->vt.pix_clk_div = best_pix_div;
-
-	pll->vt.sys_clk_freq_hz =
-		pll->pll_op_clk_freq_hz / pll->vt.sys_clk_div;
-	pll->vt.pix_clk_freq_hz =
-		pll->vt.sys_clk_freq_hz / pll->vt.pix_clk_div;
-
-out_skip_vt_calc:
-	pll->pixel_rate_csi =
-		op_pll->pix_clk_freq_hz * lane_op_clock_ratio;
-	pll->pixel_rate_pixel_array = pll->vt.pix_clk_freq_hz;
-
-	return check_all_bounds(dev, limits, op_limits, pll, op_pll);
-}
-
 int smiapp_pll_calculate(struct device *dev,
 			 const struct smiapp_pll_limits *limits,
 			 struct smiapp_pll *pll)
 {
-	const struct smiapp_pll_branch_limits *op_limits = &limits->op;
-	struct smiapp_pll_branch *op_pll = &pll->op;
 	uint16_t min_pre_pll_clk_div;
 	uint16_t max_pre_pll_clk_div;
 	uint32_t lane_op_clock_ratio;
@@ -409,23 +386,13 @@
 	unsigned int i;
 	int rval = -EINVAL;
 
-	if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
-		/*
-		 * If there's no OP PLL at all, use the VT values
-		 * instead. The OP values are ignored for the rest of
-		 * the PLL calculation.
-		 */
-		op_limits = &limits->vt;
-		op_pll = &pll->vt;
-	}
-
 	if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
 		lane_op_clock_ratio = pll->csi2.lanes;
 	else
 		lane_op_clock_ratio = 1;
-	dev_dbg(dev, "lane_op_clock_ratio: %u\n", lane_op_clock_ratio);
+	dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
 
-	dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal,
+	dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
 		pll->binning_vertical);
 
 	switch (pll->bus_type) {
@@ -444,7 +411,7 @@
 	}
 
 	/* Figure out limits for pre-pll divider based on extclk */
-	dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n",
+	dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
 		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
 	max_pre_pll_clk_div =
 		min_t(uint16_t, limits->max_pre_pll_clk_div,
@@ -455,27 +422,26 @@
 		      clk_div_even_up(
 			      DIV_ROUND_UP(pll->ext_clk_freq_hz,
 					   limits->max_pll_ip_freq_hz)));
-	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %u / %u\n",
+	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
 		min_pre_pll_clk_div, max_pre_pll_clk_div);
 
 	i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
 	mul = div_u64(pll->pll_op_clk_freq_hz, i);
 	div = pll->ext_clk_freq_hz / i;
-	dev_dbg(dev, "mul %u / div %u\n", mul, div);
+	dev_dbg(dev, "mul %d / div %d\n", mul, div);
 
 	min_pre_pll_clk_div =
 		max_t(uint16_t, min_pre_pll_clk_div,
 		      clk_div_even_up(
 			      DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
 					   limits->max_pll_op_freq_hz)));
-	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %u / %u\n",
+	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
 		min_pre_pll_clk_div, max_pre_pll_clk_div);
 
 	for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
 	     pll->pre_pll_clk_div <= max_pre_pll_clk_div;
 	     pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
-		rval = __smiapp_pll_calculate(dev, limits, op_limits, pll,
-					      op_pll, mul, div,
+		rval = __smiapp_pll_calculate(dev, limits, pll, mul, div,
 					      lane_op_clock_ratio);
 		if (rval)
 			continue;
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index e8f035a..5ce2b61 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -35,13 +35,6 @@
 #define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE			(1 << 0)
 #define SMIAPP_PLL_FLAG_NO_OP_CLOCKS				(1 << 1)
 
-struct smiapp_pll_branch {
-	uint16_t sys_clk_div;
-	uint16_t pix_clk_div;
-	uint32_t sys_clk_freq_hz;
-	uint32_t pix_clk_freq_hz;
-};
-
 struct smiapp_pll {
 	/* input values */
 	uint8_t bus_type;
@@ -60,18 +53,24 @@
 	uint8_t scale_n;
 	uint8_t bits_per_pixel;
 	uint32_t link_freq;
-	uint32_t ext_clk_freq_hz;
 
 	/* output values */
 	uint16_t pre_pll_clk_div;
 	uint16_t pll_multiplier;
+	uint16_t op_sys_clk_div;
+	uint16_t op_pix_clk_div;
+	uint16_t vt_sys_clk_div;
+	uint16_t vt_pix_clk_div;
+
+	uint32_t ext_clk_freq_hz;
 	uint32_t pll_ip_clk_freq_hz;
 	uint32_t pll_op_clk_freq_hz;
-	struct smiapp_pll_branch vt;
-	struct smiapp_pll_branch op;
+	uint32_t op_sys_clk_freq_hz;
+	uint32_t op_pix_clk_freq_hz;
+	uint32_t vt_sys_clk_freq_hz;
+	uint32_t vt_pix_clk_freq_hz;
 
 	uint32_t pixel_rate_csi;
-	uint32_t pixel_rate_pixel_array;
 };
 
 struct smiapp_pll_branch_limits {
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 0df5070..932ed9b 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -205,12 +205,12 @@
 	int rval;
 
 	rval = smiapp_write(
-		sensor, SMIAPP_REG_U16_VT_PIX_CLK_DIV, pll->vt.pix_clk_div);
+		sensor, SMIAPP_REG_U16_VT_PIX_CLK_DIV, pll->vt_pix_clk_div);
 	if (rval < 0)
 		return rval;
 
 	rval = smiapp_write(
-		sensor, SMIAPP_REG_U16_VT_SYS_CLK_DIV, pll->vt.sys_clk_div);
+		sensor, SMIAPP_REG_U16_VT_SYS_CLK_DIV, pll->vt_sys_clk_div);
 	if (rval < 0)
 		return rval;
 
@@ -227,21 +227,20 @@
 	/* Lane op clock ratio does not apply here. */
 	rval = smiapp_write(
 		sensor, SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS,
-		DIV_ROUND_UP(pll->op.sys_clk_freq_hz, 1000000 / 256 / 256));
+		DIV_ROUND_UP(pll->op_sys_clk_freq_hz, 1000000 / 256 / 256));
 	if (rval < 0 || sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
 		return rval;
 
 	rval = smiapp_write(
-		sensor, SMIAPP_REG_U16_OP_PIX_CLK_DIV, pll->op.pix_clk_div);
+		sensor, SMIAPP_REG_U16_OP_PIX_CLK_DIV, pll->op_pix_clk_div);
 	if (rval < 0)
 		return rval;
 
 	return smiapp_write(
-		sensor, SMIAPP_REG_U16_OP_SYS_CLK_DIV, pll->op.sys_clk_div);
+		sensor, SMIAPP_REG_U16_OP_SYS_CLK_DIV, pll->op_sys_clk_div);
 }
 
-static int smiapp_pll_try(struct smiapp_sensor *sensor,
-			  struct smiapp_pll *pll)
+static int smiapp_pll_update(struct smiapp_sensor *sensor)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 	struct smiapp_pll_limits lim = {
@@ -275,15 +274,19 @@
 		.min_line_length_pck_bin = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN],
 		.min_line_length_pck = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK],
 	};
-
-	return smiapp_pll_calculate(&client->dev, &lim, pll);
-}
-
-static int smiapp_pll_update(struct smiapp_sensor *sensor)
-{
 	struct smiapp_pll *pll = &sensor->pll;
 	int rval;
 
+	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) {
+		/*
+		 * Fill in operational clock divisors limits from the
+		 * video timing ones. On profile 0 sensors the
+		 * requirements regarding them are essentially the
+		 * same as on VT ones.
+		 */
+		lim.op = lim.vt;
+	}
+
 	pll->binning_horizontal = sensor->binning_horizontal;
 	pll->binning_vertical = sensor->binning_vertical;
 	pll->link_freq =
@@ -291,12 +294,12 @@
 	pll->scale_m = sensor->scale_m;
 	pll->bits_per_pixel = sensor->csi_format->compressed;
 
-	rval = smiapp_pll_try(sensor, pll);
+	rval = smiapp_pll_calculate(&client->dev, &lim, pll);
 	if (rval < 0)
 		return rval;
 
 	__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_parray,
-				 pll->pixel_rate_pixel_array);
+				 pll->vt_pix_clk_freq_hz);
 	__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_csi, pll->pixel_rate_csi);
 
 	return 0;
@@ -330,22 +333,22 @@
  *    orders must be defined.
  */
 static const struct smiapp_csi_data_format smiapp_csi_data_formats[] = {
-	{ MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GRBG, },
-	{ MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_RGGB, },
-	{ MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_BGGR, },
-	{ MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GBRG, },
-	{ MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GRBG, },
-	{ MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_RGGB, },
-	{ MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_BGGR, },
-	{ MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GBRG, },
-	{ MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GRBG, },
-	{ MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_RGGB, },
-	{ MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_BGGR, },
-	{ MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GBRG, },
-	{ MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GRBG, },
-	{ MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_RGGB, },
-	{ MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_BGGR, },
-	{ MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GBRG, },
+	{ V4L2_MBUS_FMT_SGRBG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GRBG, },
+	{ V4L2_MBUS_FMT_SRGGB12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_RGGB, },
+	{ V4L2_MBUS_FMT_SBGGR12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_BGGR, },
+	{ V4L2_MBUS_FMT_SGBRG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GBRG, },
+	{ V4L2_MBUS_FMT_SGRBG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GRBG, },
+	{ V4L2_MBUS_FMT_SRGGB10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_RGGB, },
+	{ V4L2_MBUS_FMT_SBGGR10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_BGGR, },
+	{ V4L2_MBUS_FMT_SGBRG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GBRG, },
+	{ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GRBG, },
+	{ V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_RGGB, },
+	{ V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_BGGR, },
+	{ V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GBRG, },
+	{ V4L2_MBUS_FMT_SGRBG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GRBG, },
+	{ V4L2_MBUS_FMT_SRGGB8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_RGGB, },
+	{ V4L2_MBUS_FMT_SBGGR8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_BGGR, },
+	{ V4L2_MBUS_FMT_SGBRG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GBRG, },
 };
 
 const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" };
@@ -523,8 +526,6 @@
 static int smiapp_init_controls(struct smiapp_sensor *sensor)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-	unsigned long *valid_link_freqs = &sensor->valid_link_freqs[
-		sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE];
 	unsigned int max, i;
 	int rval;
 
@@ -607,8 +608,8 @@
 
 	sensor->link_freq = v4l2_ctrl_new_int_menu(
 		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
-		V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs),
-		__ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock);
+		V4L2_CID_LINK_FREQ, max, 0,
+		sensor->platform_data->op_sys_clock);
 
 	sensor->pixel_rate_csi = v4l2_ctrl_new_std(
 		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
@@ -744,7 +745,6 @@
 static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-	struct smiapp_pll *pll = &sensor->pll;
 	unsigned int type, n;
 	unsigned int i, pixel_order;
 	int rval;
@@ -808,57 +808,14 @@
 			dev_dbg(&client->dev, "jolly good! %d\n", j);
 
 			sensor->default_mbus_frame_fmts |= 1 << j;
-		}
-	}
-
-	/* Figure out which BPP values can be used with which formats. */
-	pll->binning_horizontal = 1;
-	pll->binning_vertical = 1;
-	pll->scale_m = sensor->scale_m;
-
-	for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
-		const struct smiapp_csi_data_format *f =
-			&smiapp_csi_data_formats[i];
-		unsigned long *valid_link_freqs =
-			&sensor->valid_link_freqs[
-				f->compressed - SMIAPP_COMPRESSED_BASE];
-		unsigned int j;
-
-		BUG_ON(f->compressed < SMIAPP_COMPRESSED_BASE);
-		BUG_ON(f->compressed > SMIAPP_COMPRESSED_MAX);
-
-		if (!(sensor->default_mbus_frame_fmts & 1 << i))
-			continue;
-
-		pll->bits_per_pixel = f->compressed;
-
-		for (j = 0; sensor->platform_data->op_sys_clock[j]; j++) {
-			pll->link_freq = sensor->platform_data->op_sys_clock[j];
-
-			rval = smiapp_pll_try(sensor, pll);
-			dev_dbg(&client->dev, "link freq %u Hz, bpp %u %s\n",
-				pll->link_freq, pll->bits_per_pixel,
-				rval ? "not ok" : "ok");
-			if (rval)
-				continue;
-
-			set_bit(j, valid_link_freqs);
-		}
-
-		if (!*valid_link_freqs) {
-			dev_info(&client->dev,
-				 "no valid link frequencies for %u bpp\n",
-				 f->compressed);
-			sensor->default_mbus_frame_fmts &= ~BIT(i);
-			continue;
-		}
-
-		if (!sensor->csi_format
-		    || f->width > sensor->csi_format->width
-		    || (f->width == sensor->csi_format->width
-			&& f->compressed > sensor->csi_format->compressed)) {
-			sensor->csi_format = f;
-			sensor->internal_csi_format = f;
+			if (!sensor->csi_format
+			    || f->width > sensor->csi_format->width
+			    || (f->width == sensor->csi_format->width
+				&& f->compressed
+				> sensor->csi_format->compressed)) {
+				sensor->csi_format = f;
+				sensor->internal_csi_format = f;
+			}
 		}
 	}
 
@@ -947,7 +904,7 @@
 	dev_dbg(&client->dev, "hblank\t\t%d\n", sensor->hblank->val);
 
 	dev_dbg(&client->dev, "real timeperframe\t100/%d\n",
-		sensor->pll.pixel_rate_pixel_array /
+		sensor->pll.vt_pix_clk_freq_hz /
 		((sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
 		  + sensor->hblank->val) *
 		 (sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
@@ -1730,59 +1687,6 @@
 	return csi_format;
 }
 
-static int smiapp_set_format_source(struct v4l2_subdev *subdev,
-				    struct v4l2_subdev_fh *fh,
-				    struct v4l2_subdev_format *fmt)
-{
-	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
-	const struct smiapp_csi_data_format *csi_format,
-		*old_csi_format = sensor->csi_format;
-	unsigned long *valid_link_freqs;
-	u32 code = fmt->format.code;
-	unsigned int i;
-	int rval;
-
-	rval = __smiapp_get_format(subdev, fh, fmt);
-	if (rval)
-		return rval;
-
-	/*
-	 * Media bus code is changeable on src subdev's source pad. On
-	 * other source pads we just get format here.
-	 */
-	if (subdev != &sensor->src->sd)
-		return 0;
-
-	csi_format = smiapp_validate_csi_data_format(sensor, code);
-
-	fmt->format.code = csi_format->code;
-
-	if (fmt->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-		return 0;
-
-	sensor->csi_format = csi_format;
-
-	if (csi_format->width != old_csi_format->width)
-		for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++)
-			__v4l2_ctrl_modify_range(
-				sensor->test_data[i], 0,
-				(1 << csi_format->width) - 1, 1, 0);
-
-	if (csi_format->compressed == old_csi_format->compressed)
-		return 0;
-
-	valid_link_freqs = 
-		&sensor->valid_link_freqs[sensor->csi_format->compressed
-					  - SMIAPP_COMPRESSED_BASE];
-
-	__v4l2_ctrl_modify_range(
-		sensor->link_freq, 0,
-		__fls(*valid_link_freqs), ~*valid_link_freqs,
-		__ffs(*valid_link_freqs));
-
-	return smiapp_pll_update(sensor);
-}
-
 static int smiapp_set_format(struct v4l2_subdev *subdev,
 			     struct v4l2_subdev_fh *fh,
 			     struct v4l2_subdev_format *fmt)
@@ -1793,14 +1697,41 @@
 
 	mutex_lock(&sensor->mutex);
 
+	/*
+	 * Media bus code is changeable on src subdev's source pad. On
+	 * other source pads we just get format here.
+	 */
 	if (fmt->pad == ssd->source_pad) {
-		int rval;
+		u32 code = fmt->format.code;
+		int rval = __smiapp_get_format(subdev, fh, fmt);
+		bool range_changed = false;
+		unsigned int i;
 
-		rval = smiapp_set_format_source(subdev, fh, fmt);
+		if (!rval && subdev == &sensor->src->sd) {
+			const struct smiapp_csi_data_format *csi_format =
+				smiapp_validate_csi_data_format(sensor, code);
+
+			if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+				if (csi_format->width !=
+				    sensor->csi_format->width)
+					range_changed = true;
+
+				sensor->csi_format = csi_format;
+			}
+
+			fmt->format.code = csi_format->code;
+		}
 
 		mutex_unlock(&sensor->mutex);
+		if (rval || !range_changed)
+			return rval;
 
-		return rval;
+		for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++)
+			v4l2_ctrl_modify_range(
+				sensor->test_data[i],
+				0, (1 << sensor->csi_format->width) - 1, 1, 0);
+
+		return 0;
 	}
 
 	/* Sink pad. Width and height are changeable here. */
@@ -2092,11 +2023,6 @@
 		    == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP)
 			return 0;
 		return -EINVAL;
-	case V4L2_SEL_TGT_NATIVE_SIZE:
-		if (ssd == sensor->pixel_array
-		    && sel->pad == SMIAPP_PA_PAD_SRC)
-			return 0;
-		return -EINVAL;
 	case V4L2_SEL_TGT_COMPOSE:
 	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
 		if (sel->pad == ssd->source_pad)
@@ -2195,9 +2121,7 @@
 
 	switch (sel->target) {
 	case V4L2_SEL_TGT_CROP_BOUNDS:
-	case V4L2_SEL_TGT_NATIVE_SIZE:
 		if (ssd == sensor->pixel_array) {
-			sel->r.left = sel->r.top = 0;
 			sel->r.width =
 				sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
 			sel->r.height =
@@ -2266,7 +2190,7 @@
 		ret = smiapp_set_compose(subdev, fh, sel);
 		break;
 	default:
-		ret = -EINVAL;
+		BUG();
 	}
 
 	mutex_unlock(&sensor->mutex);
@@ -2558,6 +2482,12 @@
 		goto out_power_off;
 	}
 
+	rval = smiapp_get_mbus_formats(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_power_off;
+	}
+
 	if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY]) {
 		u32 val;
 
@@ -2639,22 +2569,6 @@
 
 	sensor->scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
 
-	/* prepare PLL configuration input values */
-	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
-	pll->csi2.lanes = sensor->platform_data->lanes;
-	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
-	pll->flags = smiapp_call_quirk(sensor, pll_flags);
-	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
-	/* Profile 0 sensors have no separate OP clock branch. */
-	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
-		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
-
-	rval = smiapp_get_mbus_formats(sensor);
-	if (rval) {
-		rval = -ENODEV;
-		goto out_nvm_release;
-	}
-
 	for (i = 0; i < SMIAPP_SUBDEVS; i++) {
 		struct {
 			struct smiapp_subdev *ssd;
@@ -2752,9 +2666,18 @@
 	if (rval < 0)
 		goto out_nvm_release;
 
-	mutex_lock(&sensor->mutex);
+	/* prepare PLL configuration input values */
+	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
+	pll->csi2.lanes = sensor->platform_data->lanes;
+	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
+	pll->flags = smiapp_call_quirk(sensor, pll_flags);
+
+	/* Profile 0 sensors have no separate OP clock branch. */
+	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
+		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
+	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+
 	rval = smiapp_update_mode(sensor);
-	mutex_unlock(&sensor->mutex);
 	if (rval) {
 		dev_err(&client->dev, "update mode failed\n");
 		goto out_nvm_release;
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
index f88f8ec..874b49f 100644
--- a/drivers/media/i2c/smiapp/smiapp.h
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -156,11 +156,6 @@
 #define SMIAPP_PAD_SRC			1
 #define SMIAPP_PADS			2
 
-#define SMIAPP_COMPRESSED_BASE		8
-#define SMIAPP_COMPRESSED_MAX		12
-#define SMIAPP_NR_OF_COMPRESSED		(SMIAPP_COMPRESSED_MAX - \
-					 SMIAPP_COMPRESSED_BASE + 1)
-
 struct smiapp_binning_subtype {
 	u8 horizontal:4;
 	u8 vertical:4;
@@ -237,9 +232,6 @@
 
 	struct smiapp_pll pll;
 
-	/* Is a default format supported for a given BPP? */
-	unsigned long valid_link_freqs[SMIAPP_NR_OF_COMPRESSED];
-
 	/* Pixel array controls */
 	struct v4l2_ctrl *analog_gain;
 	struct v4l2_ctrl *exposure;
diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c
index ec89cfa..5b91593 100644
--- a/drivers/media/i2c/soc_camera/imx074.c
+++ b/drivers/media/i2c/soc_camera/imx074.c
@@ -71,7 +71,7 @@
 
 /* IMX074 has only one fixed colorspace per pixelcode */
 struct imx074_datafmt {
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	enum v4l2_colorspace		colorspace;
 };
 
@@ -82,7 +82,7 @@
 };
 
 static const struct imx074_datafmt imx074_colour_fmts[] = {
-	{MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
 };
 
 static struct imx074 *to_imx074(const struct i2c_client *client)
@@ -91,7 +91,7 @@
 }
 
 /* Find a data format by a pixel code in an array */
-static const struct imx074_datafmt *imx074_find_datafmt(u32 code)
+static const struct imx074_datafmt *imx074_find_datafmt(enum v4l2_mbus_pixelcode code)
 {
 	int i;
 
@@ -236,7 +236,7 @@
 }
 
 static int imx074_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if ((unsigned int)index >= ARRAY_SIZE(imx074_colour_fmts))
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
index 0cc1901..8150d0d 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -53,13 +53,13 @@
 
 /* MT9M001 has only one fixed colorspace per pixelcode */
 struct mt9m001_datafmt {
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	enum v4l2_colorspace		colorspace;
 };
 
 /* Find a data format by a pixel code in an array */
 static const struct mt9m001_datafmt *mt9m001_find_datafmt(
-	u32 code, const struct mt9m001_datafmt *fmt,
+	enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt,
 	int n)
 {
 	int i;
@@ -75,14 +75,14 @@
 	 * Order important: first natively supported,
 	 * second supported with a GPIO extender
 	 */
-	{MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
 };
 
 static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
 	/* Order important - see above */
-	{MEDIA_BUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
-	{MEDIA_BUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
 };
 
 struct mt9m001 {
@@ -563,7 +563,7 @@
 };
 
 static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			    u32 *code)
+			    enum v4l2_mbus_pixelcode *code)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c
index a35a2f9..e5c5d9a 100644
--- a/drivers/media/i2c/soc_camera/mt9m111.c
+++ b/drivers/media/i2c/soc_camera/mt9m111.c
@@ -182,23 +182,23 @@
 
 /* MT9M111 has only one fixed colorspace per pixelcode */
 struct mt9m111_datafmt {
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	enum v4l2_colorspace		colorspace;
 };
 
 static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
-	{MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
-	{MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
-	{MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
-	{MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG},
-	{MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_BGR565_2X8_LE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_BGR565_2X8_BE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_BGR565_2X8_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_BGR565_2X8_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
 };
 
 struct mt9m111 {
@@ -218,7 +218,7 @@
 
 /* Find a data format by a pixel code */
 static const struct mt9m111_datafmt *mt9m111_find_datafmt(struct mt9m111 *mt9m111,
-						u32 code)
+						enum v4l2_mbus_pixelcode code)
 {
 	int i;
 	for (i = 0; i < ARRAY_SIZE(mt9m111_colour_fmts); i++)
@@ -331,7 +331,7 @@
 }
 
 static int mt9m111_setup_geometry(struct mt9m111 *mt9m111, struct v4l2_rect *rect,
-			int width, int height, u32 code)
+			int width, int height, enum v4l2_mbus_pixelcode code)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
 	int ret;
@@ -345,7 +345,7 @@
 	if (!ret)
 		ret = reg_write(WINDOW_HEIGHT, rect->height);
 
-	if (code != MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {
+	if (code != V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
 		/* IFP in use, down-scaling possible */
 		if (!ret)
 			ret = mt9m111_setup_rect_ctx(mt9m111, &context_b,
@@ -393,8 +393,8 @@
 	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 
-	if (mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
-	    mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {
+	if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+	    mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
 		/* Bayer format - even size lengths */
 		rect.width	= ALIGN(rect.width, 2);
 		rect.height	= ALIGN(rect.height, 2);
@@ -462,7 +462,7 @@
 }
 
 static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
-			      u32 code)
+			      enum v4l2_mbus_pixelcode code)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
 	u16 data_outfmt2, mask_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
@@ -474,46 +474,46 @@
 	int ret;
 
 	switch (code) {
-	case MEDIA_BUS_FMT_SBGGR8_1X8:
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
 		data_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
 			MT9M111_OUTFMT_RGB;
 		break;
-	case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
 		data_outfmt2 = MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB;
 		break;
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
 		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555 |
 			MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
 		break;
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
 		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
 		break;
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
 			MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
 		break;
-	case MEDIA_BUS_FMT_RGB565_2X8_BE:
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
 		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
 		break;
-	case MEDIA_BUS_FMT_BGR565_2X8_BE:
+	case V4L2_MBUS_FMT_BGR565_2X8_BE:
 		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
 			MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
 		break;
-	case MEDIA_BUS_FMT_BGR565_2X8_LE:
+	case V4L2_MBUS_FMT_BGR565_2X8_LE:
 		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
 			MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
 			MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
 		break;
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		data_outfmt2 = 0;
 		break;
-	case MEDIA_BUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
 		data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
 		break;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
 		break;
-	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
 		data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
 			MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
 		break;
@@ -542,8 +542,8 @@
 
 	fmt = mt9m111_find_datafmt(mt9m111, mf->code);
 
-	bayer = fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
-		fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE;
+	bayer = fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+		fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
 
 	/*
 	 * With Bayer format enforce even side lengths, but let the user play
@@ -554,7 +554,7 @@
 		rect->height = ALIGN(rect->height, 2);
 	}
 
-	if (fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {
+	if (fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
 		/* IFP bypass mode, no scaling */
 		mf->width = rect->width;
 		mf->height = rect->height;
@@ -840,7 +840,7 @@
 };
 
 static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			    u32 *code)
+			    enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
index e803676..b8d9f2c 100644
--- a/drivers/media/i2c/soc_camera/mt9t031.c
+++ b/drivers/media/i2c/soc_camera/mt9t031.c
@@ -345,7 +345,7 @@
 
 	mf->width	= mt9t031->rect.width / mt9t031->xskip;
 	mf->height	= mt9t031->rect.height / mt9t031->yskip;
-	mf->code	= MEDIA_BUS_FMT_SBGGR10_1X10;
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
 	mf->colorspace	= V4L2_COLORSPACE_SRGB;
 	mf->field	= V4L2_FIELD_NONE;
 
@@ -367,7 +367,7 @@
 	xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH);
 	yskip = mt9t031_skip(&rect.height, mf->height, MT9T031_MAX_HEIGHT);
 
-	mf->code	= MEDIA_BUS_FMT_SBGGR10_1X10;
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
 	mf->colorspace	= V4L2_COLORSPACE_SRGB;
 
 	/* mt9t031_set_params() doesn't change width and height */
@@ -385,7 +385,7 @@
 		&mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
 		&mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
 
-	mf->code	= MEDIA_BUS_FMT_SBGGR10_1X10;
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
 	mf->colorspace	= V4L2_COLORSPACE_SRGB;
 
 	return 0;
@@ -673,12 +673,12 @@
 };
 
 static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			    u32 *code)
+			    enum v4l2_mbus_pixelcode *code)
 {
 	if (index)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_SBGGR10_1X10;
+	*code = V4L2_MBUS_FMT_SBGGR10_1X10;
 	return 0;
 }
 
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
index 113f0eb..7520e11 100644
--- a/drivers/media/i2c/soc_camera/mt9t112.c
+++ b/drivers/media/i2c/soc_camera/mt9t112.c
@@ -77,7 +77,7 @@
 			struct
 ************************************************************************/
 struct mt9t112_format {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	enum v4l2_colorspace colorspace;
 	u16 fmt;
 	u16 order;
@@ -103,32 +103,32 @@
 
 static const struct mt9t112_format mt9t112_cfmts[] = {
 	{
-		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.fmt		= 1,
 		.order		= 0,
 	}, {
-		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.fmt		= 1,
 		.order		= 1,
 	}, {
-		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.fmt		= 1,
 		.order		= 2,
 	}, {
-		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.fmt		= 1,
 		.order		= 3,
 	}, {
-		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.fmt		= 8,
 		.order		= 2,
 	}, {
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_LE,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.fmt		= 4,
 		.order		= 2,
@@ -840,7 +840,7 @@
 
 static int mt9t112_set_params(struct mt9t112_priv *priv,
 			      const struct v4l2_rect *rect,
-			      u32 code)
+			      enum v4l2_mbus_pixelcode code)
 {
 	int i;
 
@@ -953,7 +953,7 @@
 			break;
 
 	if (i == priv->num_formats) {
-		mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 	} else {
 		mf->colorspace	= mt9t112_cfmts[i].colorspace;
@@ -967,7 +967,7 @@
 }
 
 static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9t112_priv *priv = to_mt9t112(client);
@@ -1101,7 +1101,7 @@
 
 	/* Cannot fail: using the default supported pixel code */
 	if (!ret)
-		mt9t112_set_params(priv, &rect, MEDIA_BUS_FMT_UYVY8_2X8);
+		mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8);
 	else
 		v4l2_clk_put(priv->clk);
 
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index a82cf3d..8250357 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -85,13 +85,13 @@
 
 /* MT9V022 has only one fixed colorspace per pixelcode */
 struct mt9v022_datafmt {
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	enum v4l2_colorspace		colorspace;
 };
 
 /* Find a data format by a pixel code in an array */
 static const struct mt9v022_datafmt *mt9v022_find_datafmt(
-	u32 code, const struct mt9v022_datafmt *fmt,
+	enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt,
 	int n)
 {
 	int i;
@@ -107,14 +107,14 @@
 	 * Order important: first natively supported,
 	 * second supported with a GPIO extender
 	 */
-	{MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
 };
 
 static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
 	/* Order important - see above */
-	{MEDIA_BUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
-	{MEDIA_BUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
 };
 
 /* only registers with different addresses on different mt9v02x sensors */
@@ -410,13 +410,13 @@
 	 * .try_mbus_fmt(), datawidth is from our supported format list
 	 */
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_Y8_1X8:
-	case MEDIA_BUS_FMT_Y10_1X10:
+	case V4L2_MBUS_FMT_Y8_1X8:
+	case V4L2_MBUS_FMT_Y10_1X10:
 		if (mt9v022->model != MT9V022IX7ATM)
 			return -EINVAL;
 		break;
-	case MEDIA_BUS_FMT_SBGGR8_1X8:
-	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
 		if (mt9v022->model != MT9V022IX7ATC)
 			return -EINVAL;
 		break;
@@ -443,8 +443,8 @@
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
 	const struct mt9v022_datafmt *fmt;
-	int align = mf->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
-		mf->code == MEDIA_BUS_FMT_SBGGR10_1X10;
+	int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_1X10;
 
 	v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH,
 		MT9V022_MAX_WIDTH, align,
@@ -759,7 +759,7 @@
 };
 
 static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			    u32 *code)
+			    enum v4l2_mbus_pixelcode *code)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index 0c05283..ce0517d 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -302,7 +302,7 @@
 struct ov2640_priv {
 	struct v4l2_subdev		subdev;
 	struct v4l2_ctrl_handler	hdl;
-	u32	cfmt_code;
+	enum v4l2_mbus_pixelcode	cfmt_code;
 	struct v4l2_clk			*clk;
 	const struct ov2640_win_size	*win;
 };
@@ -623,11 +623,11 @@
 	ENDMARKER,
 };
 
-static u32 ov2640_codes[] = {
-	MEDIA_BUS_FMT_YUYV8_2X8,
-	MEDIA_BUS_FMT_UYVY8_2X8,
-	MEDIA_BUS_FMT_RGB565_2X8_BE,
-	MEDIA_BUS_FMT_RGB565_2X8_LE,
+static enum v4l2_mbus_pixelcode ov2640_codes[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_RGB565_2X8_BE,
+	V4L2_MBUS_FMT_RGB565_2X8_LE,
 };
 
 /*
@@ -785,7 +785,7 @@
 }
 
 static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
-			     u32 code)
+			     enum v4l2_mbus_pixelcode code)
 {
 	struct ov2640_priv       *priv = to_ov2640(client);
 	const struct regval_list *selected_cfmt_regs;
@@ -797,20 +797,20 @@
 	/* select format */
 	priv->cfmt_code = 0;
 	switch (code) {
-	case MEDIA_BUS_FMT_RGB565_2X8_BE:
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
 		dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__);
 		selected_cfmt_regs = ov2640_rgb565_be_regs;
 		break;
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		dev_dbg(&client->dev, "%s: Selected cfmt RGB565 LE", __func__);
 		selected_cfmt_regs = ov2640_rgb565_le_regs;
 		break;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		dev_dbg(&client->dev, "%s: Selected cfmt YUYV (YUV422)", __func__);
 		selected_cfmt_regs = ov2640_yuyv_regs;
 		break;
 	default:
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		dev_dbg(&client->dev, "%s: Selected cfmt UYVY", __func__);
 		selected_cfmt_regs = ov2640_uyvy_regs;
 	}
@@ -869,7 +869,7 @@
 	if (!priv->win) {
 		u32 width = W_SVGA, height = H_SVGA;
 		priv->win = ov2640_select_win(&width, &height);
-		priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
+		priv->cfmt_code = V4L2_MBUS_FMT_UYVY8_2X8;
 	}
 
 	mf->width	= priv->win->width;
@@ -877,13 +877,13 @@
 	mf->code	= priv->cfmt_code;
 
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_RGB565_2X8_BE:
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 	}
 	mf->field	= V4L2_FIELD_NONE;
@@ -899,14 +899,14 @@
 
 
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_RGB565_2X8_BE:
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
-		mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 	}
 
@@ -926,14 +926,14 @@
 	mf->field	= V4L2_FIELD_NONE;
 
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_RGB565_2X8_BE:
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
-		mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 	}
 
@@ -941,7 +941,7 @@
 }
 
 static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(ov2640_codes))
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c
index e9a2931..c8a3921 100644
--- a/drivers/media/i2c/soc_camera/ov5642.c
+++ b/drivers/media/i2c/soc_camera/ov5642.c
@@ -602,7 +602,7 @@
 };
 
 struct ov5642_datafmt {
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	enum v4l2_colorspace		colorspace;
 };
 
@@ -618,7 +618,7 @@
 };
 
 static const struct ov5642_datafmt ov5642_colour_fmts[] = {
-	{MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
 };
 
 static struct ov5642 *to_ov5642(const struct i2c_client *client)
@@ -628,7 +628,7 @@
 
 /* Find a data format by a pixel code in an array */
 static const struct ov5642_datafmt
-			*ov5642_find_datafmt(u32 code)
+			*ov5642_find_datafmt(enum v4l2_mbus_pixelcode code)
 {
 	int i;
 
@@ -840,7 +840,7 @@
 }
 
 static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(ov5642_colour_fmts))
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c
index 3d3dfeb..adbc185 100644
--- a/drivers/media/i2c/soc_camera/ov6650.c
+++ b/drivers/media/i2c/soc_camera/ov6650.c
@@ -202,18 +202,18 @@
 	unsigned long		pclk_limit;	/* from host */
 	unsigned long		pclk_max;	/* from resolution and format */
 	struct v4l2_fract	tpf;		/* as requested with s_parm */
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	enum v4l2_colorspace	colorspace;
 };
 
 
-static u32 ov6650_codes[] = {
-	MEDIA_BUS_FMT_YUYV8_2X8,
-	MEDIA_BUS_FMT_UYVY8_2X8,
-	MEDIA_BUS_FMT_YVYU8_2X8,
-	MEDIA_BUS_FMT_VYUY8_2X8,
-	MEDIA_BUS_FMT_SBGGR8_1X8,
-	MEDIA_BUS_FMT_Y8_1X8,
+static enum v4l2_mbus_pixelcode ov6650_codes[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_YVYU8_2X8,
+	V4L2_MBUS_FMT_VYUY8_2X8,
+	V4L2_MBUS_FMT_SBGGR8_1X8,
+	V4L2_MBUS_FMT_Y8_1X8,
 };
 
 /* read a register */
@@ -555,29 +555,29 @@
 			.height	= mf->height << half_scale,
 		},
 	};
-	u32 code = mf->code;
+	enum v4l2_mbus_pixelcode code = mf->code;
 	unsigned long mclk, pclk;
 	u8 coma_set = 0, coma_mask = 0, coml_set, coml_mask, clkrc;
 	int ret;
 
 	/* select color matrix configuration for given color encoding */
 	switch (code) {
-	case MEDIA_BUS_FMT_Y8_1X8:
+	case V4L2_MBUS_FMT_Y8_1X8:
 		dev_dbg(&client->dev, "pixel format GREY8_1X8\n");
 		coma_mask |= COMA_RGB | COMA_WORD_SWAP | COMA_BYTE_SWAP;
 		coma_set |= COMA_BW;
 		break;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		dev_dbg(&client->dev, "pixel format YUYV8_2X8_LE\n");
 		coma_mask |= COMA_RGB | COMA_BW | COMA_BYTE_SWAP;
 		coma_set |= COMA_WORD_SWAP;
 		break;
-	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
 		dev_dbg(&client->dev, "pixel format YVYU8_2X8_LE (untested)\n");
 		coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP |
 				COMA_BYTE_SWAP;
 		break;
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		dev_dbg(&client->dev, "pixel format YUYV8_2X8_BE\n");
 		if (half_scale) {
 			coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP;
@@ -587,7 +587,7 @@
 			coma_set |= COMA_BYTE_SWAP | COMA_WORD_SWAP;
 		}
 		break;
-	case MEDIA_BUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
 		dev_dbg(&client->dev, "pixel format YVYU8_2X8_BE (untested)\n");
 		if (half_scale) {
 			coma_mask |= COMA_RGB | COMA_BW;
@@ -597,7 +597,7 @@
 			coma_set |= COMA_BYTE_SWAP;
 		}
 		break;
-	case MEDIA_BUS_FMT_SBGGR8_1X8:
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
 		dev_dbg(&client->dev, "pixel format SBGGR8_1X8 (untested)\n");
 		coma_mask |= COMA_BW | COMA_BYTE_SWAP | COMA_WORD_SWAP;
 		coma_set |= COMA_RAW_RGB | COMA_RGB;
@@ -608,8 +608,8 @@
 	}
 	priv->code = code;
 
-	if (code == MEDIA_BUS_FMT_Y8_1X8 ||
-			code == MEDIA_BUS_FMT_SBGGR8_1X8) {
+	if (code == V4L2_MBUS_FMT_Y8_1X8 ||
+			code == V4L2_MBUS_FMT_SBGGR8_1X8) {
 		coml_mask = COML_ONE_CHANNEL;
 		coml_set = 0;
 		priv->pclk_max = 4000000;
@@ -619,7 +619,7 @@
 		priv->pclk_max = 8000000;
 	}
 
-	if (code == MEDIA_BUS_FMT_SBGGR8_1X8)
+	if (code == V4L2_MBUS_FMT_SBGGR8_1X8)
 		priv->colorspace = V4L2_COLORSPACE_SRGB;
 	else if (code != 0)
 		priv->colorspace = V4L2_COLORSPACE_JPEG;
@@ -697,18 +697,18 @@
 	mf->field = V4L2_FIELD_NONE;
 
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_Y10_1X10:
-		mf->code = MEDIA_BUS_FMT_Y8_1X8;
-	case MEDIA_BUS_FMT_Y8_1X8:
-	case MEDIA_BUS_FMT_YVYU8_2X8:
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_VYUY8_2X8:
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_Y10_1X10:
+		mf->code = V4L2_MBUS_FMT_Y8_1X8;
+	case V4L2_MBUS_FMT_Y8_1X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 		break;
 	default:
-		mf->code = MEDIA_BUS_FMT_SBGGR8_1X8;
-	case MEDIA_BUS_FMT_SBGGR8_1X8:
+		mf->code = V4L2_MBUS_FMT_SBGGR8_1X8;
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
 		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	}
@@ -717,7 +717,7 @@
 }
 
 static int ov6650_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(ov6650_codes))
 		return -EINVAL;
@@ -1013,7 +1013,7 @@
 	priv->rect.width  = W_CIF;
 	priv->rect.height = H_CIF;
 	priv->half_scale  = false;
-	priv->code	  = MEDIA_BUS_FMT_YUYV8_2X8;
+	priv->code	  = V4L2_MBUS_FMT_YUYV8_2X8;
 	priv->colorspace  = V4L2_COLORSPACE_JPEG;
 
 	priv->clk = v4l2_clk_get(&client->dev, "mclk");
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c
index 4eef535..8650c78 100644
--- a/drivers/media/i2c/soc_camera/ov772x.c
+++ b/drivers/media/i2c/soc_camera/ov772x.c
@@ -376,7 +376,7 @@
  */
 
 struct ov772x_color_format {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	enum v4l2_colorspace colorspace;
 	u8 dsp3;
 	u8 dsp4;
@@ -408,7 +408,7 @@
  */
 static const struct ov772x_color_format ov772x_cfmts[] = {
 	{
-		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.dsp3		= 0x0,
 		.dsp4		= DSP_OFMT_YUV,
@@ -416,7 +416,7 @@
 		.com7		= OFMT_YUV,
 	},
 	{
-		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.dsp3		= UV_ON,
 		.dsp4		= DSP_OFMT_YUV,
@@ -424,7 +424,7 @@
 		.com7		= OFMT_YUV,
 	},
 	{
-		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.dsp3		= 0x0,
 		.dsp4		= DSP_OFMT_YUV,
@@ -432,7 +432,7 @@
 		.com7		= OFMT_YUV,
 	},
 	{
-		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.dsp3		= 0x0,
 		.dsp4		= DSP_OFMT_YUV,
@@ -440,7 +440,7 @@
 		.com7		= FMT_RGB555 | OFMT_RGB,
 	},
 	{
-		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.dsp3		= 0x0,
 		.dsp4		= DSP_OFMT_YUV,
@@ -448,7 +448,7 @@
 		.com7		= FMT_RGB555 | OFMT_RGB,
 	},
 	{
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_LE,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.dsp3		= 0x0,
 		.dsp4		= DSP_OFMT_YUV,
@@ -456,7 +456,7 @@
 		.com7		= FMT_RGB565 | OFMT_RGB,
 	},
 	{
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_BE,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.dsp3		= 0x0,
 		.dsp4		= DSP_OFMT_YUV,
@@ -468,7 +468,7 @@
 		 * regardless of the COM7 value. We can thus only support 10-bit
 		 * Bayer until someone figures it out.
 		 */
-		.code		= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.code		= V4L2_MBUS_FMT_SBGGR10_1X10,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
 		.dsp3		= 0x0,
 		.dsp4		= DSP_OFMT_RAW10,
@@ -990,7 +990,7 @@
 };
 
 static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(ov772x_cfmts))
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c
index 299308d..1a3a4a3 100644
--- a/drivers/media/i2c/soc_camera/ov9640.c
+++ b/drivers/media/i2c/soc_camera/ov9640.c
@@ -159,10 +159,10 @@
 	{ OV9640_MTXS,	0x65 },
 };
 
-static u32 ov9640_codes[] = {
-	MEDIA_BUS_FMT_UYVY8_2X8,
-	MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
-	MEDIA_BUS_FMT_RGB565_2X8_LE,
+static enum v4l2_mbus_pixelcode ov9640_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+	V4L2_MBUS_FMT_RGB565_2X8_LE,
 };
 
 /* read a register */
@@ -351,22 +351,22 @@
 }
 
 /* Prepare necessary register changes depending on color encoding */
-static void ov9640_alter_regs(u32 code,
+static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code,
 			      struct ov9640_reg_alt *alt)
 {
 	switch (code) {
 	default:
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		alt->com12	= OV9640_COM12_YUV_AVG;
 		alt->com13	= OV9640_COM13_Y_DELAY_EN |
 					OV9640_COM13_YUV_DLY(0x01);
 		break;
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
 		alt->com7	= OV9640_COM7_RGB;
 		alt->com13	= OV9640_COM13_RGB_AVG;
 		alt->com15	= OV9640_COM15_RGB_555;
 		break;
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		alt->com7	= OV9640_COM7_RGB;
 		alt->com13	= OV9640_COM13_RGB_AVG;
 		alt->com15	= OV9640_COM15_RGB_565;
@@ -376,7 +376,7 @@
 
 /* Setup registers according to resolution and color encoding */
 static int ov9640_write_regs(struct i2c_client *client, u32 width,
-		u32 code, struct ov9640_reg_alt *alts)
+		enum v4l2_mbus_pixelcode code, struct ov9640_reg_alt *alts)
 {
 	const struct ov9640_reg	*ov9640_regs, *matrix_regs;
 	int			ov9640_regs_len, matrix_regs_len;
@@ -419,7 +419,7 @@
 	}
 
 	/* select color matrix configuration for given color encoding */
-	if (code == MEDIA_BUS_FMT_UYVY8_2X8) {
+	if (code == V4L2_MBUS_FMT_UYVY8_2X8) {
 		matrix_regs	= ov9640_regs_yuv;
 		matrix_regs_len	= ARRAY_SIZE(ov9640_regs_yuv);
 	} else {
@@ -487,7 +487,7 @@
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct ov9640_reg_alt alts = {0};
 	enum v4l2_colorspace cspace;
-	u32 code = mf->code;
+	enum v4l2_mbus_pixelcode code = mf->code;
 	int ret;
 
 	ov9640_res_roundup(&mf->width, &mf->height);
@@ -500,13 +500,13 @@
 		return ret;
 
 	switch (code) {
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		cspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
-		code = MEDIA_BUS_FMT_UYVY8_2X8;
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+		code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		cspace = V4L2_COLORSPACE_JPEG;
 	}
 
@@ -527,13 +527,13 @@
 	mf->field = V4L2_FIELD_NONE;
 
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
-		mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 	}
 
@@ -541,7 +541,7 @@
 }
 
 static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(ov9640_codes))
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c
index 8cf6b21..7e2656a 100644
--- a/drivers/media/i2c/soc_camera/ov9740.c
+++ b/drivers/media/i2c/soc_camera/ov9740.c
@@ -392,8 +392,8 @@
 	{ OV9740_ISP_CTRL19,		0x02 },
 };
 
-static u32 ov9740_codes[] = {
-	MEDIA_BUS_FMT_YUYV8_2X8,
+static enum v4l2_mbus_pixelcode ov9740_codes[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
 };
 
 /* read a register */
@@ -674,13 +674,13 @@
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct ov9740_priv *priv = to_ov9740(sd);
 	enum v4l2_colorspace cspace;
-	u32 code = mf->code;
+	enum v4l2_mbus_pixelcode code = mf->code;
 	int ret;
 
 	ov9740_res_roundup(&mf->width, &mf->height);
 
 	switch (code) {
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		cspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
@@ -710,14 +710,14 @@
 	ov9740_res_roundup(&mf->width, &mf->height);
 
 	mf->field = V4L2_FIELD_NONE;
-	mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
+	mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
 	mf->colorspace = V4L2_COLORSPACE_SRGB;
 
 	return 0;
 }
 
 static int ov9740_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(ov9740_codes))
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
index 2b26200..d523249 100644
--- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c
+++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
@@ -111,13 +111,13 @@
 
 /* RJ54N1CB0C has only one fixed colorspace per pixelcode */
 struct rj54n1_datafmt {
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	enum v4l2_colorspace		colorspace;
 };
 
 /* Find a data format by a pixel code in an array */
 static const struct rj54n1_datafmt *rj54n1_find_datafmt(
-	u32 code, const struct rj54n1_datafmt *fmt,
+	enum v4l2_mbus_pixelcode code, const struct rj54n1_datafmt *fmt,
 	int n)
 {
 	int i;
@@ -129,15 +129,15 @@
 }
 
 static const struct rj54n1_datafmt rj54n1_colour_fmts[] = {
-	{MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
-	{MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
-	{MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB},
-	{MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
 };
 
 struct rj54n1_clock_div {
@@ -486,7 +486,7 @@
 }
 
 static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(rj54n1_colour_fmts))
 		return -EINVAL;
@@ -965,11 +965,11 @@
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct rj54n1 *rj54n1 = to_rj54n1(client);
 	const struct rj54n1_datafmt *fmt;
-	int align = mf->code == MEDIA_BUS_FMT_SBGGR10_1X10 ||
-		mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE ||
-		mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE ||
-		mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE ||
-		mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE;
+	int align = mf->code == V4L2_MBUS_FMT_SBGGR10_1X10 ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE;
 
 	dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
 		__func__, mf->code, mf->width, mf->height);
@@ -1025,55 +1025,55 @@
 
 	/* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 0);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
 		break;
-	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 0);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
 		break;
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
 		break;
-	case MEDIA_BUS_FMT_RGB565_2X8_BE:
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
 		break;
-	case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
 		if (!ret)
 			ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
 		break;
-	case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
 		if (!ret)
 			ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
 		break;
-	case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
 		if (!ret)
 			ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
 		break;
-	case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
 		if (!ret)
 			ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
 		break;
-	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 5);
 		break;
 	default:
@@ -1083,7 +1083,7 @@
 	/* Special case: a raw mode with 10 bits of data per clock tick */
 	if (!ret)
 		ret = reg_set(client, RJ54N1_OCLK_SEL_EN,
-			      (mf->code == MEDIA_BUS_FMT_SBGGR10_1X10) << 1, 2);
+			      (mf->code == V4L2_MBUS_FMT_SBGGR10_1X10) << 1, 2);
 
 	if (ret < 0)
 		return ret;
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c
index b5237c6..3a84291 100644
--- a/drivers/media/i2c/soc_camera/tw9910.c
+++ b/drivers/media/i2c/soc_camera/tw9910.c
@@ -705,7 +705,7 @@
 
 	mf->width	= priv->scale->width;
 	mf->height	= priv->scale->height;
-	mf->code	= MEDIA_BUS_FMT_UYVY8_2X8;
+	mf->code	= V4L2_MBUS_FMT_UYVY8_2X8;
 	mf->colorspace	= V4L2_COLORSPACE_JPEG;
 	mf->field	= V4L2_FIELD_INTERLACED_BT;
 
@@ -724,7 +724,7 @@
 	/*
 	 * check color format
 	 */
-	if (mf->code != MEDIA_BUS_FMT_UYVY8_2X8)
+	if (mf->code != V4L2_MBUS_FMT_UYVY8_2X8)
 		return -EINVAL;
 
 	mf->colorspace = V4L2_COLORSPACE_JPEG;
@@ -751,7 +751,7 @@
 		return -EINVAL;
 	}
 
-	mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+	mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
 	mf->colorspace = V4L2_COLORSPACE_JPEG;
 
 	/*
@@ -822,12 +822,12 @@
 };
 
 static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			   u32 *code)
+			   enum v4l2_mbus_pixelcode *code)
 {
 	if (index)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_UYVY8_2X8;
+	*code = V4L2_MBUS_FMT_UYVY8_2X8;
 	return 0;
 }
 
diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c
index 10c735c..118f8ee 100644
--- a/drivers/media/i2c/sr030pc30.c
+++ b/drivers/media/i2c/sr030pc30.c
@@ -165,7 +165,7 @@
 };
 
 struct sr030pc30_format {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	enum v4l2_colorspace colorspace;
 	u16 ispctl1_reg;
 };
@@ -201,23 +201,23 @@
 /* supported pixel formats */
 static const struct sr030pc30_format sr030pc30_formats[] = {
 	{
-		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0x03,
 	}, {
-		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0x02,
 	}, {
-		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0,
 	}, {
-		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0x01,
 	}, {
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_BE,
 		.colorspace	= V4L2_COLORSPACE_JPEG,
 		.ispctl1_reg	= 0x40,
 	},
@@ -472,7 +472,7 @@
 }
 
 static int sr030pc30_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-			      u32 *code)
+			      enum v4l2_mbus_pixelcode *code)
 {
 	if (!code || index >= ARRAY_SIZE(sr030pc30_formats))
 		return -EINVAL;
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index c692fdf..5a28d99 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -756,12 +756,12 @@
  */
 static int
 tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
-					u32 *code)
+					enum v4l2_mbus_pixelcode *code)
 {
 	if (index)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_YUYV10_2X10;
+	*code = V4L2_MBUS_FMT_YUYV10_2X10;
 	return 0;
 }
 
@@ -784,7 +784,7 @@
 	/* Calculate height and width based on current standard */
 	current_std = decoder->current_std;
 
-	f->code = MEDIA_BUS_FMT_YUYV8_2X8;
+	f->code = V4L2_MBUS_FMT_YUYV8_2X8;
 	f->width = decoder->std_list[current_std].width;
 	f->height = decoder->std_list[current_std].height;
 	f->field = V4L2_FIELD_INTERLACED;
@@ -942,7 +942,7 @@
 	if (index != 0)
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_YUYV8_2X8;
+	code->code = V4L2_MBUS_FMT_YUYV8_2X8;
 
 	return 0;
 }
@@ -967,7 +967,7 @@
 		return 0;
 	}
 
-	format->format.code = MEDIA_BUS_FMT_YUYV8_2X8;
+	format->format.code = V4L2_MBUS_FMT_YUYV8_2X8;
 	format->format.width = tvp514x_std_list[decoder->current_std].width;
 	format->format.height = tvp514x_std_list[decoder->current_std].height;
 	format->format.colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -991,7 +991,7 @@
 	struct tvp514x_decoder *decoder = to_decoder(sd);
 
 	if (fmt->format.field != V4L2_FIELD_INTERLACED ||
-	    fmt->format.code != MEDIA_BUS_FMT_YUYV8_2X8 ||
+	    fmt->format.code != V4L2_MBUS_FMT_YUYV8_2X8 ||
 	    fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M ||
 	    fmt->format.width != tvp514x_std_list[decoder->current_std].width ||
 	    fmt->format.height != tvp514x_std_list[decoder->current_std].height)
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index f23110c..f32495f 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -818,12 +818,12 @@
 }
 
 static int tvp5150_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
-						u32 *code)
+						enum v4l2_mbus_pixelcode *code)
 {
 	if (index)
 		return -EINVAL;
 
-	*code = MEDIA_BUS_FMT_UYVY8_2X8;
+	*code = V4L2_MBUS_FMT_UYVY8_2X8;
 	return 0;
 }
 
@@ -840,7 +840,7 @@
 	f->width = decoder->rect.width;
 	f->height = decoder->rect.height;
 
-	f->code = MEDIA_BUS_FMT_UYVY8_2X8;
+	f->code = V4L2_MBUS_FMT_UYVY8_2X8;
 	f->field = V4L2_FIELD_SEQ_TB;
 	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
 
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index 8d8e714..28f978e 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -626,7 +626,7 @@
 
 	f->width = bt->width;
 	f->height = bt->height;
-	f->code = MEDIA_BUS_FMT_YUYV10_1X20;
+	f->code = V4L2_MBUS_FMT_YUYV10_1X20;
 	f->field = device->current_timings->scanmode;
 	f->colorspace = device->current_timings->color_space;
 
@@ -756,12 +756,12 @@
  */
 
 static int tvp7002_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
-					u32 *code)
+					enum v4l2_mbus_pixelcode *code)
 {
 	/* Check requested format index is within range */
 	if (index)
 		return -EINVAL;
-	*code = MEDIA_BUS_FMT_YUYV10_1X20;
+	*code = V4L2_MBUS_FMT_YUYV10_1X20;
 	return 0;
 }
 
@@ -859,7 +859,7 @@
 	if (code->index != 0)
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_YUYV10_1X20;
+	code->code = V4L2_MBUS_FMT_YUYV10_1X20;
 
 	return 0;
 }
@@ -878,7 +878,7 @@
 {
 	struct tvp7002 *tvp7002 = to_tvp7002(sd);
 
-	fmt->format.code = MEDIA_BUS_FMT_YUYV10_1X20;
+	fmt->format.code = V4L2_MBUS_FMT_YUYV10_1X20;
 	fmt->format.width = tvp7002->current_timings->timings.bt.width;
 	fmt->format.height = tvp7002->current_timings->timings.bt.height;
 	fmt->format.field = tvp7002->current_timings->scanmode;
diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c
index 0127932..e315d8b 100644
--- a/drivers/media/i2c/vs6624.c
+++ b/drivers/media/i2c/vs6624.c
@@ -45,19 +45,19 @@
 };
 
 static const struct vs6624_format {
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 	enum v4l2_colorspace colorspace;
 } vs6624_formats[] = {
 	{
-		.mbus_code      = MEDIA_BUS_FMT_UYVY8_2X8,
+		.mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
 		.colorspace     = V4L2_COLORSPACE_JPEG,
 	},
 	{
-		.mbus_code      = MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
 		.colorspace     = V4L2_COLORSPACE_JPEG,
 	},
 	{
-		.mbus_code      = MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.mbus_code      = V4L2_MBUS_FMT_RGB565_2X8_LE,
 		.colorspace     = V4L2_COLORSPACE_SRGB,
 	},
 };
@@ -65,7 +65,7 @@
 static struct v4l2_mbus_framefmt vs6624_default_fmt = {
 	.width = VGA_WIDTH,
 	.height = VGA_HEIGHT,
-	.code = MEDIA_BUS_FMT_UYVY8_2X8,
+	.code = V4L2_MBUS_FMT_UYVY8_2X8,
 	.field = V4L2_FIELD_NONE,
 	.colorspace = V4L2_COLORSPACE_JPEG,
 };
@@ -558,7 +558,7 @@
 }
 
 static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
-				u32 *code)
+				enum v4l2_mbus_pixelcode *code)
 {
 	if (index >= ARRAY_SIZE(vs6624_formats))
 		return -EINVAL;
@@ -605,15 +605,15 @@
 
 	/* set image format */
 	switch (fmt->code) {
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
 		vs6624_write(sd, VS6624_YUV_SETUP, 0x1);
 		break;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
 		vs6624_write(sd, VS6624_YUV_SETUP, 0x3);
 		break;
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		vs6624_write(sd, VS6624_IMG_FMT0, 0x4);
 		vs6624_write(sd, VS6624_RGB_SETUP, 0x0);
 		break;
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 4d8e01c..37c334e 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -279,14 +279,8 @@
 				continue;
 
 			ret = entity->ops->link_validate(link);
-			if (ret < 0 && ret != -ENOIOCTLCMD) {
-				dev_dbg(entity->parent->dev,
-					"link validation failed for \"%s\":%u -> \"%s\":%u, error %d\n",
-					entity->name, link->source->index,
-					link->sink->entity->name,
-					link->sink->index, ret);
+			if (ret < 0 && ret != -ENOIOCTLCMD)
 				goto error;
-			}
 		}
 
 		/* Either no links or validated links are fine. */
@@ -294,11 +288,6 @@
 
 		if (!bitmap_full(active, entity->num_pads)) {
 			ret = -EPIPE;
-			dev_dbg(entity->parent->dev,
-				"\"%s\":%u must be connected by an enabled link\n",
-				entity->name,
-				(unsigned)find_first_zero_bit(
-					active, entity->num_pads));
 			goto error;
 		}
 	}
diff --git a/drivers/media/parport/Kconfig b/drivers/media/parport/Kconfig
new file mode 100644
index 0000000..ef209f5
--- /dev/null
+++ b/drivers/media/parport/Kconfig
@@ -0,0 +1,57 @@
+menuconfig MEDIA_PARPORT_SUPPORT
+	bool "ISA and parallel port devices"
+	depends on (ISA || PARPORT) && MEDIA_CAMERA_SUPPORT
+	help
+	  Enables drivers for ISA and parallel port bus. If you
+	  need media drivers using those legacy buses, say Y.
+
+if MEDIA_PARPORT_SUPPORT
+config VIDEO_BWQCAM
+	tristate "Quickcam BW Video For Linux"
+	depends on m
+	depends on PARPORT && VIDEO_V4L2
+	select VIDEOBUF2_VMALLOC
+	help
+	  Say Y have if you the black and white version of the QuickCam
+	  camera. See the next option for the color version.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bw-qcam.
+
+config VIDEO_CQCAM
+	tristate "QuickCam Colour Video For Linux"
+	depends on m
+	depends on PARPORT && VIDEO_V4L2
+	help
+	  This is the video4linux driver for the colour version of the
+	  Connectix QuickCam.  If you have one of these cameras, say Y here,
+	  otherwise say N.  This driver does not work with the original
+	  monochrome QuickCam, QuickCam VC or QuickClip.  It is also available
+	  as a module (c-qcam).
+	  Read <file:Documentation/video4linux/CQcam.txt> for more information.
+
+config VIDEO_PMS
+	tristate "Mediavision Pro Movie Studio Video For Linux"
+	depends on m
+	depends on ISA && VIDEO_V4L2
+	help
+	  Say Y if you have the ISA Mediavision Pro Movie Studio
+	  capture card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pms.
+
+config VIDEO_W9966
+	tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
+	depends on m
+	depends on PARPORT_1284 && PARPORT && VIDEO_V4L2
+	help
+	  Video4linux driver for Winbond's w9966 based Webcams.
+	  Currently tested with the LifeView FlyCam Supra.
+	  If you have one of these cameras, say Y here
+	  otherwise say N.
+	  This driver is also available as a module (w9966).
+
+	  Check out <file:Documentation/video4linux/w9966.txt> for more
+	  information.
+endif
diff --git a/drivers/media/parport/Makefile b/drivers/media/parport/Makefile
new file mode 100644
index 0000000..f0b2dbe
--- /dev/null
+++ b/drivers/media/parport/Makefile
@@ -0,0 +1,4 @@
+obj-$(CPTCFG_VIDEO_CQCAM) += c-qcam.o
+obj-$(CPTCFG_VIDEO_BWQCAM) += bw-qcam.o
+obj-$(CPTCFG_VIDEO_W9966) += w9966.o
+obj-$(CPTCFG_VIDEO_PMS) += pms.o
diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c
new file mode 100644
index 0000000..67b9da1
--- /dev/null
+++ b/drivers/media/parport/bw-qcam.c
@@ -0,0 +1,1177 @@
+/*
+ *    QuickCam Driver For Video4Linux.
+ *
+ *	Video4Linux conversion work by Alan Cox.
+ *	Parport compatibility by Phil Blundell.
+ *	Busy loop avoidance by Mark Cooke.
+ *
+ *    Module parameters:
+ *
+ *	maxpoll=<1 - 5000>
+ *
+ *	  When polling the QuickCam for a response, busy-wait for a
+ *	  maximum of this many loops. The default of 250 gives little
+ *	  impact on interactive response.
+ *
+ *	  NOTE: If this parameter is set too high, the processor
+ *		will busy wait until this loop times out, and then
+ *		slowly poll for a further 5 seconds before failing
+ *		the transaction. You have been warned.
+ *
+ *	yieldlines=<1 - 250>
+ *
+ *	  When acquiring a frame from the camera, the data gathering
+ *	  loop will yield back to the scheduler after completing
+ *	  this many lines. The default of 4 provides a trade-off
+ *	  between increased frame acquisition time and impact on
+ *	  interactive response.
+ */
+
+/* qcam-lib.c -- Library for programming with the Connectix QuickCam.
+ * See the included documentation for usage instructions and details
+ * of the protocol involved. */
+
+
+/* Version 0.5, August 4, 1996 */
+/* Version 0.7, August 27, 1996 */
+/* Version 0.9, November 17, 1996 */
+
+
+/******************************************************************
+
+Copyright (C) 1996 by Scott Laird
+
+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 SCOTT LAIRD 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 <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/parport.h>
+#include <linux/sched.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+
+/* One from column A... */
+#define QC_NOTSET 0
+#define QC_UNIDIR 1
+#define QC_BIDIR  2
+#define QC_SERIAL 3
+
+/* ... and one from column B */
+#define QC_ANY          0x00
+#define QC_FORCE_UNIDIR 0x10
+#define QC_FORCE_BIDIR  0x20
+#define QC_FORCE_SERIAL 0x30
+/* in the port_mode member */
+
+#define QC_MODE_MASK    0x07
+#define QC_FORCE_MASK   0x70
+
+#define MAX_HEIGHT 243
+#define MAX_WIDTH 336
+
+/* Bit fields for status flags */
+#define QC_PARAM_CHANGE	0x01 /* Camera status change has occurred */
+
+struct qcam {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct v4l2_ctrl_handler hdl;
+	struct vb2_queue vb_vidq;
+	struct pardevice *pdev;
+	struct parport *pport;
+	struct mutex lock;
+	struct mutex queue_lock;
+	int width, height;
+	int bpp;
+	int mode;
+	int contrast, brightness, whitebal;
+	int port_mode;
+	int transfer_scale;
+	int top, left;
+	int status;
+	unsigned int saved_bits;
+	unsigned long in_use;
+};
+
+static unsigned int maxpoll = 250;   /* Maximum busy-loop count for qcam I/O */
+static unsigned int yieldlines = 4;  /* Yield after this many during capture */
+static int video_nr = -1;
+static unsigned int force_init;		/* Whether to probe aggressively */
+
+module_param(maxpoll, int, 0);
+module_param(yieldlines, int, 0);
+module_param(video_nr, int, 0);
+
+/* Set force_init=1 to avoid detection by polling status register and
+ * immediately attempt to initialize qcam */
+module_param(force_init, int, 0);
+
+#define MAX_CAMS 4
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline int read_lpstatus(struct qcam *q)
+{
+	return parport_read_status(q->pport);
+}
+
+static inline int read_lpdata(struct qcam *q)
+{
+	return parport_read_data(q->pport);
+}
+
+static inline void write_lpdata(struct qcam *q, int d)
+{
+	parport_write_data(q->pport, d);
+}
+
+static void write_lpcontrol(struct qcam *q, int d)
+{
+	if (d & 0x20) {
+		/* Set bidirectional mode to reverse (data in) */
+		parport_data_reverse(q->pport);
+	} else {
+		/* Set bidirectional mode to forward (data out) */
+		parport_data_forward(q->pport);
+	}
+
+	/* Now issue the regular port command, but strip out the
+	 * direction flag */
+	d &= ~0x20;
+	parport_write_control(q->pport, d);
+}
+
+
+/* qc_waithand busy-waits for a handshake signal from the QuickCam.
+ * Almost all communication with the camera requires handshaking. */
+
+static int qc_waithand(struct qcam *q, int val)
+{
+	int status;
+	int runs = 0;
+
+	if (val) {
+		while (!((status = read_lpstatus(q)) & 8)) {
+			/* 1000 is enough spins on the I/O for all normal
+			   cases, at that point we start to poll slowly
+			   until the camera wakes up. However, we are
+			   busy blocked until the camera responds, so
+			   setting it lower is much better for interactive
+			   response. */
+
+			if (runs++ > maxpoll)
+				msleep_interruptible(5);
+			if (runs > (maxpoll + 1000)) /* 5 seconds */
+				return -1;
+		}
+	} else {
+		while (((status = read_lpstatus(q)) & 8)) {
+			/* 1000 is enough spins on the I/O for all normal
+			   cases, at that point we start to poll slowly
+			   until the camera wakes up. However, we are
+			   busy blocked until the camera responds, so
+			   setting it lower is much better for interactive
+			   response. */
+
+			if (runs++ > maxpoll)
+				msleep_interruptible(5);
+			if (runs++ > (maxpoll + 1000)) /* 5 seconds */
+				return -1;
+		}
+	}
+
+	return status;
+}
+
+/* Waithand2 is used when the qcam is in bidirectional mode, and the
+ * handshaking signal is CamRdy2 (bit 0 of data reg) instead of CamRdy1
+ * (bit 3 of status register).  It also returns the last value read,
+ * since this data is useful. */
+
+static unsigned int qc_waithand2(struct qcam *q, int val)
+{
+	unsigned int status;
+	int runs = 0;
+
+	do {
+		status = read_lpdata(q);
+		/* 1000 is enough spins on the I/O for all normal
+		   cases, at that point we start to poll slowly
+		   until the camera wakes up. However, we are
+		   busy blocked until the camera responds, so
+		   setting it lower is much better for interactive
+		   response. */
+
+		if (runs++ > maxpoll)
+			msleep_interruptible(5);
+		if (runs++ > (maxpoll + 1000)) /* 5 seconds */
+			return 0;
+	} while ((status & 1) != val);
+
+	return status;
+}
+
+/* qc_command is probably a bit of a misnomer -- it's used to send
+ * bytes *to* the camera.  Generally, these bytes are either commands
+ * or arguments to commands, so the name fits, but it still bugs me a
+ * bit.  See the documentation for a list of commands. */
+
+static int qc_command(struct qcam *q, int command)
+{
+	int n1, n2;
+	int cmd;
+
+	write_lpdata(q, command);
+	write_lpcontrol(q, 6);
+
+	n1 = qc_waithand(q, 1);
+
+	write_lpcontrol(q, 0xe);
+	n2 = qc_waithand(q, 0);
+
+	cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+	return cmd;
+}
+
+static int qc_readparam(struct qcam *q)
+{
+	int n1, n2;
+	int cmd;
+
+	write_lpcontrol(q, 6);
+	n1 = qc_waithand(q, 1);
+
+	write_lpcontrol(q, 0xe);
+	n2 = qc_waithand(q, 0);
+
+	cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+	return cmd;
+}
+
+
+/* Try to detect a QuickCam.  It appears to flash the upper 4 bits of
+   the status register at 5-10 Hz.  This is only used in the autoprobe
+   code.  Be aware that this isn't the way Connectix detects the
+   camera (they send a reset and try to handshake), but this should be
+   almost completely safe, while their method screws up my printer if
+   I plug it in before the camera. */
+
+static int qc_detect(struct qcam *q)
+{
+	int reg, lastreg;
+	int count = 0;
+	int i;
+
+	if (force_init)
+		return 1;
+
+	lastreg = reg = read_lpstatus(q) & 0xf0;
+
+	for (i = 0; i < 500; i++) {
+		reg = read_lpstatus(q) & 0xf0;
+		if (reg != lastreg)
+			count++;
+		lastreg = reg;
+		mdelay(2);
+	}
+
+
+#if 0
+	/* Force camera detection during testing. Sometimes the camera
+	   won't be flashing these bits. Possibly unloading the module
+	   in the middle of a grab? Or some timeout condition?
+	   I've seen this parameter as low as 19 on my 450Mhz box - mpc */
+	printk(KERN_DEBUG "Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count);
+	return 1;
+#endif
+
+	/* Be (even more) liberal in what you accept...  */
+
+	if (count > 20 && count < 400) {
+		return 1;	/* found */
+	} else {
+		printk(KERN_ERR "No Quickcam found on port %s\n",
+				q->pport->name);
+		printk(KERN_DEBUG "Quickcam detection counter: %u\n", count);
+		return 0;	/* not found */
+	}
+}
+
+/* Decide which scan mode to use.  There's no real requirement that
+ * the scanmode match the resolution in q->height and q-> width -- the
+ * camera takes the picture at the resolution specified in the
+ * "scanmode" and then returns the image at the resolution specified
+ * with the resolution commands.  If the scan is bigger than the
+ * requested resolution, the upper-left hand corner of the scan is
+ * returned.  If the scan is smaller, then the rest of the image
+ * returned contains garbage. */
+
+static int qc_setscanmode(struct qcam *q)
+{
+	int old_mode = q->mode;
+
+	switch (q->transfer_scale) {
+	case 1:
+		q->mode = 0;
+		break;
+	case 2:
+		q->mode = 4;
+		break;
+	case 4:
+		q->mode = 8;
+		break;
+	}
+
+	switch (q->bpp) {
+	case 4:
+		break;
+	case 6:
+		q->mode += 2;
+		break;
+	}
+
+	switch (q->port_mode & QC_MODE_MASK) {
+	case QC_BIDIR:
+		q->mode += 1;
+		break;
+	case QC_NOTSET:
+	case QC_UNIDIR:
+		break;
+	}
+
+	if (q->mode != old_mode)
+		q->status |= QC_PARAM_CHANGE;
+
+	return 0;
+}
+
+
+/* Reset the QuickCam.  This uses the same sequence the Windows
+ * QuickPic program uses.  Someone with a bi-directional port should
+ * check that bi-directional mode is detected right, and then
+ * implement bi-directional mode in qc_readbyte(). */
+
+static void qc_reset(struct qcam *q)
+{
+	switch (q->port_mode & QC_FORCE_MASK) {
+	case QC_FORCE_UNIDIR:
+		q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+		break;
+
+	case QC_FORCE_BIDIR:
+		q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+		break;
+
+	case QC_ANY:
+		write_lpcontrol(q, 0x20);
+		write_lpdata(q, 0x75);
+
+		if (read_lpdata(q) != 0x75)
+			q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+		else
+			q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+		break;
+	}
+
+	write_lpcontrol(q, 0xb);
+	udelay(250);
+	write_lpcontrol(q, 0xe);
+	qc_setscanmode(q);		/* in case port_mode changed */
+}
+
+
+
+/* Reset the QuickCam and program for brightness, contrast,
+ * white-balance, and resolution. */
+
+static void qc_set(struct qcam *q)
+{
+	int val;
+	int val2;
+
+	/* Set the brightness.  Yes, this is repetitive, but it works.
+	 * Shorter versions seem to fail subtly.  Feel free to try :-). */
+	/* I think the problem was in qc_command, not here -- bls */
+
+	qc_command(q, 0xb);
+	qc_command(q, q->brightness);
+
+	val = q->height / q->transfer_scale;
+	qc_command(q, 0x11);
+	qc_command(q, val);
+	if ((q->port_mode & QC_MODE_MASK) == QC_UNIDIR && q->bpp == 6) {
+		/* The normal "transfers per line" calculation doesn't seem to work
+		   as expected here (and yet it works fine in qc_scan).  No idea
+		   why this case is the odd man out.  Fortunately, Laird's original
+		   working version gives me a good way to guess at working values.
+		   -- bls */
+		val = q->width;
+		val2 = q->transfer_scale * 4;
+	} else {
+		val = q->width * q->bpp;
+		val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
+			q->transfer_scale;
+	}
+	val = DIV_ROUND_UP(val, val2);
+	qc_command(q, 0x13);
+	qc_command(q, val);
+
+	/* Setting top and left -- bls */
+	qc_command(q, 0xd);
+	qc_command(q, q->top);
+	qc_command(q, 0xf);
+	qc_command(q, q->left / 2);
+
+	qc_command(q, 0x19);
+	qc_command(q, q->contrast);
+	qc_command(q, 0x1f);
+	qc_command(q, q->whitebal);
+
+	/* Clear flag that we must update the grabbing parameters on the camera
+	   before we grab the next frame */
+	q->status &= (~QC_PARAM_CHANGE);
+}
+
+/* Qc_readbytes reads some bytes from the QC and puts them in
+   the supplied buffer.  It returns the number of bytes read,
+   or -1 on error. */
+
+static inline int qc_readbytes(struct qcam *q, char buffer[])
+{
+	int ret = 1;
+	unsigned int hi, lo;
+	unsigned int hi2, lo2;
+	static int state;
+
+	if (buffer == NULL) {
+		state = 0;
+		return 0;
+	}
+
+	switch (q->port_mode & QC_MODE_MASK) {
+	case QC_BIDIR:		/* Bi-directional Port */
+		write_lpcontrol(q, 0x26);
+		lo = (qc_waithand2(q, 1) >> 1);
+		hi = (read_lpstatus(q) >> 3) & 0x1f;
+		write_lpcontrol(q, 0x2e);
+		lo2 = (qc_waithand2(q, 0) >> 1);
+		hi2 = (read_lpstatus(q) >> 3) & 0x1f;
+		switch (q->bpp) {
+		case 4:
+			buffer[0] = lo & 0xf;
+			buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3);
+			buffer[2] = (hi & 0x1e) >> 1;
+			buffer[3] = lo2 & 0xf;
+			buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3);
+			buffer[5] = (hi2 & 0x1e) >> 1;
+			ret = 6;
+			break;
+		case 6:
+			buffer[0] = lo & 0x3f;
+			buffer[1] = ((lo & 0x40) >> 6) | (hi << 1);
+			buffer[2] = lo2 & 0x3f;
+			buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1);
+			ret = 4;
+			break;
+		}
+		break;
+
+	case QC_UNIDIR:	/* Unidirectional Port */
+		write_lpcontrol(q, 6);
+		lo = (qc_waithand(q, 1) & 0xf0) >> 4;
+		write_lpcontrol(q, 0xe);
+		hi = (qc_waithand(q, 0) & 0xf0) >> 4;
+
+		switch (q->bpp) {
+		case 4:
+			buffer[0] = lo;
+			buffer[1] = hi;
+			ret = 2;
+			break;
+		case 6:
+			switch (state) {
+			case 0:
+				buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
+				q->saved_bits = (hi & 3) << 4;
+				state = 1;
+				ret = 1;
+				break;
+			case 1:
+				buffer[0] = lo | q->saved_bits;
+				q->saved_bits = hi << 2;
+				state = 2;
+				ret = 1;
+				break;
+			case 2:
+				buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits;
+				buffer[1] = ((lo & 3) << 4) | hi;
+				state = 0;
+				ret = 2;
+				break;
+			}
+			break;
+		}
+		break;
+	}
+	return ret;
+}
+
+/* requests a scan from the camera.  It sends the correct instructions
+ * to the camera and then reads back the correct number of bytes.  In
+ * previous versions of this routine the return structure contained
+ * the raw output from the camera, and there was a 'qc_convertscan'
+ * function that converted that to a useful format.  In version 0.3 I
+ * rolled qc_convertscan into qc_scan and now I only return the
+ * converted scan.  The format is just an one-dimensional array of
+ * characters, one for each pixel, with 0=black up to n=white, where
+ * n=2^(bit depth)-1.  Ask me for more details if you don't understand
+ * this. */
+
+static long qc_capture(struct qcam *q, u8 *buf, unsigned long len)
+{
+	int i, j, k, yield;
+	int bytes;
+	int linestotrans, transperline;
+	int divisor;
+	int pixels_per_line;
+	int pixels_read = 0;
+	int got = 0;
+	char buffer[6];
+	int  shift = 8 - q->bpp;
+	char invert;
+
+	if (q->mode == -1)
+		return -ENXIO;
+
+	qc_command(q, 0x7);
+	qc_command(q, q->mode);
+
+	if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) {
+		write_lpcontrol(q, 0x2e);	/* turn port around */
+		write_lpcontrol(q, 0x26);
+		qc_waithand(q, 1);
+		write_lpcontrol(q, 0x2e);
+		qc_waithand(q, 0);
+	}
+
+	/* strange -- should be 15:63 below, but 4bpp is odd */
+	invert = (q->bpp == 4) ? 16 : 63;
+
+	linestotrans = q->height / q->transfer_scale;
+	pixels_per_line = q->width / q->transfer_scale;
+	transperline = q->width * q->bpp;
+	divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
+		q->transfer_scale;
+	transperline = DIV_ROUND_UP(transperline, divisor);
+
+	for (i = 0, yield = yieldlines; i < linestotrans; i++) {
+		for (pixels_read = j = 0; j < transperline; j++) {
+			bytes = qc_readbytes(q, buffer);
+			for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) {
+				int o;
+				if (buffer[k] == 0 && invert == 16) {
+					/* 4bpp is odd (again) -- inverter is 16, not 15, but output
+					   must be 0-15 -- bls */
+					buffer[k] = 16;
+				}
+				o = i * pixels_per_line + pixels_read + k;
+				if (o < len) {
+					u8 ch = invert - buffer[k];
+					got++;
+					buf[o] = ch << shift;
+				}
+			}
+			pixels_read += bytes;
+		}
+		qc_readbytes(q, NULL);	/* reset state machine */
+
+		/* Grabbing an entire frame from the quickcam is a lengthy
+		   process. We don't (usually) want to busy-block the
+		   processor for the entire frame. yieldlines is a module
+		   parameter. If we yield every line, the minimum frame
+		   time will be 240 / 200 = 1.2 seconds. The compile-time
+		   default is to yield every 4 lines. */
+		if (i >= yield) {
+			msleep_interruptible(5);
+			yield = i + yieldlines;
+		}
+	}
+
+	if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) {
+		write_lpcontrol(q, 2);
+		write_lpcontrol(q, 6);
+		udelay(3);
+		write_lpcontrol(q, 0xe);
+	}
+	if (got < len)
+		return got;
+	return len;
+}
+
+/* ------------------------------------------------------------------
+	Videobuf operations
+   ------------------------------------------------------------------*/
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct qcam *dev = vb2_get_drv_priv(vq);
+
+	if (0 == *nbuffers)
+		*nbuffers = 3;
+	*nplanes = 1;
+	mutex_lock(&dev->lock);
+	if (fmt)
+		sizes[0] = fmt->fmt.pix.width * fmt->fmt.pix.height;
+	else
+		sizes[0] = (dev->width / dev->transfer_scale) *
+		   (dev->height / dev->transfer_scale);
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+	vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+}
+
+static void buffer_finish(struct vb2_buffer *vb)
+{
+	struct qcam *qcam = vb2_get_drv_priv(vb->vb2_queue);
+	void *vbuf = vb2_plane_vaddr(vb, 0);
+	int size = vb->vb2_queue->plane_sizes[0];
+	int len;
+
+	if (!vb2_is_streaming(vb->vb2_queue))
+		return;
+
+	mutex_lock(&qcam->lock);
+	parport_claim_or_block(qcam->pdev);
+
+	qc_reset(qcam);
+
+	/* Update the camera parameters if we need to */
+	if (qcam->status & QC_PARAM_CHANGE)
+		qc_set(qcam);
+
+	len = qc_capture(qcam, vbuf, size);
+
+	parport_release(qcam->pdev);
+	mutex_unlock(&qcam->lock);
+	v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+	if (len != size)
+		vb->state = VB2_BUF_STATE_ERROR;
+	vb2_set_plane_payload(vb, 0, len);
+}
+
+static struct vb2_ops qcam_video_qops = {
+	.queue_setup		= queue_setup,
+	.buf_queue		= buffer_queue,
+	.buf_finish		= buffer_finish,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+};
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int qcam_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *vcap)
+{
+	struct qcam *qcam = video_drvdata(file);
+
+	strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+	strlcpy(vcap->card, "Connectix B&W Quickcam", sizeof(vcap->card));
+	strlcpy(vcap->bus_info, qcam->pport->name, sizeof(vcap->bus_info));
+	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+				V4L2_CAP_STREAMING;
+	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	if (vin->index > 0)
+		return -EINVAL;
+	strlcpy(vin->name, "Camera", sizeof(vin->name));
+	vin->type = V4L2_INPUT_TYPE_CAMERA;
+	vin->audioset = 0;
+	vin->tuner = 0;
+	vin->std = 0;
+	vin->status = 0;
+	return 0;
+}
+
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+	*inp = 0;
+	return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct qcam *qcam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	pix->width = qcam->width / qcam->transfer_scale;
+	pix->height = qcam->height / qcam->transfer_scale;
+	pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = pix->width;
+	pix->sizeimage = pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->height <= 60 || pix->width <= 80) {
+		pix->height = 60;
+		pix->width = 80;
+	} else if (pix->height <= 120 || pix->width <= 160) {
+		pix->height = 120;
+		pix->width = 160;
+	} else {
+		pix->height = 240;
+		pix->width = 320;
+	}
+	if (pix->pixelformat != V4L2_PIX_FMT_Y4 &&
+	    pix->pixelformat != V4L2_PIX_FMT_Y6)
+		pix->pixelformat = V4L2_PIX_FMT_Y4;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = pix->width;
+	pix->sizeimage = pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct qcam *qcam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+	if (ret)
+		return ret;
+	if (vb2_is_busy(&qcam->vb_vidq))
+		return -EBUSY;
+	qcam->width = 320;
+	qcam->height = 240;
+	if (pix->height == 60)
+		qcam->transfer_scale = 4;
+	else if (pix->height == 120)
+		qcam->transfer_scale = 2;
+	else
+		qcam->transfer_scale = 1;
+	if (pix->pixelformat == V4L2_PIX_FMT_Y6)
+		qcam->bpp = 6;
+	else
+		qcam->bpp = 4;
+
+	qc_setscanmode(qcam);
+	/* We must update the camera before we grab. We could
+	   just have changed the grab size */
+	qcam->status |= QC_PARAM_CHANGE;
+	return 0;
+}
+
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
+		  { 0, 0, 0, 0 }
+		},
+		{ 1, 0, 0,
+		  "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
+		  { 0, 0, 0, 0 }
+		},
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 1)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+static int qcam_enum_framesizes(struct file *file, void *fh,
+					 struct v4l2_frmsizeenum *fsize)
+{
+	static const struct v4l2_frmsize_discrete sizes[] = {
+		{  80,  60 },
+		{ 160, 120 },
+		{ 320, 240 },
+	};
+
+	if (fsize->index > 2)
+		return -EINVAL;
+	if (fsize->pixel_format != V4L2_PIX_FMT_Y4 &&
+	    fsize->pixel_format != V4L2_PIX_FMT_Y6)
+		return -EINVAL;
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fsize->discrete = sizes[fsize->index];
+	return 0;
+}
+
+static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct qcam *qcam =
+		container_of(ctrl->handler, struct qcam, hdl);
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		qcam->brightness = ctrl->val;
+		break;
+	case V4L2_CID_CONTRAST:
+		qcam->contrast = ctrl->val;
+		break;
+	case V4L2_CID_GAMMA:
+		qcam->whitebal = ctrl->val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (ret == 0)
+		qcam->status |= QC_PARAM_CHANGE;
+	return ret;
+}
+
+static const struct v4l2_file_operations qcam_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= vb2_fop_release,
+	.poll		= vb2_fop_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.read		= vb2_fop_read,
+	.mmap		= vb2_fop_mmap,
+};
+
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+	.vidioc_querycap    		    = qcam_querycap,
+	.vidioc_g_input      		    = qcam_g_input,
+	.vidioc_s_input      		    = qcam_s_input,
+	.vidioc_enum_input   		    = qcam_enum_input,
+	.vidioc_enum_fmt_vid_cap 	    = qcam_enum_fmt_vid_cap,
+	.vidioc_enum_framesizes		    = qcam_enum_framesizes,
+	.vidioc_g_fmt_vid_cap 		    = qcam_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap  		    = qcam_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap  	    = qcam_try_fmt_vid_cap,
+	.vidioc_reqbufs			    = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs		    = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf		    = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf		    = vb2_ioctl_querybuf,
+	.vidioc_qbuf			    = vb2_ioctl_qbuf,
+	.vidioc_dqbuf			    = vb2_ioctl_dqbuf,
+	.vidioc_streamon		    = vb2_ioctl_streamon,
+	.vidioc_streamoff		    = vb2_ioctl_streamoff,
+	.vidioc_log_status		    = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
+	.s_ctrl = qcam_s_ctrl,
+};
+
+/* Initialize the QuickCam driver control structure.  This is where
+ * defaults are set for people who don't have a config file.*/
+
+static struct qcam *qcam_init(struct parport *port)
+{
+	struct qcam *qcam;
+	struct v4l2_device *v4l2_dev;
+	struct vb2_queue *q;
+	int err;
+
+	qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL);
+	if (qcam == NULL)
+		return NULL;
+
+	v4l2_dev = &qcam->v4l2_dev;
+	snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%u", num_cams);
+
+	if (v4l2_device_register(port->dev, v4l2_dev) < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		kfree(qcam);
+		return NULL;
+	}
+
+	v4l2_ctrl_handler_init(&qcam->hdl, 3);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 180);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 255, 1, 192);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_GAMMA, 0, 255, 1, 105);
+	if (qcam->hdl.error) {
+		v4l2_err(v4l2_dev, "couldn't register controls\n");
+		goto exit;
+	}
+
+	mutex_init(&qcam->lock);
+	mutex_init(&qcam->queue_lock);
+
+	/* initialize queue */
+	q = &qcam->vb_vidq;
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	q->drv_priv = qcam;
+	q->ops = &qcam_video_qops;
+	q->mem_ops = &vb2_vmalloc_memops;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	err = vb2_queue_init(q);
+	if (err < 0) {
+		v4l2_err(v4l2_dev, "couldn't init vb2_queue for %s.\n", port->name);
+		goto exit;
+	}
+	qcam->vdev.queue = q;
+	qcam->vdev.queue->lock = &qcam->queue_lock;
+
+	qcam->pport = port;
+	qcam->pdev = parport_register_device(port, v4l2_dev->name, NULL, NULL,
+			NULL, 0, NULL);
+	if (qcam->pdev == NULL) {
+		v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+		goto exit;
+	}
+
+	strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name));
+	qcam->vdev.v4l2_dev = v4l2_dev;
+	qcam->vdev.ctrl_handler = &qcam->hdl;
+	qcam->vdev.fops = &qcam_fops;
+	qcam->vdev.lock = &qcam->lock;
+	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+	qcam->vdev.release = video_device_release_empty;
+	video_set_drvdata(&qcam->vdev, qcam);
+
+	qcam->port_mode = (QC_ANY | QC_NOTSET);
+	qcam->width = 320;
+	qcam->height = 240;
+	qcam->bpp = 4;
+	qcam->transfer_scale = 2;
+	qcam->contrast = 192;
+	qcam->brightness = 180;
+	qcam->whitebal = 105;
+	qcam->top = 1;
+	qcam->left = 14;
+	qcam->mode = -1;
+	qcam->status = QC_PARAM_CHANGE;
+	return qcam;
+
+exit:
+	v4l2_ctrl_handler_free(&qcam->hdl);
+	kfree(qcam);
+	return NULL;
+}
+
+static int qc_calibrate(struct qcam *q)
+{
+	/*
+	 *	Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
+	 *	The white balance is an individual value for each
+	 *	quickcam.
+	 */
+
+	int value;
+	int count = 0;
+
+	qc_command(q, 27);	/* AutoAdjustOffset */
+	qc_command(q, 0);	/* Dummy Parameter, ignored by the camera */
+
+	/* GetOffset (33) will read 255 until autocalibration */
+	/* is finished. After that, a value of 1-254 will be */
+	/* returned. */
+
+	do {
+		qc_command(q, 33);
+		value = qc_readparam(q);
+		mdelay(1);
+		schedule();
+		count++;
+	} while (value == 0xff && count < 2048);
+
+	q->whitebal = value;
+	return value;
+}
+
+static int init_bwqcam(struct parport *port)
+{
+	struct qcam *qcam;
+
+	if (num_cams == MAX_CAMS) {
+		printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
+		return -ENOSPC;
+	}
+
+	qcam = qcam_init(port);
+	if (qcam == NULL)
+		return -ENODEV;
+
+	parport_claim_or_block(qcam->pdev);
+
+	qc_reset(qcam);
+
+	if (qc_detect(qcam) == 0) {
+		parport_release(qcam->pdev);
+		parport_unregister_device(qcam->pdev);
+		kfree(qcam);
+		return -ENODEV;
+	}
+	qc_calibrate(qcam);
+	v4l2_ctrl_handler_setup(&qcam->hdl);
+
+	parport_release(qcam->pdev);
+
+	v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name);
+
+	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+		parport_unregister_device(qcam->pdev);
+		kfree(qcam);
+		return -ENODEV;
+	}
+
+	qcams[num_cams++] = qcam;
+
+	return 0;
+}
+
+static void close_bwqcam(struct qcam *qcam)
+{
+	video_unregister_device(&qcam->vdev);
+	v4l2_ctrl_handler_free(&qcam->hdl);
+	parport_unregister_device(qcam->pdev);
+	kfree(qcam);
+}
+
+/* The parport parameter controls which parports will be scanned.
+ * Scanning all parports causes some printers to print a garbage page.
+ *       -- March 14, 1999  Billy Donahue <billy@escape.com> */
+#ifdef MODULE
+static char *parport[MAX_CAMS] = { NULL, };
+module_param_array(parport, charp, NULL, 0);
+#endif
+
+static int accept_bwqcam(struct parport *port)
+{
+#ifdef MODULE
+	int n;
+
+	if (parport[0] && strncmp(parport[0], "auto", 4) != 0) {
+		/* user gave parport parameters */
+		for (n = 0; n < MAX_CAMS && parport[n]; n++) {
+			char *ep;
+			unsigned long r;
+			r = simple_strtoul(parport[n], &ep, 0);
+			if (ep == parport[n]) {
+				printk(KERN_ERR
+					"bw-qcam: bad port specifier \"%s\"\n",
+					parport[n]);
+				continue;
+			}
+			if (r == port->number)
+				return 1;
+		}
+		return 0;
+	}
+#endif
+	return 1;
+}
+
+static void bwqcam_attach(struct parport *port)
+{
+	if (accept_bwqcam(port))
+		init_bwqcam(port);
+}
+
+static void bwqcam_detach(struct parport *port)
+{
+	int i;
+	for (i = 0; i < num_cams; i++) {
+		struct qcam *qcam = qcams[i];
+		if (qcam && qcam->pdev->port == port) {
+			qcams[i] = NULL;
+			close_bwqcam(qcam);
+		}
+	}
+}
+
+static struct parport_driver bwqcam_driver = {
+	.name	= "bw-qcam",
+	.attach	= bwqcam_attach,
+	.detach	= bwqcam_detach,
+};
+
+static void __exit exit_bw_qcams(void)
+{
+	parport_unregister_driver(&bwqcam_driver);
+}
+
+static int __init init_bw_qcams(void)
+{
+#ifdef MODULE
+	/* Do some sanity checks on the module parameters. */
+	if (maxpoll > 5000) {
+		printk(KERN_INFO "Connectix Quickcam max-poll was above 5000. Using 5000.\n");
+		maxpoll = 5000;
+	}
+
+	if (yieldlines < 1) {
+		printk(KERN_INFO "Connectix Quickcam yieldlines was less than 1. Using 1.\n");
+		yieldlines = 1;
+	}
+#endif
+	return parport_register_driver(&bwqcam_driver);
+}
+
+module_init(init_bw_qcams);
+module_exit(exit_bw_qcams);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
diff --git a/drivers/media/parport/c-qcam.c b/drivers/media/parport/c-qcam.c
new file mode 100644
index 0000000..b9010bd
--- /dev/null
+++ b/drivers/media/parport/c-qcam.c
@@ -0,0 +1,882 @@
+/*
+ *	Video4Linux Colour QuickCam driver
+ *	Copyright 1997-2000 Philip Blundell <philb@gnu.org>
+ *
+ *    Module parameters:
+ *
+ *	parport=auto      -- probe all parports (default)
+ *	parport=0         -- parport0 becomes qcam1
+ *	parport=2,0,1     -- parports 2,0,1 are tried in that order
+ *
+ *	probe=0		  -- do no probing, assume camera is present
+ *	probe=1		  -- use IEEE-1284 autoprobe data only (default)
+ *	probe=2		  -- probe aggressively for cameras
+ *
+ *	force_rgb=1       -- force data format to RGB (default is BGR)
+ *
+ * The parport parameter controls which parports will be scanned.
+ * Scanning all parports causes some printers to print a garbage page.
+ *       -- March 14, 1999  Billy Donahue <billy@escape.com>
+ *
+ * Fixed data format to BGR, added force_rgb parameter. Added missing
+ * parport_unregister_driver() on module removal.
+ *       -- May 28, 2000  Claudio Matsuoka <claudio@conectiva.com>
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/parport.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/jiffies.h>
+#include <linux/videodev2.h>
+#include <asm/uaccess.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+
+struct qcam {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct v4l2_ctrl_handler hdl;
+	struct pardevice *pdev;
+	struct parport *pport;
+	int width, height;
+	int ccd_width, ccd_height;
+	int mode;
+	int contrast, brightness, whitebal;
+	int top, left;
+	unsigned int bidirectional;
+	struct mutex lock;
+};
+
+/* cameras maximum */
+#define MAX_CAMS 4
+
+/* The three possible QuickCam modes */
+#define QC_MILLIONS	0x18
+#define QC_BILLIONS	0x10
+#define QC_THOUSANDS	0x08	/* with VIDEC compression (not supported) */
+
+/* The three possible decimations */
+#define QC_DECIMATION_1		0
+#define QC_DECIMATION_2		2
+#define QC_DECIMATION_4		4
+
+#define BANNER "Colour QuickCam for Video4Linux v0.06"
+
+static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
+static int probe = 2;
+static bool force_rgb;
+static int video_nr = -1;
+
+/* FIXME: parport=auto would never have worked, surely? --RR */
+MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
+			  "probe=<0|1|2> for camera detection method\n"
+			  "force_rgb=<0|1> for RGB data format (default BGR)");
+module_param_array(parport, int, NULL, 0);
+module_param(probe, int, 0);
+module_param(force_rgb, bool, 0);
+module_param(video_nr, int, 0);
+
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
+{
+	/* note: the QC specs refer to the PCAck pin by voltage, not
+	   software level.  PC ports have builtin inverters. */
+	parport_frob_control(qcam->pport, 8, i ? 8 : 0);
+}
+
+static inline unsigned int qcam_ready1(struct qcam *qcam)
+{
+	return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
+}
+
+static inline unsigned int qcam_ready2(struct qcam *qcam)
+{
+	return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
+}
+
+static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
+{
+	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+	unsigned long oldjiffies = jiffies;
+	unsigned int i;
+
+	for (oldjiffies = jiffies;
+	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
+		if (qcam_ready1(qcam) == value)
+			return 0;
+
+	/* If the camera didn't respond within 1/25 second, poll slowly
+	   for a while. */
+	for (i = 0; i < 50; i++) {
+		if (qcam_ready1(qcam) == value)
+			return 0;
+		msleep_interruptible(100);
+	}
+
+	/* Probably somebody pulled the plug out.  Not much we can do. */
+	v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
+	       parport_read_status(qcam->pport),
+	       parport_read_control(qcam->pport));
+	return 1;
+}
+
+static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
+{
+	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+	unsigned long oldjiffies = jiffies;
+	unsigned int i;
+
+	for (oldjiffies = jiffies;
+	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
+		if (qcam_ready2(qcam) == value)
+			return 0;
+
+	/* If the camera didn't respond within 1/25 second, poll slowly
+	   for a while. */
+	for (i = 0; i < 50; i++) {
+		if (qcam_ready2(qcam) == value)
+			return 0;
+		msleep_interruptible(100);
+	}
+
+	/* Probably somebody pulled the plug out.  Not much we can do. */
+	v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
+	       parport_read_status(qcam->pport),
+	       parport_read_control(qcam->pport),
+	       parport_read_data(qcam->pport));
+	return 1;
+}
+
+static int qcam_read_data(struct qcam *qcam)
+{
+	unsigned int idata;
+
+	qcam_set_ack(qcam, 0);
+	if (qcam_await_ready1(qcam, 1))
+		return -1;
+	idata = parport_read_status(qcam->pport) & 0xf0;
+	qcam_set_ack(qcam, 1);
+	if (qcam_await_ready1(qcam, 0))
+		return -1;
+	idata |= parport_read_status(qcam->pport) >> 4;
+	return idata;
+}
+
+static int qcam_write_data(struct qcam *qcam, unsigned int data)
+{
+	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+	unsigned int idata;
+
+	parport_write_data(qcam->pport, data);
+	idata = qcam_read_data(qcam);
+	if (data != idata) {
+		v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
+		       idata);
+		return 1;
+	}
+	return 0;
+}
+
+static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
+{
+	if (qcam_write_data(qcam, cmd))
+		return -1;
+	if (qcam_write_data(qcam, data))
+		return -1;
+	return 0;
+}
+
+static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
+{
+	if (qcam_write_data(qcam, cmd))
+		return -1;
+	return qcam_read_data(qcam);
+}
+
+static int qc_detect(struct qcam *qcam)
+{
+	unsigned int stat, ostat, i, count = 0;
+
+	/* The probe routine below is not very reliable.  The IEEE-1284
+	   probe takes precedence. */
+	/* XXX Currently parport provides no way to distinguish between
+	   "the IEEE probe was not done" and "the probe was done, but
+	   no device was found".  Fix this one day. */
+	if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
+	    && qcam->pport->probe_info[0].model
+	    && !strcmp(qcam->pdev->port->probe_info[0].model,
+		       "Color QuickCam 2.0")) {
+		printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
+		return 1;
+	}
+
+	if (probe < 2)
+		return 0;
+
+	parport_write_control(qcam->pport, 0xc);
+
+	/* look for a heartbeat */
+	ostat = stat = parport_read_status(qcam->pport);
+	for (i = 0; i < 250; i++) {
+		mdelay(1);
+		stat = parport_read_status(qcam->pport);
+		if (ostat != stat) {
+			if (++count >= 3)
+				return 1;
+			ostat = stat;
+		}
+	}
+
+	/* Reset the camera and try again */
+	parport_write_control(qcam->pport, 0xc);
+	parport_write_control(qcam->pport, 0x8);
+	mdelay(1);
+	parport_write_control(qcam->pport, 0xc);
+	mdelay(1);
+	count = 0;
+
+	ostat = stat = parport_read_status(qcam->pport);
+	for (i = 0; i < 250; i++) {
+		mdelay(1);
+		stat = parport_read_status(qcam->pport);
+		if (ostat != stat) {
+			if (++count >= 3)
+				return 1;
+			ostat = stat;
+		}
+	}
+
+	/* no (or flatline) camera, give up */
+	return 0;
+}
+
+static void qc_reset(struct qcam *qcam)
+{
+	parport_write_control(qcam->pport, 0xc);
+	parport_write_control(qcam->pport, 0x8);
+	mdelay(1);
+	parport_write_control(qcam->pport, 0xc);
+	mdelay(1);
+}
+
+/* Reset the QuickCam and program for brightness, contrast,
+ * white-balance, and resolution. */
+
+static void qc_setup(struct qcam *qcam)
+{
+	qc_reset(qcam);
+
+	/* Set the brightness. */
+	qcam_set(qcam, 11, qcam->brightness);
+
+	/* Set the height and width.  These refer to the actual
+	   CCD area *before* applying the selected decimation.  */
+	qcam_set(qcam, 17, qcam->ccd_height);
+	qcam_set(qcam, 19, qcam->ccd_width / 2);
+
+	/* Set top and left.  */
+	qcam_set(qcam, 0xd, qcam->top);
+	qcam_set(qcam, 0xf, qcam->left);
+
+	/* Set contrast and white balance.  */
+	qcam_set(qcam, 0x19, qcam->contrast);
+	qcam_set(qcam, 0x1f, qcam->whitebal);
+
+	/* Set the speed.  */
+	qcam_set(qcam, 45, 2);
+}
+
+/* Read some bytes from the camera and put them in the buffer.
+   nbytes should be a multiple of 3, because bidirectional mode gives
+   us three bytes at a time.  */
+
+static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
+{
+	unsigned int bytes = 0;
+
+	qcam_set_ack(qcam, 0);
+	if (qcam->bidirectional) {
+		/* It's a bidirectional port */
+		while (bytes < nbytes) {
+			unsigned int lo1, hi1, lo2, hi2;
+			unsigned char r, g, b;
+
+			if (qcam_await_ready2(qcam, 1))
+				return bytes;
+			lo1 = parport_read_data(qcam->pport) >> 1;
+			hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+			qcam_set_ack(qcam, 1);
+			if (qcam_await_ready2(qcam, 0))
+				return bytes;
+			lo2 = parport_read_data(qcam->pport) >> 1;
+			hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+			qcam_set_ack(qcam, 0);
+			r = lo1 | ((hi1 & 1) << 7);
+			g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
+			b = lo2 | ((hi2 & 1) << 7);
+			if (force_rgb) {
+				buf[bytes++] = r;
+				buf[bytes++] = g;
+				buf[bytes++] = b;
+			} else {
+				buf[bytes++] = b;
+				buf[bytes++] = g;
+				buf[bytes++] = r;
+			}
+		}
+	} else {
+		/* It's a unidirectional port */
+		int i = 0, n = bytes;
+		unsigned char rgb[3];
+
+		while (bytes < nbytes) {
+			unsigned int hi, lo;
+
+			if (qcam_await_ready1(qcam, 1))
+				return bytes;
+			hi = (parport_read_status(qcam->pport) & 0xf0);
+			qcam_set_ack(qcam, 1);
+			if (qcam_await_ready1(qcam, 0))
+				return bytes;
+			lo = (parport_read_status(qcam->pport) & 0xf0);
+			qcam_set_ack(qcam, 0);
+			/* flip some bits */
+			rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
+			if (i >= 2) {
+get_fragment:
+				if (force_rgb) {
+					buf[n++] = rgb[0];
+					buf[n++] = rgb[1];
+					buf[n++] = rgb[2];
+				} else {
+					buf[n++] = rgb[2];
+					buf[n++] = rgb[1];
+					buf[n++] = rgb[0];
+				}
+			}
+		}
+		if (i) {
+			i = 0;
+			goto get_fragment;
+		}
+	}
+	return bytes;
+}
+
+#define BUFSZ	150
+
+static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
+{
+	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+	unsigned lines, pixelsperline;
+	unsigned int is_bi_dir = qcam->bidirectional;
+	size_t wantlen, outptr = 0;
+	char tmpbuf[BUFSZ];
+
+	if (!access_ok(VERIFY_WRITE, buf, len))
+		return -EFAULT;
+
+	/* Wait for camera to become ready */
+	for (;;) {
+		int i = qcam_get(qcam, 41);
+
+		if (i == -1) {
+			qc_setup(qcam);
+			return -EIO;
+		}
+		if ((i & 0x80) == 0)
+			break;
+		schedule();
+	}
+
+	if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
+		return -EIO;
+
+	lines = qcam->height;
+	pixelsperline = qcam->width;
+
+	if (is_bi_dir) {
+		/* Turn the port around */
+		parport_data_reverse(qcam->pport);
+		mdelay(3);
+		qcam_set_ack(qcam, 0);
+		if (qcam_await_ready1(qcam, 1)) {
+			qc_setup(qcam);
+			return -EIO;
+		}
+		qcam_set_ack(qcam, 1);
+		if (qcam_await_ready1(qcam, 0)) {
+			qc_setup(qcam);
+			return -EIO;
+		}
+	}
+
+	wantlen = lines * pixelsperline * 24 / 8;
+
+	while (wantlen) {
+		size_t t, s;
+
+		s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
+		t = qcam_read_bytes(qcam, tmpbuf, s);
+		if (outptr < len) {
+			size_t sz = len - outptr;
+
+			if (sz > t)
+				sz = t;
+			if (__copy_to_user(buf + outptr, tmpbuf, sz))
+				break;
+			outptr += sz;
+		}
+		wantlen -= t;
+		if (t < s)
+			break;
+		cond_resched();
+	}
+
+	len = outptr;
+
+	if (wantlen) {
+		v4l2_err(v4l2_dev, "short read.\n");
+		if (is_bi_dir)
+			parport_data_forward(qcam->pport);
+		qc_setup(qcam);
+		return len;
+	}
+
+	if (is_bi_dir) {
+		int l;
+
+		do {
+			l = qcam_read_bytes(qcam, tmpbuf, 3);
+			cond_resched();
+		} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
+		if (force_rgb) {
+			if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
+				v4l2_err(v4l2_dev, "bad EOF\n");
+		} else {
+			if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
+				v4l2_err(v4l2_dev, "bad EOF\n");
+		}
+		qcam_set_ack(qcam, 0);
+		if (qcam_await_ready1(qcam, 1)) {
+			v4l2_err(v4l2_dev, "no ack after EOF\n");
+			parport_data_forward(qcam->pport);
+			qc_setup(qcam);
+			return len;
+		}
+		parport_data_forward(qcam->pport);
+		mdelay(3);
+		qcam_set_ack(qcam, 1);
+		if (qcam_await_ready1(qcam, 0)) {
+			v4l2_err(v4l2_dev, "no ack to port turnaround\n");
+			qc_setup(qcam);
+			return len;
+		}
+	} else {
+		int l;
+
+		do {
+			l = qcam_read_bytes(qcam, tmpbuf, 1);
+			cond_resched();
+		} while (l && tmpbuf[0] == 0x7e);
+		l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
+		if (force_rgb) {
+			if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
+				v4l2_err(v4l2_dev, "bad EOF\n");
+		} else {
+			if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
+				v4l2_err(v4l2_dev, "bad EOF\n");
+		}
+	}
+
+	qcam_write_data(qcam, 0);
+	return len;
+}
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int qcam_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *vcap)
+{
+	struct qcam *qcam = video_drvdata(file);
+
+	strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+	strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
+	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	if (vin->index > 0)
+		return -EINVAL;
+	strlcpy(vin->name, "Camera", sizeof(vin->name));
+	vin->type = V4L2_INPUT_TYPE_CAMERA;
+	vin->audioset = 0;
+	vin->tuner = 0;
+	vin->std = 0;
+	vin->status = 0;
+	return 0;
+}
+
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+	*inp = 0;
+	return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct qcam *qcam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	pix->width = qcam->width;
+	pix->height = qcam->height;
+	pix->pixelformat = V4L2_PIX_FMT_RGB24;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 3 * qcam->width;
+	pix->sizeimage = 3 * qcam->width * qcam->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->height < 60 || pix->width < 80) {
+		pix->height = 60;
+		pix->width = 80;
+	} else if (pix->height < 120 || pix->width < 160) {
+		pix->height = 120;
+		pix->width = 160;
+	} else {
+		pix->height = 240;
+		pix->width = 320;
+	}
+	pix->pixelformat = V4L2_PIX_FMT_RGB24;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 3 * pix->width;
+	pix->sizeimage = 3 * pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct qcam *qcam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+	if (ret)
+		return ret;
+	switch (pix->height) {
+	case 60:
+		qcam->mode = QC_DECIMATION_4;
+		break;
+	case 120:
+		qcam->mode = QC_DECIMATION_2;
+		break;
+	default:
+		qcam->mode = QC_DECIMATION_1;
+		break;
+	}
+
+	mutex_lock(&qcam->lock);
+	qcam->mode |= QC_MILLIONS;
+	qcam->height = pix->height;
+	qcam->width = pix->width;
+	parport_claim_or_block(qcam->pdev);
+	qc_setup(qcam);
+	parport_release(qcam->pdev);
+	mutex_unlock(&qcam->lock);
+	return 0;
+}
+
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
+		  { 0, 0, 0, 0 }
+		},
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 0)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+static ssize_t qcam_read(struct file *file, char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	struct qcam *qcam = video_drvdata(file);
+	int len;
+
+	mutex_lock(&qcam->lock);
+	parport_claim_or_block(qcam->pdev);
+	/* Probably should have a semaphore against multiple users */
+	len = qc_capture(qcam, buf, count);
+	parport_release(qcam->pdev);
+	mutex_unlock(&qcam->lock);
+	return len;
+}
+
+static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct qcam *qcam =
+		container_of(ctrl->handler, struct qcam, hdl);
+	int ret = 0;
+
+	mutex_lock(&qcam->lock);
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		qcam->brightness = ctrl->val;
+		break;
+	case V4L2_CID_CONTRAST:
+		qcam->contrast = ctrl->val;
+		break;
+	case V4L2_CID_GAMMA:
+		qcam->whitebal = ctrl->val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (ret == 0) {
+		parport_claim_or_block(qcam->pdev);
+		qc_setup(qcam);
+		parport_release(qcam->pdev);
+	}
+	mutex_unlock(&qcam->lock);
+	return ret;
+}
+
+static const struct v4l2_file_operations qcam_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= v4l2_fh_release,
+	.poll		= v4l2_ctrl_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.read		= qcam_read,
+};
+
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+	.vidioc_querycap    		    = qcam_querycap,
+	.vidioc_g_input      		    = qcam_g_input,
+	.vidioc_s_input      		    = qcam_s_input,
+	.vidioc_enum_input   		    = qcam_enum_input,
+	.vidioc_enum_fmt_vid_cap	    = qcam_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap 		    = qcam_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap  		    = qcam_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap  	    = qcam_try_fmt_vid_cap,
+	.vidioc_log_status		    = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
+	.s_ctrl = qcam_s_ctrl,
+};
+
+/* Initialize the QuickCam driver control structure. */
+
+static struct qcam *qcam_init(struct parport *port)
+{
+	struct qcam *qcam;
+	struct v4l2_device *v4l2_dev;
+
+	qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
+	if (qcam == NULL)
+		return NULL;
+
+	v4l2_dev = &qcam->v4l2_dev;
+	strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
+
+	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		kfree(qcam);
+		return NULL;
+	}
+
+	v4l2_ctrl_handler_init(&qcam->hdl, 3);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 240);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 255, 1, 192);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_GAMMA, 0, 255, 1, 128);
+	if (qcam->hdl.error) {
+		v4l2_err(v4l2_dev, "couldn't register controls\n");
+		v4l2_ctrl_handler_free(&qcam->hdl);
+		kfree(qcam);
+		return NULL;
+	}
+
+	qcam->pport = port;
+	qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
+					  NULL, 0, NULL);
+
+	qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
+
+	if (qcam->pdev == NULL) {
+		v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+		v4l2_ctrl_handler_free(&qcam->hdl);
+		kfree(qcam);
+		return NULL;
+	}
+
+	strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
+	qcam->vdev.v4l2_dev = v4l2_dev;
+	qcam->vdev.fops = &qcam_fops;
+	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+	qcam->vdev.release = video_device_release_empty;
+	qcam->vdev.ctrl_handler = &qcam->hdl;
+	video_set_drvdata(&qcam->vdev, qcam);
+
+	mutex_init(&qcam->lock);
+	qcam->width = qcam->ccd_width = 320;
+	qcam->height = qcam->ccd_height = 240;
+	qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
+	qcam->contrast = 192;
+	qcam->brightness = 240;
+	qcam->whitebal = 128;
+	qcam->top = 1;
+	qcam->left = 14;
+	return qcam;
+}
+
+static int init_cqcam(struct parport *port)
+{
+	struct qcam *qcam;
+	struct v4l2_device *v4l2_dev;
+
+	if (parport[0] != -1) {
+		/* The user gave specific instructions */
+		int i, found = 0;
+
+		for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) {
+			if (parport[0] == port->number)
+				found = 1;
+		}
+		if (!found)
+			return -ENODEV;
+	}
+
+	if (num_cams == MAX_CAMS)
+		return -ENOSPC;
+
+	qcam = qcam_init(port);
+	if (qcam == NULL)
+		return -ENODEV;
+
+	v4l2_dev = &qcam->v4l2_dev;
+
+	parport_claim_or_block(qcam->pdev);
+
+	qc_reset(qcam);
+
+	if (probe && qc_detect(qcam) == 0) {
+		parport_release(qcam->pdev);
+		parport_unregister_device(qcam->pdev);
+		kfree(qcam);
+		return -ENODEV;
+	}
+
+	qc_setup(qcam);
+
+	parport_release(qcam->pdev);
+
+	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+		v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
+		       qcam->pport->name);
+		parport_unregister_device(qcam->pdev);
+		kfree(qcam);
+		return -ENODEV;
+	}
+
+	v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
+	       video_device_node_name(&qcam->vdev), qcam->pport->name);
+
+	qcams[num_cams++] = qcam;
+
+	return 0;
+}
+
+static void close_cqcam(struct qcam *qcam)
+{
+	video_unregister_device(&qcam->vdev);
+	v4l2_ctrl_handler_free(&qcam->hdl);
+	parport_unregister_device(qcam->pdev);
+	kfree(qcam);
+}
+
+static void cq_attach(struct parport *port)
+{
+	init_cqcam(port);
+}
+
+static void cq_detach(struct parport *port)
+{
+	/* Write this some day. */
+}
+
+static struct parport_driver cqcam_driver = {
+	.name = "cqcam",
+	.attach = cq_attach,
+	.detach = cq_detach,
+};
+
+static int __init cqcam_init(void)
+{
+	printk(KERN_INFO BANNER "\n");
+
+	return parport_register_driver(&cqcam_driver);
+}
+
+static void __exit cqcam_cleanup(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_cams; i++)
+		close_cqcam(qcams[i]);
+
+	parport_unregister_driver(&cqcam_driver);
+}
+
+MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
+MODULE_DESCRIPTION(BANNER);
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.4");
+
+module_init(cqcam_init);
+module_exit(cqcam_cleanup);
diff --git a/drivers/media/parport/pms.c b/drivers/media/parport/pms.c
new file mode 100644
index 0000000..e6b4975
--- /dev/null
+++ b/drivers/media/parport/pms.c
@@ -0,0 +1,1156 @@
+/*
+ *	Media Vision Pro Movie Studio
+ *			or
+ *	"all you need is an I2C bus some RAM and a prayer"
+ *
+ *	This draws heavily on code
+ *
+ *	(c) Wolfgang Koehler,  wolf@first.gmd.de, Dec. 1994
+ *	Kiefernring 15
+ *	14478 Potsdam, Germany
+ *
+ *	Most of this code is directly derived from his userspace driver.
+ *	His driver works so send any reports to alan@lxorguk.ukuu.org.uk
+ *	unless the userspace driver also doesn't work for you...
+ *
+ *      Changes:
+ *	25-11-2009 	Hans Verkuil <hverkuil@xs4all.nl>
+ * 			- converted to version 2 of the V4L API.
+ *      08/07/2003      Daniele Bellucci <bellucda@tiscali.it>
+ *                      - pms_capture: report back -EFAULT
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/isa.h>
+#include <asm/io.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.5");
+
+#define MOTOROLA	1
+#define PHILIPS2	2               /* SAA7191 */
+#define PHILIPS1	3
+#define MVVMEMORYWIDTH	0x40		/* 512 bytes */
+
+struct i2c_info {
+	u8 slave;
+	u8 sub;
+	u8 data;
+	u8 hits;
+};
+
+struct pms {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct v4l2_ctrl_handler hdl;
+	int height;
+	int width;
+	int depth;
+	int input;
+	struct mutex lock;
+	int i2c_count;
+	struct i2c_info i2cinfo[64];
+
+	int decoder;
+	int standard;	/* 0 - auto 1 - ntsc 2 - pal 3 - secam */
+	v4l2_std_id std;
+	int io;
+	int data;
+	void __iomem *mem;
+};
+
+/*
+ *	I/O ports and Shared Memory
+ */
+
+static int io_port = 0x250;
+module_param(io_port, int, 0);
+
+static int mem_base = 0xc8000;
+module_param(mem_base, int, 0);
+
+static int video_nr = -1;
+module_param(video_nr, int, 0);
+
+
+static inline void mvv_write(struct pms *dev, u8 index, u8 value)
+{
+	outw(index | (value << 8), dev->io);
+}
+
+static inline u8 mvv_read(struct pms *dev, u8 index)
+{
+	outb(index, dev->io);
+	return inb(dev->data);
+}
+
+static int pms_i2c_stat(struct pms *dev, u8 slave)
+{
+	int counter = 0;
+	int i;
+
+	outb(0x28, dev->io);
+
+	while ((inb(dev->data) & 0x01) == 0)
+		if (counter++ == 256)
+			break;
+
+	while ((inb(dev->data) & 0x01) != 0)
+		if (counter++ == 256)
+			break;
+
+	outb(slave, dev->io);
+
+	counter = 0;
+	while ((inb(dev->data) & 0x01) == 0)
+		if (counter++ == 256)
+			break;
+
+	while ((inb(dev->data) & 0x01) != 0)
+		if (counter++ == 256)
+			break;
+
+	for (i = 0; i < 12; i++) {
+		char st = inb(dev->data);
+
+		if ((st & 2) != 0)
+			return -1;
+		if ((st & 1) == 0)
+			break;
+	}
+	outb(0x29, dev->io);
+	return inb(dev->data);
+}
+
+static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data)
+{
+	int skip = 0;
+	int count;
+	int i;
+
+	for (i = 0; i < dev->i2c_count; i++) {
+		if ((dev->i2cinfo[i].slave == slave) &&
+		    (dev->i2cinfo[i].sub == sub)) {
+			if (dev->i2cinfo[i].data == data)
+				skip = 1;
+			dev->i2cinfo[i].data = data;
+			i = dev->i2c_count + 1;
+		}
+	}
+
+	if (i == dev->i2c_count && dev->i2c_count < 64) {
+		dev->i2cinfo[dev->i2c_count].slave = slave;
+		dev->i2cinfo[dev->i2c_count].sub = sub;
+		dev->i2cinfo[dev->i2c_count].data = data;
+		dev->i2c_count++;
+	}
+
+	if (skip)
+		return 0;
+
+	mvv_write(dev, 0x29, sub);
+	mvv_write(dev, 0x2A, data);
+	mvv_write(dev, 0x28, slave);
+
+	outb(0x28, dev->io);
+
+	count = 0;
+	while ((inb(dev->data) & 1) == 0)
+		if (count > 255)
+			break;
+	while ((inb(dev->data) & 1) != 0)
+		if (count > 255)
+			break;
+
+	count = inb(dev->data);
+
+	if (count & 2)
+		return -1;
+	return count;
+}
+
+static int pms_i2c_read(struct pms *dev, int slave, int sub)
+{
+	int i;
+
+	for (i = 0; i < dev->i2c_count; i++) {
+		if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub)
+			return dev->i2cinfo[i].data;
+	}
+	return 0;
+}
+
+
+static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or)
+{
+	u8 tmp;
+
+	tmp = pms_i2c_read(dev, slave, sub);
+	tmp = (tmp & and) | or;
+	pms_i2c_write(dev, slave, sub, tmp);
+}
+
+/*
+ *	Control functions
+ */
+
+
+static void pms_videosource(struct pms *dev, short source)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		break;
+	case PHILIPS2:
+		pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0);
+		break;
+	case PHILIPS1:
+		break;
+	}
+	mvv_write(dev, 0x2E, 0x31);
+	/* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30);
+	   But could not make this work correctly. Only Composite input
+	   worked for me. */
+}
+
+static void pms_hue(struct pms *dev, short hue)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		pms_i2c_write(dev, 0x8a, 0x00, hue);
+		break;
+	case PHILIPS2:
+		pms_i2c_write(dev, 0x8a, 0x07, hue);
+		break;
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x42, 0x07, hue);
+		break;
+	}
+}
+
+static void pms_saturation(struct pms *dev, short sat)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		pms_i2c_write(dev, 0x8a, 0x00, sat);
+		break;
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x42, 0x12, sat);
+		break;
+	}
+}
+
+
+static void pms_contrast(struct pms *dev, short contrast)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		pms_i2c_write(dev, 0x8a, 0x00, contrast);
+		break;
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x42, 0x13, contrast);
+		break;
+	}
+}
+
+static void pms_brightness(struct pms *dev, short brightness)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		pms_i2c_write(dev, 0x8a, 0x00, brightness);
+		pms_i2c_write(dev, 0x8a, 0x00, brightness);
+		pms_i2c_write(dev, 0x8a, 0x00, brightness);
+		break;
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x42, 0x19, brightness);
+		break;
+	}
+}
+
+
+static void pms_format(struct pms *dev, short format)
+{
+	int target;
+
+	dev->standard = format;
+
+	if (dev->decoder == PHILIPS1)
+		target = 0x42;
+	else if (dev->decoder == PHILIPS2)
+		target = 0x8a;
+	else
+		return;
+
+	switch (format) {
+	case 0:	/* Auto */
+		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80);
+		break;
+	case 1: /* NTSC */
+		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40);
+		break;
+	case 2: /* PAL */
+		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
+		break;
+	case 3:	/* SECAM */
+		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01);
+		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
+		break;
+	}
+}
+
+#ifdef FOR_FUTURE_EXPANSION
+
+/*
+ *	These features of the PMS card are not currently exposes. They
+ *	could become a private v4l ioctl for PMSCONFIG or somesuch if
+ *	people need it. We also don't yet use the PMS interrupt.
+ */
+
+static void pms_hstart(struct pms *dev, short start)
+{
+	switch (dev->decoder) {
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x8a, 0x05, start);
+		pms_i2c_write(dev, 0x8a, 0x18, start);
+		break;
+	case PHILIPS2:
+		pms_i2c_write(dev, 0x42, 0x05, start);
+		pms_i2c_write(dev, 0x42, 0x18, start);
+		break;
+	}
+}
+
+/*
+ *	Bandpass filters
+ */
+
+static void pms_bandpass(struct pms *dev, short pass)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4);
+}
+
+static void pms_antisnow(struct pms *dev, short snow)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2);
+}
+
+static void pms_sharpness(struct pms *dev, short sharp)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03);
+}
+
+static void pms_chromaagc(struct pms *dev, short agc)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5);
+}
+
+static void pms_vertnoise(struct pms *dev, short noise)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3);
+}
+
+static void pms_forcecolour(struct pms *dev, short colour)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7);
+}
+
+static void pms_antigamma(struct pms *dev, short gamma)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7);
+}
+
+static void pms_prefilter(struct pms *dev, short filter)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6);
+}
+
+static void pms_hfilter(struct pms *dev, short filter)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5);
+}
+
+static void pms_vfilter(struct pms *dev, short filter)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5);
+}
+
+static void pms_killcolour(struct pms *dev, short colour)
+{
+	if (dev->decoder == PHILIPS2) {
+		pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3);
+		pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3);
+	} else if (dev->decoder == PHILIPS1) {
+		pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3);
+		pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3);
+	}
+}
+
+static void pms_chromagain(struct pms *dev, short chroma)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_write(dev, 0x8a, 0x11, chroma);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_write(dev, 0x42, 0x11, chroma);
+}
+
+
+static void pms_spacialcompl(struct pms *dev, short data)
+{
+	mvv_write(dev, 0x3b, data);
+}
+
+static void pms_spacialcomph(struct pms *dev, short data)
+{
+	mvv_write(dev, 0x3a, data);
+}
+
+static void pms_vstart(struct pms *dev, short start)
+{
+	mvv_write(dev, 0x16, start);
+	mvv_write(dev, 0x17, (start >> 8) & 0x01);
+}
+
+#endif
+
+static void pms_secamcross(struct pms *dev, short cross)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5);
+}
+
+
+static void pms_swsense(struct pms *dev, short sense)
+{
+	if (dev->decoder == PHILIPS2) {
+		pms_i2c_write(dev, 0x8a, 0x0a, sense);
+		pms_i2c_write(dev, 0x8a, 0x0b, sense);
+	} else if (dev->decoder == PHILIPS1) {
+		pms_i2c_write(dev, 0x42, 0x0a, sense);
+		pms_i2c_write(dev, 0x42, 0x0b, sense);
+	}
+}
+
+
+static void pms_framerate(struct pms *dev, short frr)
+{
+	int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25;
+
+	if (frr == 0)
+		return;
+	fps = fps/frr;
+	mvv_write(dev, 0x14, 0x80 | fps);
+	mvv_write(dev, 0x15, 1);
+}
+
+static void pms_vert(struct pms *dev, u8 deciden, u8 decinum)
+{
+	mvv_write(dev, 0x1c, deciden);	/* Denominator */
+	mvv_write(dev, 0x1d, decinum);	/* Numerator */
+}
+
+/*
+ *	Turn 16bit ratios into best small ratio the chipset can grok
+ */
+
+static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden)
+{
+	/* Knock it down by / 5 once */
+	if (decinum % 5 == 0) {
+		deciden /= 5;
+		decinum /= 5;
+	}
+	/*
+	 *	3's
+	 */
+	while (decinum % 3 == 0 && deciden % 3 == 0) {
+		deciden /= 3;
+		decinum /= 3;
+	}
+	/*
+	 *	2's
+	 */
+	while (decinum % 2 == 0 && deciden % 2 == 0) {
+		decinum /= 2;
+		deciden /= 2;
+	}
+	/*
+	 *	Fudgyify
+	 */
+	while (deciden > 32) {
+		deciden /= 2;
+		decinum = (decinum + 1) / 2;
+	}
+	if (deciden == 32)
+		deciden--;
+	pms_vert(dev, deciden, decinum);
+}
+
+static void pms_horzdeci(struct pms *dev, short decinum, short deciden)
+{
+	if (decinum <= 512) {
+		if (decinum % 5 == 0) {
+			decinum /= 5;
+			deciden /= 5;
+		}
+	} else {
+		decinum = 512;
+		deciden = 640;	/* 768 would be ideal */
+	}
+
+	while (((decinum | deciden) & 1) == 0) {
+		decinum >>= 1;
+		deciden >>= 1;
+	}
+	while (deciden > 32) {
+		deciden >>= 1;
+		decinum = (decinum + 1) >> 1;
+	}
+	if (deciden == 32)
+		deciden--;
+
+	mvv_write(dev, 0x24, 0x80 | deciden);
+	mvv_write(dev, 0x25, decinum);
+}
+
+static void pms_resolution(struct pms *dev, short width, short height)
+{
+	int fg_height;
+
+	fg_height = height;
+	if (fg_height > 280)
+		fg_height = 280;
+
+	mvv_write(dev, 0x18, fg_height);
+	mvv_write(dev, 0x19, fg_height >> 8);
+
+	if (dev->std & V4L2_STD_525_60) {
+		mvv_write(dev, 0x1a, 0xfc);
+		mvv_write(dev, 0x1b, 0x00);
+		if (height > fg_height)
+			pms_vertdeci(dev, 240, 240);
+		else
+			pms_vertdeci(dev, fg_height, 240);
+	} else {
+		mvv_write(dev, 0x1a, 0x1a);
+		mvv_write(dev, 0x1b, 0x01);
+		if (fg_height > 256)
+			pms_vertdeci(dev, 270, 270);
+		else
+			pms_vertdeci(dev, fg_height, 270);
+	}
+	mvv_write(dev, 0x12, 0);
+	mvv_write(dev, 0x13, MVVMEMORYWIDTH);
+	mvv_write(dev, 0x42, 0x00);
+	mvv_write(dev, 0x43, 0x00);
+	mvv_write(dev, 0x44, MVVMEMORYWIDTH);
+
+	mvv_write(dev, 0x22, width + 8);
+	mvv_write(dev, 0x23, (width + 8) >> 8);
+
+	if (dev->std & V4L2_STD_525_60)
+		pms_horzdeci(dev, width, 640);
+	else
+		pms_horzdeci(dev, width + 8, 768);
+
+	mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe);
+	mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01);
+	mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd);
+	mvv_write(dev, 0x32, 0x00);
+	mvv_write(dev, 0x33, MVVMEMORYWIDTH);
+}
+
+
+/*
+ *	Set Input
+ */
+
+static void pms_vcrinput(struct pms *dev, short input)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7);
+}
+
+
+static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
+{
+	int y;
+	int dw = 2 * dev->width;
+	char *tmp; /* using a temp buffer is faster than direct  */
+	int cnt = 0;
+	int len = 0;
+	unsigned char r8 = 0x5;  /* value for reg8  */
+
+	tmp = kmalloc(dw + 32, GFP_KERNEL);
+	if (!tmp)
+		return 0;
+
+	if (rgb555)
+		r8 |= 0x20; /* else use untranslated rgb = 565 */
+	mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
+
+/*	printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
+
+	for (y = 0; y < dev->height; y++) {
+		writeb(0, dev->mem);  /* synchronisiert neue Zeile */
+
+		/*
+		 *	This is in truth a fifo, be very careful as if you
+		 *	forgot this odd things will occur 8)
+		 */
+
+		memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word   */
+		cnt -= dev->height;
+		while (cnt <= 0) {
+			/*
+			 *	Don't copy too far
+			 */
+			int dt = dw;
+			if (dt + len > count)
+				dt = count - len;
+			cnt += dev->height;
+			if (copy_to_user(buf, tmp + 32, dt))
+				return len ? len : -EFAULT;
+			buf += dt;
+			len += dt;
+		}
+	}
+	kfree(tmp);
+	return len;
+}
+
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int pms_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *vcap)
+{
+	struct pms *dev = video_drvdata(file);
+
+	strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
+	strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
+	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
+			"ISA:%s", dev->v4l2_dev.name);
+	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	static const char *inputs[4] = {
+		"Composite",
+		"S-Video",
+		"Composite (VCR)",
+		"S-Video (VCR)"
+	};
+
+	if (vin->index > 3)
+		return -EINVAL;
+	strlcpy(vin->name, inputs[vin->index], sizeof(vin->name));
+	vin->type = V4L2_INPUT_TYPE_CAMERA;
+	vin->audioset = 0;
+	vin->tuner = 0;
+	vin->std = V4L2_STD_ALL;
+	vin->status = 0;
+	return 0;
+}
+
+static int pms_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+	struct pms *dev = video_drvdata(file);
+
+	*inp = dev->input;
+	return 0;
+}
+
+static int pms_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	struct pms *dev = video_drvdata(file);
+
+	if (inp > 3)
+		return -EINVAL;
+
+	dev->input = inp;
+	pms_videosource(dev, inp & 1);
+	pms_vcrinput(dev, inp >> 1);
+	return 0;
+}
+
+static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+	struct pms *dev = video_drvdata(file);
+
+	*std = dev->std;
+	return 0;
+}
+
+static int pms_s_std(struct file *file, void *fh, v4l2_std_id std)
+{
+	struct pms *dev = video_drvdata(file);
+	int ret = 0;
+
+	dev->std = std;
+	if (dev->std & V4L2_STD_NTSC) {
+		pms_framerate(dev, 30);
+		pms_secamcross(dev, 0);
+		pms_format(dev, 1);
+	} else if (dev->std & V4L2_STD_PAL) {
+		pms_framerate(dev, 25);
+		pms_secamcross(dev, 0);
+		pms_format(dev, 2);
+	} else if (dev->std & V4L2_STD_SECAM) {
+		pms_framerate(dev, 25);
+		pms_secamcross(dev, 1);
+		pms_format(dev, 2);
+	} else {
+		ret = -EINVAL;
+	}
+	/*
+	switch (v->mode) {
+	case VIDEO_MODE_AUTO:
+		pms_framerate(dev, 25);
+		pms_secamcross(dev, 0);
+		pms_format(dev, 0);
+		break;
+	}*/
+	return ret;
+}
+
+static int pms_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct pms *dev = container_of(ctrl->handler, struct pms, hdl);
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		pms_brightness(dev, ctrl->val);
+		break;
+	case V4L2_CID_CONTRAST:
+		pms_contrast(dev, ctrl->val);
+		break;
+	case V4L2_CID_SATURATION:
+		pms_saturation(dev, ctrl->val);
+		break;
+	case V4L2_CID_HUE:
+		pms_hue(dev, ctrl->val);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct pms *dev = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	pix->width = dev->width;
+	pix->height = dev->height;
+	pix->pixelformat = dev->width == 15 ?
+			    V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 2 * dev->width;
+	pix->sizeimage = 2 * dev->width * dev->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->height < 16 || pix->height > 480)
+		return -EINVAL;
+	if (pix->width < 16 || pix->width > 640)
+		return -EINVAL;
+	if (pix->pixelformat != V4L2_PIX_FMT_RGB555 &&
+	    pix->pixelformat != V4L2_PIX_FMT_RGB565)
+		return -EINVAL;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 2 * pix->width;
+	pix->sizeimage = 2 * pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct pms *dev = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	int ret = pms_try_fmt_vid_cap(file, fh, fmt);
+
+	if (ret)
+		return ret;
+	dev->width = pix->width;
+	dev->height = pix->height;
+	dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16;
+	pms_resolution(dev, dev->width, dev->height);
+	/* Ok we figured out what to use from our wide choice */
+	return 0;
+}
+
+static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "RGB 5:5:5", V4L2_PIX_FMT_RGB555,
+		  { 0, 0, 0, 0 }
+		},
+		{ 1, 0, 0,
+		  "RGB 5:6:5", V4L2_PIX_FMT_RGB565,
+		  { 0, 0, 0, 0 }
+		},
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 1)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+static ssize_t pms_read(struct file *file, char __user *buf,
+		    size_t count, loff_t *ppos)
+{
+	struct pms *dev = video_drvdata(file);
+	int len;
+
+	len = pms_capture(dev, buf, (dev->depth == 15), count);
+	return len;
+}
+
+static unsigned int pms_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct v4l2_fh *fh = file->private_data;
+	unsigned int res = POLLIN | POLLRDNORM;
+
+	if (v4l2_event_pending(fh))
+		res |= POLLPRI;
+	poll_wait(file, &fh->wait, wait);
+	return res;
+}
+
+static const struct v4l2_file_operations pms_fops = {
+	.owner		= THIS_MODULE,
+	.open           = v4l2_fh_open,
+	.release        = v4l2_fh_release,
+	.poll           = pms_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.read           = pms_read,
+};
+
+static const struct v4l2_ioctl_ops pms_ioctl_ops = {
+	.vidioc_querycap	    = pms_querycap,
+	.vidioc_g_input		    = pms_g_input,
+	.vidioc_s_input		    = pms_s_input,
+	.vidioc_enum_input	    = pms_enum_input,
+	.vidioc_g_std		    = pms_g_std,
+	.vidioc_s_std		    = pms_s_std,
+	.vidioc_enum_fmt_vid_cap    = pms_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap	    = pms_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap	    = pms_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap     = pms_try_fmt_vid_cap,
+	.vidioc_subscribe_event     = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event   = v4l2_event_unsubscribe,
+};
+
+/*
+ *	Probe for and initialise the Mediavision PMS
+ */
+
+static int init_mediavision(struct pms *dev)
+{
+	int idec, decst;
+	int i;
+	static const unsigned char i2c_defs[] = {
+		0x4c, 0x30, 0x00, 0xe8,
+		0xb6, 0xe2, 0x00, 0x00,
+		0xff, 0xff, 0x00, 0x00,
+		0x00, 0x00, 0x78, 0x98,
+		0x00, 0x00, 0x00, 0x00,
+		0x34, 0x0a, 0xf4, 0xce,
+		0xe4
+	};
+
+	dev->mem = ioremap(mem_base, 0x800);
+	if (!dev->mem)
+		return -ENOMEM;
+
+	if (!request_region(0x9a01, 1, "Mediavision PMS config")) {
+		printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n");
+		iounmap(dev->mem);
+		return -EBUSY;
+	}
+	if (!request_region(dev->io, 3, "Mediavision PMS")) {
+		printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io);
+		release_region(0x9a01, 1);
+		iounmap(dev->mem);
+		return -EBUSY;
+	}
+	outb(0xb8, 0x9a01);		/* Unlock */
+	outb(dev->io >> 4, 0x9a01);	/* Set IO port */
+
+
+	decst = pms_i2c_stat(dev, 0x43);
+
+	if (decst != -1)
+		idec = 2;
+	else if (pms_i2c_stat(dev, 0xb9) != -1)
+		idec = 3;
+	else if (pms_i2c_stat(dev, 0x8b) != -1)
+		idec = 1;
+	else
+		idec = 0;
+
+	printk(KERN_INFO "PMS type is %d\n", idec);
+	if (idec == 0) {
+		release_region(dev->io, 3);
+		release_region(0x9a01, 1);
+		iounmap(dev->mem);
+		return -ENODEV;
+	}
+
+	/*
+	 *	Ok we have a PMS of some sort
+	 */
+
+	mvv_write(dev, 0x04, mem_base >> 12);	/* Set the memory area */
+
+	/* Ok now load the defaults */
+
+	for (i = 0; i < 0x19; i++) {
+		if (i2c_defs[i] == 0xff)
+			pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00);
+		else
+			pms_i2c_write(dev, 0x8a, i, i2c_defs[i]);
+	}
+
+	pms_i2c_write(dev, 0xb8, 0x00, 0x12);
+	pms_i2c_write(dev, 0xb8, 0x04, 0x00);
+	pms_i2c_write(dev, 0xb8, 0x07, 0x00);
+	pms_i2c_write(dev, 0xb8, 0x08, 0x00);
+	pms_i2c_write(dev, 0xb8, 0x09, 0xff);
+	pms_i2c_write(dev, 0xb8, 0x0a, 0x00);
+	pms_i2c_write(dev, 0xb8, 0x0b, 0x10);
+	pms_i2c_write(dev, 0xb8, 0x10, 0x03);
+
+	mvv_write(dev, 0x01, 0x00);
+	mvv_write(dev, 0x05, 0xa0);
+	mvv_write(dev, 0x08, 0x25);
+	mvv_write(dev, 0x09, 0x00);
+	mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH);
+
+	mvv_write(dev, 0x10, 0x02);
+	mvv_write(dev, 0x1e, 0x0c);
+	mvv_write(dev, 0x1f, 0x03);
+	mvv_write(dev, 0x26, 0x06);
+
+	mvv_write(dev, 0x2b, 0x00);
+	mvv_write(dev, 0x2c, 0x20);
+	mvv_write(dev, 0x2d, 0x00);
+	mvv_write(dev, 0x2f, 0x70);
+	mvv_write(dev, 0x32, 0x00);
+	mvv_write(dev, 0x33, MVVMEMORYWIDTH);
+	mvv_write(dev, 0x34, 0x00);
+	mvv_write(dev, 0x35, 0x00);
+	mvv_write(dev, 0x3a, 0x80);
+	mvv_write(dev, 0x3b, 0x10);
+	mvv_write(dev, 0x20, 0x00);
+	mvv_write(dev, 0x21, 0x00);
+	mvv_write(dev, 0x30, 0x22);
+	return 0;
+}
+
+/*
+ *	Initialization and module stuff
+ */
+
+#ifndef MODULE
+static int enable;
+module_param(enable, int, 0);
+#endif
+
+static const struct v4l2_ctrl_ops pms_ctrl_ops = {
+	.s_ctrl = pms_s_ctrl,
+};
+
+static int pms_probe(struct device *pdev, unsigned int card)
+{
+	struct pms *dev;
+	struct v4l2_device *v4l2_dev;
+	struct v4l2_ctrl_handler *hdl;
+	int res;
+
+#ifndef MODULE
+	if (!enable) {
+		pr_err("PMS: not enabled, use pms.enable=1 to probe\n");
+		return -ENODEV;
+	}
+#endif
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL)
+		return -ENOMEM;
+
+	dev->decoder = PHILIPS2;
+	dev->io = io_port;
+	dev->data = io_port + 1;
+	v4l2_dev = &dev->v4l2_dev;
+	hdl = &dev->hdl;
+
+	res = v4l2_device_register(pdev, v4l2_dev);
+	if (res < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		goto free_dev;
+	}
+	v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.05\n");
+
+	res = init_mediavision(dev);
+	if (res) {
+		v4l2_err(v4l2_dev, "Board not found.\n");
+		goto free_io;
+	}
+
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 139);
+	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 70);
+	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 64);
+	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+			V4L2_CID_HUE, 0, 255, 1, 0);
+	if (hdl->error) {
+		res = hdl->error;
+		goto free_hdl;
+	}
+
+	mutex_init(&dev->lock);
+	strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+	dev->vdev.v4l2_dev = v4l2_dev;
+	dev->vdev.ctrl_handler = hdl;
+	dev->vdev.fops = &pms_fops;
+	dev->vdev.ioctl_ops = &pms_ioctl_ops;
+	dev->vdev.release = video_device_release_empty;
+	dev->vdev.lock = &dev->lock;
+	dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
+	video_set_drvdata(&dev->vdev, dev);
+	dev->std = V4L2_STD_NTSC_M;
+	dev->height = 240;
+	dev->width = 320;
+	dev->depth = 16;
+	pms_swsense(dev, 75);
+	pms_resolution(dev, 320, 240);
+	pms_videosource(dev, 0);
+	pms_vcrinput(dev, 0);
+	v4l2_ctrl_handler_setup(hdl);
+	res = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr);
+	if (res >= 0)
+		return 0;
+
+free_hdl:
+	v4l2_ctrl_handler_free(hdl);
+	v4l2_device_unregister(&dev->v4l2_dev);
+free_io:
+	release_region(dev->io, 3);
+	release_region(0x9a01, 1);
+	iounmap(dev->mem);
+free_dev:
+	kfree(dev);
+	return res;
+}
+
+static int pms_remove(struct device *pdev, unsigned int card)
+{
+	struct pms *dev = dev_get_drvdata(pdev);
+
+	video_unregister_device(&dev->vdev);
+	v4l2_ctrl_handler_free(&dev->hdl);
+	release_region(dev->io, 3);
+	release_region(0x9a01, 1);
+	iounmap(dev->mem);
+	return 0;
+}
+
+static struct isa_driver pms_driver = {
+	.probe		= pms_probe,
+	.remove		= pms_remove,
+	.driver		= {
+		.name	= "pms",
+	},
+};
+
+static int __init pms_init(void)
+{
+	return isa_register_driver(&pms_driver, 1);
+}
+
+static void __exit pms_exit(void)
+{
+	isa_unregister_driver(&pms_driver);
+}
+
+module_init(pms_init);
+module_exit(pms_exit);
diff --git a/drivers/media/parport/w9966.c b/drivers/media/parport/w9966.c
new file mode 100644
index 0000000..f7502f3
--- /dev/null
+++ b/drivers/media/parport/w9966.c
@@ -0,0 +1,980 @@
+/*
+	Winbond w9966cf Webcam parport driver.
+
+	Version 0.33
+
+	Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/*
+	Supported devices:
+	*Lifeview FlyCam Supra (using the Philips saa7111a chip)
+
+	Does any other model using the w9966 interface chip exist ?
+
+	Todo:
+
+	*Add a working EPP mode, since DMA ECP read isn't implemented
+	in the parport drivers. (That's why it's so sloow)
+
+	*Add support for other ccd-control chips than the saa7111
+	please send me feedback on what kind of chips you have.
+
+	*Add proper probing. I don't know what's wrong with the IEEE1284
+	parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID)
+	and nibble read seems to be broken for some peripherals.
+
+	*Add probing for onboard SRAM, port directions etc. (if possible)
+
+	*Add support for the hardware compressed modes (maybe using v4l2)
+
+	*Fix better support for the capture window (no skewed images, v4l
+	interface to capt. window)
+
+	*Probably some bugs that I don't know of
+
+	Please support me by sending feedback!
+
+	Changes:
+
+	Alan Cox:	Removed RGB mode for kernel merge, added THIS_MODULE
+			and owner support for newer module locks
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <linux/parport.h>
+
+/*#define DEBUG*/				/* Undef me for production */
+
+#ifdef DEBUG
+#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
+#else
+#define DPRINTF(x...)
+#endif
+
+/*
+ *	Defines, simple typedefs etc.
+ */
+
+#define W9966_DRIVERNAME	"W9966CF Webcam"
+#define W9966_MAXCAMS		4	/* Maximum number of cameras */
+#define W9966_RBUFFER		2048	/* Read buffer (must be an even number) */
+#define W9966_SRAMSIZE		131072	/* 128kb */
+#define W9966_SRAMID		0x02	/* check w9966cf.pdf */
+
+/* Empirically determined window limits */
+#define W9966_WND_MIN_X		16
+#define W9966_WND_MIN_Y		14
+#define W9966_WND_MAX_X		705
+#define W9966_WND_MAX_Y		253
+#define W9966_WND_MAX_W		(W9966_WND_MAX_X - W9966_WND_MIN_X)
+#define W9966_WND_MAX_H		(W9966_WND_MAX_Y - W9966_WND_MIN_Y)
+
+/* Keep track of our current state */
+#define W9966_STATE_PDEV	0x01
+#define W9966_STATE_CLAIMED	0x02
+#define W9966_STATE_VDEV	0x04
+
+#define W9966_I2C_W_ID		0x48
+#define W9966_I2C_R_ID		0x49
+#define W9966_I2C_R_DATA	0x08
+#define W9966_I2C_R_CLOCK	0x04
+#define W9966_I2C_W_DATA	0x02
+#define W9966_I2C_W_CLOCK	0x01
+
+struct w9966 {
+	struct v4l2_device v4l2_dev;
+	struct v4l2_ctrl_handler hdl;
+	unsigned char dev_state;
+	unsigned char i2c_state;
+	unsigned short ppmode;
+	struct parport *pport;
+	struct pardevice *pdev;
+	struct video_device vdev;
+	unsigned short width;
+	unsigned short height;
+	unsigned char brightness;
+	signed char contrast;
+	signed char color;
+	signed char hue;
+	struct mutex lock;
+};
+
+/*
+ *	Module specific properties
+ */
+
+MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
+MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.33.1");
+
+#ifdef MODULE
+static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
+#else
+static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
+#endif
+module_param_array(pardev, charp, NULL, 0);
+MODULE_PARM_DESC(pardev, "pardev: where to search for\n"
+		"\teach camera. 'aggressive' means brute-force search.\n"
+		"\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n"
+		"\tcam 1 to parport3 and search every parport for cam 2 etc...");
+
+static int parmode;
+module_param(parmode, int, 0);
+MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
+
+static int video_nr = -1;
+module_param(video_nr, int, 0);
+
+static struct w9966 w9966_cams[W9966_MAXCAMS];
+
+/*
+ *	Private function defines
+ */
+
+
+/* Set camera phase flags, so we know what to uninit when terminating */
+static inline void w9966_set_state(struct w9966 *cam, int mask, int val)
+{
+	cam->dev_state = (cam->dev_state & ~mask) ^ val;
+}
+
+/* Get camera phase flags */
+static inline int w9966_get_state(struct w9966 *cam, int mask, int val)
+{
+	return ((cam->dev_state & mask) == val);
+}
+
+/* Claim parport for ourself */
+static void w9966_pdev_claim(struct w9966 *cam)
+{
+	if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
+		return;
+	parport_claim_or_block(cam->pdev);
+	w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
+}
+
+/* Release parport for others to use */
+static void w9966_pdev_release(struct w9966 *cam)
+{
+	if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0))
+		return;
+	parport_release(cam->pdev);
+	w9966_set_state(cam, W9966_STATE_CLAIMED, 0);
+}
+
+/* Read register from W9966 interface-chip
+   Expects a claimed pdev
+   -1 on error, else register data (byte) */
+static int w9966_read_reg(struct w9966 *cam, int reg)
+{
+	/* ECP, read, regtransfer, REG, REG, REG, REG, REG */
+	const unsigned char addr = 0x80 | (reg & 0x1f);
+	unsigned char val;
+
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
+		return -1;
+	if (parport_write(cam->pport, &addr, 1) != 1)
+		return -1;
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
+		return -1;
+	if (parport_read(cam->pport, &val, 1) != 1)
+		return -1;
+
+	return val;
+}
+
+/* Write register to W9966 interface-chip
+   Expects a claimed pdev
+   -1 on error */
+static int w9966_write_reg(struct w9966 *cam, int reg, int data)
+{
+	/* ECP, write, regtransfer, REG, REG, REG, REG, REG */
+	const unsigned char addr = 0xc0 | (reg & 0x1f);
+	const unsigned char val = data;
+
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
+		return -1;
+	if (parport_write(cam->pport, &addr, 1) != 1)
+		return -1;
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
+		return -1;
+	if (parport_write(cam->pport, &val, 1) != 1)
+		return -1;
+
+	return 0;
+}
+
+/*
+ *	Ugly and primitive i2c protocol functions
+ */
+
+/* Sets the data line on the i2c bus.
+   Expects a claimed pdev. */
+static void w9966_i2c_setsda(struct w9966 *cam, int state)
+{
+	if (state)
+		cam->i2c_state |= W9966_I2C_W_DATA;
+	else
+		cam->i2c_state &= ~W9966_I2C_W_DATA;
+
+	w9966_write_reg(cam, 0x18, cam->i2c_state);
+	udelay(5);
+}
+
+/* Get peripheral clock line
+   Expects a claimed pdev. */
+static int w9966_i2c_getscl(struct w9966 *cam)
+{
+	const unsigned char state = w9966_read_reg(cam, 0x18);
+	return ((state & W9966_I2C_R_CLOCK) > 0);
+}
+
+/* Sets the clock line on the i2c bus.
+   Expects a claimed pdev. -1 on error */
+static int w9966_i2c_setscl(struct w9966 *cam, int state)
+{
+	unsigned long timeout;
+
+	if (state)
+		cam->i2c_state |= W9966_I2C_W_CLOCK;
+	else
+		cam->i2c_state &= ~W9966_I2C_W_CLOCK;
+
+	w9966_write_reg(cam, 0x18, cam->i2c_state);
+	udelay(5);
+
+	/* we go to high, we also expect the peripheral to ack. */
+	if (state) {
+		timeout = jiffies + 100;
+		while (!w9966_i2c_getscl(cam)) {
+			if (time_after(jiffies, timeout))
+				return -1;
+		}
+	}
+	return 0;
+}
+
+#if 0
+/* Get peripheral data line
+   Expects a claimed pdev. */
+static int w9966_i2c_getsda(struct w9966 *cam)
+{
+	const unsigned char state = w9966_read_reg(cam, 0x18);
+	return ((state & W9966_I2C_R_DATA) > 0);
+}
+#endif
+
+/* Write a byte with ack to the i2c bus.
+   Expects a claimed pdev. -1 on error */
+static int w9966_i2c_wbyte(struct w9966 *cam, int data)
+{
+	int i;
+
+	for (i = 7; i >= 0; i--) {
+		w9966_i2c_setsda(cam, (data >> i) & 0x01);
+
+		if (w9966_i2c_setscl(cam, 1) == -1)
+			return -1;
+		w9966_i2c_setscl(cam, 0);
+	}
+
+	w9966_i2c_setsda(cam, 1);
+
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setscl(cam, 0);
+
+	return 0;
+}
+
+/* Read a data byte with ack from the i2c-bus
+   Expects a claimed pdev. -1 on error */
+#if 0
+static int w9966_i2c_rbyte(struct w9966 *cam)
+{
+	unsigned char data = 0x00;
+	int i;
+
+	w9966_i2c_setsda(cam, 1);
+
+	for (i = 0; i < 8; i++) {
+		if (w9966_i2c_setscl(cam, 1) == -1)
+			return -1;
+		data = data << 1;
+		if (w9966_i2c_getsda(cam))
+			data |= 0x01;
+
+		w9966_i2c_setscl(cam, 0);
+	}
+	return data;
+}
+#endif
+
+/* Read a register from the i2c device.
+   Expects claimed pdev. -1 on error */
+#if 0
+static int w9966_read_reg_i2c(struct w9966 *cam, int reg)
+{
+	int data;
+
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
+	    w9966_i2c_wbyte(cam, reg) == -1)
+		return -1;
+
+	w9966_i2c_setsda(cam, 1);
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1)
+		return -1;
+	data = w9966_i2c_rbyte(cam);
+	if (data == -1)
+		return -1;
+
+	w9966_i2c_setsda(cam, 0);
+
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setsda(cam, 1);
+
+	return data;
+}
+#endif
+
+/* Write a register to the i2c device.
+   Expects claimed pdev. -1 on error */
+static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data)
+{
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
+			w9966_i2c_wbyte(cam, reg) == -1 ||
+			w9966_i2c_wbyte(cam, data) == -1)
+		return -1;
+
+	w9966_i2c_setsda(cam, 0);
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+
+	w9966_i2c_setsda(cam, 1);
+
+	return 0;
+}
+
+/* Find a good length for capture window (used both for W and H)
+   A bit ugly but pretty functional. The capture length
+   have to match the downscale */
+static int w9966_findlen(int near, int size, int maxlen)
+{
+	int bestlen = size;
+	int besterr = abs(near - bestlen);
+	int len;
+
+	for (len = size + 1; len < maxlen; len++) {
+		int err;
+		if (((64 * size) % len) != 0)
+			continue;
+
+		err = abs(near - len);
+
+		/* Only continue as long as we keep getting better values */
+		if (err > besterr)
+			break;
+
+		besterr = err;
+		bestlen = len;
+	}
+
+	return bestlen;
+}
+
+/* Modify capture window (if necessary)
+   and calculate downscaling
+   Return -1 on error */
+static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor)
+{
+	int maxlen = max - min;
+	int len = *end - *beg + 1;
+	int newlen = w9966_findlen(len, size, maxlen);
+	int err = newlen - len;
+
+	/* Check for bad format */
+	if (newlen > maxlen || newlen < size)
+		return -1;
+
+	/* Set factor (6 bit fixed) */
+	*factor = (64 * size) / newlen;
+	if (*factor == 64)
+		*factor = 0x00;	/* downscale is disabled */
+	else
+		*factor |= 0x80; /* set downscale-enable bit */
+
+	/* Modify old beginning and end */
+	*beg -= err / 2;
+	*end += err - (err / 2);
+
+	/* Move window if outside borders */
+	if (*beg < min) {
+		*end += min - *beg;
+		*beg += min - *beg;
+	}
+	if (*end > max) {
+		*beg -= *end - max;
+		*end -= *end - max;
+	}
+
+	return 0;
+}
+
+/* Setup the cameras capture window etc.
+   Expects a claimed pdev
+   return -1 on error */
+static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h)
+{
+	unsigned int i;
+	unsigned int enh_s, enh_e;
+	unsigned char scale_x, scale_y;
+	unsigned char regs[0x1c];
+	unsigned char saa7111_regs[] = {
+		0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
+		0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
+		0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
+	};
+
+
+	if (w * h * 2 > W9966_SRAMSIZE) {
+		DPRINTF("capture window exceeds SRAM size!.\n");
+		w = 200; h = 160;	/* Pick default values */
+	}
+
+	w &= ~0x1;
+	if (w < 2)
+		w = 2;
+	if (h < 1)
+		h = 1;
+	if (w > W9966_WND_MAX_W)
+		w = W9966_WND_MAX_W;
+	if (h > W9966_WND_MAX_H)
+		h = W9966_WND_MAX_H;
+
+	cam->width = w;
+	cam->height = h;
+
+	enh_s = 0;
+	enh_e = w * h * 2;
+
+	/* Modify capture window if necessary and calculate downscaling */
+	if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
+			w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0)
+		return -1;
+
+	DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
+			w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80);
+
+	/* Setup registers */
+	regs[0x00] = 0x00;			/* Set normal operation */
+	regs[0x01] = 0x18;			/* Capture mode */
+	regs[0x02] = scale_y;			/* V-scaling */
+	regs[0x03] = scale_x;			/* H-scaling */
+
+	/* Capture window */
+	regs[0x04] = (x1 & 0x0ff);		/* X-start (8 low bits) */
+	regs[0x05] = (x1 & 0x300)>>8;		/* X-start (2 high bits) */
+	regs[0x06] = (y1 & 0x0ff);		/* Y-start (8 low bits) */
+	regs[0x07] = (y1 & 0x300)>>8;		/* Y-start (2 high bits) */
+	regs[0x08] = (x2 & 0x0ff);		/* X-end (8 low bits) */
+	regs[0x09] = (x2 & 0x300)>>8;		/* X-end (2 high bits) */
+	regs[0x0a] = (y2 & 0x0ff);		/* Y-end (8 low bits) */
+
+	regs[0x0c] = W9966_SRAMID;		/* SRAM-banks (1x 128kb) */
+
+	/* Enhancement layer */
+	regs[0x0d] = (enh_s & 0x000ff);		/* Enh. start (0-7) */
+	regs[0x0e] = (enh_s & 0x0ff00) >> 8;	/* Enh. start (8-15) */
+	regs[0x0f] = (enh_s & 0x70000) >> 16;	/* Enh. start (16-17/18??) */
+	regs[0x10] = (enh_e & 0x000ff);		/* Enh. end (0-7) */
+	regs[0x11] = (enh_e & 0x0ff00) >> 8;	/* Enh. end (8-15) */
+	regs[0x12] = (enh_e & 0x70000) >> 16;	/* Enh. end (16-17/18??) */
+
+	/* Misc */
+	regs[0x13] = 0x40;			/* VEE control (raw 4:2:2) */
+	regs[0x17] = 0x00;			/* ??? */
+	regs[0x18] = cam->i2c_state = 0x00;	/* Serial bus */
+	regs[0x19] = 0xff;			/* I/O port direction control */
+	regs[0x1a] = 0xff;			/* I/O port data register */
+	regs[0x1b] = 0x10;			/* ??? */
+
+	/* SAA7111 chip settings */
+	saa7111_regs[0x0a] = cam->brightness;
+	saa7111_regs[0x0b] = cam->contrast;
+	saa7111_regs[0x0c] = cam->color;
+	saa7111_regs[0x0d] = cam->hue;
+
+	/* Reset (ECP-fifo & serial-bus) */
+	if (w9966_write_reg(cam, 0x00, 0x03) == -1)
+		return -1;
+
+	/* Write regs to w9966cf chip */
+	for (i = 0; i < 0x1c; i++)
+		if (w9966_write_reg(cam, i, regs[i]) == -1)
+			return -1;
+
+	/* Write regs to saa7111 chip */
+	for (i = 0; i < 0x20; i++)
+		if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1)
+			return -1;
+
+	return 0;
+}
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int cam_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *vcap)
+{
+	struct w9966 *cam = video_drvdata(file);
+
+	strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver));
+	strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card));
+	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	if (vin->index > 0)
+		return -EINVAL;
+	strlcpy(vin->name, "Camera", sizeof(vin->name));
+	vin->type = V4L2_INPUT_TYPE_CAMERA;
+	vin->audioset = 0;
+	vin->tuner = 0;
+	vin->std = 0;
+	vin->status = 0;
+	return 0;
+}
+
+static int cam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+	*inp = 0;
+	return 0;
+}
+
+static int cam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	return (inp > 0) ? -EINVAL : 0;
+}
+
+static int cam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct w9966 *cam =
+		container_of(ctrl->handler, struct w9966, hdl);
+	int ret = 0;
+
+	mutex_lock(&cam->lock);
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		cam->brightness = ctrl->val;
+		break;
+	case V4L2_CID_CONTRAST:
+		cam->contrast = ctrl->val;
+		break;
+	case V4L2_CID_SATURATION:
+		cam->color = ctrl->val;
+		break;
+	case V4L2_CID_HUE:
+		cam->hue = ctrl->val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret == 0) {
+		w9966_pdev_claim(cam);
+
+		if (w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 ||
+		    w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 ||
+		    w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 ||
+		    w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1) {
+			ret = -EIO;
+		}
+
+		w9966_pdev_release(cam);
+	}
+	mutex_unlock(&cam->lock);
+	return ret;
+}
+
+static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct w9966 *cam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	pix->width = cam->width;
+	pix->height = cam->height;
+	pix->pixelformat = V4L2_PIX_FMT_YUYV;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 2 * cam->width;
+	pix->sizeimage = 2 * cam->width * cam->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
+static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->width < 2)
+		pix->width = 2;
+	if (pix->height < 1)
+		pix->height = 1;
+	if (pix->width > W9966_WND_MAX_W)
+		pix->width = W9966_WND_MAX_W;
+	if (pix->height > W9966_WND_MAX_H)
+		pix->height = W9966_WND_MAX_H;
+	pix->pixelformat = V4L2_PIX_FMT_YUYV;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 2 * pix->width;
+	pix->sizeimage = 2 * pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
+static int cam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct w9966 *cam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	int ret = cam_try_fmt_vid_cap(file, fh, fmt);
+
+	if (ret)
+		return ret;
+
+	mutex_lock(&cam->lock);
+	/* Update camera regs */
+	w9966_pdev_claim(cam);
+	ret = w9966_setup(cam, 0, 0, 1023, 1023, pix->width, pix->height);
+	w9966_pdev_release(cam);
+	mutex_unlock(&cam->lock);
+	return ret;
+}
+
+static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "YUV 4:2:2", V4L2_PIX_FMT_YUYV,
+		  { 0, 0, 0, 0 }
+		},
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 0)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+/* Capture data */
+static ssize_t w9966_v4l_read(struct file *file, char  __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct w9966 *cam = video_drvdata(file);
+	unsigned char addr = 0xa0;	/* ECP, read, CCD-transfer, 00000 */
+	unsigned char __user *dest = (unsigned char __user *)buf;
+	unsigned long dleft = count;
+	unsigned char *tbuf;
+
+	/* Why would anyone want more than this?? */
+	if (count > cam->width * cam->height * 2)
+		return -EINVAL;
+
+	mutex_lock(&cam->lock);
+	w9966_pdev_claim(cam);
+	w9966_write_reg(cam, 0x00, 0x02);	/* Reset ECP-FIFO buffer */
+	w9966_write_reg(cam, 0x00, 0x00);	/* Return to normal operation */
+	w9966_write_reg(cam, 0x01, 0x98);	/* Enable capture */
+
+	/* write special capture-addr and negotiate into data transfer */
+	if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) ||
+			(parport_write(cam->pport, &addr, 1) != 1) ||
+			(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) {
+		w9966_pdev_release(cam);
+		mutex_unlock(&cam->lock);
+		return -EFAULT;
+	}
+
+	tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);
+	if (tbuf == NULL) {
+		count = -ENOMEM;
+		goto out;
+	}
+
+	while (dleft > 0) {
+		unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
+
+		if (parport_read(cam->pport, tbuf, tsize) < tsize) {
+			count = -EFAULT;
+			goto out;
+		}
+		if (copy_to_user(dest, tbuf, tsize) != 0) {
+			count = -EFAULT;
+			goto out;
+		}
+		dest += tsize;
+		dleft -= tsize;
+	}
+
+	w9966_write_reg(cam, 0x01, 0x18);	/* Disable capture */
+
+out:
+	kfree(tbuf);
+	w9966_pdev_release(cam);
+	mutex_unlock(&cam->lock);
+
+	return count;
+}
+
+static const struct v4l2_file_operations w9966_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= v4l2_fh_release,
+	.poll		= v4l2_ctrl_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.read           = w9966_v4l_read,
+};
+
+static const struct v4l2_ioctl_ops w9966_ioctl_ops = {
+	.vidioc_querycap    		    = cam_querycap,
+	.vidioc_g_input      		    = cam_g_input,
+	.vidioc_s_input      		    = cam_s_input,
+	.vidioc_enum_input   		    = cam_enum_input,
+	.vidioc_enum_fmt_vid_cap 	    = cam_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap 		    = cam_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap  		    = cam_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap  	    = cam_try_fmt_vid_cap,
+	.vidioc_log_status		    = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops cam_ctrl_ops = {
+	.s_ctrl = cam_s_ctrl,
+};
+
+
+/* Initialize camera device. Setup all internal flags, set a
+   default video mode, setup ccd-chip, register v4l device etc..
+   Also used for 'probing' of hardware.
+   -1 on error */
+static int w9966_init(struct w9966 *cam, struct parport *port)
+{
+	struct v4l2_device *v4l2_dev = &cam->v4l2_dev;
+
+	if (cam->dev_state != 0)
+		return -1;
+
+	strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name));
+
+	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return -1;
+	}
+
+	v4l2_ctrl_handler_init(&cam->hdl, 4);
+	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+			  V4L2_CID_CONTRAST, -64, 64, 1, 64);
+	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+			  V4L2_CID_SATURATION, -64, 64, 1, 64);
+	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+			  V4L2_CID_HUE, -128, 127, 1, 0);
+	if (cam->hdl.error) {
+		v4l2_err(v4l2_dev, "couldn't register controls\n");
+		return -1;
+	}
+	cam->pport = port;
+	cam->brightness = 128;
+	cam->contrast = 64;
+	cam->color = 64;
+	cam->hue = 0;
+
+	/* Select requested transfer mode */
+	switch (parmode) {
+	default:	/* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
+	case 0:
+		if (port->modes & PARPORT_MODE_ECP)
+			cam->ppmode = IEEE1284_MODE_ECP;
+		else if (port->modes & PARPORT_MODE_EPP)
+			cam->ppmode = IEEE1284_MODE_EPP;
+		else
+			cam->ppmode = IEEE1284_MODE_ECP;
+		break;
+	case 1:		/* hw- or sw-ecp */
+		cam->ppmode = IEEE1284_MODE_ECP;
+		break;
+	case 2:		/* hw- or sw-epp */
+		cam->ppmode = IEEE1284_MODE_EPP;
+		break;
+	}
+
+	/* Tell the parport driver that we exists */
+	cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
+	if (cam->pdev == NULL) {
+		DPRINTF("parport_register_device() failed\n");
+		return -1;
+	}
+	w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
+
+	w9966_pdev_claim(cam);
+
+	/* Setup a default capture mode */
+	if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
+		DPRINTF("w9966_setup() failed.\n");
+		return -1;
+	}
+
+	w9966_pdev_release(cam);
+
+	/* Fill in the video_device struct and register us to v4l */
+	strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name));
+	cam->vdev.v4l2_dev = v4l2_dev;
+	cam->vdev.fops = &w9966_fops;
+	cam->vdev.ioctl_ops = &w9966_ioctl_ops;
+	cam->vdev.release = video_device_release_empty;
+	cam->vdev.ctrl_handler = &cam->hdl;
+	video_set_drvdata(&cam->vdev, cam);
+
+	mutex_init(&cam->lock);
+
+	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
+		return -1;
+
+	w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
+
+	/* All ok */
+	v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n",
+			cam->pport->name);
+	return 0;
+}
+
+
+/* Terminate everything gracefully */
+static void w9966_term(struct w9966 *cam)
+{
+	/* Unregister from v4l */
+	if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
+		video_unregister_device(&cam->vdev);
+		w9966_set_state(cam, W9966_STATE_VDEV, 0);
+	}
+
+	v4l2_ctrl_handler_free(&cam->hdl);
+
+	/* Terminate from IEEE1284 mode and release pdev block */
+	if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
+		w9966_pdev_claim(cam);
+		parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT);
+		w9966_pdev_release(cam);
+	}
+
+	/* Unregister from parport */
+	if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
+		parport_unregister_device(cam->pdev);
+		w9966_set_state(cam, W9966_STATE_PDEV, 0);
+	}
+	memset(cam, 0, sizeof(*cam));
+}
+
+
+/* Called once for every parport on init */
+static void w9966_attach(struct parport *port)
+{
+	int i;
+
+	for (i = 0; i < W9966_MAXCAMS; i++) {
+		if (w9966_cams[i].dev_state != 0)	/* Cam is already assigned */
+			continue;
+		if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) {
+			if (w9966_init(&w9966_cams[i], port) != 0)
+				w9966_term(&w9966_cams[i]);
+			break;	/* return */
+		}
+	}
+}
+
+/* Called once for every parport on termination */
+static void w9966_detach(struct parport *port)
+{
+	int i;
+
+	for (i = 0; i < W9966_MAXCAMS; i++)
+		if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)
+			w9966_term(&w9966_cams[i]);
+}
+
+
+static struct parport_driver w9966_ppd = {
+	.name = W9966_DRIVERNAME,
+	.attach = w9966_attach,
+	.detach = w9966_detach,
+};
+
+/* Module entry point */
+static int __init w9966_mod_init(void)
+{
+	int i;
+
+	for (i = 0; i < W9966_MAXCAMS; i++)
+		w9966_cams[i].dev_state = 0;
+
+	return parport_register_driver(&w9966_ppd);
+}
+
+/* Module cleanup */
+static void __exit w9966_mod_term(void)
+{
+	parport_unregister_driver(&w9966_ppd);
+}
+
+module_init(w9966_mod_init);
+module_exit(w9966_mod_term);
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
index 218144a..f8cec8e 100644
--- a/drivers/media/pci/Kconfig
+++ b/drivers/media/pci/Kconfig
@@ -46,7 +46,6 @@
 source "drivers/media/pci/mantis/Kconfig"
 source "drivers/media/pci/ngene/Kconfig"
 source "drivers/media/pci/ddbridge/Kconfig"
-source "drivers/media/pci/smipcie/Kconfig"
 endif
 
 endif #MEDIA_PCI_SUPPORT
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
index 7f15888..abdb56a 100644
--- a/drivers/media/pci/Makefile
+++ b/drivers/media/pci/Makefile
@@ -11,8 +11,7 @@
 		mantis/		\
 		ngene/		\
 		ddbridge/	\
-		saa7146/	\
-		smipcie/
+		saa7146/
 
 obj-$(CPTCFG_VIDEO_IVTV) += ivtv/
 obj-$(CPTCFG_VIDEO_ZORAN) += zoran/
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
index 4105560..d8ec583 100644
--- a/drivers/media/pci/bt8xx/bttv-cards.c
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -3870,10 +3870,10 @@
 	} else {
 		unsigned short type;
 
-		for (i = 4 * 16; i < 8 * 16; i += 16) {
-			u16 checksum = (__force u16)ip_compute_csum(ee + i, 16);
+		for (i = 4*16; i < 8*16; i += 16) {
+			u16 checksum = ip_compute_csum(ee + i, 16);
 
-			if ((checksum & 0xff) + (checksum >> 8) == 0xff)
+			if ((checksum&0xff) + (checksum>>8) == 0xff)
 				break;
 		}
 		if (i >= 8*16)
diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c
index 4d3f05a..82cc47d 100644
--- a/drivers/media/pci/bt8xx/bttv-risc.c
+++ b/drivers/media/pci/bt8xx/bttv-risc.c
@@ -84,7 +84,7 @@
 			continue;
 		while (offset && offset >= sg_dma_len(sg)) {
 			offset -= sg_dma_len(sg);
-			sg = sg_next(sg);
+			sg++;
 		}
 		if (bpl <= sg_dma_len(sg)-offset) {
 			/* fits into current chunk */
@@ -100,13 +100,13 @@
 			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
 			todo -= (sg_dma_len(sg)-offset);
 			offset = 0;
-			sg = sg_next(sg);
+			sg++;
 			while (todo > sg_dma_len(sg)) {
 				*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
 						    sg_dma_len(sg));
 				*(rp++)=cpu_to_le32(sg_dma_address(sg));
 				todo -= sg_dma_len(sg);
-				sg = sg_next(sg);
+				sg++;
 			}
 			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
 					    todo);
@@ -187,15 +187,15 @@
 			/* go to next sg entry if needed */
 			while (yoffset && yoffset >= sg_dma_len(ysg)) {
 				yoffset -= sg_dma_len(ysg);
-				ysg = sg_next(ysg);
+				ysg++;
 			}
 			while (uoffset && uoffset >= sg_dma_len(usg)) {
 				uoffset -= sg_dma_len(usg);
-				usg = sg_next(usg);
+				usg++;
 			}
 			while (voffset && voffset >= sg_dma_len(vsg)) {
 				voffset -= sg_dma_len(vsg);
-				vsg = sg_next(vsg);
+				vsg++;
 			}
 
 			/* calculate max number of bytes we can write */
diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c
index 7f2cec2..d2402aa 100644
--- a/drivers/media/pci/cx18/cx18-av-core.c
+++ b/drivers/media/pci/cx18/cx18-av-core.c
@@ -490,8 +490,8 @@
 
 	/* Sets horizontal blanking delay and active lines */
 	cx18_av_write(cx, 0x470, hblank);
-	cx18_av_write(cx, 0x471,
-		      (((hblank >> 8) & 0x3) | (hactive << 4)) & 0xff);
+	cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
+						(hactive << 4)));
 	cx18_av_write(cx, 0x472, hactive >> 4);
 
 	/* Sets burst gate delay */
@@ -499,14 +499,14 @@
 
 	/* Sets vertical blanking delay and active duration */
 	cx18_av_write(cx, 0x474, vblank);
-	cx18_av_write(cx, 0x475,
-		      (((vblank >> 8) & 0x3) | (vactive << 4)) & 0xff);
+	cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
+						(vactive << 4)));
 	cx18_av_write(cx, 0x476, vactive >> 4);
 	cx18_av_write(cx, 0x477, vblank656);
 
 	/* Sets src decimation rate */
-	cx18_av_write(cx, 0x478, src_decimation & 0xff);
-	cx18_av_write(cx, 0x479, (src_decimation >> 8) & 0xff);
+	cx18_av_write(cx, 0x478, 0xff & src_decimation);
+	cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
 
 	/* Sets Luma and UV Low pass filters */
 	cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
@@ -516,8 +516,8 @@
 
 	/* Sets SC Step*/
 	cx18_av_write(cx, 0x47c, sc);
-	cx18_av_write(cx, 0x47d, (sc >> 8) & 0xff);
-	cx18_av_write(cx, 0x47e, (sc >> 16) & 0xff);
+	cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
+	cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
 
 	if (std & V4L2_STD_625_50) {
 		state->slicer_line_delay = 1;
@@ -952,7 +952,7 @@
 	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
 	int is_50Hz = !(state->std & V4L2_STD_525_60);
 
-	if (fmt->code != MEDIA_BUS_FMT_FIXED)
+	if (fmt->code != V4L2_MBUS_FMT_FIXED)
 		return -EINVAL;
 
 	fmt->field = V4L2_FIELD_INTERLACED;
diff --git a/drivers/media/pci/cx18/cx18-cards.h b/drivers/media/pci/cx18/cx18-cards.h
index f6b921f..add7391 100644
--- a/drivers/media/pci/cx18/cx18-cards.h
+++ b/drivers/media/pci/cx18/cx18-cards.h
@@ -57,8 +57,7 @@
 /* V4L2 capability aliases */
 #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
 			  V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \
-			  V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE | \
-			  V4L2_CAP_SLICED_VBI_CAPTURE)
+			  V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)
 
 struct cx18_card_video_input {
 	u8  video_type; 	/* video input type */
diff --git a/drivers/media/pci/cx18/cx18-controls.c b/drivers/media/pci/cx18/cx18-controls.c
index 4aeb7c6..282a3d2 100644
--- a/drivers/media/pci/cx18/cx18-controls.c
+++ b/drivers/media/pci/cx18/cx18-controls.c
@@ -98,7 +98,7 @@
 	/* fix videodecoder resolution */
 	fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
 	fmt.height = cxhdl->height;
-	fmt.code = MEDIA_BUS_FMT_FIXED;
+	fmt.code = V4L2_MBUS_FMT_FIXED;
 	v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
 	return 0;
 }
diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h
index 207d6e8..57f4688 100644
--- a/drivers/media/pci/cx18/cx18-driver.h
+++ b/drivers/media/pci/cx18/cx18-driver.h
@@ -290,7 +290,7 @@
  * list_entry_is_past_end - check if a previous loop cursor is off list end
  * @pos:	the type * previously used as a loop cursor.
  * @head:	the head for your list.
- * @member:	the name of the list_head within the struct.
+ * @member:	the name of the list_struct within the struct.
  *
  * Check if the entry's list_head is the head of the list, thus it's not a
  * real entry but was the loop cursor that walked past the end
@@ -379,7 +379,6 @@
 	const char *name;		/* name of the stream */
 	int type;			/* stream type */
 	u32 handle;			/* task handle */
-	u32 v4l2_dev_caps;		/* device capabilities */
 	unsigned int mdl_base_idx;
 
 	u32 id;
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
index 27fdad8..0d6616b 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -294,7 +294,7 @@
 
 	mbus_fmt.width = cx->cxhdl.width = w;
 	mbus_fmt.height = cx->cxhdl.height = h;
-	mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
+	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
 	v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
 	return cx18_g_fmt_vid_cap(file, fh, fmt);
 }
@@ -393,16 +393,15 @@
 				struct v4l2_capability *vcap)
 {
 	struct cx18_open_id *id = fh2id(fh);
-	struct cx18_stream *s = video_drvdata(file);
 	struct cx18 *cx = id->cx;
 
 	strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
 	strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
 	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
 		 "PCI:%s", pci_name(cx->pci_dev));
-	vcap->capabilities = cx->v4l2_cap;	/* capabilities */
-	vcap->device_caps = s->v4l2_dev_caps;	/* device capabilities */
-	vcap->capabilities |= V4L2_CAP_DEVICE_CAPS;
+	vcap->capabilities = cx->v4l2_cap; 	    /* capabilities */
+	if (id->type == CX18_ENC_STREAM_TYPE_YUV)
+		vcap->capabilities |= V4L2_CAP_STREAMING;
 	return 0;
 }
 
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index 369445f..f3541b5 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -58,14 +58,11 @@
 	int vfl_type;
 	int num_offset;
 	int dma;
-	u32 caps;
 } cx18_stream_info[] = {
 	{	/* CX18_ENC_STREAM_TYPE_MPG */
 		"encoder MPEG",
 		VFL_TYPE_GRABBER, 0,
 		PCI_DMA_FROMDEVICE,
-		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-		V4L2_CAP_AUDIO | V4L2_CAP_TUNER
 	},
 	{	/* CX18_ENC_STREAM_TYPE_TS */
 		"TS",
@@ -76,15 +73,11 @@
 		"encoder YUV",
 		VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
 		PCI_DMA_FROMDEVICE,
-		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-		V4L2_CAP_STREAMING | V4L2_CAP_AUDIO | V4L2_CAP_TUNER
 	},
 	{	/* CX18_ENC_STREAM_TYPE_VBI */
 		"encoder VBI",
 		VFL_TYPE_VBI, 0,
 		PCI_DMA_FROMDEVICE,
-		V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE |
-		V4L2_CAP_READWRITE | V4L2_CAP_TUNER
 	},
 	{	/* CX18_ENC_STREAM_TYPE_PCM */
 		"encoder PCM audio",
@@ -100,7 +93,6 @@
 		"encoder radio",
 		VFL_TYPE_RADIO, 0,
 		PCI_DMA_NONE,
-		V4L2_CAP_RADIO | V4L2_CAP_TUNER
 	},
 };
 
@@ -268,7 +260,6 @@
 	s->handle = CX18_INVALID_TASK_HANDLE;
 
 	s->dma = cx18_stream_info[type].dma;
-	s->v4l2_dev_caps = cx18_stream_info[type].caps;
 	s->buffers = cx->stream_buffers[type];
 	s->buf_size = cx->stream_buf_size[type];
 	INIT_LIST_HEAD(&s->buf_pool);
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig
index fcbcf43..911c260 100644
--- a/drivers/media/pci/cx23885/Kconfig
+++ b/drivers/media/pci/cx23885/Kconfig
@@ -1,5 +1,5 @@
 config VIDEO_CX23885
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Conexant cx23885 (2388x successor) support"
 	depends on m
 	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index 5a0f130..4a4f949 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1148,7 +1148,6 @@
 	dev->ts1.ts_packet_count = mpeglines;
 	*num_planes = 1;
 	sizes[0] = mpeglinesize * mpeglines;
-	alloc_ctxs[0] = dev->alloc_ctx;
 	*num_buffers = mpegbufs;
 	return 0;
 }
@@ -1167,8 +1166,11 @@
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf = container_of(vb,
 		struct cx23885_buffer, vb);
+	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	cx23885_free_buffer(dev, buf);
+
+	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void buffer_queue(struct vb2_buffer *vb)
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index db99ca2..88c257d 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -680,32 +680,6 @@
 		.portb		= CX23885_MPEG_DVB,
 		.portc		= CX23885_MPEG_DVB,
 	},
-	[CX23885_BOARD_DVBSKY_T980C] = {
-		.name		= "DVBSky T980C",
-		.portb		= CX23885_MPEG_DVB,
-	},
-	[CX23885_BOARD_DVBSKY_S950C] = {
-		.name		= "DVBSky S950C",
-		.portb		= CX23885_MPEG_DVB,
-	},
-	[CX23885_BOARD_TT_CT2_4500_CI] = {
-		.name		= "Technotrend TT-budget CT2-4500 CI",
-		.portb		= CX23885_MPEG_DVB,
-	},
-	[CX23885_BOARD_DVBSKY_S950] = {
-		.name		= "DVBSky S950",
-		.portb		= CX23885_MPEG_DVB,
-	},
-	[CX23885_BOARD_DVBSKY_S952] = {
-		.name		= "DVBSky S952",
-		.portb		= CX23885_MPEG_DVB,
-		.portc		= CX23885_MPEG_DVB,
-	},
-	[CX23885_BOARD_DVBSKY_T982] = {
-		.name		= "DVBSky T982",
-		.portb		= CX23885_MPEG_DVB,
-		.portc		= CX23885_MPEG_DVB,
-	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -965,30 +939,6 @@
 		.subvendor = 0x4254,
 		.subdevice = 0x9580,
 		.card      = CX23885_BOARD_DVBSKY_T9580,
-	}, {
-		.subvendor = 0x4254,
-		.subdevice = 0x980c,
-		.card      = CX23885_BOARD_DVBSKY_T980C,
-	}, {
-		.subvendor = 0x4254,
-		.subdevice = 0x950c,
-		.card      = CX23885_BOARD_DVBSKY_S950C,
-	}, {
-		.subvendor = 0x13c2,
-		.subdevice = 0x3013,
-		.card      = CX23885_BOARD_TT_CT2_4500_CI,
-	}, {
-		.subvendor = 0x4254,
-		.subdevice = 0x0950,
-		.card      = CX23885_BOARD_DVBSKY_S950,
-	}, {
-		.subvendor = 0x4254,
-		.subdevice = 0x0952,
-		.card      = CX23885_BOARD_DVBSKY_S952,
-	}, {
-		.subvendor = 0x4254,
-		.subdevice = 0x0982,
-		.card      = CX23885_BOARD_DVBSKY_T982,
 	},
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -1584,8 +1534,6 @@
 		mdelay(60);
 		break;
 	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982:
 		/* enable GPIO3-18 pins */
 		cx_write(MC417_CTL, 0x00000037);
 		cx23885_gpio_enable(dev, GPIO_2 | GPIO_11, 1);
@@ -1593,45 +1541,6 @@
 		mdelay(100);
 		cx23885_gpio_set(dev, GPIO_2 | GPIO_11);
 		break;
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-		/*
-		 * GPIO-0 INTA from CiMax, input
-		 * GPIO-1 reset CiMax, output, high active
-		 * GPIO-2 reset demod, output, low active
-		 * GPIO-3 to GPIO-10 data/addr for CAM
-		 * GPIO-11 ~CS0 to CiMax1
-		 * GPIO-12 ~CS1 to CiMax2
-		 * GPIO-13 ADL0 load LSB addr
-		 * GPIO-14 ADL1 load MSB addr
-		 * GPIO-15 ~RDY from CiMax
-		 * GPIO-17 ~RD to CiMax
-		 * GPIO-18 ~WR to CiMax
-		 */
-
-		cx_set(GP0_IO, 0x00060002); /* GPIO 1/2 as output */
-		cx_clear(GP0_IO, 0x00010004); /* GPIO 0 as input */
-		mdelay(100); /* reset delay */
-		cx_set(GP0_IO, 0x00060004); /* GPIO as out, reset high */
-		cx_clear(GP0_IO, 0x00010002);
-		cx_write(MC417_CTL, 0x00000037); /* enable GPIO3-18 pins */
-
-		/* GPIO-15 IN as ~ACK, rest as OUT */
-		cx_write(MC417_OEN, 0x00001000);
-
-		/* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */
-		cx_write(MC417_RWD, 0x0000c300);
-
-		/* enable irq */
-		cx_write(GPIO_ISM, 0x00000000); /* INTERRUPTS active low */
-		break;
-	case CX23885_BOARD_DVBSKY_S950:
-		cx23885_gpio_enable(dev, GPIO_2, 1);
-		cx23885_gpio_clear(dev, GPIO_2);
-		msleep(100);
-		cx23885_gpio_set(dev, GPIO_2);
-		break;
 	}
 }
 
@@ -1712,13 +1621,6 @@
 	case CX23885_BOARD_MYGICA_X8507:
 	case CX23885_BOARD_TBS_6980:
 	case CX23885_BOARD_TBS_6981:
-	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982:
 		if (!enable_885_ir)
 			break;
 		dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
@@ -1765,13 +1667,6 @@
 	case CX23885_BOARD_MYGICA_X8507:
 	case CX23885_BOARD_TBS_6980:
 	case CX23885_BOARD_TBS_6981:
-	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982:
 		cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
 		/* sd_ir is a duplicate pointer to the AV Core, just clear it */
 		dev->sd_ir = NULL;
@@ -1819,13 +1714,6 @@
 	case CX23885_BOARD_MYGICA_X8507:
 	case CX23885_BOARD_TBS_6980:
 	case CX23885_BOARD_TBS_6981:
-	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982:
 		if (dev->sd_ir)
 			cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
 		break;
@@ -1929,10 +1817,6 @@
 	case CX23885_BOARD_TEVII_S471:
 	case CX23885_BOARD_DVBWORLD_2005:
 	case CX23885_BOARD_PROF_8000:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-	case CX23885_BOARD_DVBSKY_S950:
 		ts1->gen_ctrl_val  = 0x5; /* Parallel */
 		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1981,7 +1865,6 @@
 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
 		break;
 	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_T982:
 		ts1->gen_ctrl_val  = 0x5; /* Parallel */
 		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1989,14 +1872,6 @@
 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
 		break;
-	case CX23885_BOARD_DVBSKY_S952:
-		ts1->gen_ctrl_val  = 0x5; /* Parallel */
-		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
-		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
-		ts2->gen_ctrl_val  = 0xe; /* Serial bus */
-		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
-		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
-		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -2060,12 +1935,6 @@
 	case CX23885_BOARD_TBS_6980:
 	case CX23885_BOARD_TBS_6981:
 	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982:
 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
 				&dev->i2c_bus[2].i2c_adap,
 				"cx25840", 0x88 >> 1, NULL);
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 1d9d0f8..331edda 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -1078,7 +1078,7 @@
 	for (line = 0; line < lines; line++) {
 		while (offset && offset >= sg_dma_len(sg)) {
 			offset -= sg_dma_len(sg);
-			sg = sg_next(sg);
+			sg++;
 		}
 
 		if (lpi && line > 0 && !(line % lpi))
@@ -1101,14 +1101,14 @@
 			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
 			todo -= (sg_dma_len(sg)-offset);
 			offset = 0;
-			sg = sg_next(sg);
+			sg++;
 			while (todo > sg_dma_len(sg)) {
 				*(rp++) = cpu_to_le32(RISC_WRITE|
 						    sg_dma_len(sg));
 				*(rp++) = cpu_to_le32(sg_dma_address(sg));
 				*(rp++) = cpu_to_le32(0); /* bits 63-32 */
 				todo -= sg_dma_len(sg);
-				sg = sg_next(sg);
+				sg++;
 			}
 			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
 			*(rp++) = cpu_to_le32(sg_dma_address(sg));
@@ -1453,12 +1453,17 @@
 	struct cx23885_dev *dev = port->dev;
 	int size = port->ts_packet_size * port->ts_packet_count;
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
+	int rc;
 
 	dprintk(1, "%s: %p\n", __func__, buf);
 	if (vb2_plane_size(&buf->vb, 0) < size)
 		return -EINVAL;
 	vb2_set_plane_payload(&buf->vb, 0, size);
 
+	rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+	if (!rc)
+		return -EIO;
+
 	cx23885_risc_databuffer(dev->pci, &buf->risc,
 				sgt->sgl,
 				port->ts_packet_size, port->ts_packet_count, 0);
@@ -1992,14 +1997,9 @@
 	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
 		printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
 		err = -EIO;
-		goto fail_context;
+		goto fail_irq;
 	}
 
-	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
-	if (IS_ERR(dev->alloc_ctx)) {
-		err = PTR_ERR(dev->alloc_ctx);
-		goto fail_context;
-	}
 	err = request_irq(pci_dev->irq, cx23885_irq,
 			  IRQF_SHARED, dev->name, dev);
 	if (err < 0) {
@@ -2028,8 +2028,6 @@
 	return 0;
 
 fail_irq:
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
-fail_context:
 	cx23885_dev_unregister(dev);
 fail_ctrl:
 	v4l2_ctrl_handler_free(hdl);
@@ -2055,7 +2053,6 @@
 	free_irq(pci_dev->irq, dev);
 
 	cx23885_dev_unregister(dev);
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 	v4l2_ctrl_handler_free(&dev->ctrl_handler);
 	v4l2_device_unregister(v4l2_dev);
 	kfree(dev);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index c47d182..13734b8 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -71,7 +71,6 @@
 #include "si2165.h"
 #include "si2168.h"
 #include "si2157.h"
-#include "sp2.h"
 #include "m88ds3103.h"
 #include "m88ts2022.h"
 
@@ -102,7 +101,6 @@
 	port->ts_packet_count = 32;
 	*num_planes = 1;
 	sizes[0] = port->ts_packet_size * port->ts_packet_count;
-	alloc_ctxs[0] = port->dev->alloc_ctx;
 	*num_buffers = 32;
 	return 0;
 }
@@ -123,8 +121,11 @@
 	struct cx23885_dev *dev = port->dev;
 	struct cx23885_buffer *buf = container_of(vb,
 		struct cx23885_buffer, vb);
+	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	cx23885_free_buffer(dev, buf);
+
+	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void buffer_queue(struct vb2_buffer *vb)
@@ -615,103 +616,6 @@
 	return 0;
 }
 
-static int dvbsky_s952_portc_set_voltage(struct dvb_frontend *fe,
-					fe_sec_voltage_t voltage)
-{
-	struct cx23885_tsport *port = fe->dvb->priv;
-	struct cx23885_dev *dev = port->dev;
-
-	cx23885_gpio_enable(dev, GPIO_12 | GPIO_13, 1);
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		cx23885_gpio_set(dev, GPIO_13);
-		cx23885_gpio_clear(dev, GPIO_12);
-		break;
-	case SEC_VOLTAGE_18:
-		cx23885_gpio_set(dev, GPIO_13);
-		cx23885_gpio_set(dev, GPIO_12);
-		break;
-	case SEC_VOLTAGE_OFF:
-		cx23885_gpio_clear(dev, GPIO_13);
-		cx23885_gpio_clear(dev, GPIO_12);
-		break;
-	}
-	/* call the frontend set_voltage function */
-	return port->fe_set_voltage(fe, voltage);
-}
-
-static int cx23885_sp2_ci_ctrl(void *priv, u8 read, int addr,
-				u8 data, int *mem)
-{
-	/* MC417 */
-	#define SP2_DATA              0x000000ff
-	#define SP2_WR                0x00008000
-	#define SP2_RD                0x00004000
-	#define SP2_ACK               0x00001000
-	#define SP2_ADHI              0x00000800
-	#define SP2_ADLO              0x00000400
-	#define SP2_CS1               0x00000200
-	#define SP2_CS0               0x00000100
-	#define SP2_EN_ALL            0x00001000
-	#define SP2_CTRL_OFF          (SP2_CS1 | SP2_CS0 | SP2_WR | SP2_RD)
-
-	struct cx23885_tsport *port = priv;
-	struct cx23885_dev *dev = port->dev;
-	int ret;
-	int tmp = 0;
-	unsigned long timeout;
-
-	mutex_lock(&dev->gpio_lock);
-
-	/* write addr */
-	cx_write(MC417_OEN, SP2_EN_ALL);
-	cx_write(MC417_RWD, SP2_CTRL_OFF |
-				SP2_ADLO | (0xff & addr));
-	cx_clear(MC417_RWD, SP2_ADLO);
-	cx_write(MC417_RWD, SP2_CTRL_OFF |
-				SP2_ADHI | (0xff & (addr >> 8)));
-	cx_clear(MC417_RWD, SP2_ADHI);
-
-	if (read)
-		/* data in */
-		cx_write(MC417_OEN, SP2_EN_ALL | SP2_DATA);
-	else
-		/* data out */
-		cx_write(MC417_RWD, SP2_CTRL_OFF | data);
-
-	/* chip select 0 */
-	cx_clear(MC417_RWD, SP2_CS0);
-
-	/* read/write */
-	cx_clear(MC417_RWD, (read) ? SP2_RD : SP2_WR);
-
-	/* wait for a maximum of 1 msec */
-	timeout = jiffies + msecs_to_jiffies(1);
-	while (!time_after(jiffies, timeout)) {
-		tmp = cx_read(MC417_RWD);
-		if ((tmp & SP2_ACK) == 0)
-			break;
-		usleep_range(50, 100);
-	}
-
-	cx_set(MC417_RWD, SP2_CTRL_OFF);
-	*mem = tmp & 0xff;
-
-	mutex_unlock(&dev->gpio_lock);
-
-	if (!read) {
-		if (*mem < 0) {
-			ret = -EREMOTEIO;
-			goto err;
-		}
-	}
-
-	return 0;
-err:
-	return ret;
-}
-
 static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
 {
 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
@@ -889,32 +793,6 @@
 	.agc = 0x99,
 };
 
-static const struct m88ds3103_config dvbsky_s950c_m88ds3103_config = {
-	.i2c_addr = 0x68,
-	.clock = 27000000,
-	.i2c_wr_max = 33,
-	.clock_out = 0,
-	.ts_mode = M88DS3103_TS_CI,
-	.ts_clk = 10000,
-	.ts_clk_pol = 1,
-	.lnb_en_pol = 1,
-	.lnb_hv_pol = 0,
-	.agc = 0x99,
-};
-
-static const struct m88ds3103_config dvbsky_s952_portc_m88ds3103_config = {
-	.i2c_addr = 0x68,
-	.clock = 27000000,
-	.i2c_wr_max = 33,
-	.clock_out = 0,
-	.ts_mode = M88DS3103_TS_SERIAL,
-	.ts_clk = 96000,
-	.ts_clk_pol = 0,
-	.lnb_en_pol = 1,
-	.lnb_hv_pol = 0,
-	.agc = 0x99,
-};
-
 static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
 {
 	struct cx23885_dev *dev = (struct cx23885_dev *)device;
@@ -1066,13 +944,11 @@
 	struct vb2_dvb_frontend *fe0, *fe1 = NULL;
 	struct si2168_config si2168_config;
 	struct si2157_config si2157_config;
-	struct sp2_config sp2_config;
 	struct m88ts2022_config m88ts2022_config;
 	struct i2c_board_info info;
 	struct i2c_adapter *adapter;
-	struct i2c_client *client_demod = NULL, *client_tuner = NULL, *client_ci = NULL;
-	const struct m88ds3103_config *p_m88ds3103_config = NULL;
-	int (*p_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage) = NULL;
+	struct i2c_client *client_demod;
+	struct i2c_client *client_tuner;
 	int mfe_shared = 0; /* bus not shared by default */
 	int ret;
 
@@ -1097,11 +973,11 @@
 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&hauppauge_generic_config,
 						&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(mt2131_attach, fe0->dvb.frontend,
-			   &i2c_bus->i2c_adap,
-			   &hauppauge_generic_tunerconfig, 0);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(mt2131_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap,
+				   &hauppauge_generic_tunerconfig, 0);
+		}
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1270:
 	case CX23885_BOARD_HAUPPAUGE_HVR1275:
@@ -1109,11 +985,11 @@
 		fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
 					       &hauppauge_lgdt3305_config,
 					       &i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(tda18271_attach, fe0->dvb.frontend,
-			   0x60, &dev->i2c_bus[1].i2c_adap,
-			   &hauppauge_hvr127x_config);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_bus[1].i2c_adap,
+				   &hauppauge_hvr127x_config);
+		}
 		if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1275)
 			cx23885_set_frontend_hook(port, fe0->dvb.frontend);
 		break;
@@ -1123,12 +999,11 @@
 		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
 					       &hcw_s5h1411_config,
 					       &i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-
-		dvb_attach(tda18271_attach, fe0->dvb.frontend,
-			   0x60, &dev->i2c_bus[1].i2c_adap,
-			   &hauppauge_tda18271_config);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_bus[1].i2c_adap,
+				   &hauppauge_tda18271_config);
+		}
 
 		tda18271_attach(&dev->ts1.analog_fe,
 			0x60, &dev->i2c_bus[1].i2c_adap,
@@ -1143,15 +1018,14 @@
 				dvb_attach(s5h1409_attach,
 					   &hauppauge_ezqam_config,
 					   &i2c_bus->i2c_adap);
-			if (fe0->dvb.frontend == NULL)
-				break;
-
-			dvb_attach(tda829x_attach, fe0->dvb.frontend,
-				   &dev->i2c_bus[1].i2c_adap, 0x42,
-				   &tda829x_no_probe);
-			dvb_attach(tda18271_attach, fe0->dvb.frontend,
-				   0x60, &dev->i2c_bus[1].i2c_adap,
-				   &hauppauge_tda18271_config);
+			if (fe0->dvb.frontend != NULL) {
+				dvb_attach(tda829x_attach, fe0->dvb.frontend,
+					   &dev->i2c_bus[1].i2c_adap, 0x42,
+					   &tda829x_no_probe);
+				dvb_attach(tda18271_attach, fe0->dvb.frontend,
+					   0x60, &dev->i2c_bus[1].i2c_adap,
+					   &hauppauge_tda18271_config);
+			}
 			break;
 		case 0:
 		default:
@@ -1159,11 +1033,11 @@
 				dvb_attach(s5h1409_attach,
 					   &hauppauge_generic_config,
 					   &i2c_bus->i2c_adap);
-			if (fe0->dvb.frontend == NULL)
-				break;
-			dvb_attach(mt2131_attach, fe0->dvb.frontend,
-				   &i2c_bus->i2c_adap,
-				   &hauppauge_generic_tunerconfig, 0);
+			if (fe0->dvb.frontend != NULL)
+				dvb_attach(mt2131_attach, fe0->dvb.frontend,
+					   &i2c_bus->i2c_adap,
+					   &hauppauge_generic_tunerconfig, 0);
+			break;
 		}
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
@@ -1171,33 +1045,32 @@
 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&hauppauge_hvr1800lp_config,
 						&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(mt2131_attach, fe0->dvb.frontend,
-			   &i2c_bus->i2c_adap,
-			   &hauppauge_generic_tunerconfig, 0);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(mt2131_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap,
+				   &hauppauge_generic_tunerconfig, 0);
+		}
 		break;
 	case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
 		i2c_bus = &dev->i2c_bus[0];
 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 						&fusionhdtv_5_express,
 						&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-			   &i2c_bus->i2c_adap, 0x61,
-			   TUNER_LG_TDVS_H06XF);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap, 0x61,
+				   TUNER_LG_TDVS_H06XF);
+		}
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
 		i2c_bus = &dev->i2c_bus[1];
 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 						&hauppauge_hvr1500q_config,
 						&dev->i2c_bus[0].i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(xc5000_attach, fe0->dvb.frontend,
-			   &i2c_bus->i2c_adap,
-			   &hauppauge_hvr1500q_tunerconfig);
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(xc5000_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap,
+				   &hauppauge_hvr1500q_tunerconfig);
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
 		i2c_bus = &dev->i2c_bus[1];
@@ -1228,14 +1101,14 @@
 		fe0->dvb.frontend = dvb_attach(tda10048_attach,
 			&hauppauge_hvr1200_config,
 			&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(tda829x_attach, fe0->dvb.frontend,
-			   &dev->i2c_bus[1].i2c_adap, 0x42,
-			   &tda829x_no_probe);
-		dvb_attach(tda18271_attach, fe0->dvb.frontend,
-			   0x60, &dev->i2c_bus[1].i2c_adap,
-			   &hauppauge_hvr1200_tuner_config);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda829x_attach, fe0->dvb.frontend,
+				&dev->i2c_bus[1].i2c_adap, 0x42,
+				&tda829x_no_probe);
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				0x60, &dev->i2c_bus[1].i2c_adap,
+				&hauppauge_hvr1200_tuner_config);
+		}
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1210:
 		i2c_bus = &dev->i2c_bus[0];
@@ -1494,10 +1367,12 @@
 		fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
 			&mygica_x8506_lgs8gl5_config,
 			&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(xc5000_attach, fe0->dvb.frontend,
-			   &i2c_bus2->i2c_adap, &mygica_x8506_xc5000_config);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(xc5000_attach,
+				fe0->dvb.frontend,
+				&i2c_bus2->i2c_adap,
+				&mygica_x8506_xc5000_config);
+		}
 		cx23885_set_frontend_hook(port, fe0->dvb.frontend);
 		break;
 	case CX23885_BOARD_MYGICA_X8507:
@@ -1506,12 +1381,12 @@
 		fe0->dvb.frontend = dvb_attach(mb86a20s_attach,
 			&mygica_x8507_mb86a20s_config,
 			&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-
-		dvb_attach(xc5000_attach, fe0->dvb.frontend,
-			   &i2c_bus2->i2c_adap,
-			   &mygica_x8507_xc5000_config);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(xc5000_attach,
+			fe0->dvb.frontend,
+			&i2c_bus2->i2c_adap,
+			&mygica_x8507_xc5000_config);
+		}
 		cx23885_set_frontend_hook(port, fe0->dvb.frontend);
 		break;
 	case CX23885_BOARD_MAGICPRO_PROHDTVE2:
@@ -1520,11 +1395,12 @@
 		fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
 			&magicpro_prohdtve2_lgs8g75_config,
 			&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(xc5000_attach, fe0->dvb.frontend,
-			   &i2c_bus2->i2c_adap,
-			   &magicpro_prohdtve2_xc5000_config);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(xc5000_attach,
+				fe0->dvb.frontend,
+				&i2c_bus2->i2c_adap,
+				&magicpro_prohdtve2_xc5000_config);
+		}
 		cx23885_set_frontend_hook(port, fe0->dvb.frontend);
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1850:
@@ -1532,11 +1408,10 @@
 		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
 			&hcw_s5h1411_config,
 			&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(tda18271_attach, fe0->dvb.frontend,
-			   0x60, &dev->i2c_bus[0].i2c_adap,
-			   &hauppauge_tda18271_config);
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				0x60, &dev->i2c_bus[0].i2c_adap,
+				&hauppauge_tda18271_config);
 
 		tda18271_attach(&dev->ts1.analog_fe,
 			0x60, &dev->i2c_bus[1].i2c_adap,
@@ -1548,11 +1423,10 @@
 		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
 			&hcw_s5h1411_config,
 			&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(tda18271_attach, fe0->dvb.frontend,
-			   0x60, &dev->i2c_bus[0].i2c_adap,
-			   &hauppauge_tda18271_config);
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				0x60, &dev->i2c_bus[0].i2c_adap,
+				&hauppauge_tda18271_config);
 		break;
 	case CX23885_BOARD_MYGICA_X8558PRO:
 		switch (port->nr) {
@@ -1562,11 +1436,12 @@
 			fe0->dvb.frontend = dvb_attach(atbm8830_attach,
 				&mygica_x8558pro_atbm8830_cfg1,
 				&i2c_bus->i2c_adap);
-			if (fe0->dvb.frontend == NULL)
-				break;
-			dvb_attach(max2165_attach, fe0->dvb.frontend,
-				   &i2c_bus->i2c_adap,
-				   &mygic_x8558pro_max2165_cfg1);
+			if (fe0->dvb.frontend != NULL) {
+				dvb_attach(max2165_attach,
+					fe0->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&mygic_x8558pro_max2165_cfg1);
+			}
 			break;
 		/* port C */
 		case 2:
@@ -1574,11 +1449,13 @@
 			fe0->dvb.frontend = dvb_attach(atbm8830_attach,
 				&mygica_x8558pro_atbm8830_cfg2,
 				&i2c_bus->i2c_adap);
-			if (fe0->dvb.frontend == NULL)
-				break;
-			dvb_attach(max2165_attach, fe0->dvb.frontend,
-				   &i2c_bus->i2c_adap,
-				   &mygic_x8558pro_max2165_cfg2);
+			if (fe0->dvb.frontend != NULL) {
+				dvb_attach(max2165_attach,
+					fe0->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&mygic_x8558pro_max2165_cfg2);
+			}
+			break;
 		}
 		break;
 	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
@@ -1590,15 +1467,15 @@
 		fe0->dvb.frontend = dvb_attach(stv0367ter_attach,
 					&netup_stv0367_config[port->nr - 1],
 					&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		if (NULL == dvb_attach(xc5000_attach, fe0->dvb.frontend,
+		if (fe0->dvb.frontend != NULL) {
+			if (NULL == dvb_attach(xc5000_attach,
+					fe0->dvb.frontend,
 					&i2c_bus->i2c_adap,
 					&netup_xc5000_config[port->nr - 1]))
-			goto frontend_detach;
-		/* load xc5000 firmware */
-		fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
-
+				goto frontend_detach;
+			/* load xc5000 firmware */
+			fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
+		}
 		/* MFE frontend 2 */
 		fe1 = vb2_dvb_get_frontend(&port->frontends, 2);
 		if (fe1 == NULL)
@@ -1607,15 +1484,14 @@
 		fe1->dvb.frontend = dvb_attach(stv0367cab_attach,
 					&netup_stv0367_config[port->nr - 1],
 					&i2c_bus->i2c_adap);
-		if (fe1->dvb.frontend == NULL)
-			break;
-
-		fe1->dvb.frontend->id = 1;
-		if (NULL == dvb_attach(xc5000_attach,
-				       fe1->dvb.frontend,
-				       &i2c_bus->i2c_adap,
-				       &netup_xc5000_config[port->nr - 1]))
-			goto frontend_detach;
+		if (fe1->dvb.frontend != NULL) {
+			fe1->dvb.frontend->id = 1;
+			if (NULL == dvb_attach(xc5000_attach,
+					fe1->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&netup_xc5000_config[port->nr - 1]))
+				goto frontend_detach;
+		}
 		break;
 	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
 		i2c_bus = &dev->i2c_bus[0];
@@ -1627,26 +1503,26 @@
 			fe0->dvb.frontend = dvb_attach(drxk_attach,
 					&terratec_drxk_config[0],
 					&i2c_bus->i2c_adap);
-			if (fe0->dvb.frontend == NULL)
-				break;
-			if (!dvb_attach(mt2063_attach,
-					fe0->dvb.frontend,
-					&terratec_mt2063_config[0],
-					&i2c_bus2->i2c_adap))
-				goto frontend_detach;
+			if (fe0->dvb.frontend != NULL) {
+				if (!dvb_attach(mt2063_attach,
+						fe0->dvb.frontend,
+						&terratec_mt2063_config[0],
+						&i2c_bus2->i2c_adap))
+					goto frontend_detach;
+			}
 			break;
 		/* port c */
 		case 2:
 			fe0->dvb.frontend = dvb_attach(drxk_attach,
 					&terratec_drxk_config[1],
 					&i2c_bus->i2c_adap);
-			if (fe0->dvb.frontend == NULL)
-				break;
-			if (!dvb_attach(mt2063_attach,
-					fe0->dvb.frontend,
-					&terratec_mt2063_config[1],
-					&i2c_bus2->i2c_adap))
-				goto frontend_detach;
+			if (fe0->dvb.frontend != NULL) {
+				if (!dvb_attach(mt2063_attach,
+						fe0->dvb.frontend,
+						&terratec_mt2063_config[1],
+						&i2c_bus2->i2c_adap))
+					goto frontend_detach;
+			}
 			break;
 		}
 		break;
@@ -1656,10 +1532,10 @@
 		fe0->dvb.frontend = dvb_attach(ds3000_attach,
 					&tevii_ds3000_config,
 					&i2c_bus->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		dvb_attach(ts2020_attach, fe0->dvb.frontend,
-			   &tevii_ts2020_config, &i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(ts2020_attach, fe0->dvb.frontend,
+				&tevii_ts2020_config, &i2c_bus->i2c_adap);
+		}
 		break;
 	case CX23885_BOARD_PROF_8000:
 		i2c_bus = &dev->i2c_bus[0];
@@ -1668,15 +1544,15 @@
 						&prof_8000_stv090x_config,
 						&i2c_bus->i2c_adap,
 						STV090x_DEMODULATOR_0);
-		if (fe0->dvb.frontend == NULL)
-			break;
-		if (!dvb_attach(stb6100_attach,
-				fe0->dvb.frontend,
-				&prof_8000_stb6100_config,
-				&i2c_bus->i2c_adap))
-			goto frontend_detach;
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(stb6100_attach,
+					fe0->dvb.frontend,
+					&prof_8000_stb6100_config,
+					&i2c_bus->i2c_adap))
+				goto frontend_detach;
 
-		fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
+		}
 		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR4400:
 		i2c_bus = &dev->i2c_bus[0];
@@ -1687,31 +1563,30 @@
 			fe0->dvb.frontend = dvb_attach(tda10071_attach,
 						&hauppauge_tda10071_config,
 						&i2c_bus->i2c_adap);
-			if (fe0->dvb.frontend == NULL)
-				break;
-			if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
-					&i2c_bus->i2c_adap,
-					&hauppauge_a8293_config))
-				goto frontend_detach;
+			if (fe0->dvb.frontend != NULL) {
+				if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
+						&i2c_bus->i2c_adap,
+						&hauppauge_a8293_config))
+					goto frontend_detach;
+			}
 			break;
 		/* port c */
 		case 2:
 			fe0->dvb.frontend = dvb_attach(si2165_attach,
 					&hauppauge_hvr4400_si2165_config,
 					&i2c_bus->i2c_adap);
-			if (fe0->dvb.frontend == NULL)
-				break;
-			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
-			if (!dvb_attach(tda18271_attach,
-					fe0->dvb.frontend,
-					0x60, &i2c_bus2->i2c_adap,
-				  &hauppauge_hvr4400_tuner_config))
-				goto frontend_detach;
+			if (fe0->dvb.frontend != NULL) {
+				fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+				if (!dvb_attach(tda18271_attach,
+						fe0->dvb.frontend,
+						0x60, &i2c_bus2->i2c_adap,
+					  &hauppauge_hvr4400_tuner_config))
+					goto frontend_detach;
+			}
 			break;
 		}
 		break;
 	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_S950:
 		i2c_bus = &dev->i2c_bus[0];
 		i2c_bus2 = &dev->i2c_bus[1];
 		switch (port->nr) {
@@ -1725,7 +1600,6 @@
 				break;
 
 			/* attach tuner */
-			memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
 			m88ts2022_config.fe = fe0->dvb.frontend;
 			m88ts2022_config.clock = 27000000;
 			memset(&info, 0, sizeof(struct i2c_board_info));
@@ -1761,7 +1635,6 @@
 		/* port c - terrestrial/cable */
 		case 2:
 			/* attach frontend */
-			memset(&si2168_config, 0, sizeof(si2168_config));
 			si2168_config.i2c_adapter = &adapter;
 			si2168_config.fe = &fe0->dvb.frontend;
 			si2168_config.ts_mode = SI2168_TS_SERIAL;
@@ -1781,7 +1654,6 @@
 			port->i2c_client_demod = client_demod;
 
 			/* attach tuner */
-			memset(&si2157_config, 0, sizeof(si2157_config));
 			si2157_config.fe = fe0->dvb.frontend;
 			memset(&info, 0, sizeof(struct i2c_board_info));
 			strlcpy(info.type, "si2157", I2C_NAME_SIZE);
@@ -1805,201 +1677,6 @@
 			break;
 		}
 		break;
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-		i2c_bus = &dev->i2c_bus[1];
-		i2c_bus2 = &dev->i2c_bus[0];
-
-		/* attach frontend */
-		memset(&si2168_config, 0, sizeof(si2168_config));
-		si2168_config.i2c_adapter = &adapter;
-		si2168_config.fe = &fe0->dvb.frontend;
-		si2168_config.ts_mode = SI2168_TS_PARALLEL;
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "si2168", I2C_NAME_SIZE);
-		info.addr = 0x64;
-		info.platform_data = &si2168_config;
-		request_module(info.type);
-		client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
-		if (client_demod == NULL ||
-				client_demod->dev.driver == NULL)
-			goto frontend_detach;
-		if (!try_module_get(client_demod->dev.driver->owner)) {
-			i2c_unregister_device(client_demod);
-			goto frontend_detach;
-		}
-		port->i2c_client_demod = client_demod;
-
-		/* attach tuner */
-		memset(&si2157_config, 0, sizeof(si2157_config));
-		si2157_config.fe = fe0->dvb.frontend;
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "si2157", I2C_NAME_SIZE);
-		info.addr = 0x60;
-		info.platform_data = &si2157_config;
-		request_module(info.type);
-		client_tuner = i2c_new_device(adapter, &info);
-		if (client_tuner == NULL ||
-				client_tuner->dev.driver == NULL) {
-			module_put(client_demod->dev.driver->owner);
-			i2c_unregister_device(client_demod);
-			goto frontend_detach;
-		}
-		if (!try_module_get(client_tuner->dev.driver->owner)) {
-			i2c_unregister_device(client_tuner);
-			module_put(client_demod->dev.driver->owner);
-			i2c_unregister_device(client_demod);
-			goto frontend_detach;
-		}
-		port->i2c_client_tuner = client_tuner;
-		break;
-	case CX23885_BOARD_DVBSKY_S950C:
-		i2c_bus = &dev->i2c_bus[1];
-		i2c_bus2 = &dev->i2c_bus[0];
-
-		/* attach frontend */
-		fe0->dvb.frontend = dvb_attach(m88ds3103_attach,
-				&dvbsky_s950c_m88ds3103_config,
-				&i2c_bus->i2c_adap, &adapter);
-		if (fe0->dvb.frontend == NULL)
-			break;
-
-		/* attach tuner */
-		memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
-		m88ts2022_config.fe = fe0->dvb.frontend;
-		m88ts2022_config.clock = 27000000;
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
-		info.addr = 0x60;
-		info.platform_data = &m88ts2022_config;
-		request_module(info.type);
-		client_tuner = i2c_new_device(adapter, &info);
-		if (client_tuner == NULL ||
-				client_tuner->dev.driver == NULL)
-			goto frontend_detach;
-		if (!try_module_get(client_tuner->dev.driver->owner)) {
-			i2c_unregister_device(client_tuner);
-			goto frontend_detach;
-		}
-
-		/* delegate signal strength measurement to tuner */
-		fe0->dvb.frontend->ops.read_signal_strength =
-			fe0->dvb.frontend->ops.tuner_ops.get_rf_strength;
-
-		port->i2c_client_tuner = client_tuner;
-		break;
-	case CX23885_BOARD_DVBSKY_S952:
-		switch (port->nr) {
-		/* port b */
-		case 1:
-			i2c_bus = &dev->i2c_bus[1];
-			p_m88ds3103_config = &dvbsky_t9580_m88ds3103_config;
-			p_set_voltage = dvbsky_t9580_set_voltage;
-			break;
-		/* port c */
-		case 2:
-			i2c_bus = &dev->i2c_bus[0];
-			p_m88ds3103_config = &dvbsky_s952_portc_m88ds3103_config;
-			p_set_voltage = dvbsky_s952_portc_set_voltage;
-			break;
-		}
-
-		/* attach frontend */
-		fe0->dvb.frontend = dvb_attach(m88ds3103_attach,
-				p_m88ds3103_config,
-				&i2c_bus->i2c_adap, &adapter);
-		if (fe0->dvb.frontend == NULL)
-			break;
-
-		/* attach tuner */
-		memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
-		m88ts2022_config.fe = fe0->dvb.frontend;
-		m88ts2022_config.clock = 27000000;
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
-		info.addr = 0x60;
-		info.platform_data = &m88ts2022_config;
-		request_module(info.type);
-		client_tuner = i2c_new_device(adapter, &info);
-		if (client_tuner == NULL ||
-				client_tuner->dev.driver == NULL)
-			goto frontend_detach;
-		if (!try_module_get(client_tuner->dev.driver->owner)) {
-			i2c_unregister_device(client_tuner);
-			goto frontend_detach;
-		}
-
-		/* delegate signal strength measurement to tuner */
-		fe0->dvb.frontend->ops.read_signal_strength =
-			fe0->dvb.frontend->ops.tuner_ops.get_rf_strength;
-
-		/*
-		 * for setting the voltage we need to set GPIOs on
-		 * the card.
-		 */
-		port->fe_set_voltage =
-			fe0->dvb.frontend->ops.set_voltage;
-		fe0->dvb.frontend->ops.set_voltage = p_set_voltage;
-
-		port->i2c_client_tuner = client_tuner;
-		break;
-	case CX23885_BOARD_DVBSKY_T982:
-		memset(&si2168_config, 0, sizeof(si2168_config));
-		switch (port->nr) {
-		/* port b */
-		case 1:
-			i2c_bus = &dev->i2c_bus[1];
-			si2168_config.ts_mode = SI2168_TS_PARALLEL;
-			break;
-		/* port c */
-		case 2:
-			i2c_bus = &dev->i2c_bus[0];
-			si2168_config.ts_mode = SI2168_TS_SERIAL;
-			break;
-		}
-
-		/* attach frontend */
-		si2168_config.i2c_adapter = &adapter;
-		si2168_config.fe = &fe0->dvb.frontend;
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "si2168", I2C_NAME_SIZE);
-		info.addr = 0x64;
-		info.platform_data = &si2168_config;
-		request_module(info.type);
-		client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
-		if (client_demod == NULL ||
-				client_demod->dev.driver == NULL)
-			goto frontend_detach;
-		if (!try_module_get(client_demod->dev.driver->owner)) {
-			i2c_unregister_device(client_demod);
-			goto frontend_detach;
-		}
-		port->i2c_client_demod = client_demod;
-
-		/* attach tuner */
-		memset(&si2157_config, 0, sizeof(si2157_config));
-		si2157_config.fe = fe0->dvb.frontend;
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "si2157", I2C_NAME_SIZE);
-		info.addr = 0x60;
-		info.platform_data = &si2157_config;
-		request_module(info.type);
-		client_tuner = i2c_new_device(adapter, &info);
-		if (client_tuner == NULL ||
-				client_tuner->dev.driver == NULL) {
-			module_put(client_demod->dev.driver->owner);
-			i2c_unregister_device(client_demod);
-			goto frontend_detach;
-		}
-		if (!try_module_get(client_tuner->dev.driver->owner)) {
-			i2c_unregister_device(client_tuner);
-			module_put(client_demod->dev.driver->owner);
-			i2c_unregister_device(client_demod);
-			port->i2c_client_demod = NULL;
-			goto frontend_detach;
-		}
-		port->i2c_client_tuner = client_tuner;
-		break;
 	default:
 		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
 			" isn't supported yet\n",
@@ -2074,10 +1751,7 @@
 		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
 		break;
 		}
-	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982: {
+	case CX23885_BOARD_DVBSKY_T9580: {
 		u8 eeprom[256]; /* 24C02 i2c eeprom */
 
 		if (port->nr > 2)
@@ -2087,67 +1761,12 @@
 		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
 		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
 				sizeof(eeprom));
-		printk(KERN_INFO "%s port %d MAC address: %pM\n",
-			cx23885_boards[dev->board].name, port->nr,
-			eeprom + 0xc0 + (port->nr-1) * 8);
+		printk(KERN_INFO "DVBSky T9580 port %d MAC address: %pM\n",
+			port->nr, eeprom + 0xc0 + (port->nr-1) * 8);
 		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
 			(port->nr-1) * 8, 6);
 		break;
 		}
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_TT_CT2_4500_CI: {
-		u8 eeprom[256]; /* 24C02 i2c eeprom */
-
-		/* attach CI */
-		memset(&sp2_config, 0, sizeof(sp2_config));
-		sp2_config.dvb_adap = &port->frontends.adapter;
-		sp2_config.priv = port;
-		sp2_config.ci_control = cx23885_sp2_ci_ctrl;
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "sp2", I2C_NAME_SIZE);
-		info.addr = 0x40;
-		info.platform_data = &sp2_config;
-		request_module(info.type);
-		client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info);
-		if (client_ci == NULL ||
-				client_ci->dev.driver == NULL) {
-			if (client_tuner) {
-				module_put(client_tuner->dev.driver->owner);
-				i2c_unregister_device(client_tuner);
-			}
-			if (client_demod) {
-				module_put(client_demod->dev.driver->owner);
-				i2c_unregister_device(client_demod);
-			}
-			goto frontend_detach;
-		}
-		if (!try_module_get(client_ci->dev.driver->owner)) {
-			i2c_unregister_device(client_ci);
-			if (client_tuner) {
-				module_put(client_tuner->dev.driver->owner);
-				i2c_unregister_device(client_tuner);
-			}
-			if (client_demod) {
-				module_put(client_demod->dev.driver->owner);
-				i2c_unregister_device(client_demod);
-			}
-			goto frontend_detach;
-		}
-		port->i2c_client_ci = client_ci;
-
-		if (port->nr != 1)
-			break;
-
-		/* Read entire EEPROM */
-		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
-		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
-				sizeof(eeprom));
-		printk(KERN_INFO "%s MAC address: %pM\n",
-			cx23885_boards[dev->board].name, eeprom + 0xc0);
-		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6);
-		break;
-		}
 	}
 
 	return ret;
@@ -2188,7 +1807,7 @@
 
 		fe0 = vb2_dvb_get_frontend(&port->frontends, i);
 		if (!fe0)
-			return -EINVAL;
+			err = -EINVAL;
 
 		dprintk(1, "%s\n", __func__);
 		dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
@@ -2231,13 +1850,6 @@
 	struct vb2_dvb_frontend *fe0;
 	struct i2c_client *client;
 
-	/* remove I2C client for CI */
-	client = port->i2c_client_ci;
-	if (client) {
-		module_put(client->dev.driver->owner);
-		i2c_unregister_device(client);
-	}
-
 	/* remove I2C client for tuner */
 	client = port->i2c_client_tuner;
 	if (client) {
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
index 088799c..9d37fe6 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -87,13 +87,6 @@
 	case CX23885_BOARD_MYGICA_X8507:
 	case CX23885_BOARD_TBS_6980:
 	case CX23885_BOARD_TBS_6981:
-	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982:
 		/*
 		 * The only boards we handle right now.  However other boards
 		 * using the CX2388x integrated IR controller should be similar
@@ -146,13 +139,6 @@
 	case CX23885_BOARD_HAUPPAUGE_HVR1290:
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 	case CX23885_BOARD_MYGICA_X8507:
-	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_TT_CT2_4500_CI:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982:
 		/*
 		 * The IR controller on this board only returns pulse widths.
 		 * Any other mode setting will fail to set up the device.
@@ -319,23 +305,6 @@
 		/* A guess at the remote */
 		rc_map = RC_MAP_TBS_NEC;
 		break;
-	case CX23885_BOARD_DVBSKY_T9580:
-	case CX23885_BOARD_DVBSKY_T980C:
-	case CX23885_BOARD_DVBSKY_S950C:
-	case CX23885_BOARD_DVBSKY_S950:
-	case CX23885_BOARD_DVBSKY_S952:
-	case CX23885_BOARD_DVBSKY_T982:
-		/* Integrated CX23885 IR controller */
-		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = RC_BIT_ALL;
-		rc_map = RC_MAP_DVBSKY;
-		break;
-	case CX23885_BOARD_TT_CT2_4500_CI:
-		/* Integrated CX23885 IR controller */
-		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = RC_BIT_ALL;
-		rc_map = RC_MAP_TT_1500;
-		break;
 	default:
 		return -ENODEV;
 	}
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index d362d38..a7c6ef8 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -132,7 +132,6 @@
 		lines = VBI_NTSC_LINE_COUNT;
 	*num_planes = 1;
 	sizes[0] = lines * VBI_LINE_LENGTH * 2;
-	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 
@@ -143,6 +142,7 @@
 		struct cx23885_buffer, vb);
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	unsigned lines = VBI_PAL_LINE_COUNT;
+	int ret;
 
 	if (dev->tvnorm & V4L2_STD_525_60)
 		lines = VBI_NTSC_LINE_COUNT;
@@ -151,6 +151,10 @@
 		return -EINVAL;
 	vb2_set_plane_payload(vb, 0, lines * VBI_LINE_LENGTH * 2);
 
+	ret = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+	if (!ret)
+		return -EIO;
+
 	cx23885_risc_vbibuffer(dev->pci, &buf->risc,
 			 sgt->sgl,
 			 0, VBI_LINE_LENGTH * lines,
@@ -161,10 +165,14 @@
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
+	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf = container_of(vb,
 		struct cx23885_buffer, vb);
+	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
+
+	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 /*
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 2cd103d..f10469a 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -323,7 +323,6 @@
 
 	*num_planes = 1;
 	sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
-	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 
@@ -335,6 +334,7 @@
 	u32 line0_offset, line1_offset;
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	int field_tff;
+	int ret;
 
 	buf->bpl = (dev->width * dev->fmt->depth) >> 3;
 
@@ -342,6 +342,10 @@
 		return -EINVAL;
 	vb2_set_plane_payload(vb, 0, dev->height * buf->bpl);
 
+	ret = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+	if (!ret)
+		return -EIO;
+
 	switch (dev->field) {
 	case V4L2_FIELD_TOP:
 		cx23885_risc_buffer(dev->pci, &buf->risc,
@@ -409,10 +413,14 @@
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
+	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf = container_of(vb,
 		struct cx23885_buffer, vb);
+	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
+
+	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 /*
@@ -600,7 +608,7 @@
 	dev->field	= f->fmt.pix.field;
 	dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
 		dev->width, dev->height, dev->field);
-	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
 	call_all(dev, video, s_mbus_fmt, &mbus_fmt);
 	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 	/* s_mbus_fmt overwrites f->fmt.pix.field, restore it */
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index f55cd12..6c35e61 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -93,12 +93,6 @@
 #define CX23885_BOARD_HAUPPAUGE_IMPACTVCBE     43
 #define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2 44
 #define CX23885_BOARD_DVBSKY_T9580             45
-#define CX23885_BOARD_DVBSKY_T980C             46
-#define CX23885_BOARD_DVBSKY_S950C             47
-#define CX23885_BOARD_TT_CT2_4500_CI           48
-#define CX23885_BOARD_DVBSKY_S950              49
-#define CX23885_BOARD_DVBSKY_S952              50
-#define CX23885_BOARD_DVBSKY_T982              51
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
@@ -302,7 +296,6 @@
 
 	struct i2c_client *i2c_client_demod;
 	struct i2c_client *i2c_client_tuner;
-	struct i2c_client *i2c_client_ci;
 
 	int (*set_frontend)(struct dvb_frontend *fe);
 	int (*fe_set_voltage)(struct dvb_frontend *fe,
@@ -425,7 +418,6 @@
 	struct vb2_queue           vb2_vidq;
 	struct cx23885_dmaqueue    vbiq;
 	struct vb2_queue           vb2_vbiq;
-	void			   *alloc_ctx;
 
 	spinlock_t                 slock;
 
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
index 389fffd..e81173c 100644
--- a/drivers/media/pci/cx25821/cx25821-core.c
+++ b/drivers/media/pci/cx25821/cx25821-core.c
@@ -996,7 +996,7 @@
 	for (line = 0; line < lines; line++) {
 		while (offset && offset >= sg_dma_len(sg)) {
 			offset -= sg_dma_len(sg);
-			sg = sg_next(sg);
+			sg++;
 		}
 		if (bpl <= sg_dma_len(sg) - offset) {
 			/* fits into current chunk */
@@ -1014,14 +1014,14 @@
 			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
 			todo -= (sg_dma_len(sg) - offset);
 			offset = 0;
-			sg = sg_next(sg);
+			sg++;
 			while (todo > sg_dma_len(sg)) {
 				*(rp++) = cpu_to_le32(RISC_WRITE |
 						sg_dma_len(sg));
 				*(rp++) = cpu_to_le32(sg_dma_address(sg));
 				*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
 				todo -= sg_dma_len(sg);
-				sg = sg_next(sg);
+				sg++;
 			}
 			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
 			*(rp++) = cpu_to_le32(sg_dma_address(sg));
@@ -1101,7 +1101,7 @@
 	for (line = 0; line < lines; line++) {
 		while (offset && offset >= sg_dma_len(sg)) {
 			offset -= sg_dma_len(sg);
-			sg = sg_next(sg);
+			sg++;
 		}
 
 		if (lpi && line > 0 && !(line % lpi))
@@ -1125,14 +1125,14 @@
 			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
 			todo -= (sg_dma_len(sg) - offset);
 			offset = 0;
-			sg = sg_next(sg);
+			sg++;
 			while (todo > sg_dma_len(sg)) {
 				*(rp++) = cpu_to_le32(RISC_WRITE |
 						sg_dma_len(sg));
 				*(rp++) = cpu_to_le32(sg_dma_address(sg));
 				*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
 				todo -= sg_dma_len(sg);
-				sg = sg_next(sg);
+				sg++;
 			}
 			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
 			*(rp++) = cpu_to_le32(sg_dma_address(sg));
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig
index 4a7d489..3d30f90 100644
--- a/drivers/media/pci/cx88/Kconfig
+++ b/drivers/media/pci/cx88/Kconfig
@@ -3,7 +3,8 @@
 	depends on m
 	depends on VIDEO_DEV && PCI && I2C && RC_CORE
 	depends on I2C_ALGOBIT
-	select VIDEOBUF2_DMA_SG
+	select VIDEO_BTCX
+	select VIDEOBUF_DMA_SG
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
 	select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT
@@ -48,7 +49,7 @@
 	tristate "DVB/ATSC Support for cx2388x based TV cards"
 	depends on m
 	depends on VIDEO_CX88 && DVB_CORE
-	select VIDEOBUF2_DVB
+	select VIDEOBUF_DVB
 	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile
index 97b6f50..a1e2796 100644
--- a/drivers/media/pci/cx88/Makefile
+++ b/drivers/media/pci/cx88/Makefile
@@ -11,6 +11,7 @@
 obj-$(CPTCFG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 
 ccflags-y += -I$(backport_srctree)/drivers/media/i2c
+ccflags-y += -I$(backport_srctree)/drivers/media/common
 ccflags-y += -I$(backport_srctree)/drivers/media/tuners
 ccflags-y += -I$(backport_srctree)/drivers/media/dvb-core
 ccflags-y += -I$(backport_srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index 7f8dc60..a72579a 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -61,11 +61,8 @@
 
 struct cx88_audio_buffer {
 	unsigned int               bpl;
-	struct cx88_riscmem        risc;
-	void			*vaddr;
-	struct scatterlist	*sglist;
-	int                     sglen;
-	int                     nr_pages;
+	struct btcx_riscmem        risc;
+	struct videobuf_dmabuf     dma;
 };
 
 struct cx88_audio_dev {
@@ -87,6 +84,8 @@
 	unsigned int               period_size;
 	unsigned int               num_periods;
 
+	struct videobuf_dmabuf     *dma_risc;
+
 	struct cx88_audio_buffer   *buf;
 
 	struct snd_pcm_substream   *substream;
@@ -291,97 +290,19 @@
 	return IRQ_RETVAL(handled);
 }
 
-static int cx88_alsa_dma_init(struct cx88_audio_dev *chip, int nr_pages)
-{
-	struct cx88_audio_buffer *buf = chip->buf;
-	struct page *pg;
-	int i;
-
-	buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
-	if (NULL == buf->vaddr) {
-		dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
-		return -ENOMEM;
-	}
-
-	dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
-				(unsigned long)buf->vaddr,
-				nr_pages << PAGE_SHIFT);
-
-	memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
-	buf->nr_pages = nr_pages;
-
-	buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
-	if (NULL == buf->sglist)
-		goto vzalloc_err;
-
-	sg_init_table(buf->sglist, buf->nr_pages);
-	for (i = 0; i < buf->nr_pages; i++) {
-		pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
-		if (NULL == pg)
-			goto vmalloc_to_page_err;
-		sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
-	}
-	return 0;
-
-vmalloc_to_page_err:
-	vfree(buf->sglist);
-	buf->sglist = NULL;
-vzalloc_err:
-	vfree(buf->vaddr);
-	buf->vaddr = NULL;
-	return -ENOMEM;
-}
-
-static int cx88_alsa_dma_map(struct cx88_audio_dev *dev)
-{
-	struct cx88_audio_buffer *buf = dev->buf;
-
-	buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist,
-			buf->nr_pages, PCI_DMA_FROMDEVICE);
-
-	if (0 == buf->sglen) {
-		pr_warn("%s: cx88_alsa_map_sg failed\n", __func__);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-static int cx88_alsa_dma_unmap(struct cx88_audio_dev *dev)
-{
-	struct cx88_audio_buffer *buf = dev->buf;
-
-	if (!buf->sglen)
-		return 0;
-
-	dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE);
-	buf->sglen = 0;
-	return 0;
-}
-
-static int cx88_alsa_dma_free(struct cx88_audio_buffer *buf)
-{
-	vfree(buf->sglist);
-	buf->sglist = NULL;
-	vfree(buf->vaddr);
-	buf->vaddr = NULL;
-	return 0;
-}
-
 
 static int dsp_buffer_free(snd_cx88_card_t *chip)
 {
-	struct cx88_riscmem *risc = &chip->buf->risc;
-
 	BUG_ON(!chip->dma_size);
 
 	dprintk(2,"Freeing buffer\n");
-	cx88_alsa_dma_unmap(chip);
-	cx88_alsa_dma_free(chip->buf);
-	if (risc->cpu)
-		pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma);
+	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+	videobuf_dma_free(chip->dma_risc);
+	btcx_riscmem_free(chip->pci,&chip->buf->risc);
 	kfree(chip->buf);
 
-	chip->buf = NULL;
+	chip->dma_risc = NULL;
+	chip->dma_size = 0;
 
 	return 0;
 }
@@ -466,6 +387,7 @@
 			      struct snd_pcm_hw_params * hw_params)
 {
 	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct videobuf_dmabuf *dma;
 
 	struct cx88_audio_buffer *buf;
 	int ret;
@@ -486,19 +408,20 @@
 	if (NULL == buf)
 		return -ENOMEM;
 
-	chip->buf = buf;
 	buf->bpl = chip->period_size;
 
-	ret = cx88_alsa_dma_init(chip,
+	dma = &buf->dma;
+	videobuf_dma_init(dma);
+	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
 			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
 	if (ret < 0)
 		goto error;
 
-	ret = cx88_alsa_dma_map(chip);
+	ret = videobuf_dma_map(&chip->pci->dev, dma);
 	if (ret < 0)
 		goto error;
 
-	ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist,
+	ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
 				   chip->period_size, chip->num_periods, 1);
 	if (ret < 0)
 		goto error;
@@ -507,7 +430,10 @@
 	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
 	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 
-	substream->runtime->dma_area = chip->buf->vaddr;
+	chip->buf = buf;
+	chip->dma_risc = dma;
+
+	substream->runtime->dma_area = chip->dma_risc->vaddr;
 	substream->runtime->dma_bytes = chip->dma_size;
 	substream->runtime->dma_addr = 0;
 	return 0;
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index d3c79d9..150bb76 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -45,6 +45,10 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CX88_VERSION);
 
+static unsigned int mpegbufs = 32;
+module_param(mpegbufs,int,0644);
+MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
+
 static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
@@ -322,13 +326,13 @@
 	memory_read(dev->core, dev->mailbox - 4, &value);
 	if (value != 0x12345678) {
 		dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
-		return -EIO;
+		return -1;
 	}
 
 	memory_read(dev->core, dev->mailbox, &flag);
 	if (flag) {
 		dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
-		return -EIO;
+		return -1;
 	}
 
 	flag |= 1; /* tell 'em we're working on it */
@@ -348,14 +352,14 @@
 	memory_write(dev->core, dev->mailbox, flag);
 
 	/* wait for firmware to handle the API command */
-	timeout = jiffies + msecs_to_jiffies(1000);
+	timeout = jiffies + msecs_to_jiffies(10);
 	for (;;) {
 		memory_read(dev->core, dev->mailbox, &flag);
 		if (0 != (flag & 4))
 			break;
 		if (time_after(jiffies,timeout)) {
-			dprintk(0, "ERROR: API Mailbox timeout %x\n", command);
-			return -EIO;
+			dprintk(0, "ERROR: API Mailbox timeout\n");
+			return -1;
 		}
 		udelay(10);
 	}
@@ -416,7 +420,7 @@
 		}
 	}
 	dprintk(0, "Mailbox signature values not found!\n");
-	return -EIO;
+	return -1;
 }
 
 static int blackbird_load_firmware(struct cx8802_dev *dev)
@@ -428,7 +432,7 @@
 	int i, retval = 0;
 	u32 value = 0;
 	u32 checksum = 0;
-	__le32 *dataptr;
+	u32 *dataptr;
 
 	retval  = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
 	retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
@@ -445,28 +449,29 @@
 
 
 	if (retval != 0) {
-		pr_err("Hotplug firmware request failed (%s).\n",
+		dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
 			CX2341X_FIRM_ENC_FILENAME);
-		pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
-		return -EIO;
+		dprintk(0, "Please fix your hotplug setup, the board will "
+			"not work without firmware loaded!\n");
+		return -1;
 	}
 
 	if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
-		pr_err("Firmware size mismatch (have %zd, expected %d)\n",
+		dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
 			firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
 		release_firmware(firmware);
-		return -EINVAL;
+		return -1;
 	}
 
 	if (0 != memcmp(firmware->data, magic, 8)) {
-		pr_err("Firmware magic mismatch, wrong file?\n");
+		dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
 		release_firmware(firmware);
-		return -EINVAL;
+		return -1;
 	}
 
 	/* transfer to the chip */
 	dprintk(1,"Loading firmware ...\n");
-	dataptr = (__le32 *)firmware->data;
+	dataptr = (u32*)firmware->data;
 	for (i = 0; i < (firmware->size >> 2); i++) {
 		value = le32_to_cpu(*dataptr);
 		checksum += ~value;
@@ -479,11 +484,12 @@
 		memory_read(dev->core, i, &value);
 		checksum -= ~value;
 	}
-	release_firmware(firmware);
 	if (checksum) {
-		pr_err("Firmware load might have failed (checksum mismatch).\n");
-		return -EIO;
+		dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
+		release_firmware(firmware);
+		return -1;
 	}
+	release_firmware(firmware);
 	dprintk(0, "Firmware upload successful.\n");
 
 	retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
@@ -515,14 +521,12 @@
 
 static void blackbird_codec_settings(struct cx8802_dev *dev)
 {
-	struct cx88_core *core = dev->core;
-
 	/* assign frame size */
 	blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
-				core->height, core->width);
+				dev->height, dev->width);
 
-	dev->cxhdl.width = core->width;
-	dev->cxhdl.height = core->height;
+	dev->cxhdl.width = dev->width;
+	dev->cxhdl.height = dev->height;
 	cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
 	cx2341x_handler_setup(&dev->cxhdl);
 }
@@ -536,6 +540,9 @@
 	dprintk(1,"Initialize codec\n");
 	retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
 	if (retval < 0) {
+
+		dev->mpeg_active = 0;
+
 		/* ping was not successful, reset and upload firmware */
 		cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
 		cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
@@ -582,8 +589,9 @@
 	return 0;
 }
 
-static int blackbird_start_codec(struct cx8802_dev *dev)
+static int blackbird_start_codec(struct file *file, void *priv)
 {
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
 	struct cx88_core *core = dev->core;
 	/* start capturing to the host interface */
 	u32 reg;
@@ -619,6 +627,7 @@
 			BLACKBIRD_RAW_BITS_NONE
 		);
 
+	dev->mpeg_active = 1;
 	return 0;
 }
 
@@ -632,137 +641,51 @@
 
 	cx2341x_handler_set_busy(&dev->cxhdl, 0);
 
+	dev->mpeg_active = 0;
 	return 0;
 }
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], void *alloc_ctxs[])
+static int bb_buf_setup(struct videobuf_queue *q,
+			unsigned int *count, unsigned int *size)
 {
-	struct cx8802_dev *dev = q->drv_priv;
+	struct cx8802_fh *fh = q->priv_data;
 
-	*num_planes = 1;
-	dev->ts_packet_size  = 188 * 4;
-	dev->ts_packet_count  = 32;
-	sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
-	alloc_ctxs[0] = dev->alloc_ctx;
+	fh->dev->ts_packet_size  = 188 * 4; /* was: 512 */
+	fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
+
+	*size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
+	*count = fh->dev->ts_packet_count;
 	return 0;
 }
 
-static int buffer_prepare(struct vb2_buffer *vb)
+static int
+bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	       enum v4l2_field field)
 {
-	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-
-	return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
+	struct cx8802_fh *fh = q->priv_data;
+	return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
 }
 
-static void buffer_finish(struct vb2_buffer *vb)
+static void
+bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
-	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-	struct cx88_riscmem *risc = &buf->risc;
-
-	if (risc->cpu)
-		pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
-	memset(risc, 0, sizeof(*risc));
+	struct cx8802_fh *fh = q->priv_data;
+	cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
 }
 
-static void buffer_queue(struct vb2_buffer *vb)
+static void
+bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
-	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer    *buf = container_of(vb, struct cx88_buffer, vb);
-
-	cx8802_buf_queue(dev, buf);
+	cx88_free_buffer(q, (struct cx88_buffer*)vb);
 }
 
-static int start_streaming(struct vb2_queue *q, unsigned int count)
-{
-	struct cx8802_dev *dev = q->drv_priv;
-	struct cx88_dmaqueue *dmaq = &dev->mpegq;
-	struct cx8802_driver *drv;
-	struct cx88_buffer *buf;
-	unsigned long flags;
-	int err;
-
-	/* Make sure we can acquire the hardware */
-	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
-	if (!drv) {
-		dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
-		err = -ENODEV;
-		goto fail;
-	}
-
-	err = drv->request_acquire(drv);
-	if (err != 0) {
-		dprintk(1, "%s: Unable to acquire hardware, %d\n", __func__, err);
-		goto fail;
-	}
-
-	if (blackbird_initialize_codec(dev) < 0) {
-		drv->request_release(drv);
-		err = -EINVAL;
-		goto fail;
-	}
-
-	err = blackbird_start_codec(dev);
-	if (err == 0) {
-		buf = list_entry(dmaq->active.next, struct cx88_buffer, list);
-		cx8802_start_dma(dev, dmaq, buf);
-		return 0;
-	}
-
-fail:
-	spin_lock_irqsave(&dev->slock, flags);
-	while (!list_empty(&dmaq->active)) {
-		struct cx88_buffer *buf = list_entry(dmaq->active.next,
-			struct cx88_buffer, list);
-
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
-	}
-	spin_unlock_irqrestore(&dev->slock, flags);
-	return err;
-}
-
-static void stop_streaming(struct vb2_queue *q)
-{
-	struct cx8802_dev *dev = q->drv_priv;
-	struct cx88_dmaqueue *dmaq = &dev->mpegq;
-	struct cx8802_driver *drv = NULL;
-	unsigned long flags;
-
-	cx8802_cancel_buffers(dev);
-	blackbird_stop_codec(dev);
-
-	/* Make sure we release the hardware */
-	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
-	WARN_ON(!drv);
-	if (drv)
-		drv->request_release(drv);
-
-	spin_lock_irqsave(&dev->slock, flags);
-	while (!list_empty(&dmaq->active)) {
-		struct cx88_buffer *buf = list_entry(dmaq->active.next,
-			struct cx88_buffer, list);
-
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-	}
-	spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-static struct vb2_ops blackbird_qops = {
-	.queue_setup    = queue_setup,
-	.buf_prepare  = buffer_prepare,
-	.buf_finish = buffer_finish,
-	.buf_queue    = buffer_queue,
-	.wait_prepare = vb2_ops_wait_prepare,
-	.wait_finish = vb2_ops_wait_finish,
-	.start_streaming = start_streaming,
-	.stop_streaming = stop_streaming,
+static struct videobuf_queue_ops blackbird_qops = {
+	.buf_setup    = bb_buf_setup,
+	.buf_prepare  = bb_buf_prepare,
+	.buf_queue    = bb_buf_queue,
+	.buf_release  = bb_buf_release,
 };
 
 /* ------------------------------------------------------------------ */
@@ -770,8 +693,8 @@
 static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *cap)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+	struct cx88_core  *core = dev->core;
 
 	strcpy(cap->driver, "cx88_blackbird");
 	sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
@@ -791,111 +714,131 @@
 	return 0;
 }
 
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
 
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
-	f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count;
+	f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
 	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.width        = core->width;
-	f->fmt.pix.height       = core->height;
-	f->fmt.pix.field        = core->field;
+	f->fmt.pix.width        = dev->width;
+	f->fmt.pix.height       = dev->height;
+	f->fmt.pix.field        = fh->mpegq.field;
+	dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+		dev->width, dev->height, fh->mpegq.field );
 	return 0;
 }
 
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
 			struct v4l2_format *f)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
-	unsigned maxw, maxh;
-	enum v4l2_field field;
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
 
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
-	f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count;
+	f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
 	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-
-	maxw = norm_maxw(core->tvnorm);
-	maxh = norm_maxh(core->tvnorm);
-
-	field = f->fmt.pix.field;
-
-	switch (field) {
-	case V4L2_FIELD_TOP:
-	case V4L2_FIELD_BOTTOM:
-	case V4L2_FIELD_INTERLACED:
-	case V4L2_FIELD_SEQ_BT:
-	case V4L2_FIELD_SEQ_TB:
-		break;
-	default:
-		field = (f->fmt.pix.height > maxh / 2)
-			? V4L2_FIELD_INTERLACED
-			: V4L2_FIELD_BOTTOM;
-		break;
-	}
-	if (V4L2_FIELD_HAS_T_OR_B(field))
-		maxh /= 2;
-
-	v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
-			      &f->fmt.pix.height, 32, maxh, 0, 0);
-	f->fmt.pix.field = field;
+	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+		dev->width, dev->height, fh->mpegq.field );
 	return 0;
 }
 
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
 	struct cx88_core  *core = dev->core;
 
-	if (vb2_is_busy(&dev->vb2_mpegq))
-		return -EBUSY;
-	if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) ||
-			     vb2_is_busy(&core->v4ldev->vb2_vbiq)))
-		return -EBUSY;
-	vidioc_try_fmt_vid_cap(file, priv, f);
-	core->width = f->fmt.pix.width;
-	core->height = f->fmt.pix.height;
-	core->field = f->fmt.pix.field;
+	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
+	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+	dev->width              = f->fmt.pix.width;
+	dev->height             = f->fmt.pix.height;
+	fh->mpegq.field         = f->fmt.pix.field;
 	cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
 	blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
 				f->fmt.pix.height, f->fmt.pix.width);
+	dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
 	return 0;
 }
 
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_reqbufs(&fh->mpegq, p));
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_querybuf(&fh->mpegq, p));
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_qbuf(&fh->mpegq, p));
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_dqbuf(&fh->mpegq, p,
+				file->f_flags & O_NONBLOCK));
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+
+	if (!dev->mpeg_active)
+		blackbird_start_codec(file, fh);
+	return videobuf_streamon(&fh->mpegq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+
+	if (dev->mpeg_active)
+		blackbird_stop_codec(dev);
+	return videobuf_streamoff(&fh->mpegq);
+}
+
 static int vidioc_s_frequency (struct file *file, void *priv,
 				const struct v4l2_frequency *f)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
-	bool streaming;
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+	struct cx88_core  *core = dev->core;
 
 	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
 	if (unlikely(f->tuner != 0))
 		return -EINVAL;
-	streaming = vb2_start_streaming_called(&dev->vb2_mpegq);
-	if (streaming)
+	if (dev->mpeg_active)
 		blackbird_stop_codec(dev);
 
 	cx88_set_freq (core,f);
 	blackbird_initialize_codec(dev);
-	cx88_set_scale(core, core->width, core->height,
-			core->field);
-	if (streaming)
-		blackbird_start_codec(dev);
+	cx88_set_scale(dev->core, dev->width, dev->height,
+			fh->mpegq.field);
 	return 0;
 }
 
 static int vidioc_log_status (struct file *file, void *priv)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+	struct cx88_core  *core = dev->core;
 	char name[32 + 2];
 
 	snprintf(name, sizeof(name), "%s/2", core->name);
@@ -907,16 +850,15 @@
 static int vidioc_enum_input (struct file *file, void *priv,
 				struct v4l2_input *i)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 	return cx88_enum_input (core,i);
 }
 
 static int vidioc_g_frequency (struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8802_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
 
 	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
@@ -931,8 +873,7 @@
 
 static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 
 	*i = core->input;
 	return 0;
@@ -940,24 +881,24 @@
 
 static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 
 	if (i >= 4)
 		return -EINVAL;
 	if (0 == INPUT(i).type)
 		return -EINVAL;
 
+	mutex_lock(&core->lock);
 	cx88_newstation(core);
 	cx88_video_mux(core,i);
+	mutex_unlock(&core->lock);
 	return 0;
 }
 
 static int vidioc_g_tuner (struct file *file, void *priv,
 				struct v4l2_tuner *t)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 	u32 reg;
 
 	if (unlikely(UNSET == core->board.tuner_type))
@@ -979,8 +920,7 @@
 static int vidioc_s_tuner (struct file *file, void *priv,
 				const struct v4l2_tuner *t)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 
 	if (UNSET == core->board.tuner_type)
 		return -EINVAL;
@@ -993,8 +933,7 @@
 
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
 
 	*tvnorm = core->tvnorm;
 	return 0;
@@ -1002,20 +941,155 @@
 
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
-	struct cx8802_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 
-	return cx88_set_tvnorm(core, id);
+	mutex_lock(&core->lock);
+	cx88_set_tvnorm(core, id);
+	mutex_unlock(&core->lock);
+	return 0;
+}
+
+/* FIXME: cx88_ioctl_hook not implemented */
+
+static int mpeg_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8802_dev *dev = video_drvdata(file);
+	struct cx8802_fh *fh;
+	struct cx8802_driver *drv = NULL;
+	int err;
+
+	dprintk( 1, "%s\n", __func__);
+
+	mutex_lock(&dev->core->lock);
+
+	/* Make sure we can acquire the hardware */
+	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+	if (!drv) {
+		dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
+		mutex_unlock(&dev->core->lock);
+		return -ENODEV;
+	}
+
+	err = drv->request_acquire(drv);
+	if (err != 0) {
+		dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
+		mutex_unlock(&dev->core->lock);
+		return err;
+	}
+
+	if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
+		drv->request_release(drv);
+		mutex_unlock(&dev->core->lock);
+		return -EINVAL;
+	}
+	dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+	if (NULL == fh) {
+		drv->request_release(drv);
+		mutex_unlock(&dev->core->lock);
+		return -ENOMEM;
+	}
+	v4l2_fh_init(&fh->fh, vdev);
+	file->private_data = fh;
+	fh->dev      = dev;
+
+	videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct cx88_buffer),
+			    fh, NULL);
+
+	/* FIXME: locking against other video device */
+	cx88_set_scale(dev->core, dev->width, dev->height,
+			fh->mpegq.field);
+
+	dev->core->mpeg_users++;
+	mutex_unlock(&dev->core->lock);
+	v4l2_fh_add(&fh->fh);
+	return 0;
+}
+
+static int mpeg_release(struct file *file)
+{
+	struct cx8802_fh  *fh  = file->private_data;
+	struct cx8802_dev *dev = fh->dev;
+	struct cx8802_driver *drv = NULL;
+
+	mutex_lock(&dev->core->lock);
+
+	if (dev->mpeg_active && dev->core->mpeg_users == 1)
+		blackbird_stop_codec(dev);
+
+	cx8802_cancel_buffers(fh->dev);
+	/* stop mpeg capture */
+	videobuf_stop(&fh->mpegq);
+
+	videobuf_mmap_free(&fh->mpegq);
+
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	file->private_data = NULL;
+	kfree(fh);
+
+	/* Make sure we release the hardware */
+	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+	WARN_ON(!drv);
+	if (drv)
+		drv->request_release(drv);
+
+	dev->core->mpeg_users--;
+
+	mutex_unlock(&dev->core->lock);
+
+	return 0;
+}
+
+static ssize_t
+mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+	struct cx8802_fh *fh = file->private_data;
+	struct cx8802_dev *dev = fh->dev;
+
+	if (!dev->mpeg_active)
+		blackbird_start_codec(file, fh);
+
+	return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
+				    file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int
+mpeg_poll(struct file *file, struct poll_table_struct *wait)
+{
+	unsigned long req_events = poll_requested_events(wait);
+	struct cx8802_fh *fh = file->private_data;
+	struct cx8802_dev *dev = fh->dev;
+
+	if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
+		blackbird_start_codec(file, fh);
+
+	return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
+}
+
+static int
+mpeg_mmap(struct file *file, struct vm_area_struct * vma)
+{
+	struct cx8802_fh *fh = file->private_data;
+
+	return videobuf_mmap_mapper(&fh->mpegq, vma);
 }
 
 static const struct v4l2_file_operations mpeg_fops =
 {
 	.owner	       = THIS_MODULE,
-	.open	       = v4l2_fh_open,
-	.release       = vb2_fop_release,
-	.read	       = vb2_fop_read,
-	.poll          = vb2_fop_poll,
-	.mmap	       = vb2_fop_mmap,
+	.open	       = mpeg_open,
+	.release       = mpeg_release,
+	.read	       = mpeg_read,
+	.poll          = mpeg_poll,
+	.mmap	       = mpeg_mmap,
 	.unlocked_ioctl = video_ioctl2,
 };
 
@@ -1025,12 +1099,12 @@
 	.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
 	.vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
-	.vidioc_querybuf      = vb2_ioctl_querybuf,
-	.vidioc_qbuf          = vb2_ioctl_qbuf,
-	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
-	.vidioc_streamon      = vb2_ioctl_streamon,
-	.vidioc_streamoff     = vb2_ioctl_streamoff,
+	.vidioc_reqbufs       = vidioc_reqbufs,
+	.vidioc_querybuf      = vidioc_querybuf,
+	.vidioc_qbuf          = vidioc_qbuf,
+	.vidioc_dqbuf         = vidioc_dqbuf,
+	.vidioc_streamon      = vidioc_streamon,
+	.vidioc_streamoff     = vidioc_streamoff,
 	.vidioc_s_frequency   = vidioc_s_frequency,
 	.vidioc_log_status    = vidioc_log_status,
 	.vidioc_enum_input    = vidioc_enum_input,
@@ -1115,12 +1189,11 @@
 {
 	int err;
 
-	dev->mpeg_dev = cx88_vdev_init(dev->core, dev->pci,
-				       &cx8802_mpeg_template, "mpeg");
+	dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
+				       &cx8802_mpeg_template,"mpeg");
 	dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
 	video_set_drvdata(dev->mpeg_dev, dev);
-	dev->mpeg_dev->queue = &dev->vb2_mpegq;
-	err = video_register_device(dev->mpeg_dev, VFL_TYPE_GRABBER, -1);
+	err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
 	if (err < 0) {
 		printk(KERN_INFO "%s/2: can't register mpeg device\n",
 		       dev->core->name);
@@ -1137,7 +1210,6 @@
 {
 	struct cx88_core *core = drv->core;
 	struct cx8802_dev *dev = core->dvbdev;
-	struct vb2_queue *q;
 	int err;
 
 	dprintk( 1, "%s\n", __func__);
@@ -1151,9 +1223,15 @@
 	if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
 		goto fail_core;
 
+	dev->width = 720;
+	if (core->tvnorm & V4L2_STD_525_60) {
+		dev->height = 480;
+	} else {
+		dev->height = 576;
+	}
 	dev->cxhdl.port = CX2341X_PORT_STREAMING;
-	dev->cxhdl.width = core->width;
-	dev->cxhdl.height = core->height;
+	dev->cxhdl.width = dev->width;
+	dev->cxhdl.height = dev->height;
 	dev->cxhdl.func = blackbird_mbox_func;
 	dev->cxhdl.priv = dev;
 	err = cx2341x_handler_init(&dev->cxhdl, 36);
@@ -1172,30 +1250,13 @@
 //	init_controls(core);
 	cx88_set_tvnorm(core,core->tvnorm);
 	cx88_video_mux(core,0);
-	cx2341x_handler_set_50hz(&dev->cxhdl, core->height == 576);
+	cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
 	cx2341x_handler_setup(&dev->cxhdl);
-
-	q = &dev->vb2_mpegq;
-	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
-	q->gfp_flags = GFP_DMA32;
-	q->min_buffers_needed = 2;
-	q->drv_priv = dev;
-	q->buf_struct_size = sizeof(struct cx88_buffer);
-	q->ops = &blackbird_qops;
-	q->mem_ops = &vb2_dma_sg_memops;
-	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	q->lock = &core->lock;
-
-	err = vb2_queue_init(q);
-	if (err < 0)
-		goto fail_core;
-
 	blackbird_register_video(dev);
 
 	return 0;
 
-fail_core:
+ fail_core:
 	return err;
 }
 
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
index 8f2556e..851754b 100644
--- a/drivers/media/pci/cx88/cx88-cards.c
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -347,7 +347,7 @@
 	},
 	[CX88_BOARD_IODATA_GVVCP3PCI] = {
 		.name		= "IODATA GV-VCP3/PCI",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -436,7 +436,7 @@
 	},
 	[CX88_BOARD_KWORLD_DVB_T] = {
 		.name           = "KWorld/VStream XPert DVB-T",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -455,7 +455,7 @@
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
 		.name           = "DViCO FusionHDTV DVB-T1",
-		.tuner_type     = UNSET, /* No analog tuner */
+		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -542,7 +542,7 @@
 	},
 	[CX88_BOARD_HAUPPAUGE_DVB_T1] = {
 		.name           = "Hauppauge Nova-T DVB-T",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -554,7 +554,7 @@
 	},
 	[CX88_BOARD_CONEXANT_DVB_T1] = {
 		.name           = "Conexant DVB-T reference design",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -579,7 +579,7 @@
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
 		.name           = "DViCO FusionHDTV DVB-T Plus",
-		.tuner_type     = UNSET, /* No analog tuner */
+		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -596,7 +596,7 @@
 	},
 	[CX88_BOARD_DNTV_LIVE_DVB_T] = {
 		.name		= "digitalnow DNTV Live! DVB-T",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -787,7 +787,7 @@
 	},
 	[CX88_BOARD_ADSTECH_DVB_T_PCI] = {
 		.name           = "ADS Tech Instant TV DVB-T PCI",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -806,7 +806,7 @@
 	},
 	[CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
 		.name           = "TerraTec Cinergy 1400 DVB-T",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.input          = { {
 			.type   = CX88_VMUX_DVB,
 			.vmux   = 0,
@@ -924,7 +924,7 @@
 	},
 	[CX88_BOARD_WINFAST_DTV1000] = {
 		.name           = "WinFast DTV1000-T",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -972,7 +972,7 @@
 	},
 	[CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
 		.name		= "Hauppauge Nova-S-Plus DVB-S",
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.radio_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -998,7 +998,7 @@
 	},
 	[CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
 		.name		= "Hauppauge Nova-SE2 DVB-S",
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.radio_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -1010,7 +1010,7 @@
 	},
 	[CX88_BOARD_KWORLD_DVBS_100] = {
 		.name		= "KWorld DVB-S 100",
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.radio_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -1102,7 +1102,7 @@
 		/* DTT 7579 Conexant CX22702-19 Conexant CX2388x  */
 		/* Manenti Marco <marco_manenti@colman.it> */
 		.name           = "KWorld/VStream XPert DVB-T with cx22702",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -1121,7 +1121,7 @@
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
 		.name           = "DViCO FusionHDTV DVB-T Dual Digital",
-		.tuner_type     = UNSET, /* No analog tuner */
+		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -1356,7 +1356,7 @@
 	},
 	[CX88_BOARD_GENIATECH_DVBS] = {
 		.name          = "Geniatech DVB-S",
-		.tuner_type    = UNSET,
+		.tuner_type    = TUNER_ABSENT,
 		.radio_type    = UNSET,
 		.tuner_addr    = ADDR_UNSET,
 		.radio_addr    = ADDR_UNSET,
@@ -1494,7 +1494,7 @@
 	},
 	[CX88_BOARD_SAMSUNG_SMT_7020] = {
 		.name		= "Samsung SMT 7020 DVB-S",
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.radio_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -1506,7 +1506,7 @@
 	},
 	[CX88_BOARD_ADSTECH_PTV_390] = {
 		.name           = "ADS Tech Instant Video PCI",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
@@ -1553,7 +1553,7 @@
 	[CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
 		.name           = "DViCO FusionHDTV 5 PCI nano",
 		/* xc3008 tuner, digital only for now */
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -2069,7 +2069,7 @@
 	},
 	[CX88_BOARD_TBS_8920] = {
 		.name           = "TBS 8920 DVB-S/S2",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
@@ -2304,7 +2304,7 @@
 	},
 	[CX88_BOARD_TWINHAN_VP1027_DVBS] = {
 		.name		= "Twinhan VP-1027 DVB-S",
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
@@ -2921,33 +2921,33 @@
 	int  fm;
 	const char *name;
 } gdi_tuner[] = {
-	[ 0x01 ] = { .id   = UNSET,
+	[ 0x01 ] = { .id   = TUNER_ABSENT,
 		     .name = "NTSC_M" },
-	[ 0x02 ] = { .id   = UNSET,
+	[ 0x02 ] = { .id   = TUNER_ABSENT,
 		     .name = "PAL_B" },
-	[ 0x03 ] = { .id   = UNSET,
+	[ 0x03 ] = { .id   = TUNER_ABSENT,
 		     .name = "PAL_I" },
-	[ 0x04 ] = { .id   = UNSET,
+	[ 0x04 ] = { .id   = TUNER_ABSENT,
 		     .name = "PAL_D" },
-	[ 0x05 ] = { .id   = UNSET,
+	[ 0x05 ] = { .id   = TUNER_ABSENT,
 		     .name = "SECAM" },
 
-	[ 0x10 ] = { .id   = UNSET,
+	[ 0x10 ] = { .id   = TUNER_ABSENT,
 		     .fm   = 1,
 		     .name = "TEMIC_4049" },
 	[ 0x11 ] = { .id   = TUNER_TEMIC_4136FY5,
 		     .name = "TEMIC_4136" },
-	[ 0x12 ] = { .id   = UNSET,
+	[ 0x12 ] = { .id   = TUNER_ABSENT,
 		     .name = "TEMIC_4146" },
 
 	[ 0x20 ] = { .id   = TUNER_PHILIPS_FQ1216ME,
 		     .fm   = 1,
 		     .name = "PHILIPS_FQ1216_MK3" },
-	[ 0x21 ] = { .id   = UNSET, .fm = 1,
+	[ 0x21 ] = { .id   = TUNER_ABSENT, .fm = 1,
 		     .name = "PHILIPS_FQ1236_MK3" },
-	[ 0x22 ] = { .id   = UNSET,
+	[ 0x22 ] = { .id   = TUNER_ABSENT,
 		     .name = "PHILIPS_FI1236_MK3" },
-	[ 0x23 ] = { .id   = UNSET,
+	[ 0x23 ] = { .id   = TUNER_ABSENT,
 		     .name = "PHILIPS_FI1216_MK3" },
 };
 
@@ -3564,7 +3564,7 @@
 		mode_mask &= ~T_RADIO;
 	}
 
-	if (core->board.tuner_type != UNSET) {
+	if (core->board.tuner_type != TUNER_ABSENT) {
 		tun_setup.mode_mask      = mode_mask;
 		tun_setup.type           = core->board.tuner_type;
 		tun_setup.addr           = core->board.tuner_addr;
@@ -3691,11 +3691,6 @@
 	core->nr = nr;
 	sprintf(core->name, "cx88[%d]", core->nr);
 
-	core->tvnorm = V4L2_STD_NTSC_M;
-	core->width   = 320;
-	core->height  = 240;
-	core->field   = V4L2_FIELD_INTERLACED;
-
 	strcpy(core->v4l2_dev.name, core->name);
 	if (v4l2_device_register(NULL, &core->v4l2_dev)) {
 		kfree(core);
@@ -3777,7 +3772,7 @@
 	cx88_i2c_init(core, pci);
 
 	/* load tuner module, if needed */
-	if (UNSET != core->board.tuner_type) {
+	if (TUNER_ABSENT != core->board.tuner_type) {
 		/* Ignore 0x6b and 0x6f on cx88 boards.
 		 * FusionHDTV5 RT Gold has an ir receiver at 0x6b
 		 * and an RTC at 0x6f which can get corrupted if probed. */
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index dee177e..7163023 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -76,16 +76,11 @@
 static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
 			    unsigned int offset, u32 sync_line,
 			    unsigned int bpl, unsigned int padding,
-			    unsigned int lines, unsigned int lpi, bool jump)
+			    unsigned int lines, unsigned int lpi)
 {
 	struct scatterlist *sg;
 	unsigned int line,todo,sol;
 
-	if (jump) {
-		(*rp++) = cpu_to_le32(RISC_JUMP);
-		(*rp++) = 0;
-	}
-
 	/* sync instruction */
 	if (sync_line != NO_SYNC_LINE)
 		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
@@ -95,7 +90,7 @@
 	for (line = 0; line < lines; line++) {
 		while (offset && offset >= sg_dma_len(sg)) {
 			offset -= sg_dma_len(sg);
-			sg = sg_next(sg);
+			sg++;
 		}
 		if (lpi && line>0 && !(line % lpi))
 			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
@@ -114,13 +109,13 @@
 			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
 			todo -= (sg_dma_len(sg)-offset);
 			offset = 0;
-			sg = sg_next(sg);
+			sg++;
 			while (todo > sg_dma_len(sg)) {
 				*(rp++)=cpu_to_le32(RISC_WRITE|
 						    sg_dma_len(sg));
 				*(rp++)=cpu_to_le32(sg_dma_address(sg));
 				todo -= sg_dma_len(sg);
-				sg = sg_next(sg);
+				sg++;
 			}
 			*(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
 			*(rp++)=cpu_to_le32(sg_dma_address(sg));
@@ -132,13 +127,14 @@
 	return rp;
 }
 
-int cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
+int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 		     struct scatterlist *sglist,
 		     unsigned int top_offset, unsigned int bottom_offset,
 		     unsigned int bpl, unsigned int padding, unsigned int lines)
 {
 	u32 instructions,fields;
 	__le32 *rp;
+	int rc;
 
 	fields = 0;
 	if (UNSET != top_offset)
@@ -151,21 +147,18 @@
 	   can cause next bpl to start close to a page border.  First DMA
 	   region may be smaller than PAGE_SIZE */
 	instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
-	instructions += 4;
-	risc->size = instructions * 8;
-	risc->dma = 0;
-	risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
-	if (NULL == risc->cpu)
-		return -ENOMEM;
+	instructions += 2;
+	if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+		return rc;
 
 	/* write risc instructions */
 	rp = risc->cpu;
 	if (UNSET != top_offset)
 		rp = cx88_risc_field(rp, sglist, top_offset, 0,
-				     bpl, padding, lines, 0, true);
+				     bpl, padding, lines, 0);
 	if (UNSET != bottom_offset)
 		rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
-				     bpl, padding, lines, 0, top_offset == UNSET);
+				     bpl, padding, lines, 0);
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
@@ -173,28 +166,26 @@
 	return 0;
 }
 
-int cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
+int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 			 struct scatterlist *sglist, unsigned int bpl,
 			 unsigned int lines, unsigned int lpi)
 {
 	u32 instructions;
 	__le32 *rp;
+	int rc;
 
 	/* estimate risc mem: worst case is one write per page border +
 	   one write per scan line + syncs + jump (all 2 dwords).  Here
 	   there is no padding and no sync.  First DMA region may be smaller
 	   than PAGE_SIZE */
 	instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
-	instructions += 3;
-	risc->size = instructions * 8;
-	risc->dma = 0;
-	risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
-	if (NULL == risc->cpu)
-		return -ENOMEM;
+	instructions += 1;
+	if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+		return rc;
 
 	/* write risc instructions */
 	rp = risc->cpu;
-	rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi, !lpi);
+	rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
@@ -202,6 +193,39 @@
 	return 0;
 }
 
+int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+		      u32 reg, u32 mask, u32 value)
+{
+	__le32 *rp;
+	int rc;
+
+	if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	*(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2 | RISC_IMM);
+	*(rp++) = cpu_to_le32(reg);
+	*(rp++) = cpu_to_le32(value);
+	*(rp++) = cpu_to_le32(mask);
+	*(rp++) = cpu_to_le32(RISC_JUMP);
+	*(rp++) = cpu_to_le32(risc->dma);
+	return 0;
+}
+
+void
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
+{
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+	BUG_ON(in_interrupt());
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
 /* ------------------------------------------------------------------ */
 /* our SRAM memory layout                                             */
 
@@ -515,12 +539,33 @@
 		 struct cx88_dmaqueue *q, u32 count)
 {
 	struct cx88_buffer *buf;
+	int bc;
 
-	buf = list_entry(q->active.next,
-			 struct cx88_buffer, list);
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	list_del(&buf->list);
-	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	for (bc = 0;; bc++) {
+		if (list_empty(&q->active))
+			break;
+		buf = list_entry(q->active.next,
+				 struct cx88_buffer, vb.queue);
+		/* count comes from the hw and is is 16bit wide --
+		 * this trick handles wrap-arounds correctly for
+		 * up to 32767 buffers in flight... */
+		if ((s16) (count - buf->count) < 0)
+			break;
+		v4l2_get_timestamp(&buf->vb.ts);
+		dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
+			count, buf->count);
+		buf->vb.state = VIDEOBUF_DONE;
+		list_del(&buf->vb.queue);
+		wake_up(&buf->vb.done);
+	}
+	if (list_empty(&q->active)) {
+		del_timer(&q->timeout);
+	} else {
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+	}
+	if (bc != 1)
+		dprintk(2, "%s: %d buffers handled (should be 1)\n",
+			__func__, bc);
 }
 
 void cx88_shutdown(struct cx88_core *core)
@@ -864,13 +909,6 @@
 	u32 bdelay,agcdelay,htotal;
 	u32 cxiformat, cxoformat;
 
-	if (norm == core->tvnorm)
-		return 0;
-	if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) ||
-			     vb2_is_busy(&core->v4ldev->vb2_vbiq)))
-		return -EBUSY;
-	if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq))
-		return -EBUSY;
 	core->tvnorm = norm;
 	fsc8       = norm_fsc8(norm);
 	adc_clock  = xtal;
@@ -1005,7 +1043,6 @@
 	vfd->v4l2_dev = &core->v4l2_dev;
 	vfd->dev_parent = &pci->dev;
 	vfd->release = video_device_release;
-	vfd->lock = &core->lock;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
 		 core->name, type, core->board.name);
 	return vfd;
@@ -1077,6 +1114,8 @@
 
 EXPORT_SYMBOL(cx88_risc_buffer);
 EXPORT_SYMBOL(cx88_risc_databuffer);
+EXPORT_SYMBOL(cx88_risc_stopper);
+EXPORT_SYMBOL(cx88_free_buffer);
 
 EXPORT_SYMBOL(cx88_sram_channels);
 EXPORT_SYMBOL(cx88_sram_channel_setup);
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index 8b19efa..4f3c001 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -82,87 +82,43 @@
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], void *alloc_ctxs[])
+static int dvb_buf_setup(struct videobuf_queue *q,
+			 unsigned int *count, unsigned int *size)
 {
-	struct cx8802_dev *dev = q->drv_priv;
+	struct cx8802_dev *dev = q->priv_data;
 
-	*num_planes = 1;
 	dev->ts_packet_size  = 188 * 4;
 	dev->ts_packet_count = dvb_buf_tscnt;
-	sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
-	alloc_ctxs[0] = dev->alloc_ctx;
-	*num_buffers = dvb_buf_tscnt;
+
+	*size  = dev->ts_packet_size * dev->ts_packet_count;
+	*count = dvb_buf_tscnt;
 	return 0;
 }
 
-static int buffer_prepare(struct vb2_buffer *vb)
+static int dvb_buf_prepare(struct videobuf_queue *q,
+			   struct videobuf_buffer *vb, enum v4l2_field field)
 {
-	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-
-	return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
+	struct cx8802_dev *dev = q->priv_data;
+	return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
 }
 
-static void buffer_finish(struct vb2_buffer *vb)
+static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
-	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-	struct cx88_riscmem *risc = &buf->risc;
-
-	if (risc->cpu)
-		pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
-	memset(risc, 0, sizeof(*risc));
+	struct cx8802_dev *dev = q->priv_data;
+	cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
 }
 
-static void buffer_queue(struct vb2_buffer *vb)
+static void dvb_buf_release(struct videobuf_queue *q,
+			    struct videobuf_buffer *vb)
 {
-	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer    *buf = container_of(vb, struct cx88_buffer, vb);
-
-	cx8802_buf_queue(dev, buf);
+	cx88_free_buffer(q, (struct cx88_buffer*)vb);
 }
 
-static int start_streaming(struct vb2_queue *q, unsigned int count)
-{
-	struct cx8802_dev *dev = q->drv_priv;
-	struct cx88_dmaqueue *dmaq = &dev->mpegq;
-	struct cx88_buffer *buf;
-
-	buf = list_entry(dmaq->active.next, struct cx88_buffer, list);
-	cx8802_start_dma(dev, dmaq, buf);
-	return 0;
-}
-
-static void stop_streaming(struct vb2_queue *q)
-{
-	struct cx8802_dev *dev = q->drv_priv;
-	struct cx88_dmaqueue *dmaq = &dev->mpegq;
-	unsigned long flags;
-
-	cx8802_cancel_buffers(dev);
-
-	spin_lock_irqsave(&dev->slock, flags);
-	while (!list_empty(&dmaq->active)) {
-		struct cx88_buffer *buf = list_entry(dmaq->active.next,
-			struct cx88_buffer, list);
-
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-	}
-	spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-static struct vb2_ops dvb_qops = {
-	.queue_setup    = queue_setup,
-	.buf_prepare  = buffer_prepare,
-	.buf_finish = buffer_finish,
-	.buf_queue    = buffer_queue,
-	.wait_prepare = vb2_ops_wait_prepare,
-	.wait_finish = vb2_ops_wait_finish,
-	.start_streaming = start_streaming,
-	.stop_streaming = stop_streaming,
+static const struct videobuf_queue_ops dvb_qops = {
+	.buf_setup    = dvb_buf_setup,
+	.buf_prepare  = dvb_buf_prepare,
+	.buf_queue    = dvb_buf_queue,
+	.buf_release  = dvb_buf_release,
 };
 
 /* ------------------------------------------------------------------ */
@@ -174,7 +130,7 @@
 	int ret = 0;
 	int fe_id;
 
-	fe_id = vb2_dvb_find_frontend(&dev->frontends, fe);
+	fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
 	if (!fe_id) {
 		printk(KERN_ERR "%s() No frontend found\n", __func__);
 		return -EINVAL;
@@ -198,8 +154,8 @@
 
 static void cx88_dvb_gate_ctrl(struct cx88_core  *core, int open)
 {
-	struct vb2_dvb_frontends *f;
-	struct vb2_dvb_frontend *fe;
+	struct videobuf_dvb_frontends *f;
+	struct videobuf_dvb_frontend *fe;
 
 	if (!core->dvbdev)
 		return;
@@ -210,9 +166,9 @@
 		return;
 
 	if (f->gate <= 1) /* undefined or fe0 */
-		fe = vb2_dvb_get_frontend(f, 1);
+		fe = videobuf_dvb_get_frontend(f, 1);
 	else
-		fe = vb2_dvb_get_frontend(f, f->gate);
+		fe = videobuf_dvb_get_frontend(f, f->gate);
 
 	if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
 		fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
@@ -609,7 +565,7 @@
 static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
 {
 	struct dvb_frontend *fe;
-	struct vb2_dvb_frontend *fe0 = NULL;
+	struct videobuf_dvb_frontend *fe0 = NULL;
 	struct xc2028_ctrl ctl;
 	struct xc2028_config cfg = {
 		.i2c_adap  = &dev->core->i2c_adap,
@@ -618,7 +574,7 @@
 	};
 
 	/* Get the first frontend */
-	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
 	if (!fe0)
 		return -EINVAL;
 
@@ -655,10 +611,10 @@
 static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
 {
 	struct dvb_frontend *fe;
-	struct vb2_dvb_frontend *fe0 = NULL;
+	struct videobuf_dvb_frontend *fe0 = NULL;
 
 	/* Get the first frontend */
-	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
 	if (!fe0)
 		return -EINVAL;
 
@@ -789,7 +745,7 @@
 static int cx8802_alloc_frontends(struct cx8802_dev *dev)
 {
 	struct cx88_core *core = dev->core;
-	struct vb2_dvb_frontend *fe = NULL;
+	struct videobuf_dvb_frontend *fe = NULL;
 	int i;
 
 	mutex_init(&dev->frontends.lock);
@@ -801,10 +757,10 @@
 	printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
 			 core->board.num_frontends);
 	for (i = 1; i <= core->board.num_frontends; i++) {
-		fe = vb2_dvb_alloc_frontend(&dev->frontends, i);
+		fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
 		if (!fe) {
 			printk(KERN_ERR "%s() failed to alloc\n", __func__);
-			vb2_dvb_dealloc_frontends(&dev->frontends);
+			videobuf_dvb_dealloc_frontends(&dev->frontends);
 			return -ENOMEM;
 		}
 	}
@@ -1002,7 +958,7 @@
 static int dvb_register(struct cx8802_dev *dev)
 {
 	struct cx88_core *core = dev->core;
-	struct vb2_dvb_frontend *fe0, *fe1 = NULL;
+	struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
 	int mfe_shared = 0; /* bus not shared by default */
 	int res = -EINVAL;
 
@@ -1012,7 +968,7 @@
 	}
 
 	/* Get the first frontend */
-	fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
 	if (!fe0)
 		goto frontend_detach;
 
@@ -1090,7 +1046,7 @@
 				goto frontend_detach;
 		}
 		/* MFE frontend 2 */
-		fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
+		fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
 		if (!fe1)
 			goto frontend_detach;
 		/* DVB-T init */
@@ -1459,7 +1415,7 @@
 				goto frontend_detach;
 		}
 		/* MFE frontend 2 */
-		fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
+		fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
 		if (!fe1)
 			goto frontend_detach;
 		/* DVB-T Init */
@@ -1638,7 +1594,7 @@
 	call_all(core, core, s_power, 0);
 
 	/* register everything */
-	res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+	res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
 		&dev->pci->dev, adapter_nr, mfe_shared);
 	if (res)
 		goto frontend_detach;
@@ -1646,7 +1602,7 @@
 
 frontend_detach:
 	core->gate_ctrl = NULL;
-	vb2_dvb_dealloc_frontends(&dev->frontends);
+	videobuf_dvb_dealloc_frontends(&dev->frontends);
 	return res;
 }
 
@@ -1741,7 +1697,7 @@
 	struct cx88_core *core = drv->core;
 	struct cx8802_dev *dev = drv->core->dvbdev;
 	int err;
-	struct vb2_dvb_frontend *fe;
+	struct videobuf_dvb_frontend *fe;
 	int i;
 
 	dprintk( 1, "%s\n", __func__);
@@ -1770,31 +1726,19 @@
 
 	err = -ENODEV;
 	for (i = 1; i <= core->board.num_frontends; i++) {
-		struct vb2_queue *q;
-
-		fe = vb2_dvb_get_frontend(&core->dvbdev->frontends, i);
+		fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
 		if (fe == NULL) {
 			printk(KERN_ERR "%s() failed to get frontend(%d)\n",
 					__func__, i);
 			goto fail_probe;
 		}
-		q = &fe->dvb.dvbq;
-		q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
-		q->gfp_flags = GFP_DMA32;
-		q->min_buffers_needed = 2;
-		q->drv_priv = dev;
-		q->buf_struct_size = sizeof(struct cx88_buffer);
-		q->ops = &dvb_qops;
-		q->mem_ops = &vb2_dma_sg_memops;
-		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-		q->lock = &core->lock;
-
-		err = vb2_queue_init(q);
-		if (err < 0)
-			goto fail_probe;
-
-		/* init struct vb2_dvb */
+		videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
+				    &dev->pci->dev, &dev->slock,
+				    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+				    V4L2_FIELD_TOP,
+				    sizeof(struct cx88_buffer),
+				    dev, NULL);
+		/* init struct videobuf_dvb */
 		fe->dvb.name = dev->core->name;
 	}
 
@@ -1805,7 +1749,7 @@
 		       core->name, err);
 	return err;
 fail_probe:
-	vb2_dvb_dealloc_frontends(&core->dvbdev->frontends);
+	videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
 fail_core:
 	return err;
 }
@@ -1817,7 +1761,7 @@
 
 	dprintk( 1, "%s\n", __func__);
 
-	vb2_dvb_unregister_bus(&dev->frontends);
+	videobuf_dvb_unregister_bus(&dev->frontends);
 
 	vp3054_i2c_remove(dev);
 
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 1c1f69e..74b7b86 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -86,21 +86,21 @@
 static DEFINE_MUTEX(cx8802_mutex);
 /* ------------------------------------------------------------------ */
 
-int cx8802_start_dma(struct cx8802_dev    *dev,
+static int cx8802_start_dma(struct cx8802_dev    *dev,
 			    struct cx88_dmaqueue *q,
 			    struct cx88_buffer   *buf)
 {
 	struct cx88_core *core = dev->core;
 
 	dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
-		core->width, core->height, core->field);
+		buf->vb.width, buf->vb.height, buf->vb.field);
 
 	/* setup fifo + format */
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
 				dev->ts_packet_size, buf->risc.dma);
 
 	/* write TS length to chip */
-	cx_write(MO_TS_LNGTH, dev->ts_packet_size);
+	cx_write(MO_TS_LNGTH, buf->vb.width);
 
 	/* FIXME: this needs a review.
 	 * also: move to cx88-blackbird + cx88-dvb source files? */
@@ -210,40 +210,83 @@
 
 	dprintk( 1, "cx8802_restart_queue\n" );
 	if (list_empty(&q->active))
-		return 0;
+	{
+		struct cx88_buffer *prev;
+		prev = NULL;
 
-	buf = list_entry(q->active.next, struct cx88_buffer, list);
+		dprintk(1, "cx8802_restart_queue: queue is empty\n" );
+
+		for (;;) {
+			if (list_empty(&q->queued))
+				return 0;
+			buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+			if (NULL == prev) {
+				list_move_tail(&buf->vb.queue, &q->active);
+				cx8802_start_dma(dev, q, buf);
+				buf->vb.state = VIDEOBUF_ACTIVE;
+				buf->count    = q->count++;
+				mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+				dprintk(1,"[%p/%d] restart_queue - first active\n",
+					buf,buf->vb.i);
+
+			} else if (prev->vb.width  == buf->vb.width  &&
+				   prev->vb.height == buf->vb.height &&
+				   prev->fmt       == buf->fmt) {
+				list_move_tail(&buf->vb.queue, &q->active);
+				buf->vb.state = VIDEOBUF_ACTIVE;
+				buf->count    = q->count++;
+				prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+				dprintk(1,"[%p/%d] restart_queue - move to active\n",
+					buf,buf->vb.i);
+			} else {
+				return 0;
+			}
+			prev = buf;
+		}
+		return 0;
+	}
+
+	buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
 	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-		buf, buf->vb.v4l2_buf.index);
+		buf, buf->vb.i);
 	cx8802_start_dma(dev, q, buf);
-	list_for_each_entry(buf, &q->active, list)
+	list_for_each_entry(buf, &q->active, vb.queue)
 		buf->count = q->count++;
+	mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 	return 0;
 }
 
 /* ------------------------------------------------------------------ */
 
-int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
-			struct cx88_buffer *buf)
+int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
+			struct cx88_buffer *buf, enum v4l2_field field)
 {
 	int size = dev->ts_packet_size * dev->ts_packet_count;
-	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
-	struct cx88_riscmem *risc = &buf->risc;
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 	int rc;
 
-	if (vb2_plane_size(&buf->vb, 0) < size)
+	dprintk(1, "%s: %p\n", __func__, buf);
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
 		return -EINVAL;
-	vb2_set_plane_payload(&buf->vb, 0, size);
 
-	rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl,
-			     dev->ts_packet_size, dev->ts_packet_count, 0);
-	if (rc) {
-		if (risc->cpu)
-			pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
-		memset(risc, 0, sizeof(*risc));
-		return rc;
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		buf->vb.width  = dev->ts_packet_size;
+		buf->vb.height = dev->ts_packet_count;
+		buf->vb.size   = size;
+		buf->vb.field  = field /*V4L2_FIELD_TOP*/;
+
+		if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+			goto fail;
+		cx88_risc_databuffer(dev->pci, &buf->risc,
+				     dma->sglist,
+				     buf->vb.width, buf->vb.height, 0);
 	}
+	buf->vb.state = VIDEOBUF_PREPARED;
 	return 0;
+
+ fail:
+	cx88_free_buffer(q,buf);
+	return rc;
 }
 
 void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
@@ -252,33 +295,35 @@
 	struct cx88_dmaqueue  *cx88q = &dev->mpegq;
 
 	dprintk( 1, "cx8802_buf_queue\n" );
-	/* add jump to start */
-	buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
-	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
-	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
 
 	if (list_empty(&cx88q->active)) {
 		dprintk( 1, "queue is empty - first active\n" );
-		list_add_tail(&buf->list, &cx88q->active);
+		list_add_tail(&buf->vb.queue,&cx88q->active);
+		cx8802_start_dma(dev, cx88q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
 		buf->count    = cx88q->count++;
+		mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
 		dprintk(1,"[%p/%d] %s - first active\n",
-			buf, buf->vb.v4l2_buf.index, __func__);
+			buf, buf->vb.i, __func__);
 
 	} else {
-		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
 		dprintk( 1, "queue is not empty - append to active\n" );
-		prev = list_entry(cx88q->active.prev, struct cx88_buffer, list);
-		list_add_tail(&buf->list, &cx88q->active);
+		prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
+		list_add_tail(&buf->vb.queue,&cx88q->active);
+		buf->vb.state = VIDEOBUF_ACTIVE;
 		buf->count    = cx88q->count++;
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		dprintk( 1, "[%p/%d] %s - append to active\n",
-			buf, buf->vb.v4l2_buf.index, __func__);
+			buf, buf->vb.i, __func__);
 	}
 }
 
 /* ----------------------------------------------------------- */
 
-static void do_cancel_buffers(struct cx8802_dev *dev)
+static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart)
 {
 	struct cx88_dmaqueue *q = &dev->mpegq;
 	struct cx88_buffer *buf;
@@ -286,18 +331,41 @@
 
 	spin_lock_irqsave(&dev->slock,flags);
 	while (!list_empty(&q->active)) {
-		buf = list_entry(q->active.next, struct cx88_buffer, list);
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
+			buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
+	}
+	if (restart)
+	{
+		dprintk(1, "restarting queue\n" );
+		cx8802_restart_queue(dev,q);
 	}
 	spin_unlock_irqrestore(&dev->slock,flags);
 }
 
 void cx8802_cancel_buffers(struct cx8802_dev *dev)
 {
+	struct cx88_dmaqueue *q = &dev->mpegq;
+
 	dprintk( 1, "cx8802_cancel_buffers" );
+	del_timer_sync(&q->timeout);
 	cx8802_stop_dma(dev);
-	do_cancel_buffers(dev);
+	do_cancel_buffers(dev,"cancel",0);
+}
+
+static void cx8802_timeout(unsigned long data)
+{
+	struct cx8802_dev *dev = (struct cx8802_dev*)data;
+
+	dprintk(1, "%s\n",__func__);
+
+	if (debug)
+		cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+	cx8802_stop_dma(dev);
+	do_cancel_buffers(dev,"timeout",1);
 }
 
 static const char * cx88_mpeg_irqs[32] = {
@@ -343,11 +411,19 @@
 		spin_unlock(&dev->slock);
 	}
 
+	/* risc2 y */
+	if (status & 0x10) {
+		spin_lock(&dev->slock);
+		cx8802_restart_queue(dev,&dev->mpegq);
+		spin_unlock(&dev->slock);
+	}
+
 	/* other general errors */
 	if (status & 0x1f0100) {
 		dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
 		spin_lock(&dev->slock);
 		cx8802_stop_dma(dev);
+		cx8802_restart_queue(dev,&dev->mpegq);
 		spin_unlock(&dev->slock);
 	}
 }
@@ -414,6 +490,12 @@
 
 	/* init dma queue */
 	INIT_LIST_HEAD(&dev->mpegq.active);
+	INIT_LIST_HEAD(&dev->mpegq.queued);
+	dev->mpegq.timeout.function = cx8802_timeout;
+	dev->mpegq.timeout.data     = (unsigned long)dev;
+	init_timer(&dev->mpegq.timeout);
+	cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
+			  MO_TS_DMACNTRL,0x11,0x00);
 
 	/* get irq */
 	err = request_irq(dev->pci->irq, cx8802_irq,
@@ -438,6 +520,9 @@
 
 	/* unregister stuff */
 	free_irq(dev->pci->irq, dev);
+
+	/* free memory */
+	btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
 }
 
 /* ----------------------------------------------------------- */
@@ -454,6 +539,7 @@
 		dprintk( 2, "suspend\n" );
 		printk("%s: suspend mpeg\n", core->name);
 		cx8802_stop_dma(dev);
+		del_timer(&dev->mpegq.timeout);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 
@@ -729,11 +815,6 @@
 	if (NULL == dev)
 		goto fail_core;
 	dev->pci = pci_dev;
-	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
-	if (IS_ERR(dev->alloc_ctx)) {
-		err = PTR_ERR(dev->alloc_ctx);
-		goto fail_core;
-	}
 	dev->core = core;
 
 	/* Maintain a reference so cx88-video can query the 8802 device. */
@@ -753,7 +834,6 @@
 	return 0;
 
  fail_free:
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 	kfree(dev);
  fail_core:
 	core->dvbdev = NULL;
@@ -800,7 +880,6 @@
 	/* common */
 	cx8802_fini_common(dev);
 	cx88_core_put(dev->core,dev->pci);
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 	kfree(dev);
 }
 
@@ -828,7 +907,6 @@
 EXPORT_SYMBOL(cx8802_buf_prepare);
 EXPORT_SYMBOL(cx8802_buf_queue);
 EXPORT_SYMBOL(cx8802_cancel_buffers);
-EXPORT_SYMBOL(cx8802_start_dma);
 
 EXPORT_SYMBOL(cx8802_register_driver);
 EXPORT_SYMBOL(cx8802_unregister_driver);
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 32eb7fd..f8f8389 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -6,6 +6,10 @@
 
 #include "cx88.h"
 
+static unsigned int vbibufs = 4;
+module_param(vbibufs,int,0644);
+MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
+
 static unsigned int vbi_debug;
 module_param(vbi_debug,int,0644);
 MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
@@ -18,27 +22,26 @@
 int cx8800_vbi_fmt (struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
 
 	f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
 	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
 	f->fmt.vbi.offset = 244;
+	f->fmt.vbi.count[0] = VBI_LINE_COUNT;
+	f->fmt.vbi.count[1] = VBI_LINE_COUNT;
 
 	if (dev->core->tvnorm & V4L2_STD_525_60) {
 		/* ntsc */
 		f->fmt.vbi.sampling_rate = 28636363;
 		f->fmt.vbi.start[0] = 10;
 		f->fmt.vbi.start[1] = 273;
-		f->fmt.vbi.count[0] = VBI_LINE_NTSC_COUNT;
-		f->fmt.vbi.count[1] = VBI_LINE_NTSC_COUNT;
 
 	} else if (dev->core->tvnorm & V4L2_STD_625_50) {
 		/* pal */
 		f->fmt.vbi.sampling_rate = 35468950;
-		f->fmt.vbi.start[0] = V4L2_VBI_ITU_625_F1_START + 5;
-		f->fmt.vbi.start[1] = V4L2_VBI_ITU_625_F2_START + 5;
-		f->fmt.vbi.count[0] = VBI_LINE_PAL_COUNT;
-		f->fmt.vbi.count[1] = VBI_LINE_PAL_COUNT;
+		f->fmt.vbi.start[0] = 7 -1;
+		f->fmt.vbi.start[1] = 319 -1;
 	}
 	return 0;
 }
@@ -51,7 +54,7 @@
 
 	/* setup fifo + format */
 	cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
-				VBI_LINE_LENGTH, buf->risc.dma);
+				buf->vb.width, buf->risc.dma);
 
 	cx_write(MO_VBOS_CONTROL, ( (1 << 18) |  // comb filter delay fixup
 				    (1 << 15) |  // enable vbi capture
@@ -75,7 +78,7 @@
 	return 0;
 }
 
-void cx8800_stop_vbi_dma(struct cx8800_dev *dev)
+int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
 {
 	struct cx88_core *core = dev->core;
 
@@ -88,6 +91,7 @@
 	/* disable irqs */
 	cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
 	cx_clear(MO_VID_INTMSK, 0x0f0088);
+	return 0;
 }
 
 int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
@@ -98,137 +102,144 @@
 	if (list_empty(&q->active))
 		return 0;
 
-	buf = list_entry(q->active.next, struct cx88_buffer, list);
+	buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
 	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-		buf, buf->vb.v4l2_buf.index);
+		buf, buf->vb.i);
 	cx8800_start_vbi_dma(dev, q, buf);
-	list_for_each_entry(buf, &q->active, list)
+	list_for_each_entry(buf, &q->active, vb.queue)
 		buf->count = q->count++;
+	mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 	return 0;
 }
 
+void cx8800_vbi_timeout(unsigned long data)
+{
+	struct cx8800_dev *dev = (struct cx8800_dev*)data;
+	struct cx88_core *core = dev->core;
+	struct cx88_dmaqueue *q = &dev->vbiq;
+	struct cx88_buffer *buf;
+	unsigned long flags;
+
+	cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);
+
+	cx_clear(MO_VID_DMACNTRL, 0x88);
+	cx_clear(VID_CAPTURE_CONTROL, 0x18);
+
+	spin_lock_irqsave(&dev->slock,flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
+		       buf, buf->vb.i, (unsigned long)buf->risc.dma);
+	}
+	cx8800_restart_vbi_queue(dev,q);
+	spin_unlock_irqrestore(&dev->slock,flags);
+}
+
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], void *alloc_ctxs[])
+static int
+vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 {
-	struct cx8800_dev *dev = q->drv_priv;
-
-	*num_planes = 1;
-	if (dev->core->tvnorm & V4L2_STD_525_60)
-		sizes[0] = VBI_LINE_NTSC_COUNT * VBI_LINE_LENGTH * 2;
-	else
-		sizes[0] = VBI_LINE_PAL_COUNT * VBI_LINE_LENGTH * 2;
-	alloc_ctxs[0] = dev->alloc_ctx;
+	*size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+	if (0 == *count)
+		*count = vbibufs;
+	if (*count < 2)
+		*count = 2;
+	if (*count > 32)
+		*count = 32;
 	return 0;
 }
 
-
-static int buffer_prepare(struct vb2_buffer *vb)
+static int
+vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	    enum v4l2_field field)
 {
-	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
-	unsigned int lines;
+	struct cx8800_fh   *fh  = q->priv_data;
+	struct cx8800_dev  *dev = fh->dev;
+	struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
 	unsigned int size;
+	int rc;
 
-	if (dev->core->tvnorm & V4L2_STD_525_60)
-		lines = VBI_LINE_NTSC_COUNT;
-	else
-		lines = VBI_LINE_PAL_COUNT;
-	size = lines * VBI_LINE_LENGTH * 2;
-	if (vb2_plane_size(vb, 0) < size)
+	size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
 		return -EINVAL;
-	vb2_set_plane_payload(vb, 0, size);
 
-	cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
-			 0, VBI_LINE_LENGTH * lines,
-			 VBI_LINE_LENGTH, 0,
-			 lines);
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+		buf->vb.width  = VBI_LINE_LENGTH;
+		buf->vb.height = VBI_LINE_COUNT;
+		buf->vb.size   = size;
+		buf->vb.field  = V4L2_FIELD_SEQ_TB;
+
+		if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+			goto fail;
+		cx88_risc_buffer(dev->pci, &buf->risc,
+				 dma->sglist,
+				 0, buf->vb.width * buf->vb.height,
+				 buf->vb.width, 0,
+				 buf->vb.height);
+	}
+	buf->vb.state = VIDEOBUF_PREPARED;
 	return 0;
+
+ fail:
+	cx88_free_buffer(q,buf);
+	return rc;
 }
 
-static void buffer_finish(struct vb2_buffer *vb)
+static void
+vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
 {
-	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-	struct cx88_riscmem *risc = &buf->risc;
-
-	if (risc->cpu)
-		pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
-	memset(risc, 0, sizeof(*risc));
-}
-
-static void buffer_queue(struct vb2_buffer *vb)
-{
-	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer    *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer    *buf = container_of(vb,struct cx88_buffer,vb);
 	struct cx88_buffer    *prev;
+	struct cx8800_fh      *fh   = vq->priv_data;
+	struct cx8800_dev     *dev  = fh->dev;
 	struct cx88_dmaqueue  *q    = &dev->vbiq;
 
-	/* add jump to start */
-	buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
-	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
-	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
 
 	if (list_empty(&q->active)) {
-		list_add_tail(&buf->list, &q->active);
+		list_add_tail(&buf->vb.queue,&q->active);
 		cx8800_start_vbi_dma(dev, q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
 		buf->count    = q->count++;
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 		dprintk(2,"[%p/%d] vbi_queue - first active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.i);
 
 	} else {
-		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
-		prev = list_entry(q->active.prev, struct cx88_buffer, list);
-		list_add_tail(&buf->list, &q->active);
+		prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
+		list_add_tail(&buf->vb.queue,&q->active);
+		buf->vb.state = VIDEOBUF_ACTIVE;
 		buf->count    = q->count++;
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		dprintk(2,"[%p/%d] buffer_queue - append to active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.i);
 	}
 }
 
-static int start_streaming(struct vb2_queue *q, unsigned int count)
+static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
-	struct cx8800_dev *dev = q->drv_priv;
-	struct cx88_dmaqueue *dmaq = &dev->vbiq;
-	struct cx88_buffer *buf = list_entry(dmaq->active.next,
-			struct cx88_buffer, list);
+	struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
 
-	cx8800_start_vbi_dma(dev, dmaq, buf);
-	return 0;
+	cx88_free_buffer(q,buf);
 }
 
-static void stop_streaming(struct vb2_queue *q)
-{
-	struct cx8800_dev *dev = q->drv_priv;
-	struct cx88_core *core = dev->core;
-	struct cx88_dmaqueue *dmaq = &dev->vbiq;
-	unsigned long flags;
-
-	cx_clear(MO_VID_DMACNTRL, 0x11);
-	cx_clear(VID_CAPTURE_CONTROL, 0x06);
-	cx8800_stop_vbi_dma(dev);
-	spin_lock_irqsave(&dev->slock, flags);
-	while (!list_empty(&dmaq->active)) {
-		struct cx88_buffer *buf = list_entry(dmaq->active.next,
-			struct cx88_buffer, list);
-
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-	}
-	spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-const struct vb2_ops cx8800_vbi_qops = {
-	.queue_setup    = queue_setup,
-	.buf_prepare  = buffer_prepare,
-	.buf_finish = buffer_finish,
-	.buf_queue    = buffer_queue,
-	.wait_prepare = vb2_ops_wait_prepare,
-	.wait_finish = vb2_ops_wait_finish,
-	.start_streaming = start_streaming,
-	.stop_streaming = stop_streaming,
+const struct videobuf_queue_ops cx8800_vbi_qops = {
+	.buf_setup    = vbi_setup,
+	.buf_prepare  = vbi_prepare,
+	.buf_queue    = vbi_queue,
+	.buf_release  = vbi_release,
 };
+
+/* ------------------------------------------------------------------ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 05d5844..e46b732 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -70,6 +70,10 @@
 module_param(irq_debug,int,0644);
 MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
 
+static unsigned int vid_limit = 16;
+module_param(vid_limit,int,0644);
+MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+
 #define dprintk(level,fmt, arg...)	if (video_debug >= level) \
 	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
 
@@ -293,6 +297,56 @@
 	CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls),
 };
 
+/* ------------------------------------------------------------------- */
+/* resource management                                                 */
+
+static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
+{
+	struct cx88_core *core = dev->core;
+	if (fh->resources & bit)
+		/* have it already allocated */
+		return 1;
+
+	/* is it free? */
+	mutex_lock(&core->lock);
+	if (dev->resources & bit) {
+		/* no, someone else uses it */
+		mutex_unlock(&core->lock);
+		return 0;
+	}
+	/* it's free, grab it */
+	fh->resources  |= bit;
+	dev->resources |= bit;
+	dprintk(1,"res: get %d\n",bit);
+	mutex_unlock(&core->lock);
+	return 1;
+}
+
+static
+int res_check(struct cx8800_fh *fh, unsigned int bit)
+{
+	return (fh->resources & bit);
+}
+
+static
+int res_locked(struct cx8800_dev *dev, unsigned int bit)
+{
+	return (dev->resources & bit);
+}
+
+static
+void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
+{
+	struct cx88_core *core = dev->core;
+	BUG_ON((fh->resources & bits) != bits);
+
+	mutex_lock(&core->lock);
+	fh->resources  &= ~bits;
+	dev->resources &= ~bits;
+	dprintk(1,"res: put %d\n",bits);
+	mutex_unlock(&core->lock);
+}
+
 /* ------------------------------------------------------------------ */
 
 int cx88_video_mux(struct cx88_core *core, unsigned int input)
@@ -365,8 +419,8 @@
 	/* setup fifo + format */
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
 				buf->bpl, buf->risc.dma);
-	cx88_set_scale(core, core->width, core->height, core->field);
-	cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma);
+	cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
+	cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
 
 	/* reset counter */
 	cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
@@ -416,203 +470,433 @@
 			       struct cx88_dmaqueue *q)
 {
 	struct cx88_core *core = dev->core;
-	struct cx88_buffer *buf;
+	struct cx88_buffer *buf, *prev;
 
 	if (!list_empty(&q->active)) {
-		buf = list_entry(q->active.next, struct cx88_buffer, list);
+		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
 		dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.i);
 		start_video_dma(dev, q, buf);
-		list_for_each_entry(buf, &q->active, list)
+		list_for_each_entry(buf, &q->active, vb.queue)
 			buf->count = q->count++;
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+		return 0;
 	}
-	return 0;
+
+	prev = NULL;
+	for (;;) {
+		if (list_empty(&q->queued))
+			return 0;
+		buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+		if (NULL == prev) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			start_video_dma(dev, q, buf);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+			dprintk(2,"[%p/%d] restart_queue - first active\n",
+				buf,buf->vb.i);
+
+		} else if (prev->vb.width  == buf->vb.width  &&
+			   prev->vb.height == buf->vb.height &&
+			   prev->fmt       == buf->fmt) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			dprintk(2,"[%p/%d] restart_queue - move to active\n",
+				buf,buf->vb.i);
+		} else {
+			return 0;
+		}
+		prev = buf;
+	}
 }
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], void *alloc_ctxs[])
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 {
-	struct cx8800_dev *dev = q->drv_priv;
-	struct cx88_core *core = dev->core;
+	struct cx8800_fh *fh = q->priv_data;
+	struct cx8800_dev  *dev = fh->dev;
 
-	*num_planes = 1;
-	sizes[0] = (dev->fmt->depth * core->width * core->height) >> 3;
-	alloc_ctxs[0] = dev->alloc_ctx;
+	*size = dev->fmt->depth * dev->width * dev->height >> 3;
+	if (0 == *count)
+		*count = 32;
+	if (*size * *count > vid_limit * 1024 * 1024)
+		*count = (vid_limit * 1024 * 1024) / *size;
 	return 0;
 }
 
-static int buffer_prepare(struct vb2_buffer *vb)
+static int
+buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	       enum v4l2_field field)
 {
-	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
+	struct cx8800_fh   *fh  = q->priv_data;
+	struct cx8800_dev  *dev = fh->dev;
 	struct cx88_core *core = dev->core;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+	struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+	int rc, init_buffer = 0;
 
-	buf->bpl = core->width * dev->fmt->depth >> 3;
-
-	if (vb2_plane_size(vb, 0) < core->height * buf->bpl)
+	BUG_ON(NULL == dev->fmt);
+	if (dev->width  < 48 || dev->width  > norm_maxw(core->tvnorm) ||
+	    dev->height < 32 || dev->height > norm_maxh(core->tvnorm))
 		return -EINVAL;
-	vb2_set_plane_payload(vb, 0, core->height * buf->bpl);
+	buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3;
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
 
-	switch (core->field) {
-	case V4L2_FIELD_TOP:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl, 0, UNSET,
-				 buf->bpl, 0, core->height);
-		break;
-	case V4L2_FIELD_BOTTOM:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl, UNSET, 0,
-				 buf->bpl, 0, core->height);
-		break;
-	case V4L2_FIELD_SEQ_TB:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl,
-				 0, buf->bpl * (core->height >> 1),
-				 buf->bpl, 0,
-				 core->height >> 1);
-		break;
-	case V4L2_FIELD_SEQ_BT:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl,
-				 buf->bpl * (core->height >> 1), 0,
-				 buf->bpl, 0,
-				 core->height >> 1);
-		break;
-	case V4L2_FIELD_INTERLACED:
-	default:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl, 0, buf->bpl,
-				 buf->bpl, buf->bpl,
-				 core->height >> 1);
-		break;
+	if (buf->fmt       != dev->fmt    ||
+	    buf->vb.width  != dev->width  ||
+	    buf->vb.height != dev->height ||
+	    buf->vb.field  != field) {
+		buf->fmt       = dev->fmt;
+		buf->vb.width  = dev->width;
+		buf->vb.height = dev->height;
+		buf->vb.field  = field;
+		init_buffer = 1;
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		init_buffer = 1;
+		if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+			goto fail;
+	}
+
+	if (init_buffer) {
+		buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
+		switch (buf->vb.field) {
+		case V4L2_FIELD_TOP:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist, 0, UNSET,
+					 buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_BOTTOM:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist, UNSET, 0,
+					 buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_INTERLACED:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist, 0, buf->bpl,
+					 buf->bpl, buf->bpl,
+					 buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_TB:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist,
+					 0, buf->bpl * (buf->vb.height >> 1),
+					 buf->bpl, 0,
+					 buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_BT:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist,
+					 buf->bpl * (buf->vb.height >> 1), 0,
+					 buf->bpl, 0,
+					 buf->vb.height >> 1);
+			break;
+		default:
+			BUG();
+		}
 	}
 	dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
-		buf, buf->vb.v4l2_buf.index,
-		core->width, core->height, dev->fmt->depth, dev->fmt->name,
+		buf, buf->vb.i,
+		dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
 		(unsigned long)buf->risc.dma);
+
+	buf->vb.state = VIDEOBUF_PREPARED;
 	return 0;
+
+ fail:
+	cx88_free_buffer(q,buf);
+	return rc;
 }
 
-static void buffer_finish(struct vb2_buffer *vb)
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
 {
-	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-	struct cx88_riscmem *risc = &buf->risc;
-
-	if (risc->cpu)
-		pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
-	memset(risc, 0, sizeof(*risc));
-}
-
-static void buffer_queue(struct vb2_buffer *vb)
-{
-	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer    *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer    *buf = container_of(vb,struct cx88_buffer,vb);
 	struct cx88_buffer    *prev;
+	struct cx8800_fh      *fh   = vq->priv_data;
+	struct cx8800_dev     *dev  = fh->dev;
 	struct cx88_core      *core = dev->core;
 	struct cx88_dmaqueue  *q    = &dev->vidq;
 
-	/* add jump to start */
-	buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
-	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
-	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
 
-	if (list_empty(&q->active)) {
-		list_add_tail(&buf->list, &q->active);
+	if (!list_empty(&q->queued)) {
+		list_add_tail(&buf->vb.queue,&q->queued);
+		buf->vb.state = VIDEOBUF_QUEUED;
+		dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
+			buf, buf->vb.i);
+
+	} else if (list_empty(&q->active)) {
+		list_add_tail(&buf->vb.queue,&q->active);
+		start_video_dma(dev, q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
 		buf->count    = q->count++;
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 		dprintk(2,"[%p/%d] buffer_queue - first active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.i);
 
 	} else {
-		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
-		prev = list_entry(q->active.prev, struct cx88_buffer, list);
-		list_add_tail(&buf->list, &q->active);
-		buf->count    = q->count++;
-		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-		dprintk(2, "[%p/%d] buffer_queue - append to active\n",
-			buf, buf->vb.v4l2_buf.index);
+		prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
+		if (prev->vb.width  == buf->vb.width  &&
+		    prev->vb.height == buf->vb.height &&
+		    prev->fmt       == buf->fmt) {
+			list_add_tail(&buf->vb.queue,&q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			dprintk(2,"[%p/%d] buffer_queue - append to active\n",
+				buf, buf->vb.i);
+
+		} else {
+			list_add_tail(&buf->vb.queue,&q->queued);
+			buf->vb.state = VIDEOBUF_QUEUED;
+			dprintk(2,"[%p/%d] buffer_queue - first queued\n",
+				buf, buf->vb.i);
+		}
 	}
 }
 
-static int start_streaming(struct vb2_queue *q, unsigned int count)
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
-	struct cx8800_dev *dev = q->drv_priv;
-	struct cx88_dmaqueue *dmaq = &dev->vidq;
-	struct cx88_buffer *buf = list_entry(dmaq->active.next,
-			struct cx88_buffer, list);
+	struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
 
-	start_video_dma(dev, dmaq, buf);
-	return 0;
+	cx88_free_buffer(q,buf);
 }
 
-static void stop_streaming(struct vb2_queue *q)
-{
-	struct cx8800_dev *dev = q->drv_priv;
-	struct cx88_core *core = dev->core;
-	struct cx88_dmaqueue *dmaq = &dev->vidq;
-	unsigned long flags;
-
-	cx_clear(MO_VID_DMACNTRL, 0x11);
-	cx_clear(VID_CAPTURE_CONTROL, 0x06);
-	spin_lock_irqsave(&dev->slock, flags);
-	while (!list_empty(&dmaq->active)) {
-		struct cx88_buffer *buf = list_entry(dmaq->active.next,
-			struct cx88_buffer, list);
-
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-	}
-	spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-static struct vb2_ops cx8800_video_qops = {
-	.queue_setup    = queue_setup,
+static const struct videobuf_queue_ops cx8800_video_qops = {
+	.buf_setup    = buffer_setup,
 	.buf_prepare  = buffer_prepare,
-	.buf_finish = buffer_finish,
 	.buf_queue    = buffer_queue,
-	.wait_prepare = vb2_ops_wait_prepare,
-	.wait_finish = vb2_ops_wait_finish,
-	.start_streaming = start_streaming,
-	.stop_streaming = stop_streaming,
+	.buf_release  = buffer_release,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int radio_open(struct file *file)
+
+/* ------------------------------------------------------------------ */
+
+static struct videobuf_queue *get_queue(struct file *file)
 {
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh *fh = file->private_data;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		return &fh->vidq;
+	case VFL_TYPE_VBI:
+		return &fh->vbiq;
+	default:
+		BUG();
+	}
+}
+
+static int get_resource(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		return RESOURCE_VIDEO;
+	case VFL_TYPE_VBI:
+		return RESOURCE_VBI;
+	default:
+		BUG();
+	}
+}
+
+static int video_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
-	int ret = v4l2_fh_open(file);
+	struct cx8800_fh *fh;
+	enum v4l2_buf_type type = 0;
+	int radio = 0;
 
-	if (ret)
-		return ret;
-
-	cx_write(MO_GP3_IO, core->board.radio.gpio3);
-	cx_write(MO_GP0_IO, core->board.radio.gpio0);
-	cx_write(MO_GP1_IO, core->board.radio.gpio1);
-	cx_write(MO_GP2_IO, core->board.radio.gpio2);
-	if (core->board.radio.audioroute) {
-		if (core->sd_wm8775) {
-			call_all(core, audio, s_routing,
-					core->board.radio.audioroute, 0, 0);
-		}
-		/* "I2S ADC mode" */
-		core->tvaudio = WW_I2SADC;
-		cx88_set_tvaudio(core);
-	} else {
-		/* FM Mode */
-		core->tvaudio = WW_FM;
-		cx88_set_tvaudio(core);
-		cx88_set_stereo(core, V4L2_TUNER_MODE_STEREO, 1);
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
 	}
-	call_all(core, tuner, s_radio);
+
+	dprintk(1, "open dev=%s radio=%d type=%s\n",
+		video_device_node_name(vdev), radio, v4l2_type_names[type]);
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+	if (unlikely(!fh))
+		return -ENOMEM;
+
+	v4l2_fh_init(&fh->fh, vdev);
+	file->private_data = fh;
+	fh->dev      = dev;
+
+	mutex_lock(&core->lock);
+
+	videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct cx88_buffer),
+			    fh, NULL);
+	videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VBI_CAPTURE,
+			    V4L2_FIELD_SEQ_TB,
+			    sizeof(struct cx88_buffer),
+			    fh, NULL);
+
+	if (vdev->vfl_type == VFL_TYPE_RADIO) {
+		dprintk(1,"video_open: setting radio device\n");
+		cx_write(MO_GP3_IO, core->board.radio.gpio3);
+		cx_write(MO_GP0_IO, core->board.radio.gpio0);
+		cx_write(MO_GP1_IO, core->board.radio.gpio1);
+		cx_write(MO_GP2_IO, core->board.radio.gpio2);
+		if (core->board.radio.audioroute) {
+			if (core->sd_wm8775) {
+				call_all(core, audio, s_routing,
+					core->board.radio.audioroute, 0, 0);
+			}
+			/* "I2S ADC mode" */
+			core->tvaudio = WW_I2SADC;
+			cx88_set_tvaudio(core);
+		} else {
+			/* FM Mode */
+			core->tvaudio = WW_FM;
+			cx88_set_tvaudio(core);
+			cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+		}
+		call_all(core, tuner, s_radio);
+	}
+
+	core->users++;
+	mutex_unlock(&core->lock);
+	v4l2_fh_add(&fh->fh);
+
 	return 0;
 }
 
+static ssize_t
+video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh *fh = file->private_data;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		if (res_locked(fh->dev,RESOURCE_VIDEO))
+			return -EBUSY;
+		return videobuf_read_one(&fh->vidq, data, count, ppos,
+					 file->f_flags & O_NONBLOCK);
+	case VFL_TYPE_VBI:
+		if (!res_get(fh->dev,fh,RESOURCE_VBI))
+			return -EBUSY;
+		return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
+					    file->f_flags & O_NONBLOCK);
+	default:
+		BUG();
+	}
+}
+
+static unsigned int
+video_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh *fh = file->private_data;
+	struct cx88_buffer *buf;
+	unsigned int rc = v4l2_ctrl_poll(file, wait);
+
+	if (vdev->vfl_type == VFL_TYPE_VBI) {
+		if (!res_get(fh->dev,fh,RESOURCE_VBI))
+			return rc | POLLERR;
+		return rc | videobuf_poll_stream(file, &fh->vbiq, wait);
+	}
+	mutex_lock(&fh->vidq.vb_lock);
+	if (res_check(fh,RESOURCE_VIDEO)) {
+		/* streaming capture */
+		if (list_empty(&fh->vidq.stream))
+			goto done;
+		buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
+	} else {
+		/* read() capture */
+		buf = (struct cx88_buffer*)fh->vidq.read_buf;
+		if (NULL == buf)
+			goto done;
+	}
+	poll_wait(file, &buf->vb.done, wait);
+	if (buf->vb.state == VIDEOBUF_DONE ||
+	    buf->vb.state == VIDEOBUF_ERROR)
+		rc |= POLLIN|POLLRDNORM;
+done:
+	mutex_unlock(&fh->vidq.vb_lock);
+	return rc;
+}
+
+static int video_release(struct file *file)
+{
+	struct cx8800_fh  *fh  = file->private_data;
+	struct cx8800_dev *dev = fh->dev;
+
+	/* turn off overlay */
+	if (res_check(fh, RESOURCE_OVERLAY)) {
+		/* FIXME */
+		res_free(dev,fh,RESOURCE_OVERLAY);
+	}
+
+	/* stop video capture */
+	if (res_check(fh, RESOURCE_VIDEO)) {
+		videobuf_queue_cancel(&fh->vidq);
+		res_free(dev,fh,RESOURCE_VIDEO);
+	}
+	if (fh->vidq.read_buf) {
+		buffer_release(&fh->vidq,fh->vidq.read_buf);
+		kfree(fh->vidq.read_buf);
+	}
+
+	/* stop vbi capture */
+	if (res_check(fh, RESOURCE_VBI)) {
+		videobuf_stop(&fh->vbiq);
+		res_free(dev,fh,RESOURCE_VBI);
+	}
+
+	videobuf_mmap_free(&fh->vidq);
+	videobuf_mmap_free(&fh->vbiq);
+
+	mutex_lock(&dev->core->lock);
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	file->private_data = NULL;
+	kfree(fh);
+
+	dev->core->users--;
+	if (!dev->core->users)
+		call_all(dev->core, core, s_power, 0);
+	mutex_unlock(&dev->core->lock);
+
+	return 0;
+}
+
+static int
+video_mmap(struct file *file, struct vm_area_struct * vma)
+{
+	return videobuf_mmap_mapper(get_queue(file), vma);
+}
+
 /* ------------------------------------------------------------------ */
 /* VIDEO CTRL IOCTLS                                                  */
 
@@ -715,12 +999,12 @@
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev = fh->dev;
 
-	f->fmt.pix.width        = core->width;
-	f->fmt.pix.height       = core->height;
-	f->fmt.pix.field        = core->field;
+	f->fmt.pix.width        = dev->width;
+	f->fmt.pix.height       = dev->height;
+	f->fmt.pix.field        = fh->vidq.field;
 	f->fmt.pix.pixelformat  = dev->fmt->fourcc;
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * dev->fmt->depth) >> 3;
@@ -733,8 +1017,7 @@
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 			struct v4l2_format *f)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 	const struct cx8800_fmt *fmt;
 	enum v4l2_field   field;
 	unsigned int      maxw, maxh;
@@ -743,30 +1026,30 @@
 	if (NULL == fmt)
 		return -EINVAL;
 
-	maxw = norm_maxw(core->tvnorm);
-	maxh = norm_maxh(core->tvnorm);
-
 	field = f->fmt.pix.field;
+	maxw  = norm_maxw(core->tvnorm);
+	maxh  = norm_maxh(core->tvnorm);
+
+	if (V4L2_FIELD_ANY == field) {
+		field = (f->fmt.pix.height > maxh/2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
+	}
 
 	switch (field) {
 	case V4L2_FIELD_TOP:
 	case V4L2_FIELD_BOTTOM:
+		maxh = maxh / 2;
+		break;
 	case V4L2_FIELD_INTERLACED:
-	case V4L2_FIELD_SEQ_BT:
-	case V4L2_FIELD_SEQ_TB:
 		break;
 	default:
-		field = (f->fmt.pix.height > maxh / 2)
-			? V4L2_FIELD_INTERLACED
-			: V4L2_FIELD_BOTTOM;
-		break;
+		return -EINVAL;
 	}
-	if (V4L2_FIELD_HAS_T_OR_B(field))
-		maxh /= 2;
 
+	f->fmt.pix.field = field;
 	v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
 			      &f->fmt.pix.height, 32, maxh, 0, 0);
-	f->fmt.pix.field = field;
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
@@ -778,20 +1061,16 @@
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev = fh->dev;
 	int err = vidioc_try_fmt_vid_cap (file,priv,f);
 
 	if (0 != err)
 		return err;
-	if (vb2_is_busy(&dev->vb2_vidq) || vb2_is_busy(&dev->vb2_vbiq))
-		return -EBUSY;
-	if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq))
-		return -EBUSY;
-	dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-	core->width = f->fmt.pix.width;
-	core->height = f->fmt.pix.height;
-	core->field = f->fmt.pix.field;
+	dev->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+	dev->width      = f->fmt.pix.width;
+	dev->height     = f->fmt.pix.height;
+	fh->vidq.field = f->fmt.pix.field;
 	return 0;
 }
 
@@ -825,8 +1104,8 @@
 static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *cap)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;
+	struct cx88_core  *core = dev->core;
 
 	strcpy(cap->driver, "cx8800");
 	sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
@@ -846,10 +1125,64 @@
 	return 0;
 }
 
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+	return videobuf_reqbufs(get_queue(file), p);
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	return videobuf_querybuf(get_queue(file), p);
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	return videobuf_qbuf(get_queue(file), p);
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	return videobuf_dqbuf(get_queue(file), p,
+				file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
+
+	if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+	    (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	if (unlikely(!res_get(dev, fh, get_resource(file))))
+		return -EBUSY;
+	return videobuf_streamon(get_queue(file));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
+	int               err, res;
+
+	if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+	    (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	res = get_resource(file);
+	err = videobuf_streamoff(get_queue(file));
+	if (err < 0)
+		return err;
+	res_free(dev,fh,res);
+	return 0;
+}
+
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
 
 	*tvnorm = core->tvnorm;
 	return 0;
@@ -857,10 +1190,13 @@
 
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
-	return cx88_set_tvnorm(core, tvnorms);
+	mutex_lock(&core->lock);
+	cx88_set_tvnorm(core, tvnorms);
+	mutex_unlock(&core->lock);
+
+	return 0;
 }
 
 /* only one input in this sample driver */
@@ -897,15 +1233,13 @@
 static int vidioc_enum_input (struct file *file, void *priv,
 				struct v4l2_input *i)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 	return cx88_enum_input (core,i);
 }
 
 static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
 	*i = core->input;
 	return 0;
@@ -913,24 +1247,24 @@
 
 static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
 	if (i >= 4)
 		return -EINVAL;
 	if (0 == INPUT(i).type)
 		return -EINVAL;
 
+	mutex_lock(&core->lock);
 	cx88_newstation(core);
 	cx88_video_mux(core,i);
+	mutex_unlock(&core->lock);
 	return 0;
 }
 
 static int vidioc_g_tuner (struct file *file, void *priv,
 				struct v4l2_tuner *t)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 	u32 reg;
 
 	if (unlikely(UNSET == core->board.tuner_type))
@@ -952,8 +1286,7 @@
 static int vidioc_s_tuner (struct file *file, void *priv,
 				const struct v4l2_tuner *t)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
 	if (UNSET == core->board.tuner_type)
 		return -EINVAL;
@@ -967,8 +1300,8 @@
 static int vidioc_g_frequency (struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8800_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
 
 	if (unlikely(UNSET == core->board.tuner_type))
 		return -EINVAL;
@@ -992,6 +1325,7 @@
 	if (unlikely(f->tuner != 0))
 		return -EINVAL;
 
+	mutex_lock(&core->lock);
 	cx88_newstation(core);
 	call_all(core, tuner, s_frequency, f);
 	call_all(core, tuner, g_frequency, &new_freq);
@@ -1001,6 +1335,8 @@
 	msleep (10);
 	cx88_set_tvaudio(core);
 
+	mutex_unlock(&core->lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(cx88_set_freq);
@@ -1008,8 +1344,8 @@
 static int vidioc_s_frequency (struct file *file, void *priv,
 				const struct v4l2_frequency *f)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx8800_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
 
 	return cx88_set_freq(core, f);
 }
@@ -1018,8 +1354,7 @@
 static int vidioc_g_register (struct file *file, void *fh,
 				struct v4l2_dbg_register *reg)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
 
 	/* cx2388x has a 24-bit register space */
 	reg->val = cx_read(reg->reg & 0xfffffc);
@@ -1030,8 +1365,7 @@
 static int vidioc_s_register (struct file *file, void *fh,
 				const struct v4l2_dbg_register *reg)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
 
 	cx_write(reg->reg & 0xfffffc, reg->val);
 	return 0;
@@ -1045,8 +1379,7 @@
 static int radio_g_tuner (struct file *file, void *priv,
 				struct v4l2_tuner *t)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
 	if (unlikely(t->index > 0))
 		return -EINVAL;
@@ -1060,8 +1393,7 @@
 static int radio_s_tuner (struct file *file, void *priv,
 				const struct v4l2_tuner *t)
 {
-	struct cx8800_dev *dev = video_drvdata(file);
-	struct cx88_core *core = dev->core;
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
 
 	if (0 != t->index)
 		return -EINVAL;
@@ -1072,6 +1404,32 @@
 
 /* ----------------------------------------------------------- */
 
+static void cx8800_vid_timeout(unsigned long data)
+{
+	struct cx8800_dev *dev = (struct cx8800_dev*)data;
+	struct cx88_core *core = dev->core;
+	struct cx88_dmaqueue *q = &dev->vidq;
+	struct cx88_buffer *buf;
+	unsigned long flags;
+
+	cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
+
+	cx_clear(MO_VID_DMACNTRL, 0x11);
+	cx_clear(VID_CAPTURE_CONTROL, 0x06);
+
+	spin_lock_irqsave(&dev->slock,flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
+		       buf, buf->vb.i, (unsigned long)buf->risc.dma);
+	}
+	restart_video_queue(dev,q);
+	spin_unlock_irqrestore(&dev->slock,flags);
+}
+
 static const char *cx88_vid_irqs[32] = {
 	"y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
 	"y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
@@ -1118,6 +1476,22 @@
 		cx88_wakeup(core, &dev->vbiq, count);
 		spin_unlock(&dev->slock);
 	}
+
+	/* risc2 y */
+	if (status & 0x10) {
+		dprintk(2,"stopper video\n");
+		spin_lock(&dev->slock);
+		restart_video_queue(dev,&dev->vidq);
+		spin_unlock(&dev->slock);
+	}
+
+	/* risc2 vbi */
+	if (status & 0x80) {
+		dprintk(2,"stopper vbi\n");
+		spin_lock(&dev->slock);
+		cx8800_restart_vbi_queue(dev,&dev->vbiq);
+		spin_unlock(&dev->slock);
+	}
 }
 
 static irqreturn_t cx8800_irq(int irq, void *dev_id)
@@ -1156,11 +1530,11 @@
 static const struct v4l2_file_operations video_fops =
 {
 	.owner	       = THIS_MODULE,
-	.open	       = v4l2_fh_open,
-	.release       = vb2_fop_release,
-	.read	       = vb2_fop_read,
-	.poll          = vb2_fop_poll,
-	.mmap	       = vb2_fop_mmap,
+	.open	       = video_open,
+	.release       = video_release,
+	.read	       = video_read,
+	.poll          = video_poll,
+	.mmap	       = video_mmap,
 	.unlocked_ioctl = video_ioctl2,
 };
 
@@ -1170,17 +1544,17 @@
 	.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
 	.vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
-	.vidioc_querybuf      = vb2_ioctl_querybuf,
-	.vidioc_qbuf          = vb2_ioctl_qbuf,
-	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
+	.vidioc_reqbufs       = vidioc_reqbufs,
+	.vidioc_querybuf      = vidioc_querybuf,
+	.vidioc_qbuf          = vidioc_qbuf,
+	.vidioc_dqbuf         = vidioc_dqbuf,
 	.vidioc_g_std         = vidioc_g_std,
 	.vidioc_s_std         = vidioc_s_std,
 	.vidioc_enum_input    = vidioc_enum_input,
 	.vidioc_g_input       = vidioc_g_input,
 	.vidioc_s_input       = vidioc_s_input,
-	.vidioc_streamon      = vb2_ioctl_streamon,
-	.vidioc_streamoff     = vb2_ioctl_streamoff,
+	.vidioc_streamon      = vidioc_streamon,
+	.vidioc_streamoff     = vidioc_streamoff,
 	.vidioc_g_tuner       = vidioc_g_tuner,
 	.vidioc_s_tuner       = vidioc_s_tuner,
 	.vidioc_g_frequency   = vidioc_g_frequency,
@@ -1205,17 +1579,17 @@
 	.vidioc_g_fmt_vbi_cap     = cx8800_vbi_fmt,
 	.vidioc_try_fmt_vbi_cap   = cx8800_vbi_fmt,
 	.vidioc_s_fmt_vbi_cap     = cx8800_vbi_fmt,
-	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
-	.vidioc_querybuf      = vb2_ioctl_querybuf,
-	.vidioc_qbuf          = vb2_ioctl_qbuf,
-	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
+	.vidioc_reqbufs       = vidioc_reqbufs,
+	.vidioc_querybuf      = vidioc_querybuf,
+	.vidioc_qbuf          = vidioc_qbuf,
+	.vidioc_dqbuf         = vidioc_dqbuf,
 	.vidioc_g_std         = vidioc_g_std,
 	.vidioc_s_std         = vidioc_s_std,
 	.vidioc_enum_input    = vidioc_enum_input,
 	.vidioc_g_input       = vidioc_g_input,
 	.vidioc_s_input       = vidioc_s_input,
-	.vidioc_streamon      = vb2_ioctl_streamon,
-	.vidioc_streamoff     = vb2_ioctl_streamoff,
+	.vidioc_streamon      = vidioc_streamon,
+	.vidioc_streamoff     = vidioc_streamoff,
 	.vidioc_g_tuner       = vidioc_g_tuner,
 	.vidioc_s_tuner       = vidioc_s_tuner,
 	.vidioc_g_frequency   = vidioc_g_frequency,
@@ -1236,9 +1610,9 @@
 static const struct v4l2_file_operations radio_fops =
 {
 	.owner         = THIS_MODULE,
-	.open          = radio_open,
+	.open          = video_open,
 	.poll          = v4l2_ctrl_poll,
-	.release       = v4l2_fh_release,
+	.release       = video_release,
 	.unlocked_ioctl = video_ioctl2,
 };
 
@@ -1302,7 +1676,6 @@
 {
 	struct cx8800_dev *dev;
 	struct cx88_core *core;
-	struct vb2_queue *q;
 	int err;
 	int i;
 
@@ -1337,21 +1710,28 @@
 		err = -EIO;
 		goto fail_core;
 	}
-	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
-	if (IS_ERR(dev->alloc_ctx)) {
-		err = PTR_ERR(dev->alloc_ctx);
-		goto fail_core;
-	}
-
 
 	/* initialize driver struct */
 	spin_lock_init(&dev->slock);
+	core->tvnorm = V4L2_STD_NTSC_M;
 
 	/* init video dma queues */
 	INIT_LIST_HEAD(&dev->vidq.active);
+	INIT_LIST_HEAD(&dev->vidq.queued);
+	dev->vidq.timeout.function = cx8800_vid_timeout;
+	dev->vidq.timeout.data     = (unsigned long)dev;
+	init_timer(&dev->vidq.timeout);
+	cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
+			  MO_VID_DMACNTRL,0x11,0x00);
 
 	/* init vbi dma queues */
 	INIT_LIST_HEAD(&dev->vbiq.active);
+	INIT_LIST_HEAD(&dev->vbiq.queued);
+	dev->vbiq.timeout.function = cx8800_vbi_timeout;
+	dev->vbiq.timeout.data     = (unsigned long)dev;
+	init_timer(&dev->vbiq.timeout);
+	cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
+			  MO_VID_DMACNTRL,0x88,0x00);
 
 	/* get irq */
 	err = request_irq(pci_dev->irq, cx8800_irq,
@@ -1440,10 +1820,9 @@
 	/* Sets device info at pci_dev */
 	pci_set_drvdata(pci_dev, dev);
 
-	dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-
-	/* Maintain a reference so cx88-blackbird can query the 8800 device. */
-	core->v4ldev = dev;
+	dev->width   = 320;
+	dev->height  = 240;
+	dev->fmt     = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 
 	/* initial device configuration */
 	mutex_lock(&core->lock);
@@ -1452,44 +1831,11 @@
 	v4l2_ctrl_handler_setup(&core->audio_hdl);
 	cx88_video_mux(core, 0);
 
-	q = &dev->vb2_vidq;
-	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
-	q->gfp_flags = GFP_DMA32;
-	q->min_buffers_needed = 2;
-	q->drv_priv = dev;
-	q->buf_struct_size = sizeof(struct cx88_buffer);
-	q->ops = &cx8800_video_qops;
-	q->mem_ops = &vb2_dma_sg_memops;
-	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	q->lock = &core->lock;
-
-	err = vb2_queue_init(q);
-	if (err < 0)
-		goto fail_unreg;
-
-	q = &dev->vb2_vbiq;
-	q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
-	q->gfp_flags = GFP_DMA32;
-	q->min_buffers_needed = 2;
-	q->drv_priv = dev;
-	q->buf_struct_size = sizeof(struct cx88_buffer);
-	q->ops = &cx8800_vbi_qops;
-	q->mem_ops = &vb2_dma_sg_memops;
-	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	q->lock = &core->lock;
-
-	err = vb2_queue_init(q);
-	if (err < 0)
-		goto fail_unreg;
-
 	/* register v4l devices */
 	dev->video_dev = cx88_vdev_init(core,dev->pci,
 					&cx8800_video_template,"video");
 	video_set_drvdata(dev->video_dev, dev);
 	dev->video_dev->ctrl_handler = &core->video_hdl;
-	dev->video_dev->queue = &dev->vb2_vidq;
 	err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
 				    video_nr[core->nr]);
 	if (err < 0) {
@@ -1502,7 +1848,6 @@
 
 	dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
 	video_set_drvdata(dev->vbi_dev, dev);
-	dev->vbi_dev->queue = &dev->vb2_vbiq;
 	err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
 				    vbi_nr[core->nr]);
 	if (err < 0) {
@@ -1530,7 +1875,7 @@
 	}
 
 	/* start tvaudio thread */
-	if (core->board.tuner_type != UNSET) {
+	if (core->board.tuner_type != TUNER_ABSENT) {
 		core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
 		if (IS_ERR(core->kthread)) {
 			err = PTR_ERR(core->kthread);
@@ -1547,8 +1892,6 @@
 	free_irq(pci_dev->irq, dev);
 	mutex_unlock(&core->lock);
 fail_core:
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
-	core->v4ldev = NULL;
 	cx88_core_put(core,dev->pci);
 fail_free:
 	kfree(dev);
@@ -1570,18 +1913,16 @@
 		cx88_ir_stop(core);
 
 	cx88_shutdown(core); /* FIXME */
+	pci_disable_device(pci_dev);
 
 	/* unregister stuff */
 
 	free_irq(pci_dev->irq, dev);
 	cx8800_unregister_video(dev);
-	pci_disable_device(pci_dev);
-
-	core->v4ldev = NULL;
 
 	/* free memory */
+	btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
 	cx88_core_put(core,dev->pci);
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 	kfree(dev);
 }
 
@@ -1597,10 +1938,12 @@
 	if (!list_empty(&dev->vidq.active)) {
 		printk("%s/0: suspend video\n", core->name);
 		stop_video_dma(dev);
+		del_timer(&dev->vidq.timeout);
 	}
 	if (!list_empty(&dev->vbiq.active)) {
 		printk("%s/0: suspend vbi\n", core->name);
 		cx8800_stop_vbi_dma(dev);
+		del_timer(&dev->vbiq.timeout);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index f3eccd7..d744348 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -29,18 +29,19 @@
 #include <media/v4l2-fh.h>
 #include <media/tuner.h>
 #include <media/tveeprom.h>
-#include <media/videobuf2-dma-sg.h>
+#include <media/videobuf-dma-sg.h>
 #include <media/cx2341x.h>
-#include <media/videobuf2-dvb.h>
+#include <media/videobuf-dvb.h>
 #include <media/ir-kbd-i2c.h>
 #include <media/wm8775.h>
 
+#include "btcx-risc.h"
 #include "cx88-reg.h"
 #include "tuner-xc2028.h"
 
 #include <linux/mutex.h>
 
-#define CX88_VERSION "1.0.0"
+#define CX88_VERSION "0.0.9"
 
 #define UNSET (-1U)
 
@@ -61,8 +62,7 @@
 #define FORMAT_FLAGS_PACKED       0x01
 #define FORMAT_FLAGS_PLANAR       0x02
 
-#define VBI_LINE_PAL_COUNT              18
-#define VBI_LINE_NTSC_COUNT             12
+#define VBI_LINE_COUNT              17
 #define VBI_LINE_LENGTH           2048
 
 #define AUD_RDS_LINES		     4
@@ -95,13 +95,13 @@
 
 static inline unsigned int norm_maxw(v4l2_std_id norm)
 {
-	return 720;
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
 }
 
 
 static inline unsigned int norm_maxh(v4l2_std_id norm)
 {
-	return (norm & V4L2_STD_525_60) ? 480 : 576;
+	return (norm & V4L2_STD_625_50) ? 576 : 480;
 }
 
 /* ----------------------------------------------------------- */
@@ -311,33 +311,26 @@
 
 #define BUFFER_TIMEOUT     msecs_to_jiffies(2000)
 
-struct cx88_riscmem {
-	unsigned int   size;
-	__le32         *cpu;
-	__le32         *jmp;
-	dma_addr_t     dma;
-};
-
 /* buffer for one video frame */
 struct cx88_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb;
-	struct list_head       list;
+	struct videobuf_buffer vb;
 
 	/* cx88 specific */
 	unsigned int           bpl;
-	struct cx88_riscmem    risc;
+	struct btcx_riscmem    risc;
+	const struct cx8800_fmt *fmt;
 	u32                    count;
 };
 
 struct cx88_dmaqueue {
 	struct list_head       active;
+	struct list_head       queued;
+	struct timer_list      timeout;
+	struct btcx_riscmem    stopper;
 	u32                    count;
 };
 
-struct cx8800_dev;
-struct cx8802_dev;
-
 struct cx88_core {
 	struct list_head           devlist;
 	atomic_t                   refcount;
@@ -383,8 +376,6 @@
 	/* state info */
 	struct task_struct         *kthread;
 	v4l2_std_id                tvnorm;
-	unsigned		   width, height;
-	unsigned		   field;
 	enum cx88_tvaudio          tvaudio;
 	u32                        audiomode_manual;
 	u32                        audiomode_current;
@@ -404,14 +395,11 @@
 	struct mutex               lock;
 	/* various v4l controls */
 	u32                        freq;
+	int                        users;
+	int                        mpeg_users;
 
-	/*
-	 * cx88-video needs to access cx8802 for hybrid tuner pll access and
-	 * for vb2_is_busy() checks.
-	 */
+	/* cx88-video needs to access cx8802 for hybrid tuner pll access. */
 	struct cx8802_dev          *dvbdev;
-	/* cx88-blackbird needs to access cx8800 for vb2_is_busy() checks */
-	struct cx8800_dev          *v4ldev;
 	enum cx88_board_type       active_type_id;
 	int			   active_ref;
 	int			   active_fe_id;
@@ -465,9 +453,24 @@
 		val;								\
 	})
 
+struct cx8800_dev;
+struct cx8802_dev;
+
 /* ----------------------------------------------------------- */
 /* function 0: video stuff                                     */
 
+struct cx8800_fh {
+	struct v4l2_fh		   fh;
+	struct cx8800_dev          *dev;
+	unsigned int               resources;
+
+	/* video capture */
+	struct videobuf_queue      vidq;
+
+	/* vbi capture */
+	struct videobuf_queue      vbiq;
+};
+
 struct cx8800_suspend_state {
 	int                        disabled;
 };
@@ -485,15 +488,13 @@
 	/* pci i/o */
 	struct pci_dev             *pci;
 	unsigned char              pci_rev,pci_lat;
-	void			   *alloc_ctx;
 
 	const struct cx8800_fmt    *fmt;
+	unsigned int               width, height;
 
 	/* capture queues */
 	struct cx88_dmaqueue       vidq;
-	struct vb2_queue           vb2_vidq;
 	struct cx88_dmaqueue       vbiq;
-	struct vb2_queue           vb2_vbiq;
 
 	/* various v4l controls */
 
@@ -509,6 +510,12 @@
 /* ----------------------------------------------------------- */
 /* function 2: mpeg stuff                                      */
 
+struct cx8802_fh {
+	struct v4l2_fh		   fh;
+	struct cx8802_dev          *dev;
+	struct videobuf_queue      mpegq;
+};
+
 struct cx8802_suspend_state {
 	int                        disabled;
 };
@@ -549,11 +556,9 @@
 	/* pci i/o */
 	struct pci_dev             *pci;
 	unsigned char              pci_rev,pci_lat;
-	void			   *alloc_ctx;
 
 	/* dma queues */
 	struct cx88_dmaqueue       mpegq;
-	struct vb2_queue           vb2_mpegq;
 	u32                        ts_packet_size;
 	u32                        ts_packet_count;
 
@@ -565,6 +570,9 @@
 #if IS_ENABLED(CPTCFG_VIDEO_CX88_BLACKBIRD)
 	struct video_device        *mpeg_dev;
 	u32                        mailbox;
+	int                        width;
+	int                        height;
+	unsigned char              mpeg_active; /* nonzero if mpeg encoder is active */
 
 	/* mpeg params */
 	struct cx2341x_handler     cxhdl;
@@ -572,7 +580,7 @@
 
 #if IS_ENABLED(CPTCFG_VIDEO_CX88_DVB)
 	/* for dvb only */
-	struct vb2_dvb_frontends frontends;
+	struct videobuf_dvb_frontends frontends;
 #endif
 
 #if IS_ENABLED(CPTCFG_VIDEO_CX88_VP3054)
@@ -626,17 +634,22 @@
 extern int cx88_reset(struct cx88_core *core);
 
 extern int
-cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
+cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 		 struct scatterlist *sglist,
 		 unsigned int top_offset, unsigned int bottom_offset,
 		 unsigned int bpl, unsigned int padding, unsigned int lines);
 extern int
-cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
+cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 		     struct scatterlist *sglist, unsigned int bpl,
 		     unsigned int lines, unsigned int lpi);
+extern int
+cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+		  u32 reg, u32 mask, u32 value);
+extern void
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
 
 extern void cx88_risc_disasm(struct cx88_core *core,
-			     struct cx88_riscmem *risc);
+			     struct btcx_riscmem *risc);
 extern int cx88_sram_channel_setup(struct cx88_core *core,
 				   const struct sram_channel *ch,
 				   unsigned int bpl, u32 risc);
@@ -651,7 +664,7 @@
 					   struct pci_dev *pci,
 					   const struct video_device *template_,
 					   const char *type);
-extern struct cx88_core *cx88_core_get(struct pci_dev *pci);
+extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
 extern void cx88_core_put(struct cx88_core *core,
 			  struct pci_dev *pci);
 
@@ -671,10 +684,12 @@
 			 struct cx88_dmaqueue *q,
 			 struct cx88_buffer   *buf);
 */
-void cx8800_stop_vbi_dma(struct cx8800_dev *dev);
-int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q);
+int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
+int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
+			     struct cx88_dmaqueue *q);
+void cx8800_vbi_timeout(unsigned long data);
 
-extern const struct vb2_ops cx8800_vbi_qops;
+extern const struct videobuf_queue_ops cx8800_vbi_qops;
 
 /* ----------------------------------------------------------- */
 /* cx88-i2c.c                                                  */
@@ -724,17 +739,14 @@
 /* ----------------------------------------------------------- */
 /* cx88-mpeg.c                                                 */
 
-int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
-			struct cx88_buffer *buf);
+int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
+			struct cx88_buffer *buf, enum v4l2_field field);
 void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
 void cx8802_cancel_buffers(struct cx8802_dev *dev);
-int cx8802_start_dma(struct cx8802_dev    *dev,
-			    struct cx88_dmaqueue *q,
-			    struct cx88_buffer   *buf);
 
 /* ----------------------------------------------------------- */
 /* cx88-video.c*/
-int cx88_enum_input(struct cx88_core *core, struct v4l2_input *i);
+int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i);
 int cx88_set_freq(struct cx88_core  *core, const struct v4l2_frequency *f);
 int cx88_video_mux(struct cx88_core *core, unsigned int input);
 void cx88_querycap(struct file *file, struct cx88_core *core,
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index 9c00ff1..ad8dfdd 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1118,7 +1118,8 @@
 			dvb_input_detach(port->input[1]);
 			break;
 		case DDB_PORT_CI:
-			dvb_unregister_device(port->output->dev);
+			if (port->output->dev)
+				dvb_unregister_device(port->output->dev);
 			if (port->en) {
 				ddb_input_stop(port->input[0]);
 				ddb_output_stop(port->output);
diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c
index ccf548c..2b0ab26 100644
--- a/drivers/media/pci/ivtv/ivtv-controls.c
+++ b/drivers/media/pci/ivtv/ivtv-controls.c
@@ -69,7 +69,7 @@
 	/* fix videodecoder resolution */
 	fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
 	fmt.height = cxhdl->height;
-	fmt.code = MEDIA_BUS_FMT_FIXED;
+	fmt.code = V4L2_MBUS_FMT_FIXED;
 	v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
 	return 0;
 }
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
index 9c5f710..b9744b5 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -595,7 +595,7 @@
 		fmt->fmt.pix.width /= 2;
 	mbus_fmt.width = fmt->fmt.pix.width;
 	mbus_fmt.height = h;
-	mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
+	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
 	v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
 	return ivtv_g_fmt_vid_cap(file, fh, fmt);
 }
diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c
index bee2329..7338cb2 100644
--- a/drivers/media/pci/ivtv/ivtv-udma.c
+++ b/drivers/media/pci/ivtv/ivtv-udma.c
@@ -76,7 +76,7 @@
 	int i;
 	struct scatterlist *sg;
 
-	for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg = sg_next(sg)) {
+	for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg++) {
 		dma->SGarray[i].size = cpu_to_le32(sg_dma_len(sg));
 		dma->SGarray[i].src = cpu_to_le32(sg_dma_address(sg));
 		dma->SGarray[i].dst = cpu_to_le32(buffer_offset);
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index 9d9f90c..aeae547 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1031,6 +1031,9 @@
 	strcpy(cap->card, "meye");
 	sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
 
+	cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
+		       MEYE_DRIVER_MINORVERSION;
+
 	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
 			    V4L2_CAP_STREAMING;
 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c
index acc35b4..db887b0 100644
--- a/drivers/media/pci/pt1/pt1.c
+++ b/drivers/media/pci/pt1/pt1.c
@@ -109,6 +109,9 @@
 	int sleep;
 };
 
+#define pt1_printk(level, pt1, format, arg...)	\
+	dev_printk(level, &(pt1)->pdev->dev, format, ##arg)
+
 static void pt1_write_reg(struct pt1 *pt1, int reg, u32 data)
 {
 	writel(data, pt1->regs + reg * 4);
@@ -151,7 +154,7 @@
 			return 0;
 		pt1_write_reg(pt1, 0, 0x00000008);
 	}
-	dev_err(&pt1->pdev->dev, "could not sync\n");
+	pt1_printk(KERN_ERR, pt1, "could not sync\n");
 	return -EIO;
 }
 
@@ -176,7 +179,7 @@
 			return 0;
 		schedule_timeout_uninterruptible((HZ + 999) / 1000);
 	}
-	dev_err(&pt1->pdev->dev, "could not unlock\n");
+	pt1_printk(KERN_ERR, pt1, "could not unlock\n");
 	return -EIO;
 }
 
@@ -190,7 +193,7 @@
 			return 0;
 		schedule_timeout_uninterruptible((HZ + 999) / 1000);
 	}
-	dev_err(&pt1->pdev->dev, "could not reset PCI\n");
+	pt1_printk(KERN_ERR, pt1, "could not reset PCI\n");
 	return -EIO;
 }
 
@@ -204,7 +207,7 @@
 			return 0;
 		schedule_timeout_uninterruptible((HZ + 999) / 1000);
 	}
-	dev_err(&pt1->pdev->dev, "could not reset RAM\n");
+	pt1_printk(KERN_ERR, pt1, "could not reset RAM\n");
 	return -EIO;
 }
 
@@ -221,7 +224,7 @@
 		}
 		schedule_timeout_uninterruptible((HZ + 999) / 1000);
 	}
-	dev_err(&pt1->pdev->dev, "could not enable RAM\n");
+	pt1_printk(KERN_ERR, pt1, "could not enable RAM\n");
 	return -EIO;
 }
 
diff --git a/drivers/media/pci/pt3/Kconfig b/drivers/media/pci/pt3/Kconfig
index 6a1671a..f62f306 100644
--- a/drivers/media/pci/pt3/Kconfig
+++ b/drivers/media/pci/pt3/Kconfig
@@ -1,5 +1,5 @@
 config DVB_PT3
-	depends on !KERNEL_3_3
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Earthsoft PT3 cards"
 	depends on m
 	depends on DVB_CORE && PCI && I2C
diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c
index 7a37e8f..1fdeac1 100644
--- a/drivers/media/pci/pt3/pt3.c
+++ b/drivers/media/pci/pt3/pt3.c
@@ -255,7 +255,7 @@
 	pt3_i2c_reset(pt3);
 	ret = pt3_init_all_demods(pt3);
 	if (ret < 0) {
-		dev_warn(&pt3->pdev->dev, "Failed to init demod chips\n");
+		dev_warn(&pt3->pdev->dev, "Failed to init demod chips.");
 		return ret;
 	}
 
@@ -271,7 +271,7 @@
 					      init0_ter, ARRAY_SIZE(init0_ter));
 		if (ret < 0) {
 			dev_warn(&pt3->pdev->dev,
-				 "demod[%d] failed in init sequence0\n", i);
+				 "demod[%d] faild in init sequence0.", i);
 			return ret;
 		}
 		ret = fe->ops.init(fe);
@@ -282,7 +282,7 @@
 	usleep_range(2000, 4000);
 	ret = pt3_set_tuner_power(pt3, true, false);
 	if (ret < 0) {
-		dev_warn(&pt3->pdev->dev, "Failed to control tuner module\n");
+		dev_warn(&pt3->pdev->dev, "Failed to control tuner module.");
 		return ret;
 	}
 
@@ -297,7 +297,7 @@
 						cfg_ter, ARRAY_SIZE(cfg_ter));
 		if (ret < 0) {
 			dev_warn(&pt3->pdev->dev,
-				 "demod[%d] failed in init sequence1\n", i);
+				 "demod[%d] faild in init sequence1.", i);
 			return ret;
 		}
 	}
@@ -311,19 +311,19 @@
 		ret = fe->ops.tuner_ops.init(fe);
 		if (ret < 0) {
 			dev_warn(&pt3->pdev->dev,
-				 "Failed to init SAT-tuner[%d]\n", i);
+				 "Failed to init SAT-tuner[%d].", i);
 			return ret;
 		}
 	}
 	ret = pt3_init_all_mxl301rf(pt3);
 	if (ret < 0) {
-		dev_warn(&pt3->pdev->dev, "Failed to init TERR-tuners\n");
+		dev_warn(&pt3->pdev->dev, "Failed to init TERR-tuners.");
 		return ret;
 	}
 
 	ret = pt3_set_tuner_power(pt3, true, true);
 	if (ret < 0) {
-		dev_warn(&pt3->pdev->dev, "Failed to control tuner module\n");
+		dev_warn(&pt3->pdev->dev, "Failed to control tuner module.");
 		return ret;
 	}
 
@@ -344,7 +344,7 @@
 		}
 		if (ret < 0) {
 			dev_warn(&pt3->pdev->dev,
-				 "Failed in initial tuning of tuner[%d]\n", i);
+				 "Failed in initial tuning of tuner[%d].", i);
 			return ret;
 		}
 	}
@@ -366,7 +366,7 @@
 			fe->ops.set_lna = &pt3_set_lna;
 	}
 	if (i < PT3_NUM_FE) {
-		dev_warn(&pt3->pdev->dev, "FE[%d] failed to standby\n", i);
+		dev_warn(&pt3->pdev->dev, "FE[%d] failed to standby.", i);
 		return ret;
 	}
 	return 0;
@@ -453,8 +453,8 @@
 	pt3_init_dmabuf(adap);
 	adap->num_discard = PT3_INITIAL_BUF_DROPS;
 
-	dev_dbg(adap->dvb_adap.device, "PT3: [%s] started\n",
-		adap->thread->comm);
+	dev_dbg(adap->dvb_adap.device,
+		"PT3: [%s] started.\n", adap->thread->comm);
 	set_freezable();
 	while (!kthread_freezable_should_stop(&was_frozen)) {
 		if (was_frozen)
@@ -468,8 +468,8 @@
 					PT3_FETCH_DELAY_DELTA * NSEC_PER_MSEC,
 					HRTIMER_MODE_REL);
 	}
-	dev_dbg(adap->dvb_adap.device, "PT3: [%s] exited\n",
-		adap->thread->comm);
+	dev_dbg(adap->dvb_adap.device,
+		"PT3: [%s] exited.\n", adap->thread->comm);
 	adap->thread = NULL;
 	return 0;
 }
@@ -485,8 +485,8 @@
 		int ret = PTR_ERR(thread);
 
 		dev_warn(adap->dvb_adap.device,
-			 "PT3 (adap:%d, dmx:%d): failed to start kthread\n",
-			 adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
+			"PT3 (adap:%d, dmx:%d): failed to start kthread.\n",
+			adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
 		return ret;
 	}
 	adap->thread = thread;
@@ -501,8 +501,8 @@
 	ret = pt3_stop_dma(adap);
 	if (ret)
 		dev_warn(adap->dvb_adap.device,
-			 "PT3: failed to stop streaming of adap:%d/FE:%d\n",
-			 adap->dvb_adap.num, adap->fe->id);
+			"PT3: failed to stop streaming of adap:%d/FE:%d\n",
+			adap->dvb_adap.num, adap->fe->id);
 
 	/* kill the fetching thread */
 	ret = kthread_stop(adap->thread);
@@ -522,8 +522,8 @@
 		return 0;
 	if (adap->num_feeds != 1) {
 		dev_warn(adap->dvb_adap.device,
-			 "%s: unmatched start/stop_feed in adap:%i/dmx:%i\n",
-			 __func__, adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
+			"%s: unmatched start/stop_feed in adap:%i/dmx:%i.\n",
+			__func__, adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
 		adap->num_feeds = 1;
 	}
 
@@ -553,9 +553,10 @@
 	struct dvb_adapter *da;
 
 	adap = kzalloc(sizeof(*adap), GFP_KERNEL);
-	if (!adap)
+	if (!adap) {
+		dev_err(&pt3->pdev->dev, "failed to alloc mem for adapter.\n");
 		return -ENOMEM;
-
+	}
 	pt3->adaps[index] = adap;
 	adap->adap_idx = index;
 
@@ -564,7 +565,7 @@
 				THIS_MODULE, &pt3->pdev->dev, adapter_nr);
 		if (ret < 0) {
 			dev_err(&pt3->pdev->dev,
-				"failed to register adapter dev\n");
+				"failed to register adapter dev.\n");
 			goto err_mem;
 		}
 		da = &adap->dvb_adap;
@@ -580,7 +581,7 @@
 	adap->demux.stop_feed = pt3_stop_feed;
 	ret = dvb_dmx_init(&adap->demux);
 	if (ret < 0) {
-		dev_err(&pt3->pdev->dev, "failed to init dmx dev\n");
+		dev_err(&pt3->pdev->dev, "failed to init dmx dev.\n");
 		goto err_adap;
 	}
 
@@ -588,13 +589,13 @@
 	adap->dmxdev.demux = &adap->demux.dmx;
 	ret = dvb_dmxdev_init(&adap->dmxdev, da);
 	if (ret < 0) {
-		dev_err(&pt3->pdev->dev, "failed to init dmxdev\n");
+		dev_err(&pt3->pdev->dev, "failed to init dmxdev.\n");
 		goto err_demux;
 	}
 
 	ret = pt3_alloc_dmabuf(adap);
 	if (ret) {
-		dev_err(&pt3->pdev->dev, "failed to alloc DMA buffers\n");
+		dev_err(&pt3->pdev->dev, "failed to alloc DMA buffers.\n");
 		goto err_dmabuf;
 	}
 
@@ -694,7 +695,7 @@
 		dvb_frontend_resume(adap->fe);
 		ret = pt3_alloc_dmabuf(adap);
 		if (ret) {
-			dev_err(&pt3->pdev->dev, "failed to alloc DMA bufs\n");
+			dev_err(&pt3->pdev->dev, "failed to alloc DMA bufs.\n");
 			continue;
 		}
 		if (adap->num_feeds > 0)
@@ -752,14 +753,15 @@
 		if (ret == 0)
 			dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 		else {
-			dev_err(&pdev->dev, "Failed to set DMA mask\n");
+			dev_err(&pdev->dev, "Failed to set DMA mask.\n");
 			goto err_release_regions;
 		}
-		dev_info(&pdev->dev, "Use 32bit DMA\n");
+		dev_info(&pdev->dev, "Use 32bit DMA.\n");
 	}
 
 	pt3 = kzalloc(sizeof(*pt3), GFP_KERNEL);
 	if (!pt3) {
+		dev_err(&pdev->dev, "Failed to alloc mem for this dev.\n");
 		ret = -ENOMEM;
 		goto err_release_regions;
 	}
@@ -769,15 +771,15 @@
 	pt3->regs[0] = pci_ioremap_bar(pdev, 0);
 	pt3->regs[1] = pci_ioremap_bar(pdev, 2);
 	if (pt3->regs[0] == NULL || pt3->regs[1] == NULL) {
-		dev_err(&pdev->dev, "Failed to ioremap\n");
+		dev_err(&pdev->dev, "Failed to ioremap.\n");
 		ret = -ENOMEM;
 		goto err_kfree;
 	}
 
 	ver = ioread32(pt3->regs[0] + REG_VERSION);
 	if ((ver >> 16) != 0x0301) {
-		dev_warn(&pdev->dev, "PT%d, I/F-ver.:%d not supported\n",
-			 ver >> 24, (ver & 0x00ff0000) >> 16);
+		dev_warn(&pdev->dev, "PT%d, I/F-ver.:%d not supported",
+			ver >> 24, (ver & 0x00ff0000) >> 16);
 		ret = -ENODEV;
 		goto err_iounmap;
 	}
@@ -786,6 +788,7 @@
 
 	pt3->i2c_buf = kmalloc(sizeof(*pt3->i2c_buf), GFP_KERNEL);
 	if (pt3->i2c_buf == NULL) {
+		dev_err(&pdev->dev, "Failed to alloc mem for i2c.\n");
 		ret = -ENOMEM;
 		goto err_iounmap;
 	}
@@ -798,7 +801,7 @@
 	i2c_set_adapdata(i2c, pt3);
 	ret = i2c_add_adapter(i2c);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to add i2c adapter\n");
+		dev_err(&pdev->dev, "Failed to add i2c adapter.\n");
 		goto err_i2cbuf;
 	}
 
@@ -812,20 +815,20 @@
 			break;
 	}
 	if (i < PT3_NUM_FE) {
-		dev_err(&pdev->dev, "Failed to create FE%d\n", i);
+		dev_err(&pdev->dev, "Failed to create FE%d.\n", i);
 		goto err_cleanup_adapters;
 	}
 
 	ret = pt3_fe_init(pt3);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to init frontends\n");
+		dev_err(&pdev->dev, "Failed to init frontends.\n");
 		i = PT3_NUM_FE - 1;
 		goto err_cleanup_adapters;
 	}
 
 	dev_info(&pdev->dev,
-		 "successfully init'ed PT%d (fw:0x%02x, I/F:0x%02x)\n",
-		 ver >> 24, (ver >> 8) & 0xff, (ver >> 16) & 0xff);
+		"successfully init'ed PT%d (fw:0x%02x, I/F:0x%02x).\n",
+		ver >> 24, (ver >> 8) & 0xff, (ver >> 16) & 0xff);
 	return 0;
 
 err_cleanup_adapters:
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index ac3cd74..4056989 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -173,7 +173,9 @@
 		dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
 			dev->dmasound.bufsize, dev->dmasound.blocks);
 		spin_unlock(&dev->slock);
-		snd_pcm_stop_xrun(dev->dmasound.substream);
+		snd_pcm_stream_lock(dev->dmasound.substream);
+		snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
+		snd_pcm_stream_unlock(dev->dmasound.substream);
 		return;
 	}
 
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index a349e96..236ed72 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -1001,18 +1001,13 @@
 	saa7134_board_init1(dev);
 	saa7134_hwinit1(dev);
 
-	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
-	if (IS_ERR(dev->alloc_ctx)) {
-		err = PTR_ERR(dev->alloc_ctx);
-		goto fail3;
-	}
 	/* get irq */
 	err = request_irq(pci_dev->irq, saa7134_irq,
 			  IRQF_SHARED, dev->name, dev);
 	if (err < 0) {
 		printk(KERN_ERR "%s: can't get IRQ %d\n",
 		       dev->name,pci_dev->irq);
-		goto fail4;
+		goto fail3;
 	}
 
 	/* wait a bit, register i2c bus */
@@ -1070,7 +1065,7 @@
 	if (err < 0) {
 		printk(KERN_INFO "%s: can't register video device\n",
 		       dev->name);
-		goto fail5;
+		goto fail4;
 	}
 	printk(KERN_INFO "%s: registered device %s [v4l2]\n",
 	       dev->name, video_device_node_name(dev->video_dev));
@@ -1083,7 +1078,7 @@
 	err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
 				    vbi_nr[dev->nr]);
 	if (err < 0)
-		goto fail5;
+		goto fail4;
 	printk(KERN_INFO "%s: registered device %s\n",
 	       dev->name, video_device_node_name(dev->vbi_dev));
 
@@ -1094,7 +1089,7 @@
 		err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
 					    radio_nr[dev->nr]);
 		if (err < 0)
-			goto fail5;
+			goto fail4;
 		printk(KERN_INFO "%s: registered device %s\n",
 		       dev->name, video_device_node_name(dev->radio_dev));
 	}
@@ -1108,12 +1103,10 @@
 	request_submodules(dev);
 	return 0;
 
- fail5:
+ fail4:
 	saa7134_unregister_video(dev);
 	saa7134_i2c_unregister(dev);
 	free_irq(pci_dev->irq, dev);
- fail4:
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
  fail3:
 	saa7134_hwfini(dev);
 	iounmap(dev->lmmio);
@@ -1180,7 +1173,6 @@
 
 	/* release resources */
 	free_irq(pci_dev->irq, dev);
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 	iounmap(dev->lmmio);
 	release_mem_region(pci_resource_start(pci_dev,0),
 			   pci_resource_len(pci_dev,0));
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 594dc3a..e4ea85f 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -96,6 +96,7 @@
 	.queue_setup	= saa7134_ts_queue_setup,
 	.buf_init	= saa7134_ts_buffer_init,
 	.buf_prepare	= saa7134_ts_buffer_prepare,
+	.buf_finish	= saa7134_ts_buffer_finish,
 	.buf_queue	= saa7134_vb2_buffer_queue,
 	.wait_prepare	= vb2_ops_wait_prepare,
 	.wait_finish	= vb2_ops_wait_finish,
@@ -139,7 +140,7 @@
 	struct saa7134_dev *dev = video_drvdata(file);
 	struct v4l2_mbus_framefmt mbus_fmt;
 
-	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
 	saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
 	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 
@@ -156,7 +157,7 @@
 	struct saa7134_dev *dev = video_drvdata(file);
 	struct v4l2_mbus_framefmt mbus_fmt;
 
-	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
 	saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt);
 	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 2709b83..bd25323 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -94,6 +94,7 @@
 	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
 	unsigned int lines, llength, size;
+	int ret;
 
 	dprintk("buffer_prepare [%p]\n", buf);
 
@@ -107,11 +108,25 @@
 	vb2_set_plane_payload(vb2, 0, size);
 	vb2->v4l2_buf.field = dev->field;
 
+	ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+	if (!ret)
+		return -EIO;
 	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 				    saa7134_buffer_startpage(buf));
 }
 EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
 
+void saa7134_ts_buffer_finish(struct vb2_buffer *vb2)
+{
+	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+	struct saa7134_dev *dev = dmaq->dev;
+	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+
+	dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+}
+EXPORT_SYMBOL_GPL(saa7134_ts_buffer_finish);
+
 int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
@@ -127,7 +142,6 @@
 		*nbuffers = 3;
 	*nplanes = 1;
 	sizes[0] = size;
-	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(saa7134_ts_queue_setup);
@@ -173,6 +187,7 @@
 	.queue_setup	= saa7134_ts_queue_setup,
 	.buf_init	= saa7134_ts_buffer_init,
 	.buf_prepare	= saa7134_ts_buffer_prepare,
+	.buf_finish	= saa7134_ts_buffer_finish,
 	.buf_queue	= saa7134_vb2_buffer_queue,
 	.wait_prepare	= vb2_ops_wait_prepare,
 	.wait_finish	= vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index 5306e54..4f0b101 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -120,6 +120,7 @@
 	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
 	unsigned int size;
+	int ret;
 
 	if (dma->sgl->offset) {
 		pr_err("The buffer is not page-aligned\n");
@@ -131,6 +132,9 @@
 
 	vb2_set_plane_payload(vb2, 0, size);
 
+	ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+	if (!ret)
+		return -EIO;
 	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 				    saa7134_buffer_startpage(buf));
 }
@@ -152,7 +156,6 @@
 	*nbuffers = saa7134_buffer_count(size, *nbuffers);
 	*nplanes = 1;
 	sizes[0] = size;
-	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 
@@ -166,10 +169,21 @@
 	return 0;
 }
 
+static void buffer_finish(struct vb2_buffer *vb2)
+{
+	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+	struct saa7134_dev *dev = dmaq->dev;
+	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+
+	dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+}
+
 struct vb2_ops saa7134_vbi_qops = {
 	.queue_setup	= queue_setup,
 	.buf_init	= buffer_init,
 	.buf_prepare	= buffer_prepare,
+	.buf_finish	= buffer_finish,
 	.buf_queue	= saa7134_vb2_buffer_queue,
 	.wait_prepare	= vb2_ops_wait_prepare,
 	.wait_finish	= vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 87ca35a..b0f279c 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -883,6 +883,7 @@
 	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
 	unsigned int size;
+	int ret;
 
 	if (dma->sgl->offset) {
 		pr_err("The buffer is not page-aligned\n");
@@ -895,10 +896,23 @@
 	vb2_set_plane_payload(vb2, 0, size);
 	vb2->v4l2_buf.field = dev->field;
 
+	ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+	if (!ret)
+		return -EIO;
 	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 				    saa7134_buffer_startpage(buf));
 }
 
+static void buffer_finish(struct vb2_buffer *vb2)
+{
+	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+	struct saa7134_dev *dev = dmaq->dev;
+	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+
+	dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+}
+
 static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
@@ -918,7 +932,6 @@
 	*nbuffers = saa7134_buffer_count(size, *nbuffers);
 	*nplanes = 1;
 	sizes[0] = size;
-	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 
@@ -991,6 +1004,7 @@
 	.queue_setup	= queue_setup,
 	.buf_init	= buffer_init,
 	.buf_prepare	= buffer_prepare,
+	.buf_finish	= buffer_finish,
 	.buf_queue	= saa7134_vb2_buffer_queue,
 	.wait_prepare	= vb2_ops_wait_prepare,
 	.wait_finish	= vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index d244ab1..5e9cc30 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -588,7 +588,6 @@
 
 
 	/* video+ts+vbi capture */
-	void			   *alloc_ctx;
 	struct saa7134_dmaqueue    video_q;
 	struct vb2_queue           video_vbq;
 	struct saa7134_dmaqueue    vbi_q;
@@ -815,6 +814,7 @@
 
 int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
 int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
+void saa7134_ts_buffer_finish(struct vb2_buffer *vb2);
 int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[]);
diff --git a/drivers/media/pci/saa7164/saa7164-buffer.c b/drivers/media/pci/saa7164/saa7164-buffer.c
index 9bd1f73..66696fa 100644
--- a/drivers/media/pci/saa7164/saa7164-buffer.c
+++ b/drivers/media/pci/saa7164/saa7164-buffer.c
@@ -130,9 +130,9 @@
 		goto fail2;
 
 	/* init the buffers to a known pattern, easier during debugging */
-	memset(buf->cpu, 0xff, buf->pci_size);
+	memset_io(buf->cpu, 0xff, buf->pci_size);
 	buf->crc = crc32(0, buf->cpu, buf->actual_size);
-	memset(buf->pt_cpu, 0xff, buf->pt_size);
+	memset_io(buf->pt_cpu, 0xff, buf->pt_size);
 
 	dprintk(DBGLVL_BUF, "%s()   allocated buffer @ 0x%p (%d pageptrs)\n",
 		__func__, buf, params->numpagetables);
diff --git a/drivers/media/pci/saa7164/saa7164-bus.c b/drivers/media/pci/saa7164/saa7164-bus.c
index 6c73f5b..5f6f309 100644
--- a/drivers/media/pci/saa7164/saa7164-bus.c
+++ b/drivers/media/pci/saa7164/saa7164-bus.c
@@ -33,12 +33,12 @@
 	b->Type			= TYPE_BUS_PCIe;
 	b->m_wMaxReqSize	= SAA_DEVICE_MAXREQUESTSIZE;
 
-	b->m_pdwSetRing		= (u8 __iomem *)(dev->bmmio +
+	b->m_pdwSetRing		= (u8 *)(dev->bmmio +
 		((u32)dev->busdesc.CommandRing));
 
 	b->m_dwSizeSetRing	= SAA_DEVICE_BUFFERBLOCKSIZE;
 
-	b->m_pdwGetRing		= (u8 __iomem *)(dev->bmmio +
+	b->m_pdwGetRing		= (u8 *)(dev->bmmio +
 		((u32)dev->busdesc.ResponseRing));
 
 	b->m_dwSizeGetRing	= SAA_DEVICE_BUFFERBLOCKSIZE;
@@ -138,7 +138,6 @@
 	u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp;
 	u32 new_swp, space_rem;
 	int ret = SAA_ERR_BAD_PARAMETER;
-	u16 size;
 
 	if (!msg) {
 		printk(KERN_ERR "%s() !msg\n", __func__);
@@ -149,6 +148,10 @@
 
 	saa7164_bus_verify(dev);
 
+	msg->size = cpu_to_le16(msg->size);
+	msg->command = cpu_to_le32(msg->command);
+	msg->controlselector = cpu_to_le16(msg->controlselector);
+
 	if (msg->size > dev->bus.m_wMaxReqSize) {
 		printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n",
 			__func__);
@@ -166,8 +169,8 @@
 	bytes_to_write = sizeof(*msg) + msg->size;
 	free_write_space = 0;
 	timeout = SAA_BUS_TIMEOUT;
-	curr_srp = saa7164_readl(bus->m_dwSetReadPos);
-	curr_swp = saa7164_readl(bus->m_dwSetWritePos);
+	curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
+	curr_swp = le32_to_cpu(saa7164_readl(bus->m_dwSetWritePos));
 
 	/* Deal with ring wrapping issues */
 	if (curr_srp > curr_swp)
@@ -200,7 +203,7 @@
 		mdelay(1);
 
 		/* Check the space usage again */
-		curr_srp = saa7164_readl(bus->m_dwSetReadPos);
+		curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
 
 		/* Deal with ring wrapping issues */
 		if (curr_srp > curr_swp)
@@ -220,16 +223,6 @@
 	dprintk(DBGLVL_BUS, "%s() bus->m_dwSizeSetRing = %x\n", __func__,
 		bus->m_dwSizeSetRing);
 
-	/*
-	 * Make a copy of msg->size before it is converted to le16 since it is
-	 * used in the code below.
-	 */
-	size = msg->size;
-	/* Convert to le16/le32 */
-	msg->size = (__force u16)cpu_to_le16(msg->size);
-	msg->command = (__force u32)cpu_to_le32(msg->command);
-	msg->controlselector = (__force u16)cpu_to_le16(msg->controlselector);
-
 	/* Mental Note: line 462 tmmhComResBusPCIe.cpp */
 
 	/* Check if we're going to wrap again */
@@ -250,28 +243,28 @@
 			dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
 
 			/* Split the msg into pieces as the ring wraps */
-			memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, space_rem);
-			memcpy_toio(bus->m_pdwSetRing, (u8 *)msg + space_rem,
+			memcpy(bus->m_pdwSetRing + curr_swp, msg, space_rem);
+			memcpy(bus->m_pdwSetRing, (u8 *)msg + space_rem,
 				sizeof(*msg) - space_rem);
 
-			memcpy_toio(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
-				buf, size);
+			memcpy(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
+				buf, msg->size);
 
 		} else if (space_rem == sizeof(*msg)) {
 			dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
 
 			/* Additional data at the beginning of the ring */
-			memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
-			memcpy_toio(bus->m_pdwSetRing, buf, size);
+			memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+			memcpy(bus->m_pdwSetRing, buf, msg->size);
 
 		} else {
 			/* Additional data wraps around the ring */
-			memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
-			if (size > 0) {
-				memcpy_toio(bus->m_pdwSetRing + curr_swp +
+			memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+			if (msg->size > 0) {
+				memcpy(bus->m_pdwSetRing + curr_swp +
 					sizeof(*msg), buf, space_rem -
 					sizeof(*msg));
-				memcpy_toio(bus->m_pdwSetRing, (u8 *)buf +
+				memcpy(bus->m_pdwSetRing, (u8 *)buf +
 					space_rem - sizeof(*msg),
 					bytes_to_write - space_rem);
 			}
@@ -283,20 +276,15 @@
 		dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
 
 		/* The ring buffer doesn't wrap, two simple copies */
-		memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
-		memcpy_toio(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
-			size);
+		memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+		memcpy(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
+			msg->size);
 	}
 
 	dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
 
 	/* Update the bus write position */
-	saa7164_writel(bus->m_dwSetWritePos, new_swp);
-
-	/* Convert back to cpu after writing the msg to the ringbuffer. */
-	msg->size = le16_to_cpu((__force __le16)msg->size);
-	msg->command = le32_to_cpu((__force __le32)msg->command);
-	msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector);
+	saa7164_writel(bus->m_dwSetWritePos, cpu_to_le32(new_swp));
 	ret = SAA_OK;
 
 out:
@@ -348,8 +336,8 @@
 	/* Peek the bus to see if a msg exists, if it's not what we're expecting
 	 * then return cleanly else read the message from the bus.
 	 */
-	curr_gwp = saa7164_readl(bus->m_dwGetWritePos);
-	curr_grp = saa7164_readl(bus->m_dwGetReadPos);
+	curr_gwp = le32_to_cpu(saa7164_readl(bus->m_dwGetWritePos));
+	curr_grp = le32_to_cpu(saa7164_readl(bus->m_dwGetReadPos));
 
 	if (curr_gwp == curr_grp) {
 		ret = SAA_ERR_EMPTY;
@@ -381,18 +369,14 @@
 		new_grp -= bus->m_dwSizeGetRing;
 		space_rem = bus->m_dwSizeGetRing - curr_grp;
 
-		memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
-		memcpy_fromio((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
+		memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
+		memcpy((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
 			bytes_to_read - space_rem);
 
 	} else {
 		/* No wrapping */
-		memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
+		memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
 	}
-	/* Convert from little endian to CPU */
-	msg_tmp.size = le16_to_cpu((__force __le16)msg_tmp.size);
-	msg_tmp.command = le32_to_cpu((__force __le32)msg_tmp.command);
-	msg_tmp.controlselector = le16_to_cpu((__force __le16)msg_tmp.controlselector);
 
 	/* No need to update the read positions, because this was a peek */
 	/* If the caller specifically want to peek, return */
@@ -443,24 +427,24 @@
 
 		if (space_rem < sizeof(*msg)) {
 			/* msg wraps around the ring */
-			memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem);
-			memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing,
+			memcpy(msg, bus->m_pdwGetRing + curr_grp, space_rem);
+			memcpy((u8 *)msg + space_rem, bus->m_pdwGetRing,
 				sizeof(*msg) - space_rem);
 			if (buf)
-				memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) -
+				memcpy(buf, bus->m_pdwGetRing + sizeof(*msg) -
 					space_rem, buf_size);
 
 		} else if (space_rem == sizeof(*msg)) {
-			memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+			memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
 			if (buf)
-				memcpy_fromio(buf, bus->m_pdwGetRing, buf_size);
+				memcpy(buf, bus->m_pdwGetRing, buf_size);
 		} else {
 			/* Additional data wraps around the ring */
-			memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+			memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
 			if (buf) {
-				memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp +
+				memcpy(buf, bus->m_pdwGetRing + curr_grp +
 					sizeof(*msg), space_rem - sizeof(*msg));
-				memcpy_fromio(buf + space_rem - sizeof(*msg),
+				memcpy(buf + space_rem - sizeof(*msg),
 					bus->m_pdwGetRing, bytes_to_read -
 					space_rem);
 			}
@@ -469,20 +453,19 @@
 
 	} else {
 		/* No wrapping */
-		memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+		memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
 		if (buf)
-			memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
+			memcpy(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
 				buf_size);
 	}
-	/* Convert from little endian to CPU */
-	msg->size = le16_to_cpu((__force __le16)msg->size);
-	msg->command = le32_to_cpu((__force __le32)msg->command);
-	msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector);
 
 	/* Update the read positions, adjusting the ring */
-	saa7164_writel(bus->m_dwGetReadPos, new_grp);
+	saa7164_writel(bus->m_dwGetReadPos, cpu_to_le32(new_grp));
 
 peekout:
+	msg->size = le16_to_cpu(msg->size);
+	msg->command = le32_to_cpu(msg->command);
+	msg->controlselector = le16_to_cpu(msg->controlselector);
 	ret = SAA_OK;
 out:
 	mutex_unlock(&bus->lock);
diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c
index 4b0bec3..cc1be8a 100644
--- a/drivers/media/pci/saa7164/saa7164-core.c
+++ b/drivers/media/pci/saa7164/saa7164-core.c
@@ -119,7 +119,7 @@
 	u32 i;
 	u8 cc, a;
 	u16 pid;
-	u8 *bufcpu = (u8 *)buf->cpu;
+	u8 __iomem *bufcpu = (u8 *)buf->cpu;
 
 	port->sync_errors = 0;
 	port->v_cc_errors = 0;
@@ -260,7 +260,7 @@
 	struct saa7164_user_buffer *ubuf = NULL;
 	struct list_head *c, *n;
 	int i = 0;
-	u8 *p;
+	u8 __iomem *p;
 
 	mutex_lock(&port->dmaqueue_lock);
 	list_for_each_safe(c, n, &port->dmaqueue.list) {
@@ -318,7 +318,8 @@
 
 				if (buf->actual_size <= ubuf->actual_size) {
 
-					memcpy(ubuf->data, buf->cpu, ubuf->actual_size);
+					memcpy_fromio(ubuf->data, buf->cpu,
+						ubuf->actual_size);
 
 					if (crc_checking) {
 						/* Throw a new checksum on the read buffer */
@@ -345,7 +346,7 @@
 			 * with known bad data. We check for this data at a later point
 			 * in time. */
 			saa7164_buffer_zero_offsets(port, bufnr);
-			memset(buf->cpu, 0xff, buf->pci_size);
+			memset_io(buf->cpu, 0xff, buf->pci_size);
 			if (crc_checking) {
 				/* Throw yet aanother new checksum on the dma buffer */
 				buf->crc = crc32(0, buf->cpu, buf->actual_size);
@@ -1095,7 +1096,7 @@
 			if (c == 0)
 				seq_printf(m, " %04x:", i);
 
-			seq_printf(m, " %02x", readb(b->m_pdwSetRing + i));
+			seq_printf(m, " %02x", *(b->m_pdwSetRing + i));
 
 			if (++c == 16) {
 				seq_printf(m, "\n");
@@ -1110,7 +1111,7 @@
 			if (c == 0)
 				seq_printf(m, " %04x:", i);
 
-			seq_printf(m, " %02x", readb(b->m_pdwGetRing + i));
+			seq_printf(m, " %02x", *(b->m_pdwGetRing + i));
 
 			if (++c == 16) {
 				seq_printf(m, "\n");
diff --git a/drivers/media/pci/saa7164/saa7164-fw.c b/drivers/media/pci/saa7164/saa7164-fw.c
index add06ab..8676320 100644
--- a/drivers/media/pci/saa7164/saa7164-fw.c
+++ b/drivers/media/pci/saa7164/saa7164-fw.c
@@ -72,7 +72,7 @@
 /* TODO: move dlflags into dev-> and change to write/readl/b */
 /* TODO: Excessive levels of debug */
 static int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize,
-				 u32 dlflags, u8 __iomem *dst, u32 dstsize)
+				 u32 dlflags, u8 *dst, u32 dstsize)
 {
 	u32 reg, timeout, offset;
 	u8 *srcbuf = NULL;
@@ -136,7 +136,7 @@
 		srcsize -= dstsize, offset += dstsize) {
 
 		dprintk(DBGLVL_FW, "%s() memcpy %d\n", __func__, dstsize);
-		memcpy_toio(dst, srcbuf + offset, dstsize);
+		memcpy(dst, srcbuf + offset, dstsize);
 
 		/* Flag the data as ready */
 		saa7164_writel(drflag, 1);
@@ -154,7 +154,7 @@
 
 	dprintk(DBGLVL_FW, "%s() memcpy(l) %d\n", __func__, dstsize);
 	/* Write last block to the device */
-	memcpy_toio(dst, srcbuf+offset, srcsize);
+	memcpy(dst, srcbuf+offset, srcsize);
 
 	/* Flag the data as ready */
 	saa7164_writel(drflag, 1);
diff --git a/drivers/media/pci/saa7164/saa7164-types.h b/drivers/media/pci/saa7164/saa7164-types.h
index f48ba97..1d2140a 100644
--- a/drivers/media/pci/saa7164/saa7164-types.h
+++ b/drivers/media/pci/saa7164/saa7164-types.h
@@ -78,9 +78,9 @@
 struct tmComResBusInfo {
 	enum tmBusType Type;
 	u16	m_wMaxReqSize;
-	u8 __iomem *m_pdwSetRing;
+	u8	*m_pdwSetRing;
 	u32	m_dwSizeSetRing;
-	u8 __iomem *m_pdwGetRing;
+	u8	*m_pdwGetRing;
 	u32	m_dwSizeGetRing;
 	u32	m_dwSetWritePos;
 	u32	m_dwSetReadPos;
diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h
index cd1a07c..8b29e89 100644
--- a/drivers/media/pci/saa7164/saa7164.h
+++ b/drivers/media/pci/saa7164/saa7164.h
@@ -313,13 +313,13 @@
 
 	/* A block of page align PCI memory */
 	u32 pci_size;	/* PCI allocation size in bytes */
-	u64 *cpu;	/* Virtual address */
+	u64 __iomem *cpu;	/* Virtual address */
 	dma_addr_t dma;	/* Physical address */
 	u32 crc;	/* Checksum for the entire buffer data */
 
 	/* A page table that splits the block into a number of entries */
 	u32 pt_size;		/* PCI allocation size in bytes */
-	u64 *pt_cpu;		/* Virtual address */
+	u64 __iomem *pt_cpu;		/* Virtual address */
 	dma_addr_t pt_dma;	/* Physical address */
 
 	/* Encoder fops */
diff --git a/drivers/media/pci/smipcie/Kconfig b/drivers/media/pci/smipcie/Kconfig
deleted file mode 100644
index 45d6a31..0000000
--- a/drivers/media/pci/smipcie/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-config DVB_SMIPCIE
-	depends on !KERNEL_3_4
-	tristate "SMI PCIe DVBSky cards"
-	depends on m
-	depends on DVB_CORE && PCI && I2C
-	depends on I2C_ALGOBIT
-	select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
-	select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
-	select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
-	select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT
-	select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
-	help
-	  Support for cards with SMI PCIe bridge:
-	  - DVBSky S950 V3
-	  - DVBSky S952 V3
-	  - DVBSky T9580 V3
-
-	  Say Y or M if you own such a device and want to use it.
-	  If unsure say N.
diff --git a/drivers/media/pci/smipcie/Makefile b/drivers/media/pci/smipcie/Makefile
deleted file mode 100644
index ac5f289..0000000
--- a/drivers/media/pci/smipcie/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-obj-$(CPTCFG_DVB_SMIPCIE) += smipcie.o
-
-ccflags-y += -I$(backport_srctree)/drivers/media/tuners
-ccflags-y += -I$(backport_srctree)/drivers/media/dvb-core
-ccflags-y += -I$(backport_srctree)/drivers/media/dvb-frontends
-
diff --git a/drivers/media/pci/smipcie/smipcie.c b/drivers/media/pci/smipcie/smipcie.c
deleted file mode 100644
index f773350..0000000
--- a/drivers/media/pci/smipcie/smipcie.c
+++ /dev/null
@@ -1,1099 +0,0 @@
-/*
- * SMI PCIe driver for DVBSky cards.
- *
- * Copyright (C) 2014 Max nibble <nibble.max@gmail.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 "smipcie.h"
-#include "m88ds3103.h"
-#include "m88ts2022.h"
-#include "m88rs6000t.h"
-#include "si2168.h"
-#include "si2157.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int smi_hw_init(struct smi_dev *dev)
-{
-	u32 port_mux, port_ctrl, int_stat;
-
-	/* set port mux.*/
-	port_mux = smi_read(MUX_MODE_CTRL);
-	port_mux &= ~(rbPaMSMask);
-	port_mux |= rbPaMSDtvNoGpio;
-	port_mux &= ~(rbPbMSMask);
-	port_mux |= rbPbMSDtvNoGpio;
-	port_mux &= ~(0x0f0000);
-	port_mux |= 0x50000;
-	smi_write(MUX_MODE_CTRL, port_mux);
-
-	/* set DTV register.*/
-	/* Port A */
-	port_ctrl = smi_read(VIDEO_CTRL_STATUS_A);
-	port_ctrl &= ~0x01;
-	smi_write(VIDEO_CTRL_STATUS_A, port_ctrl);
-	port_ctrl = smi_read(MPEG2_CTRL_A);
-	port_ctrl &= ~0x40;
-	port_ctrl |= 0x80;
-	smi_write(MPEG2_CTRL_A, port_ctrl);
-	/* Port B */
-	port_ctrl = smi_read(VIDEO_CTRL_STATUS_B);
-	port_ctrl &= ~0x01;
-	smi_write(VIDEO_CTRL_STATUS_B, port_ctrl);
-	port_ctrl = smi_read(MPEG2_CTRL_B);
-	port_ctrl &= ~0x40;
-	port_ctrl |= 0x80;
-	smi_write(MPEG2_CTRL_B, port_ctrl);
-
-	/* disable and clear interrupt.*/
-	smi_write(MSI_INT_ENA_CLR, ALL_INT);
-	int_stat = smi_read(MSI_INT_STATUS);
-	smi_write(MSI_INT_STATUS_CLR, int_stat);
-
-	/* reset demod.*/
-	smi_clear(PERIPHERAL_CTRL, 0x0303);
-	msleep(50);
-	smi_set(PERIPHERAL_CTRL, 0x0101);
-	return 0;
-}
-
-/* i2c bit bus.*/
-static void smi_i2c_cfg(struct smi_dev *dev, u32 sw_ctl)
-{
-	u32 dwCtrl;
-
-	dwCtrl = smi_read(sw_ctl);
-	dwCtrl &= ~0x18; /* disable output.*/
-	dwCtrl |= 0x21; /* reset and software mode.*/
-	dwCtrl &= ~0xff00;
-	dwCtrl |= 0x6400;
-	smi_write(sw_ctl, dwCtrl);
-	msleep(20);
-	dwCtrl = smi_read(sw_ctl);
-	dwCtrl &= ~0x20;
-	smi_write(sw_ctl, dwCtrl);
-}
-
-static void smi_i2c_setsda(struct smi_dev *dev, int state, u32 sw_ctl)
-{
-	if (state) {
-		/* set as input.*/
-		smi_clear(sw_ctl, SW_I2C_MSK_DAT_EN);
-	} else {
-		smi_clear(sw_ctl, SW_I2C_MSK_DAT_OUT);
-		/* set as output.*/
-		smi_set(sw_ctl, SW_I2C_MSK_DAT_EN);
-	}
-}
-
-static void smi_i2c_setscl(void *data, int state, u32 sw_ctl)
-{
-	struct smi_dev *dev = data;
-
-	if (state) {
-		/* set as input.*/
-		smi_clear(sw_ctl, SW_I2C_MSK_CLK_EN);
-	} else {
-		smi_clear(sw_ctl, SW_I2C_MSK_CLK_OUT);
-		/* set as output.*/
-		smi_set(sw_ctl, SW_I2C_MSK_CLK_EN);
-	}
-}
-
-static int smi_i2c_getsda(void *data, u32 sw_ctl)
-{
-	struct smi_dev *dev = data;
-	/* set as input.*/
-	smi_clear(sw_ctl, SW_I2C_MSK_DAT_EN);
-	udelay(1);
-	return (smi_read(sw_ctl) & SW_I2C_MSK_DAT_IN) ? 1 : 0;
-}
-
-static int smi_i2c_getscl(void *data, u32 sw_ctl)
-{
-	struct smi_dev *dev = data;
-	/* set as input.*/
-	smi_clear(sw_ctl, SW_I2C_MSK_CLK_EN);
-	udelay(1);
-	return (smi_read(sw_ctl) & SW_I2C_MSK_CLK_IN) ? 1 : 0;
-}
-/* i2c 0.*/
-static void smi_i2c0_setsda(void *data, int state)
-{
-	struct smi_dev *dev = data;
-
-	smi_i2c_setsda(dev, state, I2C_A_SW_CTL);
-}
-
-static void smi_i2c0_setscl(void *data, int state)
-{
-	struct smi_dev *dev = data;
-
-	smi_i2c_setscl(dev, state, I2C_A_SW_CTL);
-}
-
-static int smi_i2c0_getsda(void *data)
-{
-	struct smi_dev *dev = data;
-
-	return	smi_i2c_getsda(dev, I2C_A_SW_CTL);
-}
-
-static int smi_i2c0_getscl(void *data)
-{
-	struct smi_dev *dev = data;
-
-	return	smi_i2c_getscl(dev, I2C_A_SW_CTL);
-}
-/* i2c 1.*/
-static void smi_i2c1_setsda(void *data, int state)
-{
-	struct smi_dev *dev = data;
-
-	smi_i2c_setsda(dev, state, I2C_B_SW_CTL);
-}
-
-static void smi_i2c1_setscl(void *data, int state)
-{
-	struct smi_dev *dev = data;
-
-	smi_i2c_setscl(dev, state, I2C_B_SW_CTL);
-}
-
-static int smi_i2c1_getsda(void *data)
-{
-	struct smi_dev *dev = data;
-
-	return	smi_i2c_getsda(dev, I2C_B_SW_CTL);
-}
-
-static int smi_i2c1_getscl(void *data)
-{
-	struct smi_dev *dev = data;
-
-	return	smi_i2c_getscl(dev, I2C_B_SW_CTL);
-}
-
-static int smi_i2c_init(struct smi_dev *dev)
-{
-	int ret;
-
-	/* i2c bus 0 */
-	smi_i2c_cfg(dev, I2C_A_SW_CTL);
-	i2c_set_adapdata(&dev->i2c_bus[0], dev);
-	strcpy(dev->i2c_bus[0].name, "SMI-I2C0");
-	dev->i2c_bus[0].owner = THIS_MODULE;
-	dev->i2c_bus[0].dev.parent = &dev->pci_dev->dev;
-	dev->i2c_bus[0].algo_data = &dev->i2c_bit[0];
-	dev->i2c_bit[0].data = dev;
-	dev->i2c_bit[0].setsda = smi_i2c0_setsda;
-	dev->i2c_bit[0].setscl = smi_i2c0_setscl;
-	dev->i2c_bit[0].getsda = smi_i2c0_getsda;
-	dev->i2c_bit[0].getscl = smi_i2c0_getscl;
-	dev->i2c_bit[0].udelay = 12;
-	dev->i2c_bit[0].timeout = 10;
-	/* Raise SCL and SDA */
-	smi_i2c0_setsda(dev, 1);
-	smi_i2c0_setscl(dev, 1);
-
-	ret = i2c_bit_add_bus(&dev->i2c_bus[0]);
-	if (ret < 0)
-		return ret;
-
-	/* i2c bus 1 */
-	smi_i2c_cfg(dev, I2C_B_SW_CTL);
-	i2c_set_adapdata(&dev->i2c_bus[1], dev);
-	strcpy(dev->i2c_bus[1].name, "SMI-I2C1");
-	dev->i2c_bus[1].owner = THIS_MODULE;
-	dev->i2c_bus[1].dev.parent = &dev->pci_dev->dev;
-	dev->i2c_bus[1].algo_data = &dev->i2c_bit[1];
-	dev->i2c_bit[1].data = dev;
-	dev->i2c_bit[1].setsda = smi_i2c1_setsda;
-	dev->i2c_bit[1].setscl = smi_i2c1_setscl;
-	dev->i2c_bit[1].getsda = smi_i2c1_getsda;
-	dev->i2c_bit[1].getscl = smi_i2c1_getscl;
-	dev->i2c_bit[1].udelay = 12;
-	dev->i2c_bit[1].timeout = 10;
-	/* Raise SCL and SDA */
-	smi_i2c1_setsda(dev, 1);
-	smi_i2c1_setscl(dev, 1);
-
-	ret = i2c_bit_add_bus(&dev->i2c_bus[1]);
-	if (ret < 0)
-		i2c_del_adapter(&dev->i2c_bus[0]);
-
-	return ret;
-}
-
-static void smi_i2c_exit(struct smi_dev *dev)
-{
-	i2c_del_adapter(&dev->i2c_bus[0]);
-	i2c_del_adapter(&dev->i2c_bus[1]);
-}
-
-static int smi_read_eeprom(struct i2c_adapter *i2c, u16 reg, u8 *data, u16 size)
-{
-	int ret;
-	u8 b0[2] = { (reg >> 8) & 0xff, reg & 0xff };
-
-	struct i2c_msg msg[] = {
-		{ .addr = 0x50, .flags = 0,
-			.buf = b0, .len = 2 },
-		{ .addr = 0x50, .flags = I2C_M_RD,
-			.buf = data, .len = size }
-	};
-
-	ret = i2c_transfer(i2c, msg, 2);
-
-	if (ret != 2) {
-		dev_err(&i2c->dev, "%s: reg=0x%x (error=%d)\n",
-			__func__, reg, ret);
-		return ret;
-	}
-	return ret;
-}
-
-/* ts port interrupt operations */
-static void smi_port_disableInterrupt(struct smi_port *port)
-{
-	struct smi_dev *dev = port->dev;
-
-	smi_write(MSI_INT_ENA_CLR,
-		(port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
-}
-
-static void smi_port_enableInterrupt(struct smi_port *port)
-{
-	struct smi_dev *dev = port->dev;
-
-	smi_write(MSI_INT_ENA_SET,
-		(port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
-}
-
-static void smi_port_clearInterrupt(struct smi_port *port)
-{
-	struct smi_dev *dev = port->dev;
-
-	smi_write(MSI_INT_STATUS_CLR,
-		(port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
-}
-
-/* tasklet handler: DMA data to dmx.*/
-static void smi_dma_xfer(unsigned long data)
-{
-	struct smi_port *port = (struct smi_port *) data;
-	struct smi_dev *dev = port->dev;
-	u32 intr_status, finishedData, dmaManagement;
-	u8 dmaChan0State, dmaChan1State;
-
-	intr_status = port->_int_status;
-	dmaManagement = smi_read(port->DMA_MANAGEMENT);
-	dmaChan0State = (u8)((dmaManagement & 0x00000030) >> 4);
-	dmaChan1State = (u8)((dmaManagement & 0x00300000) >> 20);
-
-	/* CH-0 DMA interrupt.*/
-	if ((intr_status & port->_dmaInterruptCH0) && (dmaChan0State == 0x01)) {
-		dev_dbg(&dev->pci_dev->dev,
-			"Port[%d]-DMA CH0 engine complete successful !\n",
-			port->idx);
-		finishedData = smi_read(port->DMA_CHAN0_TRANS_STATE);
-		finishedData &= 0x003FFFFF;
-		/* value of DMA_PORT0_CHAN0_TRANS_STATE register [21:0]
-		 * indicate dma total transfer length and
-		 * zero of [21:0] indicate dma total transfer length
-		 * equal to 0x400000 (4MB)*/
-		if (finishedData == 0)
-			finishedData = 0x00400000;
-		if (finishedData != SMI_TS_DMA_BUF_SIZE) {
-			dev_dbg(&dev->pci_dev->dev,
-				"DMA CH0 engine complete length mismatched, finish data=%d !\n",
-				finishedData);
-		}
-		dvb_dmx_swfilter_packets(&port->demux,
-			port->cpu_addr[0], (finishedData / 188));
-		/*dvb_dmx_swfilter(&port->demux,
-			port->cpu_addr[0], finishedData);*/
-	}
-	/* CH-1 DMA interrupt.*/
-	if ((intr_status & port->_dmaInterruptCH1) && (dmaChan1State == 0x01)) {
-		dev_dbg(&dev->pci_dev->dev,
-			"Port[%d]-DMA CH1 engine complete successful !\n",
-			port->idx);
-		finishedData = smi_read(port->DMA_CHAN1_TRANS_STATE);
-		finishedData &= 0x003FFFFF;
-		/* value of DMA_PORT0_CHAN0_TRANS_STATE register [21:0]
-		 * indicate dma total transfer length and
-		 * zero of [21:0] indicate dma total transfer length
-		 * equal to 0x400000 (4MB)*/
-		if (finishedData == 0)
-			finishedData = 0x00400000;
-		if (finishedData != SMI_TS_DMA_BUF_SIZE) {
-			dev_dbg(&dev->pci_dev->dev,
-				"DMA CH1 engine complete length mismatched, finish data=%d !\n",
-				finishedData);
-		}
-		dvb_dmx_swfilter_packets(&port->demux,
-			port->cpu_addr[1], (finishedData / 188));
-		/*dvb_dmx_swfilter(&port->demux,
-			port->cpu_addr[1], finishedData);*/
-	}
-	/* restart DMA.*/
-	if (intr_status & port->_dmaInterruptCH0)
-		dmaManagement |= 0x00000002;
-	if (intr_status & port->_dmaInterruptCH1)
-		dmaManagement |= 0x00020000;
-	smi_write(port->DMA_MANAGEMENT, dmaManagement);
-	/* Re-enable interrupts */
-	smi_port_enableInterrupt(port);
-}
-
-static void smi_port_dma_free(struct smi_port *port)
-{
-	if (port->cpu_addr[0]) {
-		pci_free_consistent(port->dev->pci_dev, SMI_TS_DMA_BUF_SIZE,
-				    port->cpu_addr[0], port->dma_addr[0]);
-		port->cpu_addr[0] = NULL;
-	}
-	if (port->cpu_addr[1]) {
-		pci_free_consistent(port->dev->pci_dev, SMI_TS_DMA_BUF_SIZE,
-				    port->cpu_addr[1], port->dma_addr[1]);
-		port->cpu_addr[1] = NULL;
-	}
-}
-
-static int smi_port_init(struct smi_port *port, int dmaChanUsed)
-{
-	dev_dbg(&port->dev->pci_dev->dev,
-		"%s, port %d, dmaused %d\n", __func__, port->idx, dmaChanUsed);
-	port->enable = 0;
-	if (port->idx == 0) {
-		/* Port A */
-		port->_dmaInterruptCH0 = dmaChanUsed & 0x01;
-		port->_dmaInterruptCH1 = dmaChanUsed & 0x02;
-
-		port->DMA_CHAN0_ADDR_LOW	= DMA_PORTA_CHAN0_ADDR_LOW;
-		port->DMA_CHAN0_ADDR_HI		= DMA_PORTA_CHAN0_ADDR_HI;
-		port->DMA_CHAN0_TRANS_STATE	= DMA_PORTA_CHAN0_TRANS_STATE;
-		port->DMA_CHAN0_CONTROL		= DMA_PORTA_CHAN0_CONTROL;
-		port->DMA_CHAN1_ADDR_LOW	= DMA_PORTA_CHAN1_ADDR_LOW;
-		port->DMA_CHAN1_ADDR_HI		= DMA_PORTA_CHAN1_ADDR_HI;
-		port->DMA_CHAN1_TRANS_STATE	= DMA_PORTA_CHAN1_TRANS_STATE;
-		port->DMA_CHAN1_CONTROL		= DMA_PORTA_CHAN1_CONTROL;
-		port->DMA_MANAGEMENT		= DMA_PORTA_MANAGEMENT;
-	} else {
-		/* Port B */
-		port->_dmaInterruptCH0 = (dmaChanUsed << 2) & 0x04;
-		port->_dmaInterruptCH1 = (dmaChanUsed << 2) & 0x08;
-
-		port->DMA_CHAN0_ADDR_LOW	= DMA_PORTB_CHAN0_ADDR_LOW;
-		port->DMA_CHAN0_ADDR_HI		= DMA_PORTB_CHAN0_ADDR_HI;
-		port->DMA_CHAN0_TRANS_STATE	= DMA_PORTB_CHAN0_TRANS_STATE;
-		port->DMA_CHAN0_CONTROL		= DMA_PORTB_CHAN0_CONTROL;
-		port->DMA_CHAN1_ADDR_LOW	= DMA_PORTB_CHAN1_ADDR_LOW;
-		port->DMA_CHAN1_ADDR_HI		= DMA_PORTB_CHAN1_ADDR_HI;
-		port->DMA_CHAN1_TRANS_STATE	= DMA_PORTB_CHAN1_TRANS_STATE;
-		port->DMA_CHAN1_CONTROL		= DMA_PORTB_CHAN1_CONTROL;
-		port->DMA_MANAGEMENT		= DMA_PORTB_MANAGEMENT;
-	}
-
-	if (port->_dmaInterruptCH0) {
-		port->cpu_addr[0] = pci_alloc_consistent(port->dev->pci_dev,
-					SMI_TS_DMA_BUF_SIZE,
-					&port->dma_addr[0]);
-		if (!port->cpu_addr[0]) {
-			dev_err(&port->dev->pci_dev->dev,
-				"Port[%d] DMA CH0 memory allocation failed!\n",
-				port->idx);
-			goto err;
-		}
-	}
-
-	if (port->_dmaInterruptCH1) {
-		port->cpu_addr[1] = pci_alloc_consistent(port->dev->pci_dev,
-					SMI_TS_DMA_BUF_SIZE,
-					&port->dma_addr[1]);
-		if (!port->cpu_addr[1]) {
-			dev_err(&port->dev->pci_dev->dev,
-				"Port[%d] DMA CH1 memory allocation failed!\n",
-				port->idx);
-			goto err;
-		}
-	}
-
-	smi_port_disableInterrupt(port);
-	tasklet_init(&port->tasklet, smi_dma_xfer, (unsigned long)port);
-	tasklet_disable(&port->tasklet);
-	port->enable = 1;
-	return 0;
-err:
-	smi_port_dma_free(port);
-	return -ENOMEM;
-}
-
-static void smi_port_exit(struct smi_port *port)
-{
-	smi_port_disableInterrupt(port);
-	tasklet_kill(&port->tasklet);
-	smi_port_dma_free(port);
-	port->enable = 0;
-}
-
-static void smi_port_irq(struct smi_port *port, u32 int_status)
-{
-	u32 port_req_irq = port->_dmaInterruptCH0 | port->_dmaInterruptCH1;
-
-	if (int_status & port_req_irq) {
-		smi_port_disableInterrupt(port);
-		port->_int_status = int_status;
-		smi_port_clearInterrupt(port);
-		tasklet_schedule(&port->tasklet);
-	}
-}
-
-static irqreturn_t smi_irq_handler(int irq, void *dev_id)
-{
-	struct smi_dev *dev = dev_id;
-	struct smi_port *port0 = &dev->ts_port[0];
-	struct smi_port *port1 = &dev->ts_port[1];
-
-	u32 intr_status = smi_read(MSI_INT_STATUS);
-
-	/* ts0 interrupt.*/
-	if (dev->info->ts_0)
-		smi_port_irq(port0, intr_status);
-
-	/* ts1 interrupt.*/
-	if (dev->info->ts_1)
-		smi_port_irq(port1, intr_status);
-
-	return IRQ_HANDLED;
-}
-
-static struct i2c_client *smi_add_i2c_client(struct i2c_adapter *adapter,
-			struct i2c_board_info *info)
-{
-	struct i2c_client *client;
-
-	request_module(info->type);
-	client = i2c_new_device(adapter, info);
-	if (client == NULL || client->dev.driver == NULL)
-		goto err_add_i2c_client;
-
-	if (!try_module_get(client->dev.driver->owner)) {
-		i2c_unregister_device(client);
-		goto err_add_i2c_client;
-	}
-	return client;
-
-err_add_i2c_client:
-	client = NULL;
-	return client;
-}
-
-static void smi_del_i2c_client(struct i2c_client *client)
-{
-	module_put(client->dev.driver->owner);
-	i2c_unregister_device(client);
-}
-
-static const struct m88ds3103_config smi_dvbsky_m88ds3103_cfg = {
-	.i2c_addr = 0x68,
-	.clock = 27000000,
-	.i2c_wr_max = 33,
-	.clock_out = 0,
-	.ts_mode = M88DS3103_TS_PARALLEL,
-	.ts_clk = 16000,
-	.ts_clk_pol = 1,
-	.agc = 0x99,
-	.lnb_hv_pol = 0,
-	.lnb_en_pol = 1,
-};
-
-static int smi_dvbsky_m88ds3103_fe_attach(struct smi_port *port)
-{
-	int ret = 0;
-	struct smi_dev *dev = port->dev;
-	struct i2c_adapter *i2c;
-	/* tuner I2C module */
-	struct i2c_adapter *tuner_i2c_adapter;
-	struct i2c_client *tuner_client;
-	struct i2c_board_info tuner_info;
-	struct m88ts2022_config m88ts2022_config = {
-		.clock = 27000000,
-	};
-	memset(&tuner_info, 0, sizeof(struct i2c_board_info));
-	i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];
-
-	/* attach demod */
-	port->fe = dvb_attach(m88ds3103_attach,
-			&smi_dvbsky_m88ds3103_cfg, i2c, &tuner_i2c_adapter);
-	if (!port->fe) {
-		ret = -ENODEV;
-		return ret;
-	}
-	/* attach tuner */
-	m88ts2022_config.fe = port->fe;
-	strlcpy(tuner_info.type, "m88ts2022", I2C_NAME_SIZE);
-	tuner_info.addr = 0x60;
-	tuner_info.platform_data = &m88ts2022_config;
-	tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);
-	if (!tuner_client) {
-		ret = -ENODEV;
-		goto err_tuner_i2c_device;
-	}
-
-	/* delegate signal strength measurement to tuner */
-	port->fe->ops.read_signal_strength =
-			port->fe->ops.tuner_ops.get_rf_strength;
-
-	port->i2c_client_tuner = tuner_client;
-	return ret;
-
-err_tuner_i2c_device:
-	dvb_frontend_detach(port->fe);
-	return ret;
-}
-
-static const struct m88ds3103_config smi_dvbsky_m88rs6000_cfg = {
-	.i2c_addr = 0x69,
-	.clock = 27000000,
-	.i2c_wr_max = 33,
-	.ts_mode = M88DS3103_TS_PARALLEL,
-	.ts_clk = 16000,
-	.ts_clk_pol = 1,
-	.agc = 0x99,
-	.lnb_hv_pol = 0,
-	.lnb_en_pol = 1,
-};
-
-static int smi_dvbsky_m88rs6000_fe_attach(struct smi_port *port)
-{
-	int ret = 0;
-	struct smi_dev *dev = port->dev;
-	struct i2c_adapter *i2c;
-	/* tuner I2C module */
-	struct i2c_adapter *tuner_i2c_adapter;
-	struct i2c_client *tuner_client;
-	struct i2c_board_info tuner_info;
-	struct m88rs6000t_config m88rs6000t_config;
-
-	memset(&tuner_info, 0, sizeof(struct i2c_board_info));
-	i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];
-
-	/* attach demod */
-	port->fe = dvb_attach(m88ds3103_attach,
-			&smi_dvbsky_m88rs6000_cfg, i2c, &tuner_i2c_adapter);
-	if (!port->fe) {
-		ret = -ENODEV;
-		return ret;
-	}
-	/* attach tuner */
-	m88rs6000t_config.fe = port->fe;
-	strlcpy(tuner_info.type, "m88rs6000t", I2C_NAME_SIZE);
-	tuner_info.addr = 0x21;
-	tuner_info.platform_data = &m88rs6000t_config;
-	tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);
-	if (!tuner_client) {
-		ret = -ENODEV;
-		goto err_tuner_i2c_device;
-	}
-
-	/* delegate signal strength measurement to tuner */
-	port->fe->ops.read_signal_strength =
-			port->fe->ops.tuner_ops.get_rf_strength;
-
-	port->i2c_client_tuner = tuner_client;
-	return ret;
-
-err_tuner_i2c_device:
-	dvb_frontend_detach(port->fe);
-	return ret;
-}
-
-static int smi_dvbsky_sit2_fe_attach(struct smi_port *port)
-{
-	int ret = 0;
-	struct smi_dev *dev = port->dev;
-	struct i2c_adapter *i2c;
-	struct i2c_adapter *tuner_i2c_adapter;
-	struct i2c_client *client_tuner, *client_demod;
-	struct i2c_board_info client_info;
-	struct si2168_config si2168_config;
-	struct si2157_config si2157_config;
-
-	/* select i2c bus */
-	i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];
-
-	/* attach demod */
-	memset(&si2168_config, 0, sizeof(si2168_config));
-	si2168_config.i2c_adapter = &tuner_i2c_adapter;
-	si2168_config.fe = &port->fe;
-	si2168_config.ts_mode = SI2168_TS_PARALLEL;
-
-	memset(&client_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(client_info.type, "si2168", I2C_NAME_SIZE);
-	client_info.addr = 0x64;
-	client_info.platform_data = &si2168_config;
-
-	client_demod = smi_add_i2c_client(i2c, &client_info);
-	if (!client_demod) {
-		ret = -ENODEV;
-		return ret;
-	}
-	port->i2c_client_demod = client_demod;
-
-	/* attach tuner */
-	memset(&si2157_config, 0, sizeof(si2157_config));
-	si2157_config.fe = port->fe;
-
-	memset(&client_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(client_info.type, "si2157", I2C_NAME_SIZE);
-	client_info.addr = 0x60;
-	client_info.platform_data = &si2157_config;
-
-	client_tuner = smi_add_i2c_client(tuner_i2c_adapter, &client_info);
-	if (!client_tuner) {
-		smi_del_i2c_client(port->i2c_client_demod);
-		port->i2c_client_demod = NULL;
-		ret = -ENODEV;
-		return ret;
-	}
-	port->i2c_client_tuner = client_tuner;
-	return ret;
-}
-
-static int smi_fe_init(struct smi_port *port)
-{
-	int ret = 0;
-	struct smi_dev *dev = port->dev;
-	struct dvb_adapter *adap = &port->dvb_adapter;
-	u8 mac_ee[16];
-
-	dev_dbg(&port->dev->pci_dev->dev,
-		"%s: port %d, fe_type = %d\n",
-		__func__, port->idx, port->fe_type);
-	switch (port->fe_type) {
-	case DVBSKY_FE_M88DS3103:
-		ret = smi_dvbsky_m88ds3103_fe_attach(port);
-		break;
-	case DVBSKY_FE_M88RS6000:
-		ret = smi_dvbsky_m88rs6000_fe_attach(port);
-		break;
-	case DVBSKY_FE_SIT2:
-		ret = smi_dvbsky_sit2_fe_attach(port);
-		break;
-	}
-	if (ret < 0)
-		return ret;
-
-	/* register dvb frontend */
-	ret = dvb_register_frontend(adap, port->fe);
-	if (ret < 0) {
-		if (port->i2c_client_tuner)
-			smi_del_i2c_client(port->i2c_client_tuner);
-		if (port->i2c_client_demod)
-			smi_del_i2c_client(port->i2c_client_demod);
-		dvb_frontend_detach(port->fe);
-		return ret;
-	}
-	/* init MAC.*/
-	ret = smi_read_eeprom(&dev->i2c_bus[0], 0xc0, mac_ee, 16);
-	dev_info(&port->dev->pci_dev->dev,
-		"DVBSky SMI PCIe MAC= %pM\n", mac_ee + (port->idx)*8);
-	memcpy(adap->proposed_mac, mac_ee + (port->idx)*8, 6);
-	return ret;
-}
-
-static void smi_fe_exit(struct smi_port *port)
-{
-	dvb_unregister_frontend(port->fe);
-	/* remove I2C demod and tuner */
-	if (port->i2c_client_tuner)
-		smi_del_i2c_client(port->i2c_client_tuner);
-	if (port->i2c_client_demod)
-		smi_del_i2c_client(port->i2c_client_demod);
-	dvb_frontend_detach(port->fe);
-}
-
-static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
-			    int (*start_feed)(struct dvb_demux_feed *),
-			    int (*stop_feed)(struct dvb_demux_feed *),
-			    void *priv)
-{
-	dvbdemux->priv = priv;
-
-	dvbdemux->filternum = 256;
-	dvbdemux->feednum = 256;
-	dvbdemux->start_feed = start_feed;
-	dvbdemux->stop_feed = stop_feed;
-	dvbdemux->write_to_decoder = NULL;
-	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
-				      DMX_SECTION_FILTERING |
-				      DMX_MEMORY_BASED_FILTERING);
-	return dvb_dmx_init(dvbdemux);
-}
-
-static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
-			       struct dvb_demux *dvbdemux,
-			       struct dmx_frontend *hw_frontend,
-			       struct dmx_frontend *mem_frontend,
-			       struct dvb_adapter *dvb_adapter)
-{
-	int ret;
-
-	dmxdev->filternum = 256;
-	dmxdev->demux = &dvbdemux->dmx;
-	dmxdev->capabilities = 0;
-	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
-	if (ret < 0)
-		return ret;
-
-	hw_frontend->source = DMX_FRONTEND_0;
-	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
-	mem_frontend->source = DMX_MEMORY_FE;
-	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
-	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
-}
-
-static u32 smi_config_DMA(struct smi_port *port)
-{
-	struct smi_dev *dev = port->dev;
-	u32 totalLength = 0, dmaMemPtrLow, dmaMemPtrHi, dmaCtlReg;
-	u8 chanLatencyTimer = 0, dmaChanEnable = 1, dmaTransStart = 1;
-	u32 dmaManagement = 0, tlpTransUnit = DMA_TRANS_UNIT_188;
-	u8 tlpTc = 0, tlpTd = 1, tlpEp = 0, tlpAttr = 0;
-	u64 mem;
-
-	dmaManagement = smi_read(port->DMA_MANAGEMENT);
-	/* Setup Channel-0 */
-	if (port->_dmaInterruptCH0) {
-		totalLength = SMI_TS_DMA_BUF_SIZE;
-		mem = port->dma_addr[0];
-		dmaMemPtrLow = mem & 0xffffffff;
-		dmaMemPtrHi = mem >> 32;
-		dmaCtlReg = (totalLength) | (tlpTransUnit << 22) | (tlpTc << 25)
-			| (tlpTd << 28) | (tlpEp << 29) | (tlpAttr << 30);
-		dmaManagement |= dmaChanEnable | (dmaTransStart << 1)
-			| (chanLatencyTimer << 8);
-		/* write DMA register, start DMA engine */
-		smi_write(port->DMA_CHAN0_ADDR_LOW, dmaMemPtrLow);
-		smi_write(port->DMA_CHAN0_ADDR_HI, dmaMemPtrHi);
-		smi_write(port->DMA_CHAN0_CONTROL, dmaCtlReg);
-	}
-	/* Setup Channel-1 */
-	if (port->_dmaInterruptCH1) {
-		totalLength = SMI_TS_DMA_BUF_SIZE;
-		mem = port->dma_addr[1];
-		dmaMemPtrLow = mem & 0xffffffff;
-		dmaMemPtrHi = mem >> 32;
-		dmaCtlReg = (totalLength) | (tlpTransUnit << 22) | (tlpTc << 25)
-			| (tlpTd << 28) | (tlpEp << 29) | (tlpAttr << 30);
-		dmaManagement |= (dmaChanEnable << 16) | (dmaTransStart << 17)
-			| (chanLatencyTimer << 24);
-		/* write DMA register, start DMA engine */
-		smi_write(port->DMA_CHAN1_ADDR_LOW, dmaMemPtrLow);
-		smi_write(port->DMA_CHAN1_ADDR_HI, dmaMemPtrHi);
-		smi_write(port->DMA_CHAN1_CONTROL, dmaCtlReg);
-	}
-	return dmaManagement;
-}
-
-static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct smi_port *port = dvbdmx->priv;
-	struct smi_dev *dev = port->dev;
-	u32 dmaManagement;
-
-	if (port->users++ == 0) {
-		dmaManagement = smi_config_DMA(port);
-		smi_port_clearInterrupt(port);
-		smi_port_enableInterrupt(port);
-		smi_write(port->DMA_MANAGEMENT, dmaManagement);
-		tasklet_enable(&port->tasklet);
-	}
-	return port->users;
-}
-
-static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct smi_port *port = dvbdmx->priv;
-	struct smi_dev *dev = port->dev;
-
-	if (--port->users)
-		return port->users;
-
-	tasklet_disable(&port->tasklet);
-	smi_port_disableInterrupt(port);
-	smi_clear(port->DMA_MANAGEMENT, 0x30003);
-	return 0;
-}
-
-static int smi_dvb_init(struct smi_port *port)
-{
-	int ret;
-	struct dvb_adapter *adap = &port->dvb_adapter;
-	struct dvb_demux *dvbdemux = &port->demux;
-
-	dev_dbg(&port->dev->pci_dev->dev,
-		"%s, port %d\n", __func__, port->idx);
-
-	ret = dvb_register_adapter(adap, "SMI_DVB", THIS_MODULE,
-				   &port->dev->pci_dev->dev,
-				   adapter_nr);
-	if (ret < 0) {
-		dev_err(&port->dev->pci_dev->dev, "Fail to register DVB adapter.\n");
-		return ret;
-	}
-	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
-				      smi_start_feed,
-				      smi_stop_feed, port);
-	if (ret < 0)
-		goto err_del_dvb_register_adapter;
-
-	ret = my_dvb_dmxdev_ts_card_init(&port->dmxdev, &port->demux,
-					 &port->hw_frontend,
-					 &port->mem_frontend, adap);
-	if (ret < 0)
-		goto err_del_dvb_dmx;
-
-	ret = dvb_net_init(adap, &port->dvbnet, port->dmxdev.demux);
-	if (ret < 0)
-		goto err_del_dvb_dmxdev;
-	return 0;
-err_del_dvb_dmxdev:
-	dvbdemux->dmx.close(&dvbdemux->dmx);
-	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->hw_frontend);
-	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->mem_frontend);
-	dvb_dmxdev_release(&port->dmxdev);
-err_del_dvb_dmx:
-	dvb_dmx_release(&port->demux);
-err_del_dvb_register_adapter:
-	dvb_unregister_adapter(&port->dvb_adapter);
-	return ret;
-}
-
-static void smi_dvb_exit(struct smi_port *port)
-{
-	struct dvb_demux *dvbdemux = &port->demux;
-
-	dvb_net_release(&port->dvbnet);
-
-	dvbdemux->dmx.close(&dvbdemux->dmx);
-	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->hw_frontend);
-	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->mem_frontend);
-	dvb_dmxdev_release(&port->dmxdev);
-	dvb_dmx_release(&port->demux);
-
-	dvb_unregister_adapter(&port->dvb_adapter);
-}
-
-static int smi_port_attach(struct smi_dev *dev,
-		struct smi_port *port, int index)
-{
-	int ret, dmachs;
-
-	port->dev = dev;
-	port->idx = index;
-	port->fe_type = (index == 0) ? dev->info->fe_0 : dev->info->fe_1;
-	dmachs = (index == 0) ? dev->info->ts_0 : dev->info->ts_1;
-	/* port init.*/
-	ret = smi_port_init(port, dmachs);
-	if (ret < 0)
-		return ret;
-	/* dvb init.*/
-	ret = smi_dvb_init(port);
-	if (ret < 0)
-		goto err_del_port_init;
-	/* fe init.*/
-	ret = smi_fe_init(port);
-	if (ret < 0)
-		goto err_del_dvb_init;
-	return 0;
-err_del_dvb_init:
-	smi_dvb_exit(port);
-err_del_port_init:
-	smi_port_exit(port);
-	return ret;
-}
-
-static void smi_port_detach(struct smi_port *port)
-{
-	smi_fe_exit(port);
-	smi_dvb_exit(port);
-	smi_port_exit(port);
-}
-
-static int smi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct smi_dev *dev;
-	int ret = -ENOMEM;
-
-	if (pci_enable_device(pdev) < 0)
-		return -ENODEV;
-
-	dev = kzalloc(sizeof(struct smi_dev), GFP_KERNEL);
-	if (!dev) {
-		ret = -ENOMEM;
-		goto err_pci_disable_device;
-	}
-
-	dev->pci_dev = pdev;
-	pci_set_drvdata(pdev, dev);
-	dev->info = (struct smi_cfg_info *) id->driver_data;
-	dev_info(&dev->pci_dev->dev,
-		"card detected: %s\n", dev->info->name);
-
-	dev->nr = dev->info->type;
-	dev->lmmio = ioremap(pci_resource_start(dev->pci_dev, 0),
-			    pci_resource_len(dev->pci_dev, 0));
-	if (!dev->lmmio) {
-		ret = -ENOMEM;
-		goto err_kfree;
-	}
-
-	/* should we set to 32bit DMA? */
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (ret < 0)
-		goto err_pci_iounmap;
-
-	pci_set_master(pdev);
-
-	ret = smi_hw_init(dev);
-	if (ret < 0)
-		goto err_pci_iounmap;
-
-	ret = smi_i2c_init(dev);
-	if (ret < 0)
-		goto err_pci_iounmap;
-
-	if (dev->info->ts_0) {
-		ret = smi_port_attach(dev, &dev->ts_port[0], 0);
-		if (ret < 0)
-			goto err_del_i2c_adaptor;
-	}
-
-	if (dev->info->ts_1) {
-		ret = smi_port_attach(dev, &dev->ts_port[1], 1);
-		if (ret < 0)
-			goto err_del_port0_attach;
-	}
-
-#ifdef CONFIG_PCI_MSI /* to do msi interrupt.???*/
-	if (pci_msi_enabled())
-		ret = pci_enable_msi(dev->pci_dev);
-	if (ret)
-		dev_info(&dev->pci_dev->dev, "MSI not available.\n");
-#endif
-
-	ret = request_irq(dev->pci_dev->irq, smi_irq_handler,
-			   IRQF_SHARED, "SMI_PCIE", dev);
-	if (ret < 0)
-		goto err_del_port1_attach;
-
-	return 0;
-
-err_del_port1_attach:
-	if (dev->info->ts_1)
-		smi_port_detach(&dev->ts_port[1]);
-err_del_port0_attach:
-	if (dev->info->ts_0)
-		smi_port_detach(&dev->ts_port[0]);
-err_del_i2c_adaptor:
-	smi_i2c_exit(dev);
-err_pci_iounmap:
-	iounmap(dev->lmmio);
-err_kfree:
-	pci_set_drvdata(pdev, NULL);
-	kfree(dev);
-err_pci_disable_device:
-	pci_disable_device(pdev);
-	return ret;
-}
-
-static void smi_remove(struct pci_dev *pdev)
-{
-	struct smi_dev *dev = pci_get_drvdata(pdev);
-
-	smi_write(MSI_INT_ENA_CLR, ALL_INT);
-	free_irq(dev->pci_dev->irq, dev);
-#ifdef CONFIG_PCI_MSI
-	pci_disable_msi(dev->pci_dev);
-#endif
-	if (dev->info->ts_1)
-		smi_port_detach(&dev->ts_port[1]);
-	if (dev->info->ts_0)
-		smi_port_detach(&dev->ts_port[0]);
-
-	smi_i2c_exit(dev);
-	iounmap(dev->lmmio);
-	pci_set_drvdata(pdev, NULL);
-	pci_disable_device(pdev);
-	kfree(dev);
-}
-
-/* DVBSky cards */
-static struct smi_cfg_info dvbsky_s950_cfg = {
-	.type = SMI_DVBSKY_S950,
-	.name = "DVBSky S950 V3",
-	.ts_0 = SMI_TS_NULL,
-	.ts_1 = SMI_TS_DMA_BOTH,
-	.fe_0 = DVBSKY_FE_NULL,
-	.fe_1 = DVBSKY_FE_M88DS3103,
-};
-
-static struct smi_cfg_info dvbsky_s952_cfg = {
-	.type = SMI_DVBSKY_S952,
-	.name = "DVBSky S952 V3",
-	.ts_0 = SMI_TS_DMA_BOTH,
-	.ts_1 = SMI_TS_DMA_BOTH,
-	.fe_0 = DVBSKY_FE_M88RS6000,
-	.fe_1 = DVBSKY_FE_M88RS6000,
-};
-
-static struct smi_cfg_info dvbsky_t9580_cfg = {
-	.type = SMI_DVBSKY_T9580,
-	.name = "DVBSky T9580 V3",
-	.ts_0 = SMI_TS_DMA_BOTH,
-	.ts_1 = SMI_TS_DMA_BOTH,
-	.fe_0 = DVBSKY_FE_SIT2,
-	.fe_1 = DVBSKY_FE_M88DS3103,
-};
-
-/* PCI IDs */
-#define SMI_ID(_subvend, _subdev, _driverdata) {	\
-	.vendor      = SMI_VID,    .device    = SMI_PID, \
-	.subvendor   = _subvend, .subdevice = _subdev, \
-	.driver_data = (unsigned long)&_driverdata }
-
-static const struct pci_device_id smi_id_table[] = {
-	SMI_ID(0x4254, 0x0550, dvbsky_s950_cfg),
-	SMI_ID(0x4254, 0x0552, dvbsky_s952_cfg),
-	SMI_ID(0x4254, 0x5580, dvbsky_t9580_cfg),
-	{0}
-};
-MODULE_DEVICE_TABLE(pci, smi_id_table);
-
-static struct pci_driver smipcie_driver = {
-	.name = "SMI PCIe driver",
-	.id_table = smi_id_table,
-	.probe = smi_probe,
-	.remove = smi_remove,
-};
-
-module_pci_driver(smipcie_driver);
-
-MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
-MODULE_DESCRIPTION("SMI PCIe driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h
deleted file mode 100644
index 10cdf20..0000000
--- a/drivers/media/pci/smipcie/smipcie.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * SMI PCIe driver for DVBSky cards.
- *
- * Copyright (C) 2014 Max nibble <nibble.max@gmail.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 _SMI_PCIE_H_
-#define _SMI_PCIE_H_
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <media/rc-core.h>
-
-#include "demux.h"
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-#include "dvbdev.h"
-
-/* -------- Register Base -------- */
-#define    MSI_CONTROL_REG_BASE                 0x0800
-#define    SYSTEM_CONTROL_REG_BASE              0x0880
-#define    PCIE_EP_DEBUG_REG_BASE               0x08C0
-#define    IR_CONTROL_REG_BASE                  0x0900
-#define    I2C_A_CONTROL_REG_BASE               0x0940
-#define    I2C_B_CONTROL_REG_BASE               0x0980
-#define    ATV_PORTA_CONTROL_REG_BASE           0x09C0
-#define    DTV_PORTA_CONTROL_REG_BASE           0x0A00
-#define    AES_PORTA_CONTROL_REG_BASE           0x0A80
-#define    DMA_PORTA_CONTROL_REG_BASE           0x0AC0
-#define    ATV_PORTB_CONTROL_REG_BASE           0x0B00
-#define    DTV_PORTB_CONTROL_REG_BASE           0x0B40
-#define    AES_PORTB_CONTROL_REG_BASE           0x0BC0
-#define    DMA_PORTB_CONTROL_REG_BASE           0x0C00
-#define    UART_A_REGISTER_BASE                 0x0C40
-#define    UART_B_REGISTER_BASE                 0x0C80
-#define    GPS_CONTROL_REG_BASE                 0x0CC0
-#define    DMA_PORTC_CONTROL_REG_BASE           0x0D00
-#define    DMA_PORTD_CONTROL_REG_BASE           0x0D00
-#define    AES_RANDOM_DATA_BASE                 0x0D80
-#define    AES_KEY_IN_BASE                      0x0D90
-#define    RANDOM_DATA_LIB_BASE                 0x0E00
-#define    IR_DATA_BUFFER_BASE                  0x0F00
-#define    PORTA_TS_BUFFER_BASE                 0x1000
-#define    PORTA_I2S_BUFFER_BASE                0x1400
-#define    PORTB_TS_BUFFER_BASE                 0x1800
-#define    PORTB_I2S_BUFFER_BASE                0x1C00
-
-/* -------- MSI control and state register -------- */
-#define MSI_DELAY_TIMER             (MSI_CONTROL_REG_BASE + 0x00)
-#define MSI_INT_STATUS              (MSI_CONTROL_REG_BASE + 0x08)
-#define MSI_INT_STATUS_CLR          (MSI_CONTROL_REG_BASE + 0x0C)
-#define MSI_INT_STATUS_SET          (MSI_CONTROL_REG_BASE + 0x10)
-#define MSI_INT_ENA                 (MSI_CONTROL_REG_BASE + 0x14)
-#define MSI_INT_ENA_CLR             (MSI_CONTROL_REG_BASE + 0x18)
-#define MSI_INT_ENA_SET             (MSI_CONTROL_REG_BASE + 0x1C)
-#define MSI_SOFT_RESET              (MSI_CONTROL_REG_BASE + 0x20)
-#define MSI_CFG_SRC0                (MSI_CONTROL_REG_BASE + 0x24)
-
-/* -------- Hybird Controller System Control register -------- */
-#define MUX_MODE_CTRL         (SYSTEM_CONTROL_REG_BASE + 0x00)
-	#define rbPaMSMask        0x07
-	#define rbPaMSDtvNoGpio   0x00 /*[2:0], DTV Simple mode */
-	#define rbPaMSDtv4bitGpio 0x01 /*[2:0], DTV TS2 Serial mode)*/
-	#define rbPaMSDtv7bitGpio 0x02 /*[2:0], DTV TS0 Serial mode*/
-	#define rbPaMS8bitGpio    0x03 /*[2:0], GPIO mode selected;(8bit GPIO)*/
-	#define rbPaMSAtv         0x04 /*[2:0], 3'b1xx: ATV mode select*/
-	#define rbPbMSMask        0x38
-	#define rbPbMSDtvNoGpio   0x00 /*[5:3], DTV Simple mode */
-	#define rbPbMSDtv4bitGpio 0x08 /*[5:3], DTV TS2 Serial mode*/
-	#define rbPbMSDtv7bitGpio 0x10 /*[5:3], DTV TS0 Serial mode*/
-	#define rbPbMS8bitGpio    0x18 /*[5:3], GPIO mode selected;(8bit GPIO)*/
-	#define rbPbMSAtv         0x20 /*[5:3], 3'b1xx: ATV mode select*/
-	#define rbPaAESEN         0x40 /*[6], port A AES enable bit*/
-	#define rbPbAESEN         0x80 /*[7], port B AES enable bit*/
-
-#define INTERNAL_RST                (SYSTEM_CONTROL_REG_BASE + 0x04)
-#define PERIPHERAL_CTRL             (SYSTEM_CONTROL_REG_BASE + 0x08)
-#define GPIO_0to7_CTRL              (SYSTEM_CONTROL_REG_BASE + 0x0C)
-#define GPIO_8to15_CTRL             (SYSTEM_CONTROL_REG_BASE + 0x10)
-#define GPIO_16to24_CTRL            (SYSTEM_CONTROL_REG_BASE + 0x14)
-#define GPIO_INT_SRC_CFG            (SYSTEM_CONTROL_REG_BASE + 0x18)
-#define SYS_BUF_STATUS              (SYSTEM_CONTROL_REG_BASE + 0x1C)
-#define PCIE_IP_REG_ACS             (SYSTEM_CONTROL_REG_BASE + 0x20)
-#define PCIE_IP_REG_ACS_ADDR        (SYSTEM_CONTROL_REG_BASE + 0x24)
-#define PCIE_IP_REG_ACS_DATA        (SYSTEM_CONTROL_REG_BASE + 0x28)
-
-/* -------- IR Control register -------- */
-#define   IR_Init_Reg         (IR_CONTROL_REG_BASE + 0x00)
-#define   IR_Idle_Cnt_Low     (IR_CONTROL_REG_BASE + 0x04)
-#define   IR_Idle_Cnt_High    (IR_CONTROL_REG_BASE + 0x05)
-#define   IR_Unit_Cnt_Low     (IR_CONTROL_REG_BASE + 0x06)
-#define   IR_Unit_Cnt_High    (IR_CONTROL_REG_BASE + 0x07)
-#define   IR_Data_Cnt         (IR_CONTROL_REG_BASE + 0x08)
-#define   rbIRen            0x80
-#define   rbIRhighidle      0x10
-#define   rbIRlowidle       0x00
-#define   rbIRVld           0x04
-
-/* -------- I2C A control and state register -------- */
-#define I2C_A_CTL_STATUS                 (I2C_A_CONTROL_REG_BASE + 0x00)
-#define I2C_A_ADDR                       (I2C_A_CONTROL_REG_BASE + 0x04)
-#define I2C_A_SW_CTL                     (I2C_A_CONTROL_REG_BASE + 0x08)
-#define I2C_A_TIME_OUT_CNT               (I2C_A_CONTROL_REG_BASE + 0x0C)
-#define I2C_A_FIFO_STATUS                (I2C_A_CONTROL_REG_BASE + 0x10)
-#define I2C_A_FS_EN                      (I2C_A_CONTROL_REG_BASE + 0x14)
-#define I2C_A_FIFO_DATA                  (I2C_A_CONTROL_REG_BASE + 0x20)
-
-/* -------- I2C B control and state register -------- */
-#define I2C_B_CTL_STATUS                 (I2C_B_CONTROL_REG_BASE + 0x00)
-#define I2C_B_ADDR                       (I2C_B_CONTROL_REG_BASE + 0x04)
-#define I2C_B_SW_CTL                     (I2C_B_CONTROL_REG_BASE + 0x08)
-#define I2C_B_TIME_OUT_CNT               (I2C_B_CONTROL_REG_BASE + 0x0C)
-#define I2C_B_FIFO_STATUS                (I2C_B_CONTROL_REG_BASE + 0x10)
-#define I2C_B_FS_EN                      (I2C_B_CONTROL_REG_BASE + 0x14)
-#define I2C_B_FIFO_DATA                  (I2C_B_CONTROL_REG_BASE + 0x20)
-
-#define VIDEO_CTRL_STATUS_A	(ATV_PORTA_CONTROL_REG_BASE + 0x04)
-
-/* -------- Digital TV control register, Port A -------- */
-#define MPEG2_CTRL_A		(DTV_PORTA_CONTROL_REG_BASE + 0x00)
-#define SERIAL_IN_ADDR_A	(DTV_PORTA_CONTROL_REG_BASE + 0x4C)
-#define VLD_CNT_ADDR_A		(DTV_PORTA_CONTROL_REG_BASE + 0x60)
-#define ERR_CNT_ADDR_A		(DTV_PORTA_CONTROL_REG_BASE + 0x64)
-#define BRD_CNT_ADDR_A		(DTV_PORTA_CONTROL_REG_BASE + 0x68)
-
-/* -------- DMA Control Register, Port A  -------- */
-#define DMA_PORTA_CHAN0_ADDR_LOW        (DMA_PORTA_CONTROL_REG_BASE + 0x00)
-#define DMA_PORTA_CHAN0_ADDR_HI         (DMA_PORTA_CONTROL_REG_BASE + 0x04)
-#define DMA_PORTA_CHAN0_TRANS_STATE     (DMA_PORTA_CONTROL_REG_BASE + 0x08)
-#define DMA_PORTA_CHAN0_CONTROL         (DMA_PORTA_CONTROL_REG_BASE + 0x0C)
-#define DMA_PORTA_CHAN1_ADDR_LOW        (DMA_PORTA_CONTROL_REG_BASE + 0x10)
-#define DMA_PORTA_CHAN1_ADDR_HI         (DMA_PORTA_CONTROL_REG_BASE + 0x14)
-#define DMA_PORTA_CHAN1_TRANS_STATE     (DMA_PORTA_CONTROL_REG_BASE + 0x18)
-#define DMA_PORTA_CHAN1_CONTROL         (DMA_PORTA_CONTROL_REG_BASE + 0x1C)
-#define DMA_PORTA_MANAGEMENT            (DMA_PORTA_CONTROL_REG_BASE + 0x20)
-#define VIDEO_CTRL_STATUS_B             (ATV_PORTB_CONTROL_REG_BASE + 0x04)
-
-/* -------- Digital TV control register, Port B -------- */
-#define MPEG2_CTRL_B		(DTV_PORTB_CONTROL_REG_BASE + 0x00)
-#define SERIAL_IN_ADDR_B	(DTV_PORTB_CONTROL_REG_BASE + 0x4C)
-#define VLD_CNT_ADDR_B		(DTV_PORTB_CONTROL_REG_BASE + 0x60)
-#define ERR_CNT_ADDR_B		(DTV_PORTB_CONTROL_REG_BASE + 0x64)
-#define BRD_CNT_ADDR_B		(DTV_PORTB_CONTROL_REG_BASE + 0x68)
-
-/* -------- AES control register, Port B -------- */
-#define AES_CTRL_B		(AES_PORTB_CONTROL_REG_BASE + 0x00)
-#define AES_KEY_BASE_B	(AES_PORTB_CONTROL_REG_BASE + 0x04)
-
-/* -------- DMA Control Register, Port B  -------- */
-#define DMA_PORTB_CHAN0_ADDR_LOW        (DMA_PORTB_CONTROL_REG_BASE + 0x00)
-#define DMA_PORTB_CHAN0_ADDR_HI         (DMA_PORTB_CONTROL_REG_BASE + 0x04)
-#define DMA_PORTB_CHAN0_TRANS_STATE     (DMA_PORTB_CONTROL_REG_BASE + 0x08)
-#define DMA_PORTB_CHAN0_CONTROL         (DMA_PORTB_CONTROL_REG_BASE + 0x0C)
-#define DMA_PORTB_CHAN1_ADDR_LOW        (DMA_PORTB_CONTROL_REG_BASE + 0x10)
-#define DMA_PORTB_CHAN1_ADDR_HI         (DMA_PORTB_CONTROL_REG_BASE + 0x14)
-#define DMA_PORTB_CHAN1_TRANS_STATE     (DMA_PORTB_CONTROL_REG_BASE + 0x18)
-#define DMA_PORTB_CHAN1_CONTROL         (DMA_PORTB_CONTROL_REG_BASE + 0x1C)
-#define DMA_PORTB_MANAGEMENT            (DMA_PORTB_CONTROL_REG_BASE + 0x20)
-
-#define DMA_TRANS_UNIT_188 (0x00000007)
-
-/* -------- Macro define of 24 interrupt resource --------*/
-#define DMA_A_CHAN0_DONE_INT   (0x00000001)
-#define DMA_A_CHAN1_DONE_INT   (0x00000002)
-#define DMA_B_CHAN0_DONE_INT   (0x00000004)
-#define DMA_B_CHAN1_DONE_INT   (0x00000008)
-#define DMA_C_CHAN0_DONE_INT   (0x00000010)
-#define DMA_C_CHAN1_DONE_INT   (0x00000020)
-#define DMA_D_CHAN0_DONE_INT   (0x00000040)
-#define DMA_D_CHAN1_DONE_INT   (0x00000080)
-#define DATA_BUF_OVERFLOW_INT  (0x00000100)
-#define UART_0_X_INT           (0x00000200)
-#define UART_1_X_INT           (0x00000400)
-#define IR_X_INT               (0x00000800)
-#define GPIO_0_INT             (0x00001000)
-#define GPIO_1_INT             (0x00002000)
-#define GPIO_2_INT             (0x00004000)
-#define GPIO_3_INT             (0x00008000)
-#define ALL_INT                (0x0000FFFF)
-
-/* software I2C bit mask */
-#define SW_I2C_MSK_MODE         0x01
-#define SW_I2C_MSK_CLK_OUT      0x02
-#define SW_I2C_MSK_DAT_OUT      0x04
-#define SW_I2C_MSK_CLK_EN       0x08
-#define SW_I2C_MSK_DAT_EN       0x10
-#define SW_I2C_MSK_DAT_IN       0x40
-#define SW_I2C_MSK_CLK_IN       0x80
-
-#define SMI_VID		0x1ADE
-#define SMI_PID		0x3038
-#define SMI_TS_DMA_BUF_SIZE	(1024 * 188)
-
-struct smi_cfg_info {
-#define SMI_DVBSKY_S952         0
-#define SMI_DVBSKY_S950         1
-#define SMI_DVBSKY_T9580        2
-#define SMI_DVBSKY_T982         3
-	int type;
-	char *name;
-#define SMI_TS_NULL             0
-#define SMI_TS_DMA_SINGLE       1
-#define SMI_TS_DMA_BOTH         3
-/* SMI_TS_NULL: not use;
- * SMI_TS_DMA_SINGLE: use DMA 0 only;
- * SMI_TS_DMA_BOTH:use DMA 0 and 1.*/
-	int ts_0;
-	int ts_1;
-#define DVBSKY_FE_NULL          0
-#define DVBSKY_FE_M88RS6000     1
-#define DVBSKY_FE_M88DS3103     2
-#define DVBSKY_FE_SIT2          3
-	int fe_0;
-	int fe_1;
-};
-
-struct smi_port {
-	struct smi_dev *dev;
-	int idx;
-	int enable;
-	int fe_type;
-	/* regs */
-	u32 DMA_CHAN0_ADDR_LOW;
-	u32 DMA_CHAN0_ADDR_HI;
-	u32 DMA_CHAN0_TRANS_STATE;
-	u32 DMA_CHAN0_CONTROL;
-	u32 DMA_CHAN1_ADDR_LOW;
-	u32 DMA_CHAN1_ADDR_HI;
-	u32 DMA_CHAN1_TRANS_STATE;
-	u32 DMA_CHAN1_CONTROL;
-	u32 DMA_MANAGEMENT;
-	/* dma */
-	dma_addr_t dma_addr[2];
-	u8 *cpu_addr[2];
-	u32 _dmaInterruptCH0;
-	u32 _dmaInterruptCH1;
-	u32 _int_status;
-	struct tasklet_struct tasklet;
-	/* dvb */
-	struct dmx_frontend hw_frontend;
-	struct dmx_frontend mem_frontend;
-	struct dmxdev dmxdev;
-	struct dvb_adapter dvb_adapter;
-	struct dvb_demux demux;
-	struct dvb_net dvbnet;
-	int users;
-	struct dvb_frontend *fe;
-	/* frontend i2c module */
-	struct i2c_client *i2c_client_demod;
-	struct i2c_client *i2c_client_tuner;
-};
-
-struct smi_dev {
-	int nr;
-	struct smi_cfg_info *info;
-
-	/* pcie */
-	struct pci_dev *pci_dev;
-	u32 __iomem *lmmio;
-
-	/* ts port */
-	struct smi_port ts_port[2];
-
-	/* i2c */
-	struct i2c_adapter i2c_bus[2];
-	struct i2c_algo_bit_data i2c_bit[2];
-};
-
-#define smi_read(reg)             readl(dev->lmmio + ((reg)>>2))
-#define smi_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
-
-#define smi_andor(reg, mask, value) \
-	writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
-	((value) & (mask)), dev->lmmio+((reg)>>2))
-
-#define smi_set(reg, bit)          smi_andor((reg), (bit), (bit))
-#define smi_clear(reg, bit)        smi_andor((reg), (bit), 0)
-
-#endif /* #ifndef _SMI_PCIE_H_ */
diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c
index 8cbe6b4..172583d 100644
--- a/drivers/media/pci/solo6x10/solo6x10-core.c
+++ b/drivers/media/pci/solo6x10/solo6x10-core.c
@@ -105,8 +105,11 @@
 	if (!status)
 		return IRQ_NONE;
 
-	/* Acknowledge all interrupts immediately */
-	solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
+	if (status & ~solo_dev->irq_mask) {
+		solo_reg_write(solo_dev, SOLO_IRQ_STAT,
+			       status & ~solo_dev->irq_mask);
+		status &= solo_dev->irq_mask;
+	}
 
 	if (status & SOLO_IRQ_PCI_ERR)
 		solo_p2m_error_isr(solo_dev);
@@ -129,6 +132,9 @@
 	if (status & SOLO_IRQ_G723)
 		solo_g723_isr(solo_dev);
 
+	/* Clear all interrupts handled */
+	solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
+
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 6e933d3..28023f9 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -463,6 +463,7 @@
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
 	int frame_size;
+	int ret;
 
 	vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
 
@@ -472,10 +473,22 @@
 	frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
 	vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
 
-	return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
+	/* may discard all previous data in vbuf->sgl */
+	if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+			DMA_FROM_DEVICE))
+		return -ENOMEM;
+	ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
 			     vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
 			     frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
 			     SOLO_JPEG_EXT_SIZE(solo_dev));
+	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+			DMA_FROM_DEVICE);
+
+	/* add the header only after dma_unmap_sg() */
+	sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+			    solo_enc->jpeg_header, solo_enc->jpeg_len);
+
+	return ret;
 }
 
 static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
@@ -485,6 +498,7 @@
 	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
 	int frame_off, frame_size;
 	int skip = 0;
+	int ret;
 
 	if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
 		return -EIO;
@@ -507,9 +521,21 @@
 		sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
 	frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
 
-	return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
+	/* may discard all previous data in vbuf->sgl */
+	if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+			DMA_FROM_DEVICE))
+		return -ENOMEM;
+	ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
 			SOLO_MP4E_EXT_ADDR(solo_dev),
 			SOLO_MP4E_EXT_SIZE(solo_dev));
+	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+			DMA_FROM_DEVICE);
+
+	/* add the header only after dma_unmap_sg() */
+	if (!vop_type(vh))
+		sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+				    solo_enc->vop, solo_enc->vop_len);
+	return ret;
 }
 
 static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
@@ -677,7 +703,9 @@
 
 		if (timeout == -ERESTARTSYS || kthread_should_stop())
 			break;
+		solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
 		solo_handle_ring(solo_dev);
+		solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
 		try_to_freeze();
 	}
 
@@ -692,10 +720,7 @@
 				unsigned int *num_planes, unsigned int sizes[],
 				void *alloc_ctxs[])
 {
-	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
-
 	sizes[0] = FRAME_BUF_SIZE;
-	alloc_ctxs[0] = solo_enc->alloc_ctx;
 	*num_planes = 1;
 
 	if (*num_buffers < MIN_VID_BUFFERS)
@@ -745,51 +770,26 @@
 static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
 {
 	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
+	int ret;
 
-	return solo_enc_on(solo_enc);
+	ret = solo_enc_on(solo_enc);
+	if (ret)
+		return ret;
+	return solo_ring_start(solo_enc->solo_dev);
 }
 
 static void solo_enc_stop_streaming(struct vb2_queue *q)
 {
 	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
-	unsigned long flags;
 
-	spin_lock_irqsave(&solo_enc->av_lock, flags);
 	solo_enc_off(solo_enc);
-	while (!list_empty(&solo_enc->vidq_active)) {
-		struct solo_vb2_buf *buf = list_entry(
-				solo_enc->vidq_active.next,
-				struct solo_vb2_buf, list);
-
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-	}
-	spin_unlock_irqrestore(&solo_enc->av_lock, flags);
-}
-
-static void solo_enc_buf_finish(struct vb2_buffer *vb)
-{
-	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
-	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
-
-	switch (solo_enc->fmt) {
-	case V4L2_PIX_FMT_MPEG4:
-	case V4L2_PIX_FMT_H264:
-		if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME)
-			sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
-					solo_enc->vop, solo_enc->vop_len);
-		break;
-	default: /* V4L2_PIX_FMT_MJPEG */
-		sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
-				solo_enc->jpeg_header, solo_enc->jpeg_len);
-		break;
-	}
+	INIT_LIST_HEAD(&solo_enc->vidq_active);
+	solo_ring_stop(solo_enc->solo_dev);
 }
 
 static struct vb2_ops solo_enc_video_qops = {
 	.queue_setup	= solo_enc_queue_setup,
 	.buf_queue	= solo_enc_buf_queue,
-	.buf_finish	= solo_enc_buf_finish,
 	.start_streaming = solo_enc_start_streaming,
 	.stop_streaming = solo_enc_stop_streaming,
 	.wait_prepare	= vb2_ops_wait_prepare,
@@ -1263,11 +1263,6 @@
 		return ERR_PTR(-ENOMEM);
 
 	hdl = &solo_enc->hdl;
-	solo_enc->alloc_ctx = vb2_dma_sg_init_ctx(&solo_dev->pdev->dev);
-	if (IS_ERR(solo_enc->alloc_ctx)) {
-		ret = PTR_ERR(solo_enc->alloc_ctx);
-		goto hdl_free;
-	}
 	v4l2_ctrl_handler_init(hdl, 10);
 	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
@@ -1371,7 +1366,6 @@
 			solo_enc->desc_items, solo_enc->desc_dma);
 hdl_free:
 	v4l2_ctrl_handler_free(hdl);
-	vb2_dma_sg_cleanup_ctx(solo_enc->alloc_ctx);
 	kfree(solo_enc);
 	return ERR_PTR(ret);
 }
@@ -1381,12 +1375,8 @@
 	if (solo_enc == NULL)
 		return;
 
-	pci_free_consistent(solo_enc->solo_dev->pdev,
-			sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
-			solo_enc->desc_items, solo_enc->desc_dma);
 	video_unregister_device(solo_enc->vfd);
 	v4l2_ctrl_handler_free(&solo_enc->hdl);
-	vb2_dma_sg_cleanup_ctx(solo_enc->alloc_ctx);
 	kfree(solo_enc);
 }
 
@@ -1429,15 +1419,13 @@
 		 solo_dev->v4l2_enc[0]->vfd->num,
 		 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
 
-	return solo_ring_start(solo_dev);
+	return 0;
 }
 
 void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
 {
 	int i;
 
-	solo_ring_stop(solo_dev);
-
 	for (i = 0; i < solo_dev->nr_chans; i++)
 		solo_enc_free(solo_dev->v4l2_enc[i]);
 
diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index bd8edfa..72017b7 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -180,7 +180,6 @@
 	u32			sequence;
 	struct vb2_queue	vidq;
 	struct list_head	vidq_active;
-	void			*alloc_ctx;
 	int			desc_count;
 	int			desc_nelts;
 	struct solo_p2m_desc	*desc_items;
diff --git a/drivers/media/pci/ttpci/budget-patch.c b/drivers/media/pci/ttpci/budget-patch.c
index a4d8867..2cb35c2 100644
--- a/drivers/media/pci/ttpci/budget-patch.c
+++ b/drivers/media/pci/ttpci/budget-patch.c
@@ -490,7 +490,7 @@
 
 	if(detected == 0)
 		printk("budget-patch not detected or saa7146 in non-default state.\n"
-		       "try enabling resetting of 7146 with MASK_31 in MC1 register\n");
+		       "try enabling ressetting of 7146 with MASK_31 in MC1 register\n");
 
 	else
 		printk("BUDGET-PATCH DETECTED.\n");
diff --git a/drivers/media/pci/tw68/Kconfig b/drivers/media/pci/tw68/Kconfig
index 45b845e..61b3e24 100644
--- a/drivers/media/pci/tw68/Kconfig
+++ b/drivers/media/pci/tw68/Kconfig
@@ -2,6 +2,7 @@
 	tristate "Techwell tw68x Video For Linux"
 	depends on m
 	depends on VIDEO_DEV && PCI && VIDEO_V4L2
+	depends on I2C_ALGOBIT
 	select VIDEOBUF2_DMA_SG
 	---help---
 	  Support for Techwell tw68xx based frame grabber boards.
diff --git a/drivers/media/pci/tw68/tw68-core.c b/drivers/media/pci/tw68/tw68-core.c
index c135165..a6fb48c 100644
--- a/drivers/media/pci/tw68/tw68-core.c
+++ b/drivers/media/pci/tw68/tw68-core.c
@@ -304,19 +304,13 @@
 	/* Then do any initialisation wanted before interrupts are on */
 	tw68_hw_init1(dev);
 
-	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
-	if (IS_ERR(dev->alloc_ctx)) {
-		err = PTR_ERR(dev->alloc_ctx);
-		goto fail3;
-	}
-
 	/* get irq */
 	err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw68_irq,
-			  IRQF_SHARED, dev->name, dev);
+			  IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
 	if (err < 0) {
 		pr_err("%s: can't get IRQ %d\n",
 		       dev->name, pci_dev->irq);
-		goto fail4;
+		goto fail3;
 	}
 
 	/*
@@ -330,7 +324,7 @@
 	if (err < 0) {
 		pr_err("%s: can't register video device\n",
 		       dev->name);
-		goto fail5;
+		goto fail4;
 	}
 	tw_setl(TW68_INTMASK, dev->pci_irqmask);
 
@@ -339,10 +333,8 @@
 
 	return 0;
 
-fail5:
-	video_unregister_device(&dev->vdev);
 fail4:
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
+	video_unregister_device(&dev->vdev);
 fail3:
 	iounmap(dev->lmmio);
 fail2:
@@ -366,7 +358,6 @@
 	/* unregister */
 	video_unregister_device(&dev->vdev);
 	v4l2_ctrl_handler_free(&dev->hdl);
-	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 
 	/* release resources */
 	iounmap(dev->lmmio);
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index abe6314..25f0cc8 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -384,7 +384,6 @@
 	unsigned tot_bufs = q->num_buffers + *num_buffers;
 
 	sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
-	alloc_ctxs[0] = dev->alloc_ctx;
 	/*
 	 * We allow create_bufs, but only if the sizeimage is the same as the
 	 * current sizeimage. The tw68_buffer_count calculation becomes quite
@@ -462,12 +461,17 @@
 	struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
 	unsigned size, bpl;
+	int rc;
 
 	size = (dev->width * dev->height * dev->fmt->depth) >> 3;
 	if (vb2_plane_size(vb, 0) < size)
 		return -EINVAL;
 	vb2_set_plane_payload(vb, 0, size);
 
+	rc = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+	if (!rc)
+		return -EIO;
+
 	bpl = (dev->width * dev->fmt->depth) >> 3;
 	switch (dev->field) {
 	case V4L2_FIELD_TOP:
@@ -501,8 +505,11 @@
 {
 	struct vb2_queue *vq = vb->vb2_queue;
 	struct tw68_dev *dev = vb2_get_drv_priv(vq);
+	struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
 	struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
 
+	dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+
 	pci_free_consistent(dev->pci, buf->size, buf->cpu, buf->dma);
 }
 
diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h
index 7a7501b..2c8abe2 100644
--- a/drivers/media/pci/tw68/tw68.h
+++ b/drivers/media/pci/tw68/tw68.h
@@ -181,7 +181,6 @@
 	unsigned		field;
 	struct vb2_queue	vidq;
 	struct list_head	active;
-	void			*alloc_ctx;
 
 	/* various v4l controls */
 	const struct tw68_tvnorm *tvnorm;	/* video */
diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c
index 2b25d31..099d5fb 100644
--- a/drivers/media/pci/zoran/zoran_driver.c
+++ b/drivers/media/pci/zoran/zoran_driver.c
@@ -1528,9 +1528,8 @@
 	strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
 	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
 		 pci_name(zr->pci_dev));
-	cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
-			   V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
+			    V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
 	return 0;
 }
 
diff --git a/drivers/media/pci/zoran/zoran_procfs.c b/drivers/media/pci/zoran/zoran_procfs.c
index 4376527..f7ceee0 100644
--- a/drivers/media/pci/zoran/zoran_procfs.c
+++ b/drivers/media/pci/zoran/zoran_procfs.c
@@ -157,8 +157,8 @@
 		return -EFAULT;
 	}
 	string[count] = 0;
-	dprintk(4, KERN_INFO "%s: write_proc: name=%pD count=%zu zr=%p\n",
-		ZR_DEVNAME(zr), file, count, zr);
+	dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
+		ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
 	ldelim = " \t\n";
 	tdelim = "=";
 	line = strpbrk(sp, ldelim);
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 4a5f12a..56ec66e 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -58,7 +58,7 @@
 	  In doubt, say N.
 
 config VIDEO_TIMBERDALE
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Support for timberdale Video In/LogiWIN"
 	depends on m
 	depends on VIDEO_V4L2 && I2C && DMADEVICES
@@ -70,6 +70,15 @@
 	---help---
 	  Add support for the Video In peripherial of the timberdale FPGA.
 
+config VIDEO_VINO
+	tristate "SGI Vino Video For Linux"
+	depends on m
+	depends on I2C && SGI_IP22 && VIDEO_V4L2
+	select VIDEO_SAA7191 if MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y here to build in support for the Vino video input system found
+	  on SGI Indy machines.
+
 config VIDEO_M32R_AR
 	tristate "AR devices"
 	depends on m
@@ -113,7 +122,7 @@
 	tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
 	depends on m
 	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
-	depends on PM
+	depends on PM_RUNTIME
 	depends on ARCH_S3C64XX || PLAT_S3C24XX || COMPILE_TEST
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
@@ -157,7 +166,7 @@
 	   H.264, MPEG-4, and other video formats.
 
 config VIDEO_MEM2MEM_DEINTERLACE
-	depends on !KERNEL_3_3
+	depends on !BACKPORT_KERNEL_3_3
 	tristate "Deinterlace support"
 	depends on m
 	depends on VIDEO_DEV && VIDEO_V4L2 && DMA_ENGINE
@@ -171,7 +180,7 @@
 	tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver"
 	depends on m
 	depends on VIDEO_DEV && VIDEO_V4L2
-	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+	depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
@@ -184,7 +193,7 @@
 	tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver"
 	depends on m
 	depends on VIDEO_DEV && VIDEO_V4L2
-	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+	depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
@@ -196,7 +205,7 @@
 	tristate "Samsung S5P MFC Video Codec"
 	depends on m
 	depends on VIDEO_DEV && VIDEO_V4L2
-	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+	depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
 	default n
@@ -239,7 +248,7 @@
 	    SH-Mobile SoCs.
 
 config VIDEO_RENESAS_VSP1
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Renesas VSP1 Video Processing Engine"
 	depends on m
 	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA
@@ -280,8 +289,8 @@
 
 source "drivers/media/platform/vivid/Kconfig"
 
-config VIDEO_VIM2M
-	tristate "Virtual Memory-to-Memory Driver"
+config VIDEO_MEM2MEM_TESTDEV
+	tristate "Virtual test device for mem2mem framework"
 	depends on m
 	depends on VIDEO_DEV && VIDEO_V4L2
 	select VIDEOBUF2_VMALLOC
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 6449a06..140e3e5 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -2,6 +2,9 @@
 # Makefile for the video capture/playback device drivers.
 #
 
+obj-$(CPTCFG_VIDEO_VINO) += indycam.o
+obj-$(CPTCFG_VIDEO_VINO) += vino.o
+
 obj-$(CPTCFG_VIDEO_TIMBERDALE)	+= timblogiw.o
 obj-$(CPTCFG_VIDEO_M32R_AR_M64278) += arv.o
 
@@ -14,7 +17,7 @@
 obj-$(CPTCFG_VIDEO_VIU) += fsl-viu.o
 
 obj-$(CPTCFG_VIDEO_VIVID)		+= vivid/
-obj-$(CPTCFG_VIDEO_VIM2M)		+= vim2m.o
+obj-$(CPTCFG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
 
 obj-$(CPTCFG_VIDEO_TI_VPE)		+= ti-vpe/
 
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index 8f66986..9b5daa6 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -49,7 +49,7 @@
 struct bcap_format {
 	char *desc;
 	u32 pixelformat;
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 	int bpp; /* bits per pixel */
 	int dlen; /* data length for ppi in bits */
 };
@@ -116,35 +116,35 @@
 	{
 		.desc        = "YCbCr 4:2:2 Interleaved UYVY",
 		.pixelformat = V4L2_PIX_FMT_UYVY,
-		.mbus_code   = MEDIA_BUS_FMT_UYVY8_2X8,
+		.mbus_code   = V4L2_MBUS_FMT_UYVY8_2X8,
 		.bpp         = 16,
 		.dlen        = 8,
 	},
 	{
 		.desc        = "YCbCr 4:2:2 Interleaved YUYV",
 		.pixelformat = V4L2_PIX_FMT_YUYV,
-		.mbus_code   = MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code   = V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp         = 16,
 		.dlen        = 8,
 	},
 	{
 		.desc        = "YCbCr 4:2:2 Interleaved UYVY",
 		.pixelformat = V4L2_PIX_FMT_UYVY,
-		.mbus_code   = MEDIA_BUS_FMT_UYVY8_1X16,
+		.mbus_code   = V4L2_MBUS_FMT_UYVY8_1X16,
 		.bpp         = 16,
 		.dlen        = 16,
 	},
 	{
 		.desc        = "RGB 565",
 		.pixelformat = V4L2_PIX_FMT_RGB565,
-		.mbus_code   = MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.mbus_code   = V4L2_MBUS_FMT_RGB565_2X8_LE,
 		.bpp         = 16,
 		.dlen        = 8,
 	},
 	{
 		.desc        = "RGB 444",
 		.pixelformat = V4L2_PIX_FMT_RGB444,
-		.mbus_code   = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE,
+		.mbus_code   = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
 		.bpp         = 16,
 		.dlen        = 8,
 	},
@@ -161,7 +161,7 @@
 
 static int bcap_init_sensor_formats(struct bcap_device *bcap_dev)
 {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	struct bcap_format *sf;
 	unsigned int num_formats = 0;
 	int i, j;
@@ -349,6 +349,18 @@
 	spin_unlock_irqrestore(&bcap_dev->lock, flags);
 }
 
+static void bcap_lock(struct vb2_queue *vq)
+{
+	struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
+	mutex_lock(&bcap_dev->mutex);
+}
+
+static void bcap_unlock(struct vb2_queue *vq)
+{
+	struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
+	mutex_unlock(&bcap_dev->mutex);
+}
+
 static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
@@ -445,8 +457,8 @@
 	.buf_prepare            = bcap_buffer_prepare,
 	.buf_cleanup            = bcap_buffer_cleanup,
 	.buf_queue              = bcap_buffer_queue,
-	.wait_prepare           = vb2_ops_wait_prepare,
-	.wait_finish            = vb2_ops_wait_finish,
+	.wait_prepare           = bcap_unlock,
+	.wait_finish            = bcap_lock,
 	.start_streaming        = bcap_start_streaming,
 	.stop_streaming         = bcap_stop_streaming,
 };
@@ -829,8 +841,7 @@
 {
 	struct bcap_device *bcap_dev = video_drvdata(file);
 
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 	strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
 	strlcpy(cap->bus_info, "Blackfin Platform", sizeof(cap->bus_info));
 	strlcpy(cap->card, bcap_dev->cfg->card_name, sizeof(cap->card));
@@ -984,7 +995,6 @@
 	q->ops = &bcap_video_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	q->lock = &bcap_dev->mutex;
 
 	ret = vb2_queue_init(q);
 	if (ret)
@@ -1120,6 +1130,7 @@
 static struct platform_driver bcap_driver = {
 	.driver = {
 		.name  = CAPTURE_DRV_NAME,
+		.owner = THIS_MODULE,
 	},
 	.probe = bcap_probe,
 	.remove = bcap_remove,
diff --git a/drivers/media/platform/coda/Makefile b/drivers/media/platform/coda/Makefile
index eee8998..fb7529f 100644
--- a/drivers/media/platform/coda/Makefile
+++ b/drivers/media/platform/coda/Makefile
@@ -1,3 +1,3 @@
-coda-objs := coda-common.o coda-bit.o coda-h264.o coda-jpeg.o
+coda-objs := coda-common.o coda-bit.o coda-h264.o
 
 obj-$(CPTCFG_VIDEO_CODA) += coda.o
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index b4029ae..9b8ea8b 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -217,34 +217,11 @@
 void coda_fill_bitstream(struct coda_ctx *ctx)
 {
 	struct vb2_buffer *src_buf;
-	struct coda_buffer_meta *meta;
-	u32 start;
+	struct coda_timestamp *ts;
 
 	while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
-		/*
-		 * Only queue a single JPEG into the bitstream buffer, except
-		 * to increase payload over 512 bytes or if in hold state.
-		 */
-		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
-		    (coda_get_bitstream_payload(ctx) >= 512) && !ctx->hold)
-			break;
-
 		src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
 
-		/* Drop frames that do not start/end with a SOI/EOI markers */
-		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
-		    !coda_jpeg_check_buffer(ctx, src_buf)) {
-			v4l2_err(&ctx->dev->v4l2_dev,
-				 "dropping invalid JPEG frame\n");
-			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
-			continue;
-		}
-
-		/* Buffer start position */
-		start = ctx->bitstream_fifo.kfifo.in &
-			ctx->bitstream_fifo.kfifo.mask;
-
 		if (coda_bitstream_try_queue(ctx, src_buf)) {
 			/*
 			 * Source buffer is queued in the bitstream ringbuffer;
@@ -252,16 +229,12 @@
 			 */
 			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 
-			meta = kmalloc(sizeof(*meta), GFP_KERNEL);
-			if (meta) {
-				meta->sequence = src_buf->v4l2_buf.sequence;
-				meta->timecode = src_buf->v4l2_buf.timecode;
-				meta->timestamp = src_buf->v4l2_buf.timestamp;
-				meta->start = start;
-				meta->end = ctx->bitstream_fifo.kfifo.in &
-					    ctx->bitstream_fifo.kfifo.mask;
-				list_add_tail(&meta->list,
-					      &ctx->buffer_meta_list);
+			ts = kmalloc(sizeof(*ts), GFP_KERNEL);
+			if (ts) {
+				ts->sequence = src_buf->v4l2_buf.sequence;
+				ts->timecode = src_buf->v4l2_buf.timecode;
+				ts->timestamp = src_buf->v4l2_buf.timestamp;
+				list_add_tail(&ts->list, &ctx->timestamp_list);
 			}
 
 			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
@@ -718,7 +691,6 @@
 	struct vb2_buffer *buf;
 	int gamma, ret, value;
 	u32 dst_fourcc;
-	u32 stride;
 
 	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -738,14 +710,6 @@
 		return -EFAULT;
 	}
 
-	if (dst_fourcc == V4L2_PIX_FMT_JPEG) {
-		if (!ctx->params.jpeg_qmat_tab[0])
-			ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL);
-		if (!ctx->params.jpeg_qmat_tab[1])
-			ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL);
-		coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality);
-	}
-
 	mutex_lock(&dev->coda_mutex);
 
 	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
@@ -765,10 +729,10 @@
 		break;
 	}
 
-	ctx->frame_mem_ctrl &= ~CODA_FRAME_CHROMA_INTERLEAVE;
-	if (q_data_src->fourcc == V4L2_PIX_FMT_NV12)
-		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
-	coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
+	value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL);
+	value &= ~(1 << 2 | 0x7 << 9);
+	ctx->frame_mem_ctrl = value;
+	coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL);
 
 	if (dev->devtype->product == CODA_DX6) {
 		/* Configure the coda */
@@ -777,7 +741,6 @@
 	}
 
 	/* Could set rotation here if needed */
-	value = 0;
 	switch (dev->devtype->product) {
 	case CODA_DX6:
 		value = (q_data_src->width & CODADX6_PICWIDTH_MASK)
@@ -801,8 +764,6 @@
 			 << CODA_PICHEIGHT_OFFSET;
 	}
 	coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE);
-	if (dst_fourcc == V4L2_PIX_FMT_JPEG)
-		ctx->params.framerate = 0;
 	coda_write(dev, ctx->params.framerate,
 		   CODA_CMD_ENC_SEQ_SRC_F_RATE);
 
@@ -836,16 +797,6 @@
 		}
 		coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
 		break;
-	case V4L2_PIX_FMT_JPEG:
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_PARA);
-		coda_write(dev, ctx->params.jpeg_restart_interval,
-				CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL);
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_EN);
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE);
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET);
-
-		coda_jpeg_write_tables(ctx);
-		break;
 	default:
 		v4l2_err(v4l2_dev,
 			 "dst format (0x%08x) invalid.\n", dst_fourcc);
@@ -853,36 +804,28 @@
 		goto out;
 	}
 
-	/*
-	 * slice mode and GOP size registers are used for thumb size/offset
-	 * in JPEG mode
-	 */
-	if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
-		switch (ctx->params.slice_mode) {
-		case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
-			value = 0;
-			break;
-		case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
-			value  = (ctx->params.slice_max_mb &
-				  CODA_SLICING_SIZE_MASK)
-				 << CODA_SLICING_SIZE_OFFSET;
-			value |= (1 & CODA_SLICING_UNIT_MASK)
-				 << CODA_SLICING_UNIT_OFFSET;
-			value |=  1 & CODA_SLICING_MODE_MASK;
-			break;
-		case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
-			value  = (ctx->params.slice_max_bits &
-				  CODA_SLICING_SIZE_MASK)
-				 << CODA_SLICING_SIZE_OFFSET;
-			value |= (0 & CODA_SLICING_UNIT_MASK)
-				 << CODA_SLICING_UNIT_OFFSET;
-			value |=  1 & CODA_SLICING_MODE_MASK;
-			break;
-		}
-		coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
-		value = ctx->params.gop_size & CODA_GOP_SIZE_MASK;
-		coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
+	switch (ctx->params.slice_mode) {
+	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
+		value = 0;
+		break;
+	case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
+		value  = (ctx->params.slice_max_mb & CODA_SLICING_SIZE_MASK)
+			 << CODA_SLICING_SIZE_OFFSET;
+		value |= (1 & CODA_SLICING_UNIT_MASK)
+			 << CODA_SLICING_UNIT_OFFSET;
+		value |=  1 & CODA_SLICING_MODE_MASK;
+		break;
+	case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
+		value  = (ctx->params.slice_max_bits & CODA_SLICING_SIZE_MASK)
+			 << CODA_SLICING_SIZE_OFFSET;
+		value |= (0 & CODA_SLICING_UNIT_MASK)
+			 << CODA_SLICING_UNIT_OFFSET;
+		value |=  1 & CODA_SLICING_MODE_MASK;
+		break;
 	}
+	coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
+	value = ctx->params.gop_size & CODA_GOP_SIZE_MASK;
+	coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
 
 	if (ctx->params.bitrate) {
 		/* Rate control enabled */
@@ -973,24 +916,19 @@
 		goto out;
 	}
 
-	if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
-		if (dev->devtype->product == CODA_960)
-			ctx->num_internal_frames = 4;
-		else
-			ctx->num_internal_frames = 2;
-		ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
-		if (ret < 0) {
-			v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
-			goto out;
-		}
-		stride = q_data_src->bytesperline;
-	} else {
-		ctx->num_internal_frames = 0;
-		stride = 0;
+	if (dev->devtype->product == CODA_960)
+		ctx->num_internal_frames = 4;
+	else
+		ctx->num_internal_frames = 2;
+	ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
+		goto out;
 	}
-	coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
-	coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE);
 
+	coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
+	coda_write(dev, q_data_src->bytesperline,
+			CODA_CMD_SET_FRAME_BUF_STRIDE);
 	if (dev->devtype->product == CODA_7541) {
 		coda_write(dev, q_data_src->bytesperline,
 				CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
@@ -1098,10 +1036,9 @@
 	struct coda_dev *dev = ctx->dev;
 	int force_ipicture;
 	int quant_param = 0;
+	u32 picture_y, picture_cb, picture_cr;
 	u32 pic_stream_buffer_addr, pic_stream_buffer_size;
-	u32 rot_mode = 0;
 	u32 dst_fourcc;
-	u32 reg;
 
 	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
@@ -1139,7 +1076,7 @@
 			ctx->vpu_header_size[0] +
 			ctx->vpu_header_size[1] +
 			ctx->vpu_header_size[2];
-		pic_stream_buffer_size = q_data_dst->sizeimage -
+		pic_stream_buffer_size = CODA_MAX_FRAME_SIZE -
 			ctx->vpu_header_size[0] -
 			ctx->vpu_header_size[1] -
 			ctx->vpu_header_size[2];
@@ -1153,7 +1090,7 @@
 	} else {
 		pic_stream_buffer_addr =
 			vb2_dma_contig_plane_dma_addr(dst_buf, 0);
-		pic_stream_buffer_size = q_data_dst->sizeimage;
+		pic_stream_buffer_size = CODA_MAX_FRAME_SIZE;
 	}
 
 	if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
@@ -1165,9 +1102,6 @@
 		case V4L2_PIX_FMT_MPEG4:
 			quant_param = ctx->params.mpeg4_intra_qp;
 			break;
-		case V4L2_PIX_FMT_JPEG:
-			quant_param = 30;
-			break;
 		default:
 			v4l2_warn(&ctx->dev->v4l2_dev,
 				"cannot set intra qp, fmt not supported\n");
@@ -1190,22 +1124,42 @@
 	}
 
 	/* submit */
-	if (ctx->params.rot_mode)
-		rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode;
-	coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE);
+	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
+		   CODA_CMD_ENC_PIC_ROT_MODE);
 	coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS);
 
+
+	picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+	switch (q_data_src->fourcc) {
+	case V4L2_PIX_FMT_YVU420:
+		/* Switch Cb and Cr for YVU420 format */
+		picture_cr = picture_y + q_data_src->bytesperline *
+				q_data_src->height;
+		picture_cb = picture_cr + q_data_src->bytesperline / 2 *
+				q_data_src->height / 2;
+		break;
+	case V4L2_PIX_FMT_YUV420:
+	default:
+		picture_cb = picture_y + q_data_src->bytesperline *
+				q_data_src->height;
+		picture_cr = picture_cb + q_data_src->bytesperline / 2 *
+				q_data_src->height / 2;
+		break;
+	}
+
 	if (dev->devtype->product == CODA_960) {
 		coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX);
 		coda_write(dev, q_data_src->width, CODA9_CMD_ENC_PIC_SRC_STRIDE);
 		coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC);
 
-		reg = CODA9_CMD_ENC_PIC_SRC_ADDR_Y;
+		coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y);
+		coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB);
+		coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR);
 	} else {
-		reg = CODA_CMD_ENC_PIC_SRC_ADDR_Y;
+		coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
+		coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
+		coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
 	}
-	coda_write_base(ctx, q_data_src, src_buf, reg);
-
 	coda_write(dev, force_ipicture << 1 & 0x2,
 		   CODA_CMD_ENC_PIC_OPTION);
 
@@ -1339,7 +1293,7 @@
 	u32 bitstream_buf, bitstream_size;
 	struct coda_dev *dev = ctx->dev;
 	int width, height;
-	u32 src_fourcc, dst_fourcc;
+	u32 src_fourcc;
 	u32 val;
 	int ret;
 
@@ -1349,7 +1303,6 @@
 	bitstream_buf = ctx->bitstream.paddr;
 	bitstream_size = ctx->bitstream.size;
 	src_fourcc = q_data_src->fourcc;
-	dst_fourcc = q_data_dst->fourcc;
 
 	/* Allocate per-instance buffers */
 	ret = coda_alloc_context_buffers(ctx, q_data_src);
@@ -1361,11 +1314,6 @@
 	/* Update coda bitstream read and write pointers from kfifo */
 	coda_kfifo_sync_to_device_full(ctx);
 
-	ctx->frame_mem_ctrl &= ~CODA_FRAME_CHROMA_INTERLEAVE;
-	if (dst_fourcc == V4L2_PIX_FMT_NV12)
-		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
-	coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
-
 	ctx->display_idx = -1;
 	ctx->frm_dis_flg = 0;
 	coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
@@ -1379,8 +1327,6 @@
 	if ((dev->devtype->product == CODA_7541) ||
 	    (dev->devtype->product == CODA_960))
 		val |= CODA_REORDER_ENABLE;
-	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG)
-		val |= CODA_NO_INT_ENABLE;
 	coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
 
 	ctx->params.codec_mode = ctx->codec->mode;
@@ -1496,23 +1442,13 @@
 	}
 
 	if (dev->devtype->product == CODA_960) {
-		int cbb_size, crb_size;
-
 		coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
-		/* Luma 2x0 page, 2x6 cache, chroma 2x0 page, 2x4 cache size */
-		coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE);
 
-		if (dst_fourcc == V4L2_PIX_FMT_NV12) {
-			cbb_size = 0;
-			crb_size = 16;
-		} else {
-			cbb_size = 8;
-			crb_size = 8;
-		}
+		coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE);
 		coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET |
 				32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
-				cbb_size << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
-				crb_size << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
+				8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
+				8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
 				CODA9_CMD_SET_FRAME_CACHE_CONFIG);
 	}
 
@@ -1565,11 +1501,20 @@
 	struct vb2_buffer *dst_buf;
 	struct coda_dev *dev = ctx->dev;
 	struct coda_q_data *q_data_dst;
-	u32 reg_addr, reg_stride;
+	u32 stridey, height;
+	u32 picture_y, picture_cb, picture_cr;
 
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 
+	if (ctx->params.rot_mode & CODA_ROT_90) {
+		stridey = q_data_dst->height;
+		height = q_data_dst->width;
+	} else {
+		stridey = q_data_dst->width;
+		height = q_data_dst->height;
+	}
+
 	/* Try to copy source buffer contents into the bitstream ringbuffer */
 	mutex_lock(&ctx->bitstream_mutex);
 	coda_fill_bitstream(ctx);
@@ -1600,6 +1545,17 @@
 	if (dev->devtype->product == CODA_960)
 		coda_set_gdi_regs(ctx);
 
+	/* Set rotator output */
+	picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) {
+		/* Switch Cr and Cb for YVU420 format */
+		picture_cr = picture_y + stridey * height;
+		picture_cb = picture_cr + stridey / 2 * height / 2;
+	} else {
+		picture_cb = picture_y + stridey * height;
+		picture_cr = picture_cb + stridey / 2 * height / 2;
+	}
+
 	if (dev->devtype->product == CODA_960) {
 		/*
 		 * The CODA960 seems to have an internal list of buffers with
@@ -1609,16 +1565,16 @@
 		 */
 		coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->v4l2_buf.index,
 				CODA9_CMD_DEC_PIC_ROT_INDEX);
-
-		reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
-		reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE;
+		coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y);
+		coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB);
+		coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR);
+		coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE);
 	} else {
-		reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y;
-		reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE;
+		coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
+		coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
+		coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
+		coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
 	}
-	coda_write_base(ctx, q_data_dst, dst_buf, reg_addr);
-	coda_write(dev, q_data_dst->bytesperline, reg_stride);
-
 	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
 			CODA_CMD_DEC_PIC_ROT_MODE);
 
@@ -1643,26 +1599,6 @@
 		coda_write(dev, ctx->iram_info.axi_sram_use,
 				CODA7_REG_BIT_AXI_SRAM_USE);
 
-	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) {
-		struct coda_buffer_meta *meta;
-
-		/* If this is the last buffer in the bitstream, add padding */
-		meta = list_first_entry(&ctx->buffer_meta_list,
-				      struct coda_buffer_meta, list);
-		if (meta->end == (ctx->bitstream_fifo.kfifo.in &
-				  ctx->bitstream_fifo.kfifo.mask)) {
-			static unsigned char buf[512];
-			unsigned int pad;
-
-			/* Pad to multiple of 256 and then add 256 more */
-			pad = ((0 - meta->end) & 0xff) + 256;
-
-			memset(buf, 0xff, sizeof(buf));
-
-			kfifo_in(&ctx->bitstream_fifo, buf, pad);
-		}
-	}
-
 	coda_kfifo_sync_to_device_full(ctx);
 
 	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
@@ -1676,8 +1612,7 @@
 	struct coda_q_data *q_data_src;
 	struct coda_q_data *q_data_dst;
 	struct vb2_buffer *dst_buf;
-	struct coda_buffer_meta *meta;
-	unsigned long payload;
+	struct coda_timestamp *ts;
 	int width, height;
 	int decoded_idx;
 	int display_idx;
@@ -1804,23 +1739,23 @@
 		val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1;
 		val -= ctx->sequence_offset;
 		mutex_lock(&ctx->bitstream_mutex);
-		if (!list_empty(&ctx->buffer_meta_list)) {
-			meta = list_first_entry(&ctx->buffer_meta_list,
-					      struct coda_buffer_meta, list);
-			list_del(&meta->list);
-			if (val != (meta->sequence & 0xffff)) {
+		if (!list_empty(&ctx->timestamp_list)) {
+			ts = list_first_entry(&ctx->timestamp_list,
+					      struct coda_timestamp, list);
+			list_del(&ts->list);
+			if (val != (ts->sequence & 0xffff)) {
 				v4l2_err(&dev->v4l2_dev,
 					 "sequence number mismatch (%d(%d) != %d)\n",
 					 val, ctx->sequence_offset,
-					 meta->sequence);
+					 ts->sequence);
 			}
-			ctx->frame_metas[decoded_idx] = *meta;
-			kfree(meta);
+			ctx->frame_timestamps[decoded_idx] = *ts;
+			kfree(ts);
 		} else {
 			v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n");
-			memset(&ctx->frame_metas[decoded_idx], 0,
-			       sizeof(struct coda_buffer_meta));
-			ctx->frame_metas[decoded_idx].sequence = val;
+			memset(&ctx->frame_timestamps[decoded_idx], 0,
+			       sizeof(struct coda_timestamp));
+			ctx->frame_timestamps[decoded_idx].sequence = val;
 		}
 		mutex_unlock(&ctx->bitstream_mutex);
 
@@ -1859,22 +1794,11 @@
 					     V4L2_BUF_FLAG_PFRAME |
 					     V4L2_BUF_FLAG_BFRAME);
 		dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx];
-		meta = &ctx->frame_metas[ctx->display_idx];
-		dst_buf->v4l2_buf.timecode = meta->timecode;
-		dst_buf->v4l2_buf.timestamp = meta->timestamp;
+		ts = &ctx->frame_timestamps[ctx->display_idx];
+		dst_buf->v4l2_buf.timecode = ts->timecode;
+		dst_buf->v4l2_buf.timestamp = ts->timestamp;
 
-		switch (q_data_dst->fourcc) {
-		case V4L2_PIX_FMT_YUV420:
-		case V4L2_PIX_FMT_YVU420:
-		case V4L2_PIX_FMT_NV12:
-		default:
-			payload = width * height * 3 / 2;
-			break;
-		case V4L2_PIX_FMT_YUV422P:
-			payload = width * height * 2;
-			break;
-		}
-		vb2_set_plane_payload(dst_buf, 0, payload);
+		vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2);
 
 		v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ?
 				  VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 0813f46..ced4760 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -43,7 +43,6 @@
 #define CODA_NAME		"coda"
 
 #define CODADX6_MAX_INSTANCES	4
-#define CODA_MAX_FORMATS	4
 
 #define CODA_PARA_BUF_SIZE	(10 * 1024)
 #define CODA_ISRAM_SIZE	(2048 * 2)
@@ -83,34 +82,6 @@
 	return data;
 }
 
-void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
-		     struct vb2_buffer *buf, unsigned int reg_y)
-{
-	u32 base_y = vb2_dma_contig_plane_dma_addr(buf, 0);
-	u32 base_cb, base_cr;
-
-	switch (q_data->fourcc) {
-	case V4L2_PIX_FMT_YVU420:
-		/* Switch Cb and Cr for YVU420 format */
-		base_cr = base_y + q_data->bytesperline * q_data->height;
-		base_cb = base_cr + q_data->bytesperline * q_data->height / 4;
-		break;
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_NV12:
-	default:
-		base_cb = base_y + q_data->bytesperline * q_data->height;
-		base_cr = base_cb + q_data->bytesperline * q_data->height / 4;
-		break;
-	case V4L2_PIX_FMT_YUV422P:
-		base_cb = base_y + q_data->bytesperline * q_data->height;
-		base_cr = base_cb + q_data->bytesperline * q_data->height / 2;
-	}
-
-	coda_write(ctx->dev, base_y, reg_y);
-	coda_write(ctx->dev, base_cb, reg_y + 4);
-	coda_write(ctx->dev, base_cr, reg_y + 8);
-}
-
 /*
  * Array of all formats supported by any version of Coda:
  */
@@ -124,14 +95,6 @@
 		.fourcc = V4L2_PIX_FMT_YVU420,
 	},
 	{
-		.name = "YUV 4:2:0 Partial interleaved Y/CbCr",
-		.fourcc = V4L2_PIX_FMT_NV12,
-	},
-	{
-		.name = "YUV 4:2:2 Planar, YCbCr",
-		.fourcc = V4L2_PIX_FMT_YUV422P,
-	},
-	{
 		.name = "H264 Encoded Stream",
 		.fourcc = V4L2_PIX_FMT_H264,
 	},
@@ -139,10 +102,6 @@
 		.name = "MPEG4 Encoded Stream",
 		.fourcc = V4L2_PIX_FMT_MPEG4,
 	},
-	{
-		.name = "JPEG Encoded Images",
-		.fourcc = V4L2_PIX_FMT_JPEG,
-	},
 };
 
 #define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \
@@ -163,10 +122,8 @@
 static const struct coda_codec coda7_codecs[] = {
 	CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   1280, 720),
 	CODA_CODEC(CODA7_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4,  1280, 720),
-	CODA_CODEC(CODA7_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG,   8192, 8192),
 	CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1088),
 	CODA_CODEC(CODA7_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA7_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG,   V4L2_PIX_FMT_YUV420, 8192, 8192),
 };
 
 static const struct coda_codec coda9_codecs[] = {
@@ -176,115 +133,17 @@
 	CODA_CODEC(CODA9_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1088),
 };
 
-struct coda_video_device {
-	const char *name;
-	enum coda_inst_type type;
-	const struct coda_context_ops *ops;
-	u32 src_formats[CODA_MAX_FORMATS];
-	u32 dst_formats[CODA_MAX_FORMATS];
-};
-
-static const struct coda_video_device coda_bit_encoder = {
-	.name = "coda-encoder",
-	.type = CODA_INST_ENCODER,
-	.ops = &coda_bit_encode_ops,
-	.src_formats = {
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		V4L2_PIX_FMT_NV12,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_H264,
-		V4L2_PIX_FMT_MPEG4,
-	},
-};
-
-static const struct coda_video_device coda_bit_jpeg_encoder = {
-	.name = "coda-jpeg-encoder",
-	.type = CODA_INST_ENCODER,
-	.ops = &coda_bit_encode_ops,
-	.src_formats = {
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV422P,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_JPEG,
-	},
-};
-
-static const struct coda_video_device coda_bit_decoder = {
-	.name = "coda-decoder",
-	.type = CODA_INST_DECODER,
-	.ops = &coda_bit_decode_ops,
-	.src_formats = {
-		V4L2_PIX_FMT_H264,
-		V4L2_PIX_FMT_MPEG4,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		V4L2_PIX_FMT_NV12,
-	},
-};
-
-static const struct coda_video_device coda_bit_jpeg_decoder = {
-	.name = "coda-jpeg-decoder",
-	.type = CODA_INST_DECODER,
-	.ops = &coda_bit_decode_ops,
-	.src_formats = {
-		V4L2_PIX_FMT_JPEG,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV422P,
-	},
-};
-
-static const struct coda_video_device *codadx6_video_devices[] = {
-	&coda_bit_encoder,
-};
-
-static const struct coda_video_device *coda7_video_devices[] = {
-	&coda_bit_jpeg_encoder,
-	&coda_bit_jpeg_decoder,
-	&coda_bit_encoder,
-	&coda_bit_decoder,
-};
-
-static const struct coda_video_device *coda9_video_devices[] = {
-	&coda_bit_encoder,
-	&coda_bit_decoder,
-};
-
 static bool coda_format_is_yuv(u32 fourcc)
 {
 	switch (fourcc) {
 	case V4L2_PIX_FMT_YUV420:
 	case V4L2_PIX_FMT_YVU420:
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_YUV422P:
 		return true;
 	default:
 		return false;
 	}
 }
 
-static const char *coda_format_name(u32 fourcc)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(coda_formats); i++) {
-		if (coda_formats[i].fourcc == fourcc)
-			return coda_formats[i].name;
-	}
-
-	return NULL;
-}
-
 /*
  * Normalize all supported YUV 4:2:0 formats to the value used in the codec
  * tables.
@@ -343,17 +202,6 @@
 		*max_h = h;
 }
 
-const struct coda_video_device *to_coda_video_device(struct video_device *vdev)
-{
-	struct coda_dev *dev = video_get_drvdata(vdev);
-	unsigned int i = vdev - dev->vfd;
-
-	if (i >= dev->devtype->num_vdevs)
-		return NULL;
-
-	return dev->devtype->vdevs[i];
-}
-
 const char *coda_product_name(int product)
 {
 	static char buf[9];
@@ -392,28 +240,58 @@
 static int coda_enum_fmt(struct file *file, void *priv,
 			 struct v4l2_fmtdesc *f)
 {
-	struct video_device *vdev = video_devdata(file);
-	const struct coda_video_device *cvd = to_coda_video_device(vdev);
-	const u32 *formats;
-	const char *name;
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	const struct coda_codec *codecs = ctx->dev->devtype->codecs;
+	const struct coda_fmt *formats = coda_formats;
+	const struct coda_fmt *fmt;
+	int num_codecs = ctx->dev->devtype->num_codecs;
+	int num_formats = ARRAY_SIZE(coda_formats);
+	int i, k, num = 0;
+	bool yuv;
 
-	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		formats = cvd->src_formats;
-	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		formats = cvd->dst_formats;
+	if (ctx->inst_type == CODA_INST_ENCODER)
+		yuv = (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	else
-		return -EINVAL;
+		yuv = (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
 
-	if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0)
-		return -EINVAL;
+	for (i = 0; i < num_formats; i++) {
+		/* Skip either raw or compressed formats */
+		if (yuv != coda_format_is_yuv(formats[i].fourcc))
+			continue;
+		/* All uncompressed formats are always supported */
+		if (yuv) {
+			if (num == f->index)
+				break;
+			++num;
+			continue;
+		}
+		/* Compressed formats may be supported, check the codec list */
+		for (k = 0; k < num_codecs; k++) {
+			if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+			    formats[i].fourcc == codecs[k].dst_fourcc)
+				break;
+			if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+			    formats[i].fourcc == codecs[k].src_fourcc)
+				break;
+		}
+		if (k < num_codecs) {
+			if (num == f->index)
+				break;
+			++num;
+		}
+	}
 
-	name = coda_format_name(formats[f->index]);
-	strlcpy(f->description, name, sizeof(f->description));
-	f->pixelformat = formats[f->index];
-	if (!coda_format_is_yuv(formats[f->index]))
-		f->flags |= V4L2_FMT_FLAG_COMPRESSED;
+	if (i < num_formats) {
+		fmt = &formats[i];
+		strlcpy(f->description, fmt->name, sizeof(f->description));
+		f->pixelformat = fmt->fourcc;
+		if (!yuv)
+			f->flags |= V4L2_FMT_FLAG_COMPRESSED;
+		return 0;
+	}
 
-	return 0;
+	/* Format not found */
+	return -EINVAL;
 }
 
 static int coda_g_fmt(struct file *file, void *priv,
@@ -433,37 +311,7 @@
 	f->fmt.pix.bytesperline = q_data->bytesperline;
 
 	f->fmt.pix.sizeimage	= q_data->sizeimage;
-	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
-		f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-	else
-		f->fmt.pix.colorspace = ctx->colorspace;
-
-	return 0;
-}
-
-static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
-{
-	struct coda_q_data *q_data;
-	const u32 *formats;
-	int i;
-
-	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		formats = ctx->cvd->src_formats;
-	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		formats = ctx->cvd->dst_formats;
-	else
-		return -EINVAL;
-
-	for (i = 0; i < CODA_MAX_FORMATS; i++) {
-		if (formats[i] == f->fmt.pix.pixelformat) {
-			f->fmt.pix.pixelformat = formats[i];
-			return 0;
-		}
-	}
-
-	/* Fall back to currently set pixelformat */
-	q_data = get_q_data(ctx, f->type);
-	f->fmt.pix.pixelformat = q_data->fourcc;
+	f->fmt.pix.colorspace	= ctx->colorspace;
 
 	return 0;
 }
@@ -472,6 +320,7 @@
 			struct v4l2_format *f)
 {
 	struct coda_dev *dev = ctx->dev;
+	struct coda_q_data *q_data;
 	unsigned int max_w, max_h;
 	enum v4l2_field field;
 
@@ -493,35 +342,30 @@
 	switch (f->fmt.pix.pixelformat) {
 	case V4L2_PIX_FMT_YUV420:
 	case V4L2_PIX_FMT_YVU420:
-	case V4L2_PIX_FMT_NV12:
-		/*
-		 * Frame stride must be at least multiple of 8,
-		 * but multiple of 16 for h.264 or JPEG 4:2:x
-		 */
+	case V4L2_PIX_FMT_H264:
+	case V4L2_PIX_FMT_MPEG4:
+	case V4L2_PIX_FMT_JPEG:
+		break;
+	default:
+		q_data = get_q_data(ctx, f->type);
+		if (!q_data)
+			return -EINVAL;
+		f->fmt.pix.pixelformat = q_data->fourcc;
+	}
+
+	switch (f->fmt.pix.pixelformat) {
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		/* Frame stride must be multiple of 8, but 16 for h.264 */
 		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
 		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
 					f->fmt.pix.height * 3 / 2;
 		break;
-	case V4L2_PIX_FMT_YUV422P:
-		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
-		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
-					f->fmt.pix.height * 2;
-		break;
-	case V4L2_PIX_FMT_JPEG:
-		f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-		/* fallthrough */
 	case V4L2_PIX_FMT_H264:
 	case V4L2_PIX_FMT_MPEG4:
+	case V4L2_PIX_FMT_JPEG:
 		f->fmt.pix.bytesperline = 0;
-		/*
-		 * This is a rough estimate for sensible compressed buffer
-		 * sizes (between 1 and 16 bits per pixel). This could be
-		 * improved by better format specific worst case estimates.
-		 */
-		f->fmt.pix.sizeimage = round_up(clamp(f->fmt.pix.sizeimage,
-				f->fmt.pix.width * f->fmt.pix.height / 8,
-				f->fmt.pix.width * f->fmt.pix.height * 2),
-				PAGE_SIZE);
+		f->fmt.pix.sizeimage = CODA_MAX_FRAME_SIZE;
 		break;
 	default:
 		BUG();
@@ -534,35 +378,34 @@
 				struct v4l2_format *f)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
-	const struct coda_q_data *q_data_src;
-	const struct coda_codec *codec;
+	const struct coda_codec *codec = NULL;
 	struct vb2_queue *src_vq;
 	int ret;
 
-	ret = coda_try_pixelformat(ctx, f);
-	if (ret < 0)
-		return ret;
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-
 	/*
-	 * If the source format is already fixed, only allow the same output
-	 * resolution
+	 * If the source format is already fixed, try to find a codec that
+	 * converts to the given destination format
 	 */
 	src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	if (vb2_is_streaming(src_vq)) {
+		struct coda_q_data *q_data_src;
+
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
+					f->fmt.pix.pixelformat);
+		if (!codec)
+			return -EINVAL;
+
 		f->fmt.pix.width = q_data_src->width;
 		f->fmt.pix.height = q_data_src->height;
+	} else {
+		/* Otherwise determine codec by encoded format, if possible */
+		codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
+					f->fmt.pix.pixelformat);
 	}
 
 	f->fmt.pix.colorspace = ctx->colorspace;
 
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
-				f->fmt.pix.pixelformat);
-	if (!codec)
-		return -EINVAL;
-
 	ret = coda_try_fmt(ctx, codec, f);
 	if (ret < 0)
 		return ret;
@@ -583,24 +426,21 @@
 				struct v4l2_format *f)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
-	struct coda_dev *dev = ctx->dev;
-	const struct coda_q_data *q_data_dst;
-	const struct coda_codec *codec;
-	int ret;
+	const struct coda_codec *codec = NULL;
 
-	ret = coda_try_pixelformat(ctx, f);
-	if (ret < 0)
-		return ret;
-
-	if (!f->fmt.pix.colorspace) {
-		if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
-			f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-		else
-			f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+	/* Determine codec by encoded format, returns NULL if raw or invalid */
+	if (ctx->inst_type == CODA_INST_DECODER) {
+		codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat,
+					V4L2_PIX_FMT_YUV420);
+		if (!codec)
+			codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_H264,
+						V4L2_PIX_FMT_YUV420);
+		if (!codec)
+			return -EINVAL;
 	}
 
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc);
+	if (!f->fmt.pix.colorspace)
+		f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
 
 	return coda_try_fmt(ctx, codec, f);
 }
@@ -831,9 +671,7 @@
 	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
 
 	.vidioc_qbuf		= coda_qbuf,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
 	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
-#endif
 	.vidioc_dqbuf		= coda_dqbuf,
 	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
 
@@ -943,7 +781,6 @@
 
 	if (ctx->hold ||
 	    ((ctx->inst_type == CODA_INST_DECODER) &&
-	     !v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
 	     (coda_get_bitstream_payload(ctx) < 512) &&
 	     !(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
@@ -1025,17 +862,25 @@
 
 static void set_default_params(struct coda_ctx *ctx)
 {
-	unsigned int max_w, max_h, size;
+	u32 src_fourcc, dst_fourcc;
+	int max_w;
+	int max_h;
 
-	ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0],
-				     ctx->cvd->dst_formats[0]);
-	max_w = min(ctx->codec->max_w, 1920U);
-	max_h = min(ctx->codec->max_h, 1088U);
-	size = max_w * max_h * 3 / 2;
+	if (ctx->inst_type == CODA_INST_ENCODER) {
+		src_fourcc = V4L2_PIX_FMT_YUV420;
+		dst_fourcc = V4L2_PIX_FMT_H264;
+	} else {
+		src_fourcc = V4L2_PIX_FMT_H264;
+		dst_fourcc = V4L2_PIX_FMT_YUV420;
+	}
+	ctx->codec = coda_find_codec(ctx->dev, src_fourcc, dst_fourcc);
+	max_w = ctx->codec->max_w;
+	max_h = ctx->codec->max_h;
 
 	ctx->params.codec_mode = ctx->codec->mode;
 	ctx->colorspace = V4L2_COLORSPACE_REC709;
 	ctx->params.framerate = 30;
+	ctx->aborting = 0;
 
 	/* Default formats for output and input queues */
 	ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->codec->src_fourcc;
@@ -1046,14 +891,14 @@
 	ctx->q_data[V4L2_M2M_DST].height = max_h;
 	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) {
 		ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w;
-		ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
+		ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2;
 		ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
-		ctx->q_data[V4L2_M2M_DST].sizeimage = round_up(size, PAGE_SIZE);
+		ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE;
 	} else {
 		ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
-		ctx->q_data[V4L2_M2M_SRC].sizeimage = round_up(size, PAGE_SIZE);
+		ctx->q_data[V4L2_M2M_SRC].sizeimage = CODA_MAX_FRAME_SIZE;
 		ctx->q_data[V4L2_M2M_DST].bytesperline = max_w;
-		ctx->q_data[V4L2_M2M_DST].sizeimage = size;
+		ctx->q_data[V4L2_M2M_DST].sizeimage = (max_w * max_h * 3) / 2;
 	}
 	ctx->q_data[V4L2_M2M_SRC].rect.width = max_w;
 	ctx->q_data[V4L2_M2M_SRC].rect.height = max_h;
@@ -1119,7 +964,7 @@
 	 * In the decoder case, immediately try to copy the buffer into the
 	 * bitstream ringbuffer and mark it as ready to be dequeued.
 	 */
-	if (ctx->inst_type == CODA_INST_DECODER &&
+	if (q_data->fourcc == V4L2_PIX_FMT_H264 &&
 	    vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
 		/*
 		 * For backwards compatibility, queuing an empty buffer marks
@@ -1182,13 +1027,12 @@
 	struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
 	struct coda_q_data *q_data_src, *q_data_dst;
 	struct vb2_buffer *buf;
+	u32 dst_fourcc;
 	int ret = 0;
 
 	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		if (q_data_src->fourcc == V4L2_PIX_FMT_H264 ||
-		    (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
-		     ctx->dev->devtype->product == CODA_7541)) {
+		if (q_data_src->fourcc == V4L2_PIX_FMT_H264) {
 			/* copy the buffers that where queued before streamon */
 			mutex_lock(&ctx->bitstream_mutex);
 			coda_fill_bitstream(ctx);
@@ -1219,12 +1063,13 @@
 	if (!(ctx->streamon_out & ctx->streamon_cap))
 		return 0;
 
-	/* Allow BIT decoder device_run with no new buffers queued */
+	/* Allow decoder device_run with no new buffers queued */
 	if (ctx->inst_type == CODA_INST_DECODER)
 		v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
 
 	ctx->gopcounter = ctx->params.gop_size - 1;
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	dst_fourcc = q_data_dst->fourcc;
 
 	ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
 				     q_data_dst->fourcc);
@@ -1234,10 +1079,6 @@
 		goto err;
 	}
 
-	if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG)
-		ctx->params.gop_size = 1;
-	ctx->gopcounter = ctx->params.gop_size - 1;
-
 	ret = ctx->ops->start_streaming(ctx);
 	if (ctx->inst_type == CODA_INST_DECODER) {
 		if (ret == -EAGAIN)
@@ -1252,10 +1093,10 @@
 err:
 	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
 		while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
-			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_DEQUEUED);
 	} else {
 		while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
-			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_DEQUEUED);
 	}
 	return ret;
 }
@@ -1290,20 +1131,19 @@
 	}
 
 	if (!ctx->streamon_out && !ctx->streamon_cap) {
-		struct coda_buffer_meta *meta;
+		struct coda_timestamp *ts;
 
 		mutex_lock(&ctx->bitstream_mutex);
-		while (!list_empty(&ctx->buffer_meta_list)) {
-			meta = list_first_entry(&ctx->buffer_meta_list,
-						struct coda_buffer_meta, list);
-			list_del(&meta->list);
-			kfree(meta);
+		while (!list_empty(&ctx->timestamp_list)) {
+			ts = list_first_entry(&ctx->timestamp_list,
+					      struct coda_timestamp, list);
+			list_del(&ts->list);
+			kfree(ts);
 		}
 		mutex_unlock(&ctx->bitstream_mutex);
 		kfifo_init(&ctx->bitstream_fifo,
 			ctx->bitstream.vaddr, ctx->bitstream.size);
 		ctx->runcounter = 0;
-		ctx->aborting = 0;
 	}
 }
 
@@ -1386,12 +1226,6 @@
 	case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
 		ctx->params.intra_refresh = ctrl->val;
 		break;
-	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-		coda_set_jpeg_compression_quality(ctx, ctrl->val);
-		break;
-	case V4L2_CID_JPEG_RESTART_INTERVAL:
-		ctx->params.jpeg_restart_interval = ctrl->val;
-		break;
 	default:
 		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
 			"Invalid control, id=%d, val=%d\n",
@@ -1406,8 +1240,14 @@
 	.s_ctrl = coda_s_ctrl,
 };
 
-static void coda_encode_ctrls(struct coda_ctx *ctx)
+static int coda_ctrls_setup(struct coda_ctx *ctx)
 {
+	v4l2_ctrl_handler_init(&ctx->ctrls, 9);
+
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_VFLIP, 0, 1, 1, 0);
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1, 0);
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
@@ -1451,30 +1291,6 @@
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0,
 		1920 * 1088 / 256, 1, 0);
-}
-
-static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx)
-{
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_JPEG_COMPRESSION_QUALITY, 5, 100, 1, 50);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_JPEG_RESTART_INTERVAL, 0, 100, 1, 0);
-}
-
-static int coda_ctrls_setup(struct coda_ctx *ctx)
-{
-	v4l2_ctrl_handler_init(&ctx->ctrls, 2);
-
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_HFLIP, 0, 1, 1, 0);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_VFLIP, 0, 1, 1, 0);
-	if (ctx->inst_type == CODA_INST_ENCODER) {
-		if (ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG)
-			coda_jpeg_encode_ctrls(ctx);
-		else
-			coda_encode_ctrls(ctx);
-	}
 
 	if (ctx->ctrls.error) {
 		v4l2_err(&ctx->dev->v4l2_dev,
@@ -1548,14 +1364,10 @@
 	return idx;
 }
 
-/*
- * File operations
- */
-
-static int coda_open(struct file *file)
+static int coda_open(struct file *file, enum coda_inst_type inst_type,
+		     const struct coda_context_ops *ctx_ops)
 {
-	struct video_device *vdev = video_devdata(file);
-	struct coda_dev *dev = video_get_drvdata(vdev);
+	struct coda_dev *dev = video_drvdata(file);
 	struct coda_ctx *ctx = NULL;
 	char *name;
 	int ret;
@@ -1576,9 +1388,8 @@
 	ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
 	kfree(name);
 
-	ctx->cvd = to_coda_video_device(vdev);
-	ctx->inst_type = ctx->cvd->type;
-	ctx->ops = ctx->cvd->ops;
+	ctx->inst_type = inst_type;
+	ctx->ops = ctx_ops;
 	init_completion(&ctx->completion);
 	INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
 	INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
@@ -1588,10 +1399,8 @@
 	ctx->dev = dev;
 	ctx->idx = idx;
 	switch (dev->devtype->product) {
-	case CODA_960:
-		ctx->frame_mem_ctrl = 1 << 12;
-		/* fallthrough */
 	case CODA_7541:
+	case CODA_960:
 		ctx->reg_idx = 0;
 		break;
 	default:
@@ -1632,17 +1441,16 @@
 
 	ctx->fh.ctrl_handler = &ctx->ctrls;
 
-	ret = coda_alloc_context_buf(ctx, &ctx->parabuf,
-				     CODA_PARA_BUF_SIZE, "parabuf");
+	ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE,
+				     "parabuf");
 	if (ret < 0) {
 		v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
 		goto err_dma_alloc;
 	}
 
 	ctx->bitstream.size = CODA_MAX_FRAME_SIZE;
-	ctx->bitstream.vaddr = dma_alloc_writecombine(
-			&dev->plat_dev->dev, ctx->bitstream.size,
-			&ctx->bitstream.paddr, GFP_KERNEL);
+	ctx->bitstream.vaddr = dma_alloc_writecombine(&dev->plat_dev->dev,
+			ctx->bitstream.size, &ctx->bitstream.paddr, GFP_KERNEL);
 	if (!ctx->bitstream.vaddr) {
 		v4l2_err(&dev->v4l2_dev,
 			 "failed to allocate bitstream ringbuffer");
@@ -1653,7 +1461,7 @@
 		ctx->bitstream.vaddr, ctx->bitstream.size);
 	mutex_init(&ctx->bitstream_mutex);
 	mutex_init(&ctx->buffer_mutex);
-	INIT_LIST_HEAD(&ctx->buffer_meta_list);
+	INIT_LIST_HEAD(&ctx->timestamp_list);
 
 	coda_lock(ctx);
 	list_add(&ctx->list, &dev->instances);
@@ -1687,6 +1495,16 @@
 	return ret;
 }
 
+static int coda_encoder_open(struct file *file)
+{
+	return coda_open(file, CODA_INST_ENCODER, &coda_bit_encode_ops);
+}
+
+static int coda_decoder_open(struct file *file)
+{
+	return coda_open(file, CODA_INST_DECODER, &coda_bit_decode_ops);
+}
+
 static int coda_release(struct file *file)
 {
 	struct coda_dev *dev = video_drvdata(file);
@@ -1697,9 +1515,6 @@
 
 	debugfs_remove_recursive(ctx->debugfs_entry);
 
-	if (ctx->inst_type == CODA_INST_DECODER)
-		coda_bit_stream_end_flag(ctx);
-
 	/* If this instance is running, call .job_abort and wait for it to end */
 	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 
@@ -1713,10 +1528,8 @@
 	list_del(&ctx->list);
 	coda_unlock(ctx);
 
-	if (ctx->bitstream.vaddr) {
-		dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size,
-			ctx->bitstream.vaddr, ctx->bitstream.paddr);
-	}
+	dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size,
+		ctx->bitstream.vaddr, ctx->bitstream.paddr);
 	if (ctx->dev->devtype->product == CODA_DX6)
 		coda_free_aux_buf(dev, &ctx->workbuf);
 
@@ -1735,9 +1548,18 @@
 	return 0;
 }
 
-static const struct v4l2_file_operations coda_fops = {
+static const struct v4l2_file_operations coda_encoder_fops = {
 	.owner		= THIS_MODULE,
-	.open		= coda_open,
+	.open		= coda_encoder_open,
+	.release	= coda_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static const struct v4l2_file_operations coda_decoder_fops = {
+	.owner		= THIS_MODULE,
+	.open		= coda_decoder_open,
 	.release	= coda_release,
 	.poll		= v4l2_m2m_fop_poll,
 	.unlocked_ioctl	= video_ioctl2,
@@ -1842,16 +1664,8 @@
 	return ret;
 }
 
-static int coda_register_device(struct coda_dev *dev, int i)
+static int coda_register_device(struct coda_dev *dev, struct video_device *vfd)
 {
-	struct video_device *vfd = &dev->vfd[i];
-
-	if (i > ARRAY_SIZE(dev->vfd))
-		return -EINVAL;
-
-	snprintf(vfd->name, sizeof(vfd->name), dev->devtype->vdevs[i]->name);
-	vfd->fops	= &coda_fops;
-	vfd->ioctl_ops	= &coda_ioctl_ops;
 	vfd->release	= video_device_release_empty,
 	vfd->lock	= &dev->dev_mutex;
 	vfd->v4l2_dev	= &dev->v4l2_dev;
@@ -1870,7 +1684,7 @@
 {
 	struct coda_dev *dev = context;
 	struct platform_device *pdev = dev->plat_dev;
-	int i, ret;
+	int ret;
 
 	if (!fw) {
 		v4l2_err(&dev->v4l2_dev, "firmware request failed\n");
@@ -1911,25 +1725,33 @@
 		goto rel_ctx;
 	}
 
-	for (i = 0; i < dev->devtype->num_vdevs; i++) {
-		ret = coda_register_device(dev, i);
-		if (ret) {
-			v4l2_err(&dev->v4l2_dev,
-				 "Failed to register %s video device: %d\n",
-				 dev->devtype->vdevs[i]->name, ret);
-			goto rel_vfd;
-		}
+	dev->vfd[0].fops      = &coda_encoder_fops,
+	dev->vfd[0].ioctl_ops = &coda_ioctl_ops;
+	snprintf(dev->vfd[0].name, sizeof(dev->vfd[0].name), "coda-encoder");
+	ret = coda_register_device(dev, &dev->vfd[0]);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev,
+			 "Failed to register encoder video device\n");
+		goto rel_m2m;
+	}
+
+	dev->vfd[1].fops      = &coda_decoder_fops,
+	dev->vfd[1].ioctl_ops = &coda_ioctl_ops;
+	snprintf(dev->vfd[1].name, sizeof(dev->vfd[1].name), "coda-decoder");
+	ret = coda_register_device(dev, &dev->vfd[1]);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev,
+			 "Failed to register decoder video device\n");
+		goto rel_m2m;
 	}
 
 	v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video[%d-%d]\n",
-		  dev->vfd[0].num, dev->vfd[i - 1].num);
+		  dev->vfd[0].num, dev->vfd[1].num);
 
 	pm_runtime_put_sync(&pdev->dev);
 	return;
 
-rel_vfd:
-	while (--i >= 0)
-		video_unregister_device(&dev->vfd[i]);
+rel_m2m:
 	v4l2_m2m_release(dev->m2m_dev);
 rel_ctx:
 	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
@@ -1961,8 +1783,6 @@
 		.product      = CODA_DX6,
 		.codecs       = codadx6_codecs,
 		.num_codecs   = ARRAY_SIZE(codadx6_codecs),
-		.vdevs        = codadx6_video_devices,
-		.num_vdevs    = ARRAY_SIZE(codadx6_video_devices),
 		.workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024,
 		.iram_size    = 0xb000,
 	},
@@ -1971,8 +1791,6 @@
 		.product      = CODA_7541,
 		.codecs       = coda7_codecs,
 		.num_codecs   = ARRAY_SIZE(coda7_codecs),
-		.vdevs        = coda7_video_devices,
-		.num_vdevs    = ARRAY_SIZE(coda7_video_devices),
 		.workbuf_size = 128 * 1024,
 		.tempbuf_size = 304 * 1024,
 		.iram_size    = 0x14000,
@@ -1982,8 +1800,6 @@
 		.product      = CODA_960,
 		.codecs       = coda9_codecs,
 		.num_codecs   = ARRAY_SIZE(coda9_codecs),
-		.vdevs        = coda9_video_devices,
-		.num_vdevs    = ARRAY_SIZE(coda9_video_devices),
 		.workbuf_size = 80 * 1024,
 		.tempbuf_size = 204 * 1024,
 		.iram_size    = 0x21000,
@@ -1993,8 +1809,6 @@
 		.product      = CODA_960,
 		.codecs       = coda9_codecs,
 		.num_codecs   = ARRAY_SIZE(coda9_codecs),
-		.vdevs        = coda9_video_devices,
-		.num_vdevs    = ARRAY_SIZE(coda9_video_devices),
 		.workbuf_size = 80 * 1024,
 		.tempbuf_size = 204 * 1024,
 		.iram_size    = 0x20000,
@@ -2032,18 +1846,10 @@
 	int ret, irq;
 
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-	if (!dev)
+	if (!dev) {
+		dev_err(&pdev->dev, "Not enough memory for %s\n",
+			CODA_NAME);
 		return -ENOMEM;
-
-	pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
-
-	if (of_id) {
-		dev->devtype = of_id->data;
-	} else if (pdev_id) {
-		dev->devtype = &coda_devdata[pdev_id->driver_data];
-	} else {
-		ret = -EINVAL;
-		goto err_v4l2_register;
 	}
 
 	spin_lock_init(&dev->irqlock);
@@ -2113,6 +1919,17 @@
 	mutex_init(&dev->dev_mutex);
 	mutex_init(&dev->coda_mutex);
 
+	pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
+
+	if (of_id) {
+		dev->devtype = of_id->data;
+	} else if (pdev_id) {
+		dev->devtype = &coda_devdata[pdev_id->driver_data];
+	} else {
+		v4l2_device_unregister(&dev->v4l2_dev);
+		return -EINVAL;
+	}
+
 	dev->debugfs_root = debugfs_create_dir("coda", NULL);
 	if (!dev->debugfs_root)
 		dev_warn(&pdev->dev, "failed to create debugfs root\n");
@@ -2124,7 +1941,8 @@
 					 dev->debugfs_root);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "failed to allocate work buffer\n");
-			goto err_v4l2_register;
+			v4l2_device_unregister(&dev->v4l2_dev);
+			return ret;
 		}
 	}
 
@@ -2134,7 +1952,8 @@
 					 dev->debugfs_root);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "failed to allocate temp buffer\n");
-			goto err_v4l2_register;
+			v4l2_device_unregister(&dev->v4l2_dev);
+			return ret;
 		}
 	}
 
@@ -2154,15 +1973,14 @@
 	dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
 	if (!dev->workqueue) {
 		dev_err(&pdev->dev, "unable to alloc workqueue\n");
-		ret = -ENOMEM;
-		goto err_v4l2_register;
+		return -ENOMEM;
 	}
 
 	platform_set_drvdata(pdev, dev);
 
 	/*
 	 * Start activated so we can directly call coda_hw_init in
-	 * coda_fw_callback regardless of whether CONFIG_PM is
+	 * coda_fw_callback regardless of whether CONFIG_PM_RUNTIME is
 	 * enabled or whether the device is associated with a PM domain.
 	 */
 	pm_runtime_get_noresume(&pdev->dev);
@@ -2170,21 +1988,14 @@
 	pm_runtime_enable(&pdev->dev);
 
 	return coda_firmware_request(dev);
-
-err_v4l2_register:
-	v4l2_device_unregister(&dev->v4l2_dev);
-	return ret;
 }
 
 static int coda_remove(struct platform_device *pdev)
 {
 	struct coda_dev *dev = platform_get_drvdata(pdev);
-	int i;
 
-	for (i = 0; i < ARRAY_SIZE(dev->vfd); i++) {
-		if (video_get_drvdata(&dev->vfd[i]))
-			video_unregister_device(&dev->vfd[i]);
-	}
+	video_unregister_device(&dev->vfd[0]);
+	video_unregister_device(&dev->vfd[1]);
 	if (dev->m2m_dev)
 		v4l2_m2m_release(dev->m2m_dev);
 	pm_runtime_disable(&pdev->dev);
@@ -2202,7 +2013,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 static int coda_runtime_resume(struct device *dev)
 {
 	struct coda_dev *cdev = dev_get_drvdata(dev);
@@ -2227,6 +2038,7 @@
 	.remove	= coda_remove,
 	.driver	= {
 		.name	= CODA_NAME,
+		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(coda_dt_ids),
 		.pm	= &coda_pm_ops,
 	},
diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c
deleted file mode 100644
index 8fa3e35..0000000
--- a/drivers/media/platform/coda/coda-jpeg.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Coda multi-standard codec IP - JPEG support functions
- *
- * Copyright (C) 2014 Philipp Zabel, Pengutronix
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/swab.h>
-
-#include "coda.h"
-
-#define SOI_MARKER	0xffd8
-#define EOI_MARKER	0xffd9
-
-/*
- * Typical Huffman tables for 8-bit precision luminance and
- * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3
- */
-
-static const unsigned char luma_dc_bits[16] = {
-	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static const unsigned char luma_dc_value[12] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b,
-};
-
-static const unsigned char chroma_dc_bits[16] = {
-	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static const unsigned char chroma_dc_value[12] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b,
-};
-
-static const unsigned char luma_ac_bits[16] = {
-	0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
-	0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
-};
-
-static const unsigned char luma_ac_value[162 + 2] = {
-	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
-	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
-	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
-	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
-	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
-	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
-	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
-	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
-	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
-	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
-	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
-	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
-	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
-	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
-	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
-	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-	0xf9, 0xfa, /* padded to 32-bit */
-};
-
-static const unsigned char chroma_ac_bits[16] = {
-	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
-	0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
-};
-
-static const unsigned char chroma_ac_value[162 + 2] = {
-	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
-	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
-	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
-	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
-	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
-	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
-	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
-	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
-	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
-	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
-	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
-	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
-	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
-	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-	0xf9, 0xfa, /* padded to 32-bit */
-};
-
-/*
- * Quantization tables for luminance and chrominance components in
- * zig-zag scan order from the Freescale i.MX VPU libaries
- */
-
-static unsigned char luma_q[64] = {
-	0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05,
-	0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b,
-	0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a,
-	0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-};
-
-static unsigned char chroma_q[64] = {
-	0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10,
-	0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14,
-	0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-};
-
-struct coda_memcpy_desc {
-	int offset;
-	const void *src;
-	size_t len;
-};
-
-static void coda_memcpy_parabuf(void *parabuf,
-				const struct coda_memcpy_desc *desc)
-{
-	u32 *dst = parabuf + desc->offset;
-	const u32 *src = desc->src;
-	int len = desc->len / 4;
-	int i;
-
-	for (i = 0; i < len; i += 2) {
-		dst[i + 1] = swab32(src[i]);
-		dst[i] = swab32(src[i + 1]);
-	}
-}
-
-int coda_jpeg_write_tables(struct coda_ctx *ctx)
-{
-	int i;
-	static const struct coda_memcpy_desc huff[8] = {
-		{ 0,   luma_dc_bits,    sizeof(luma_dc_bits)    },
-		{ 16,  luma_dc_value,   sizeof(luma_dc_value)   },
-		{ 32,  luma_ac_bits,    sizeof(luma_ac_bits)    },
-		{ 48,  luma_ac_value,   sizeof(luma_ac_value)   },
-		{ 216, chroma_dc_bits,  sizeof(chroma_dc_bits)  },
-		{ 232, chroma_dc_value, sizeof(chroma_dc_value) },
-		{ 248, chroma_ac_bits,  sizeof(chroma_ac_bits)  },
-		{ 264, chroma_ac_value, sizeof(chroma_ac_value) },
-	};
-	struct coda_memcpy_desc qmat[3] = {
-		{ 512, ctx->params.jpeg_qmat_tab[0], 64 },
-		{ 576, ctx->params.jpeg_qmat_tab[1], 64 },
-		{ 640, ctx->params.jpeg_qmat_tab[1], 64 },
-	};
-
-	/* Write huffman tables to parameter memory */
-	for (i = 0; i < ARRAY_SIZE(huff); i++)
-		coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
-
-	/* Write Q-matrix to parameter memory */
-	for (i = 0; i < ARRAY_SIZE(qmat); i++)
-		coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
-
-	return 0;
-}
-
-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
-{
-	void *vaddr = vb2_plane_vaddr(vb, 0);
-	u16 soi = be16_to_cpup((__be16 *)vaddr);
-	u16 eoi = be16_to_cpup((__be16 *)(vaddr +
-					  vb2_get_plane_payload(vb, 0) - 2));
-
-	return soi == SOI_MARKER && eoi == EOI_MARKER;
-}
-
-/*
- * Scale quantization table using nonlinear scaling factor
- * u8 qtab[64], scale [50,190]
- */
-static void coda_scale_quant_table(u8 *q_tab, int scale)
-{
-	unsigned int temp;
-	int i;
-
-	for (i = 0; i < 64; i++) {
-		temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
-		if (temp <= 0)
-			temp = 1;
-		if (temp > 255)
-			temp = 255;
-		q_tab[i] = (unsigned char)temp;
-	}
-}
-
-void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
-{
-	unsigned int scale;
-
-	ctx->params.jpeg_quality = quality;
-
-	/* Clip quality setting to [5,100] interval */
-	if (quality > 100)
-		quality = 100;
-	if (quality < 5)
-		quality = 5;
-
-	/*
-	 * Non-linear scaling factor:
-	 * [5,50] -> [1000..100], [51,100] -> [98..0]
-	 */
-	if (quality < 50)
-		scale = 5000 / quality;
-	else
-		scale = 200 - 2 * quality;
-
-	if (ctx->params.jpeg_qmat_tab[0]) {
-		memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
-		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
-	}
-	if (ctx->params.jpeg_qmat_tab[1]) {
-		memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
-		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
-	}
-}
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 5dd47e5..bbc18c0 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -45,15 +45,11 @@
 	CODA_960 = 0xf020,
 };
 
-struct coda_video_device;
-
 struct coda_devtype {
 	char			*firmware;
 	enum coda_product	product;
 	const struct coda_codec	*codecs;
 	unsigned int		num_codecs;
-	const struct coda_video_device **vdevs;
-	unsigned int		num_vdevs;
 	size_t			workbuf_size;
 	size_t			tempbuf_size;
 	size_t			iram_size;
@@ -69,7 +65,7 @@
 
 struct coda_dev {
 	struct v4l2_device	v4l2_dev;
-	struct video_device	vfd[5];
+	struct video_device	vfd[2];
 	struct platform_device	*plat_dev;
 	const struct coda_devtype *devtype;
 
@@ -118,9 +114,6 @@
 	u8			mpeg4_inter_qp;
 	u8			gop_size;
 	int			intra_refresh;
-	u8			jpeg_quality;
-	u8			jpeg_restart_interval;
-	u8			*jpeg_qmat_tab[3];
 	int			codec_mode;
 	int			codec_mode_aux;
 	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
@@ -130,13 +123,11 @@
 	u32			slice_max_mb;
 };
 
-struct coda_buffer_meta {
+struct coda_timestamp {
 	struct list_head	list;
 	u32			sequence;
 	struct v4l2_timecode	timecode;
 	struct timeval		timestamp;
-	u32			start;
-	u32			end;
 };
 
 /* Per-queue, driver-specific private data */
@@ -192,7 +183,6 @@
 	struct work_struct		pic_run_work;
 	struct work_struct		seq_end_work;
 	struct completion		completion;
-	const struct coda_video_device	*cvd;
 	const struct coda_context_ops	*ops;
 	int				aborting;
 	int				initialized;
@@ -222,9 +212,9 @@
 	struct coda_aux_buf		slicebuf;
 	struct coda_aux_buf		internal_frames[CODA_MAX_FRAMEBUFFERS];
 	u32				frame_types[CODA_MAX_FRAMEBUFFERS];
-	struct coda_buffer_meta		frame_metas[CODA_MAX_FRAMEBUFFERS];
+	struct coda_timestamp		frame_timestamps[CODA_MAX_FRAMEBUFFERS];
 	u32				frame_errors[CODA_MAX_FRAMEBUFFERS];
-	struct list_head		buffer_meta_list;
+	struct list_head		timestamp_list;
 	struct coda_aux_buf		workbuf;
 	int				num_internal_frames;
 	int				idx;
@@ -242,8 +232,6 @@
 
 void coda_write(struct coda_dev *dev, u32 data, u32 reg);
 unsigned int coda_read(struct coda_dev *dev, u32 reg);
-void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
-		     struct vb2_buffer *buf, unsigned int reg_y);
 
 int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
 		       size_t size, const char *name, struct dentry *parent);
@@ -293,10 +281,6 @@
 
 int coda_h264_padding(int size, char *p);
 
-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
-int coda_jpeg_write_tables(struct coda_ctx *ctx);
-void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality);
-
 extern const struct coda_context_ops coda_bit_encode_ops;
 extern const struct coda_context_ops coda_bit_decode_ops;
 
diff --git a/drivers/media/platform/coda/coda_regs.h b/drivers/media/platform/coda/coda_regs.h
index 8e015b8..c791275 100644
--- a/drivers/media/platform/coda/coda_regs.h
+++ b/drivers/media/platform/coda/coda_regs.h
@@ -147,7 +147,6 @@
 #define CODA_CMD_DEC_SEQ_BB_START		0x180
 #define CODA_CMD_DEC_SEQ_BB_SIZE		0x184
 #define CODA_CMD_DEC_SEQ_OPTION			0x188
-#define		CODA_NO_INT_ENABLE			(1 << 10)
 #define		CODA_REORDER_ENABLE			(1 << 1)
 #define		CODADX6_QP_REPORT			(1 << 0)
 #define		CODA7_MP4_DEBLK_ENABLE			(1 << 0)
@@ -333,12 +332,6 @@
 #define CODA9_CMD_ENC_SEQ_ME_OPTION				0x1d8
 #define CODA_RET_ENC_SEQ_SUCCESS				0x1c0
 
-#define CODA_CMD_ENC_SEQ_JPG_PARA				0x198
-#define CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL			0x19C
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_EN				0x1a0
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE				0x1a4
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET			0x1a8
-
 /* Encoder Picture Run */
 #define CODA9_CMD_ENC_PIC_SRC_INDEX		0x180
 #define CODA9_CMD_ENC_PIC_SRC_STRIDE		0x184
diff --git a/drivers/media/platform/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c
index c90b9a4..3f44deb 100644
--- a/drivers/media/platform/davinci/dm355_ccdc.c
+++ b/drivers/media/platform/davinci/dm355_ccdc.c
@@ -1030,6 +1030,7 @@
 static struct platform_driver dm355_ccdc_driver = {
 	.driver = {
 		.name	= "dm355_ccdc",
+		.owner = THIS_MODULE,
 	},
 	.remove = dm355_ccdc_remove,
 	.probe = dm355_ccdc_probe,
diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c
index ffbefdf..62a0ebb 100644
--- a/drivers/media/platform/davinci/dm644x_ccdc.c
+++ b/drivers/media/platform/davinci/dm644x_ccdc.c
@@ -1029,6 +1029,7 @@
 static struct platform_driver dm644x_ccdc_driver = {
 	.driver = {
 		.name	= "dm644x_ccdc",
+		.owner = THIS_MODULE,
 		.pm = &dm644x_ccdc_pm_ops,
 	},
 	.remove = dm644x_ccdc_remove,
diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c
index 99faea2..3332cca 100644
--- a/drivers/media/platform/davinci/isif.c
+++ b/drivers/media/platform/davinci/isif.c
@@ -1134,6 +1134,7 @@
 static struct platform_driver isif_driver = {
 	.driver = {
 		.name	= "isif",
+		.owner = THIS_MODULE,
 	},
 	.remove = isif_remove,
 	.probe = isif_probe,
diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c
index 9a6c2cc..33b9660 100644
--- a/drivers/media/platform/davinci/vpbe.c
+++ b/drivers/media/platform/davinci/vpbe.c
@@ -227,7 +227,7 @@
 			vpbe_current_encoder_info(vpbe_dev);
 	struct vpbe_config *cfg = vpbe_dev->cfg;
 	struct venc_platform_data *venc_device = vpbe_dev->venc_device;
-	u32 if_params;
+	enum v4l2_mbus_pixelcode if_params;
 	int enc_out_index;
 	int sd_index;
 	int ret = 0;
@@ -341,7 +341,7 @@
 
 	if (!(cfg->outputs[out_index].output.capabilities &
 	    V4L2_OUT_CAP_DV_TIMINGS))
-		return -ENODATA;
+		return -EINVAL;
 
 	for (i = 0; i < output->num_modes; i++) {
 		if (output->modes[i].timings_type == VPBE_ENC_DV_TIMINGS &&
@@ -384,13 +384,6 @@
 static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
 		     struct v4l2_dv_timings *dv_timings)
 {
-	struct vpbe_config *cfg = vpbe_dev->cfg;
-	int out_index = vpbe_dev->current_out_index;
-
-	if (!(cfg->outputs[out_index].output.capabilities &
-		V4L2_OUT_CAP_DV_TIMINGS))
-		return -ENODATA;
-
 	if (vpbe_dev->current_timings.timings_type &
 	  VPBE_ENC_DV_TIMINGS) {
 		*dv_timings = vpbe_dev->current_timings.dv_timings;
@@ -416,7 +409,7 @@
 	int i;
 
 	if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS))
-		return -ENODATA;
+		return -EINVAL;
 
 	for (i = 0; i < output->num_modes; i++) {
 		if (output->modes[i].timings_type == VPBE_ENC_DV_TIMINGS) {
@@ -447,7 +440,7 @@
 
 	if (!(cfg->outputs[out_index].output.capabilities &
 		V4L2_OUT_CAP_STD))
-		return -ENODATA;
+		return -EINVAL;
 
 	ret = vpbe_get_std_info(vpbe_dev, std_id);
 	if (ret)
@@ -480,11 +473,6 @@
 static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
 {
 	struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings;
-	struct vpbe_config *cfg = vpbe_dev->cfg;
-	int out_index = vpbe_dev->current_out_index;
-
-	if (!(cfg->outputs[out_index].output.capabilities & V4L2_OUT_CAP_STD))
-		return -ENODATA;
 
 	if (cur_timings->timings_type & VPBE_ENC_STD) {
 		*std_id = cur_timings->std_id;
@@ -625,7 +613,6 @@
 		}
 		if (clk_prepare_enable(vpbe_dev->dac_clk)) {
 			ret =  -ENODEV;
-			clk_put(vpbe_dev->dac_clk);
 			goto fail_mutex_unlock;
 		}
 	}
@@ -876,6 +863,7 @@
 static struct platform_driver vpbe_driver = {
 	.driver	= {
 		.name	= "vpbe_controller",
+		.owner	= THIS_MODULE,
 	},
 	.probe = vpbe_probe,
 	.remove = vpbe_remove,
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index c4ab46f..73496d9 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -152,8 +152,8 @@
 
 	for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
 		layer = disp_dev->dev[i];
-
-		if (!vb2_start_streaming_called(&layer->buffer_queue))
+		/* If streaming is started in this layer */
+		if (!layer->started)
 			continue;
 
 		if (layer->layer_first_int) {
@@ -207,23 +207,31 @@
  */
 static int vpbe_buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
 	struct vb2_queue *q = vb->vb2_queue;
-	struct vpbe_layer *layer = vb2_get_drv_priv(q);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	unsigned long addr;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
 				"vpbe_buffer_prepare\n");
 
-	vb2_set_plane_payload(vb, 0, layer->pix_fmt.sizeimage);
-	if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
-		return -EINVAL;
+	if (vb->state != VB2_BUF_STATE_ACTIVE &&
+		vb->state != VB2_BUF_STATE_PREPARED) {
+		vb2_set_plane_payload(vb, 0, layer->pix_fmt.sizeimage);
+		if (vb2_plane_vaddr(vb, 0) &&
+		vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
+			return -EINVAL;
 
-	addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-	if (!IS_ALIGNED(addr, 8)) {
-		v4l2_err(&vpbe_dev->v4l2_dev,
-			 "buffer_prepare:offset is not aligned to 32 bytes\n");
-		return -EINVAL;
+		addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+		if (q->streaming) {
+			if (!IS_ALIGNED(addr, 8)) {
+				v4l2_err(&vpbe_dev->v4l2_dev,
+					"buffer_prepare:offset is \
+					not aligned to 32 bytes\n");
+				return -EINVAL;
+			}
+		}
 	}
 	return 0;
 }
@@ -239,20 +247,18 @@
 
 {
 	/* Get the file handle object and layer object */
-	struct vpbe_layer *layer = vb2_get_drv_priv(vq);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_buffer_setup\n");
 
-	if (fmt && fmt->fmt.pix.sizeimage < layer->pix_fmt.sizeimage)
-		return -EINVAL;
-
 	/* Store number of buffers allocated in numbuffer member */
-	if (vq->num_buffers + *nbuffers < VPBE_DEFAULT_NUM_BUFS)
-		*nbuffers = VPBE_DEFAULT_NUM_BUFS - vq->num_buffers;
+	if (*nbuffers < VPBE_DEFAULT_NUM_BUFS)
+		*nbuffers = layer->numbuffers = VPBE_DEFAULT_NUM_BUFS;
 
 	*nplanes = 1;
-	sizes[0] = fmt ? fmt->fmt.pix.sizeimage : layer->pix_fmt.sizeimage;
+	sizes[0] = layer->pix_fmt.sizeimage;
 	alloc_ctxs[0] = layer->alloc_ctx;
 
 	return 0;
@@ -265,11 +271,12 @@
 static void vpbe_buffer_queue(struct vb2_buffer *vb)
 {
 	/* Get the file handle object and layer object */
+	struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
 	struct vpbe_disp_buffer *buf = container_of(vb,
 				struct vpbe_disp_buffer, vb);
-	struct vpbe_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
-	struct vpbe_display *disp = layer->disp_dev;
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_display *disp = fh->disp_dev;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	unsigned long flags;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -281,14 +288,61 @@
 	spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
 }
 
+/*
+ * vpbe_buf_cleanup()
+ * This function is called from the vb2 layer to free memory allocated to
+ * the buffers
+ */
+static void vpbe_buf_cleanup(struct vb2_buffer *vb)
+{
+	/* Get the file handle object and layer object */
+	struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	struct vpbe_disp_buffer *buf = container_of(vb,
+					struct vpbe_disp_buffer, vb);
+	unsigned long flags;
+
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+			"vpbe_buf_cleanup\n");
+
+	spin_lock_irqsave(&layer->irqlock, flags);
+	if (vb->state == VB2_BUF_STATE_ACTIVE)
+		list_del_init(&buf->list);
+	spin_unlock_irqrestore(&layer->irqlock, flags);
+}
+
+static void vpbe_wait_prepare(struct vb2_queue *vq)
+{
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
+
+	mutex_unlock(&layer->opslock);
+}
+
+static void vpbe_wait_finish(struct vb2_queue *vq)
+{
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
+
+	mutex_lock(&layer->opslock);
+}
+
+static int vpbe_buffer_init(struct vb2_buffer *vb)
+{
+	struct vpbe_disp_buffer *buf = container_of(vb,
+					struct vpbe_disp_buffer, vb);
+
+	INIT_LIST_HEAD(&buf->list);
+	return 0;
+}
+
 static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
-	struct vpbe_layer *layer = vb2_get_drv_priv(vq);
-	struct osd_state *osd_device = layer->disp_dev->osd_device;
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
 	int ret;
 
-	 osd_device->ops.disable_layer(osd_device, layer->layer_info.id);
-
 	/* Get the next frame from the buffer queue */
 	layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,
 				struct vpbe_disp_buffer, list);
@@ -300,7 +354,7 @@
 	layer->field_id = 0;
 
 	/* Set parameters in OSD and VENC */
-	ret = vpbe_set_osd_display_params(layer->disp_dev, layer);
+	ret = vpbe_set_osd_display_params(fh->disp_dev, layer);
 	if (ret < 0) {
 		struct vpbe_disp_buffer *buf, *tmp;
 
@@ -317,6 +371,7 @@
 	 * if request format is yuv420 semiplanar, need to
 	 * enable both video windows
 	 */
+	layer->started = 1;
 	layer->layer_first_int = 1;
 
 	return ret;
@@ -324,16 +379,14 @@
 
 static void vpbe_stop_streaming(struct vb2_queue *vq)
 {
-	struct vpbe_layer *layer = vb2_get_drv_priv(vq);
-	struct osd_state *osd_device = layer->disp_dev->osd_device;
-	struct vpbe_display *disp = layer->disp_dev;
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_display *disp = fh->disp_dev;
 	unsigned long flags;
 
 	if (!vb2_is_streaming(vq))
 		return;
 
-	osd_device->ops.disable_layer(osd_device, layer->layer_info.id);
-
 	/* release all active buffers */
 	spin_lock_irqsave(&disp->dma_queue_lock, flags);
 	if (layer->cur_frm == layer->next_frm) {
@@ -358,11 +411,13 @@
 
 static struct vb2_ops video_qops = {
 	.queue_setup = vpbe_buffer_queue_setup,
-	.wait_prepare = vb2_ops_wait_prepare,
-	.wait_finish = vb2_ops_wait_finish,
+	.wait_prepare = vpbe_wait_prepare,
+	.wait_finish = vpbe_wait_finish,
+	.buf_init = vpbe_buffer_init,
 	.buf_prepare = vpbe_buffer_prepare,
 	.start_streaming = vpbe_start_streaming,
 	.stop_streaming = vpbe_stop_streaming,
+	.buf_cleanup = vpbe_buf_cleanup,
 	.buf_queue = vpbe_buffer_queue,
 };
 
@@ -636,9 +691,10 @@
 static int vpbe_display_querycap(struct file *file, void  *priv,
 			       struct v4l2_capability *cap)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
+	cap->version = VPBE_DISPLAY_VERSION_CODE;
 	cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	snprintf(cap->driver, sizeof(cap->driver), "%s",
@@ -653,8 +709,9 @@
 static int vpbe_display_s_crop(struct file *file, void *priv,
 			     const struct v4l2_crop *crop)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_display *disp_dev = layer->disp_dev;
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_display *disp_dev = fh->disp_dev;
 	struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
 	struct osd_layer_config *cfg = &layer->layer_info.config;
 	struct osd_state *osd_device = disp_dev->osd_device;
@@ -721,10 +778,11 @@
 static int vpbe_display_g_crop(struct file *file, void *priv,
 			     struct v4l2_crop *crop)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
 	struct osd_layer_config *cfg = &layer->layer_info.config;
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
-	struct osd_state *osd_device = layer->disp_dev->osd_device;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	struct osd_state *osd_device = fh->disp_dev->osd_device;
 	struct v4l2_rect *rect = &crop->c;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -748,8 +806,8 @@
 static int vpbe_display_cropcap(struct file *file, void *priv,
 			      struct v4l2_cropcap *cropcap)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_CROPCAP ioctl\n");
 
@@ -766,8 +824,9 @@
 static int vpbe_display_g_fmt(struct file *file, void *priv,
 				struct v4l2_format *fmt)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
 			"VIDIOC_G_FMT, layer id = %d\n",
@@ -787,8 +846,9 @@
 static int vpbe_display_enum_fmt(struct file *file, void  *priv,
 				   struct v4l2_fmtdesc *fmt)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	unsigned int index = 0;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -818,8 +878,9 @@
 static int vpbe_display_s_fmt(struct file *file, void *priv,
 				struct v4l2_format *fmt)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_display *disp_dev = layer->disp_dev;
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_display *disp_dev = fh->disp_dev;
 	struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
 	struct osd_layer_config *cfg  = &layer->layer_info.config;
 	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
@@ -830,9 +891,11 @@
 			"VIDIOC_S_FMT, layer id = %d\n",
 			layer->device_id);
 
-	if (vb2_is_busy(&layer->buffer_queue))
+	/* If streaming is started, return error */
+	if (layer->started) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
 		return -EBUSY;
-
+	}
 	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != fmt->type) {
 		v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "invalid type\n");
 		return -EINVAL;
@@ -904,9 +967,9 @@
 static int vpbe_display_try_fmt(struct file *file, void *priv,
 				  struct v4l2_format *fmt)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_display *disp_dev = layer->disp_dev;
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_display *disp_dev = fh->disp_dev;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_TRY_FMT\n");
@@ -930,15 +993,18 @@
 static int vpbe_display_s_std(struct file *file, void *priv,
 				v4l2_std_id std_id)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = priv;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	int ret;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_STD\n");
 
-	if (vb2_is_busy(&layer->buffer_queue))
+	/* If streaming is started, return error */
+	if (layer->started) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
 		return -EBUSY;
-
+	}
 	if (NULL != vpbe_dev->ops.s_std) {
 		ret = vpbe_dev->ops.s_std(vpbe_dev, std_id);
 		if (ret) {
@@ -962,8 +1028,8 @@
 static int vpbe_display_g_std(struct file *file, void *priv,
 				v4l2_std_id *std_id)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = priv;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,	"VIDIOC_G_STD\n");
 
@@ -985,8 +1051,8 @@
 static int vpbe_display_enum_output(struct file *file, void *priv,
 				    struct v4l2_output *output)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = priv;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	int ret;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,	"VIDIOC_ENUM_OUTPUT\n");
@@ -1013,15 +1079,17 @@
 static int vpbe_display_s_output(struct file *file, void *priv,
 				unsigned int i)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = priv;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	int ret;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,	"VIDIOC_S_OUTPUT\n");
-
-	if (vb2_is_busy(&layer->buffer_queue))
+	/* If streaming is started, return error */
+	if (layer->started) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
 		return -EBUSY;
-
+	}
 	if (NULL == vpbe_dev->ops.set_output)
 		return -EINVAL;
 
@@ -1042,8 +1110,8 @@
 static int vpbe_display_g_output(struct file *file, void *priv,
 				unsigned int *i)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = priv;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_OUTPUT\n");
 	/* Get the standard from the current encoder */
@@ -1062,8 +1130,8 @@
 vpbe_display_enum_dv_timings(struct file *file, void *priv,
 			struct v4l2_enum_dv_timings *timings)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = priv;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	int ret;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n");
@@ -1092,14 +1160,19 @@
 vpbe_display_s_dv_timings(struct file *file, void *priv,
 				struct v4l2_dv_timings *timings)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = priv;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	int ret;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_TIMINGS\n");
 
-	if (vb2_is_busy(&layer->buffer_queue))
+
+	/* If streaming is started, return error */
+	if (layer->started) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
 		return -EBUSY;
+	}
 
 	/* Set the given standard in the encoder */
 	if (!vpbe_dev->ops.s_dv_timings)
@@ -1125,8 +1198,8 @@
 vpbe_display_g_dv_timings(struct file *file, void *priv,
 				struct v4l2_dv_timings *dv_timings)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
-	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+	struct vpbe_fh *fh = priv;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_TIMINGS\n");
 
@@ -1142,6 +1215,259 @@
 	return 0;
 }
 
+static int vpbe_display_streamoff(struct file *file, void *priv,
+				enum v4l2_buf_type buf_type)
+{
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	struct osd_state *osd_device = fh->disp_dev->osd_device;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+			"VIDIOC_STREAMOFF,layer id = %d\n",
+			layer->device_id);
+
+	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	/* If io is allowed for this file handle, return error */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+		return -EACCES;
+	}
+
+	/* If streaming is not started, return error */
+	if (!layer->started) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "streaming not started in layer"
+			" id = %d\n", layer->device_id);
+		return -EINVAL;
+	}
+
+	osd_device->ops.disable_layer(osd_device,
+			layer->layer_info.id);
+	layer->started = 0;
+	ret = vb2_streamoff(&layer->buffer_queue, buf_type);
+
+	return ret;
+}
+
+static int vpbe_display_streamon(struct file *file, void *priv,
+			 enum v4l2_buf_type buf_type)
+{
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_display *disp_dev = fh->disp_dev;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	struct osd_state *osd_device = disp_dev->osd_device;
+	int ret;
+
+	osd_device->ops.disable_layer(osd_device,
+			layer->layer_info.id);
+
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_STREAMON, layerid=%d\n",
+						layer->device_id);
+
+	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	/* If file handle is not allowed IO, return error */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+		return -EACCES;
+	}
+	/* If Streaming is already started, return error */
+	if (layer->started) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "layer is already streaming\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * Call vb2_streamon to start streaming
+	 * in videobuf
+	 */
+	ret = vb2_streamon(&layer->buffer_queue, buf_type);
+	if (ret) {
+		v4l2_err(&vpbe_dev->v4l2_dev,
+		"error in vb2_streamon\n");
+		return ret;
+	}
+	return ret;
+}
+
+static int vpbe_display_dqbuf(struct file *file, void *priv,
+		      struct v4l2_buffer *buf)
+{
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+		"VIDIOC_DQBUF, layer id = %d\n",
+		layer->device_id);
+
+	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+		return -EINVAL;
+	}
+	/* If this file handle is not allowed to do IO, return error */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+		return -EACCES;
+	}
+	if (file->f_flags & O_NONBLOCK)
+		/* Call videobuf_dqbuf for non blocking mode */
+		ret = vb2_dqbuf(&layer->buffer_queue, buf, 1);
+	else
+		/* Call videobuf_dqbuf for blocking mode */
+		ret = vb2_dqbuf(&layer->buffer_queue, buf, 0);
+
+	return ret;
+}
+
+static int vpbe_display_qbuf(struct file *file, void *priv,
+		     struct v4l2_buffer *p)
+{
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+		"VIDIOC_QBUF, layer id = %d\n",
+		layer->device_id);
+
+	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != p->type) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	/* If this file handle is not allowed to do IO, return error */
+	if (!fh->io_allowed) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+		return -EACCES;
+	}
+
+	return vb2_qbuf(&layer->buffer_queue, p);
+}
+
+static int vpbe_display_querybuf(struct file *file, void *priv,
+			 struct v4l2_buffer *buf)
+{
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+		"VIDIOC_QUERYBUF, layer id = %d\n",
+		layer->device_id);
+
+	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+		return -EINVAL;
+	}
+	/* Call vb2_querybuf to get information */
+	return vb2_querybuf(&layer->buffer_queue, buf);
+}
+
+static int vpbe_display_reqbufs(struct file *file, void *priv,
+			struct v4l2_requestbuffers *req_buf)
+{
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	struct vb2_queue *q;
+	int ret;
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_reqbufs\n");
+
+	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != req_buf->type) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	/* If io users of the layer is not zero, return error */
+	if (0 != layer->io_usrs) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "not IO user\n");
+		return -EBUSY;
+	}
+	/* Initialize videobuf queue as per the buffer type */
+	layer->alloc_ctx = vb2_dma_contig_init_ctx(vpbe_dev->pdev);
+	if (IS_ERR(layer->alloc_ctx)) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Failed to get the context\n");
+		return PTR_ERR(layer->alloc_ctx);
+	}
+	q = &layer->buffer_queue;
+	memset(q, 0, sizeof(*q));
+	q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->drv_priv = fh;
+	q->ops = &video_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct vpbe_disp_buffer);
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->min_buffers_needed = 1;
+
+	ret = vb2_queue_init(q);
+	if (ret) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "vb2_queue_init() failed\n");
+		vb2_dma_contig_cleanup_ctx(layer->alloc_ctx);
+		return ret;
+	}
+	/* Set io allowed member of file handle to TRUE */
+	fh->io_allowed = 1;
+	/* Increment io usrs member of layer object to 1 */
+	layer->io_usrs = 1;
+	/* Store type of memory requested in layer object */
+	layer->memory = req_buf->memory;
+	/* Initialize buffer queue */
+	INIT_LIST_HEAD(&layer->dma_queue);
+	/* Allocate buffers */
+	return vb2_reqbufs(q, req_buf);
+}
+
+/*
+ * vpbe_display_mmap()
+ * It is used to map kernel space buffers into user spaces
+ */
+static int vpbe_display_mmap(struct file *filep, struct vm_area_struct *vma)
+{
+	/* Get the layer object and file handle object */
+	struct vpbe_fh *fh = filep->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	int ret;
+
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_mmap\n");
+
+	if (mutex_lock_interruptible(&layer->opslock))
+		return -ERESTARTSYS;
+	ret = vb2_mmap(&layer->buffer_queue, vma);
+	mutex_unlock(&layer->opslock);
+	return ret;
+}
+
+/* vpbe_display_poll(): It is used for select/poll system call
+ */
+static unsigned int vpbe_display_poll(struct file *filep, poll_table *wait)
+{
+	struct vpbe_fh *fh = filep->private_data;
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	unsigned int err = 0;
+
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_poll\n");
+	if (layer->started) {
+		mutex_lock(&layer->opslock);
+		err = vb2_poll(&layer->buffer_queue, filep, wait);
+		mutex_unlock(&layer->opslock);
+	}
+	return err;
+}
+
 /*
  * vpbe_display_open()
  * It creates object of file handle structure and stores it in private_data
@@ -1149,22 +1475,30 @@
  */
 static int vpbe_display_open(struct file *file)
 {
+	struct vpbe_fh *fh = NULL;
 	struct vpbe_layer *layer = video_drvdata(file);
+	struct video_device *vdev = video_devdata(file);
 	struct vpbe_display *disp_dev = layer->disp_dev;
 	struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
 	struct osd_state *osd_device = disp_dev->osd_device;
 	int err;
 
-	/* creating context for file descriptor */
-	err = v4l2_fh_open(file);
-	if (err) {
-		v4l2_err(&vpbe_dev->v4l2_dev, "v4l2_fh_open failed\n");
-		return err;
+	/* Allocate memory for the file handle object */
+	fh = kmalloc(sizeof(struct vpbe_fh), GFP_KERNEL);
+	if (fh == NULL) {
+		v4l2_err(&vpbe_dev->v4l2_dev,
+			"unable to allocate memory for file handle object\n");
+		return -ENOMEM;
 	}
+	v4l2_fh_init(&fh->fh, vdev);
+	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+			"vpbe display open plane = %d\n",
+			layer->device_id);
 
-	/* leaving if layer is already initialized */
-	if (!v4l2_fh_is_singular_file(file))
-		return err;
+	/* store pointer to fh in private_data member of filep */
+	file->private_data = fh;
+	fh->layer = layer;
+	fh->disp_dev = disp_dev;
 
 	if (!layer->usrs) {
 		if (mutex_lock_interruptible(&layer->opslock))
@@ -1177,12 +1511,15 @@
 			/* Couldn't get layer */
 			v4l2_err(&vpbe_dev->v4l2_dev,
 				"Display Manager failed to allocate layer\n");
-			v4l2_fh_release(file);
+			kfree(fh);
 			return -EINVAL;
 		}
 	}
 	/* Increment layer usrs counter */
 	layer->usrs++;
+	/* Set io_allowed member to false */
+	fh->io_allowed = 0;
+	v4l2_fh_add(&fh->fh);
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
 			"vpbe display device opened successfully\n");
 	return 0;
@@ -1195,18 +1532,30 @@
  */
 static int vpbe_display_release(struct file *file)
 {
-	struct vpbe_layer *layer = video_drvdata(file);
+	/* Get the layer object and file handle object */
+	struct vpbe_fh *fh = file->private_data;
+	struct vpbe_layer *layer = fh->layer;
 	struct osd_layer_config *cfg  = &layer->layer_info.config;
-	struct vpbe_display *disp_dev = layer->disp_dev;
+	struct vpbe_display *disp_dev = fh->disp_dev;
 	struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
 	struct osd_state *osd_device = disp_dev->osd_device;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_release\n");
 
 	mutex_lock(&layer->opslock);
+	/* if this instance is doing IO */
+	if (fh->io_allowed) {
+		/* Reset io_usrs member of layer object */
+		layer->io_usrs = 0;
 
-	osd_device->ops.disable_layer(osd_device,
-			layer->layer_info.id);
+		osd_device->ops.disable_layer(osd_device,
+				layer->layer_info.id);
+		layer->started = 0;
+		/* Free buffers allocated */
+		vb2_queue_release(&layer->buffer_queue);
+		vb2_dma_contig_cleanup_ctx(&layer->buffer_queue);
+	}
+
 	/* Decrement layer usrs counter */
 	layer->usrs--;
 	/* If this file handle has initialize encoder device, reset it */
@@ -1226,9 +1575,14 @@
 				layer->layer_info.id);
 	}
 
-	_vb2_fop_release(file, NULL);
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	file->private_data = NULL;
 	mutex_unlock(&layer->opslock);
 
+	/* Free memory allocated to file handle object */
+	kfree(fh);
+
 	disp_dev->cbcr_ofst = 0;
 
 	return 0;
@@ -1241,27 +1595,20 @@
 	.vidioc_enum_fmt_vid_out = vpbe_display_enum_fmt,
 	.vidioc_s_fmt_vid_out    = vpbe_display_s_fmt,
 	.vidioc_try_fmt_vid_out  = vpbe_display_try_fmt,
-
-	.vidioc_reqbufs		 = vb2_ioctl_reqbufs,
-	.vidioc_create_bufs	 = vb2_ioctl_create_bufs,
-	.vidioc_querybuf	 = vb2_ioctl_querybuf,
-	.vidioc_qbuf		 = vb2_ioctl_qbuf,
-	.vidioc_dqbuf		 = vb2_ioctl_dqbuf,
-	.vidioc_streamon	 = vb2_ioctl_streamon,
-	.vidioc_streamoff	 = vb2_ioctl_streamoff,
-	.vidioc_expbuf		 = vb2_ioctl_expbuf,
-
+	.vidioc_reqbufs		 = vpbe_display_reqbufs,
+	.vidioc_querybuf	 = vpbe_display_querybuf,
+	.vidioc_qbuf		 = vpbe_display_qbuf,
+	.vidioc_dqbuf		 = vpbe_display_dqbuf,
+	.vidioc_streamon	 = vpbe_display_streamon,
+	.vidioc_streamoff	 = vpbe_display_streamoff,
 	.vidioc_cropcap		 = vpbe_display_cropcap,
 	.vidioc_g_crop		 = vpbe_display_g_crop,
 	.vidioc_s_crop		 = vpbe_display_s_crop,
-
 	.vidioc_s_std		 = vpbe_display_s_std,
 	.vidioc_g_std		 = vpbe_display_g_std,
-
 	.vidioc_enum_output	 = vpbe_display_enum_output,
 	.vidioc_s_output	 = vpbe_display_s_output,
 	.vidioc_g_output	 = vpbe_display_g_output,
-
 	.vidioc_s_dv_timings	 = vpbe_display_s_dv_timings,
 	.vidioc_g_dv_timings	 = vpbe_display_g_dv_timings,
 	.vidioc_enum_dv_timings	 = vpbe_display_enum_dv_timings,
@@ -1272,8 +1619,8 @@
 	.open = vpbe_display_open,
 	.release = vpbe_display_release,
 	.unlocked_ioctl = video_ioctl2,
-	.mmap = vb2_fop_mmap,
-	.poll =  vb2_fop_poll,
+	.mmap = vpbe_display_mmap,
+	.poll = vpbe_display_poll
 };
 
 static int vpbe_device_get(struct device *dev, void *data)
@@ -1353,7 +1700,6 @@
 		  (int)vpbe_display_layer,
 		  (int)&vpbe_display_layer->video_dev);
 
-	vpbe_display_layer->video_dev.queue = &vpbe_display_layer->buffer_queue;
 	err = video_register_device(&vpbe_display_layer->video_dev,
 				    VFL_TYPE_GRABBER,
 				    -1);
@@ -1378,10 +1724,9 @@
  */
 static int vpbe_display_probe(struct platform_device *pdev)
 {
+	struct vpbe_layer *vpbe_display_layer;
 	struct vpbe_display *disp_dev;
-	struct v4l2_device *v4l2_dev;
 	struct resource *res = NULL;
-	struct vb2_queue *q;
 	int k;
 	int i;
 	int err;
@@ -1403,14 +1748,13 @@
 			vpbe_device_get);
 	if (err < 0)
 		return err;
-
-	v4l2_dev = &disp_dev->vpbe_dev->v4l2_dev;
 	/* Initialize the vpbe display controller */
 	if (NULL != disp_dev->vpbe_dev->ops.initialize) {
 		err = disp_dev->vpbe_dev->ops.initialize(&pdev->dev,
 							 disp_dev->vpbe_dev);
 		if (err) {
-			v4l2_err(v4l2_dev, "Error initing vpbe\n");
+			v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+					"Error initing vpbe\n");
 			err = -ENOMEM;
 			goto probe_out;
 		}
@@ -1425,7 +1769,8 @@
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
-		v4l2_err(v4l2_dev, "Unable to get VENC interrupt resource\n");
+		v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+			 "Unable to get VENC interrupt resource\n");
 		err = -ENODEV;
 		goto probe_out;
 	}
@@ -1434,57 +1779,30 @@
 	err = devm_request_irq(&pdev->dev, irq, venc_isr, 0,
 			       VPBE_DISPLAY_DRIVER, disp_dev);
 	if (err) {
-		v4l2_err(v4l2_dev, "VPBE IRQ request failed\n");
+		v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+				"Unable to request interrupt\n");
 		goto probe_out;
 	}
 
 	for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
-		/* initialize vb2 queue */
-		q = &disp_dev->dev[i]->buffer_queue;
-		memset(q, 0, sizeof(*q));
-		q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
-		q->drv_priv = disp_dev->dev[i];
-		q->ops = &video_qops;
-		q->mem_ops = &vb2_dma_contig_memops;
-		q->buf_struct_size = sizeof(struct vpbe_disp_buffer);
-		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-		q->min_buffers_needed = 1;
-		q->lock = &disp_dev->dev[i]->opslock;
-		err = vb2_queue_init(q);
-		if (err) {
-			v4l2_err(v4l2_dev, "vb2_queue_init() failed\n");
-			goto probe_out;
-		}
-
-		disp_dev->dev[i]->alloc_ctx =
-			vb2_dma_contig_init_ctx(disp_dev->vpbe_dev->pdev);
-		if (IS_ERR(disp_dev->dev[i]->alloc_ctx)) {
-			v4l2_err(v4l2_dev, "Failed to get the context\n");
-			err = PTR_ERR(disp_dev->dev[i]->alloc_ctx);
-			goto probe_out;
-		}
-
-		INIT_LIST_HEAD(&disp_dev->dev[i]->dma_queue);
-
 		if (register_device(disp_dev->dev[i], disp_dev, pdev)) {
 			err = -ENODEV;
 			goto probe_out;
 		}
 	}
 
-	v4l2_dbg(1, debug, v4l2_dev,
-		 "Successfully completed the probing of vpbe v4l2 device\n");
-
+	printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n");
 	return 0;
 
 probe_out:
 	for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) {
+		/* Get the pointer to the layer object */
+		vpbe_display_layer = disp_dev->dev[k];
 		/* Unregister video device */
-		if (disp_dev->dev[k] != NULL) {
-			vb2_dma_contig_cleanup_ctx(disp_dev->dev[k]->alloc_ctx);
-			video_unregister_device(&disp_dev->dev[k]->video_dev);
-			kfree(disp_dev->dev[k]);
+		if (vpbe_display_layer) {
+			video_unregister_device(
+				&vpbe_display_layer->video_dev);
+				kfree(disp_dev->dev[k]);
 		}
 	}
 	return err;
@@ -1510,7 +1828,6 @@
 	for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
 		/* Get the pointer to the layer object */
 		vpbe_display_layer = disp_dev->dev[i];
-		vb2_dma_contig_cleanup_ctx(vpbe_display_layer->alloc_ctx);
 		/* Unregister video device */
 		video_unregister_device(&vpbe_display_layer->video_dev);
 
@@ -1526,6 +1843,7 @@
 static struct platform_driver vpbe_display_driver = {
 	.driver = {
 		.name = VPBE_DISPLAY_DRIVER,
+		.owner = THIS_MODULE,
 		.bus = &platform_bus_type,
 	},
 	.probe = vpbe_display_probe,
diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c
index 7d96a4b..d053c26 100644
--- a/drivers/media/platform/davinci/vpbe_osd.c
+++ b/drivers/media/platform/davinci/vpbe_osd.c
@@ -1585,6 +1585,7 @@
 	.remove		= osd_remove,
 	.driver		= {
 		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
 	},
 	.id_table	= vpbe_osd_devtype
 };
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c
index 36ed146..14a023a 100644
--- a/drivers/media/platform/davinci/vpbe_venc.c
+++ b/drivers/media/platform/davinci/vpbe_venc.c
@@ -687,6 +687,7 @@
 	.remove		= venc_remove,
 	.driver		= {
 		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
 	},
 	.id_table	= vpbe_venc_devtype
 };
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index b41bf7e..de55f47 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -414,13 +414,13 @@
 		/* assume V4L2_PIX_FMT_UYVY as default */
 		pix->pixelformat = V4L2_PIX_FMT_UYVY;
 		v4l2_fill_mbus_format(&mbus_fmt, pix,
-				MEDIA_BUS_FMT_YUYV10_2X10);
+				V4L2_MBUS_FMT_YUYV10_2X10);
 	} else {
 		pix->field = V4L2_FIELD_NONE;
 		/* assume V4L2_PIX_FMT_SBGGR8 */
 		pix->pixelformat = V4L2_PIX_FMT_SBGGR8;
 		v4l2_fill_mbus_format(&mbus_fmt, pix,
-				MEDIA_BUS_FMT_SBGGR8_1X8);
+				V4L2_MBUS_FMT_SBGGR8_1X8);
 	}
 
 	/* if sub device supports g_mbus_fmt, override the defaults */
@@ -930,8 +930,8 @@
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
 
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	cap->version = VPFE_CAPTURE_VERSION_CODE;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 	strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
 	strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
 	strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
@@ -2031,6 +2031,7 @@
 static struct platform_driver vpfe_driver = {
 	.driver = {
 		.name = CAPTURE_DRV_NAME,
+		.owner = THIS_MODULE,
 		.pm = &vpfe_dev_pm_ops,
 	},
 	.probe = vpfe_probe,
diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c
index 0380cf2..3dad5bd 100644
--- a/drivers/media/platform/davinci/vpif.c
+++ b/drivers/media/platform/davinci/vpif.c
@@ -467,6 +467,7 @@
 static struct platform_driver vpif_driver = {
 	.driver = {
 		.name	= "vpif",
+		.owner = THIS_MODULE,
 		.pm	= vpif_pm_ops,
 	},
 	.remove = vpif_remove,
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index fa0a515..3ccb26f 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -311,8 +311,6 @@
 	.start_streaming	= vpif_start_streaming,
 	.stop_streaming		= vpif_stop_streaming,
 	.buf_queue		= vpif_buffer_queue,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
 };
 
 /**
@@ -1658,6 +1656,7 @@
 static __refdata struct platform_driver vpif_driver = {
 	.driver	= {
 		.name	= VPIF_DRIVER_NAME,
+		.owner	= THIS_MODULE,
 		.pm	= &vpif_pm_ops,
 	},
 	.probe = vpif_probe,
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 839c24d..8d6ced5 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -1459,6 +1459,7 @@
 static __refdata struct platform_driver vpif_driver = {
 	.driver	= {
 			.name	= VPIF_DRIVER_NAME,
+			.owner	= THIS_MODULE,
 			.pm	= &vpif_pm_ops,
 	},
 	.probe	= vpif_probe,
diff --git a/drivers/media/platform/davinci/vpss.c b/drivers/media/platform/davinci/vpss.c
index fce86f1..31120b4 100644
--- a/drivers/media/platform/davinci/vpss.c
+++ b/drivers/media/platform/davinci/vpss.c
@@ -504,6 +504,7 @@
 static struct platform_driver vpss_driver = {
 	.driver = {
 		.name	= "vpss",
+		.owner = THIS_MODULE,
 		.pm = &vpss_pm_ops,
 	},
 	.remove = vpss_remove,
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
index fd2891c..b4c9f1d 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/exynos-gsc/gsc-core.c
@@ -54,7 +54,7 @@
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 	}, {
 		.name		= "YUV 4:2:2 packed, CbYCrY",
 		.pixelformat	= V4L2_PIX_FMT_UYVY,
@@ -64,7 +64,7 @@
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_UYVY8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
 	}, {
 		.name		= "YUV 4:2:2 packed, CrYCbY",
 		.pixelformat	= V4L2_PIX_FMT_VYUY,
@@ -74,7 +74,7 @@
 		.corder		= GSC_CRCB,
 		.num_planes	= 1,
 		.num_comp	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_VYUY8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_VYUY8_2X8,
 	}, {
 		.name		= "YUV 4:2:2 packed, YCrYCb",
 		.pixelformat	= V4L2_PIX_FMT_YVYU,
@@ -84,7 +84,7 @@
 		.corder		= GSC_CRCB,
 		.num_planes	= 1,
 		.num_comp	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_YVYU8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YVYU8_2X8,
 	}, {
 		.name		= "YUV 4:4:4 planar, YCbYCr",
 		.pixelformat	= V4L2_PIX_FMT_YUV32,
@@ -319,22 +319,21 @@
 	return 0;
 }
 
-static int get_plane_info(struct gsc_frame *frm, u32 addr, u32 *index, u32 *ret_addr)
+static u32 get_plane_info(struct gsc_frame *frm, u32 addr, u32 *index)
 {
 	if (frm->addr.y == addr) {
 		*index = 0;
-		*ret_addr = frm->addr.y;
+		return frm->addr.y;
 	} else if (frm->addr.cb == addr) {
 		*index = 1;
-		*ret_addr = frm->addr.cb;
+		return frm->addr.cb;
 	} else if (frm->addr.cr == addr) {
 		*index = 2;
-		*ret_addr = frm->addr.cr;
+		return frm->addr.cr;
 	} else {
 		pr_err("Plane address is wrong");
 		return -EINVAL;
 	}
-	return 0;
 }
 
 void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm)
@@ -353,11 +352,9 @@
 		u32 t_min, t_max;
 
 		t_min = min3(frm->addr.y, frm->addr.cb, frm->addr.cr);
-		if (get_plane_info(frm, t_min, &low_plane, &low_addr))
-			return;
+		low_addr = get_plane_info(frm, t_min, &low_plane);
 		t_max = max3(frm->addr.y, frm->addr.cb, frm->addr.cr);
-		if (get_plane_info(frm, t_max, &high_plane, &high_addr))
-			return;
+		high_addr = get_plane_info(frm, t_max, &high_plane);
 
 		mid_plane = 3 - (low_plane + high_plane);
 		if (mid_plane == 0)
@@ -1256,6 +1253,7 @@
 	.id_table	= gsc_driver_ids,
 	.driver = {
 		.name	= GSC_MODULE_NAME,
+		.owner	= THIS_MODULE,
 		.pm	= &gsc_pm_ops,
 		.of_match_table = exynos_gsc_match,
 	}
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index 0abdb17..ef0a656 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -117,7 +117,7 @@
  * @flags: flags indicating which operation mode format applies to
  */
 struct gsc_fmt {
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 	char	*name;
 	u32	pixelformat;
 	u32	color;
diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig
index 9986ed7..8b0a506 100644
--- a/drivers/media/platform/exynos4-is/Kconfig
+++ b/drivers/media/platform/exynos4-is/Kconfig
@@ -2,7 +2,7 @@
 config VIDEO_SAMSUNG_EXYNOS4_IS
 	bool "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver"
 	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+	depends on (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST)
 	depends on OF && COMMON_CLK
 	help
 	  Say Y here to enable camera host interface devices for
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index 8a2fd8c..3d2babd 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -749,7 +749,7 @@
 		return -EINVAL;
 	strncpy(f->description, fmt->name, sizeof(f->description) - 1);
 	f->pixelformat = fmt->fourcc;
-	if (fmt->fourcc == MEDIA_BUS_FMT_JPEG_1X8)
+	if (fmt->fourcc == V4L2_MBUS_FMT_JPEG_1X8)
 		f->flags |= V4L2_FMT_FLAG_COMPRESSED;
 	return 0;
 }
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
index 1101c41..b70fd99 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -81,7 +81,7 @@
 		.flags		= FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
 	}, {
 		.name		= "YUV 4:4:4",
-		.mbus_code	= MEDIA_BUS_FMT_YUV10_1X30,
+		.mbus_code	= V4L2_MBUS_FMT_YUV10_1X30,
 		.flags		= FMT_FLAGS_WRITEBACK,
 	}, {
 		.name		= "YUV 4:2:2 packed, YCbYCr",
@@ -90,7 +90,7 @@
 		.color		= FIMC_FMT_YCBYCR422,
 		.memplanes	= 1,
 		.colplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
 	}, {
 		.name		= "YUV 4:2:2 packed, CbYCrY",
@@ -99,7 +99,7 @@
 		.color		= FIMC_FMT_CBYCRY422,
 		.memplanes	= 1,
 		.colplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_UYVY8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
 		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
 	}, {
 		.name		= "YUV 4:2:2 packed, CrYCbY",
@@ -108,7 +108,7 @@
 		.color		= FIMC_FMT_CRYCBY422,
 		.memplanes	= 1,
 		.colplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_VYUY8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_VYUY8_2X8,
 		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
 	}, {
 		.name		= "YUV 4:2:2 packed, YCrYCb",
@@ -117,7 +117,7 @@
 		.color		= FIMC_FMT_YCRYCB422,
 		.memplanes	= 1,
 		.colplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_YVYU8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YVYU8_2X8,
 		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
 	}, {
 		.name		= "YUV 4:2:2 planar, Y/Cb/Cr",
@@ -190,7 +190,7 @@
 		.depth		= { 8 },
 		.memplanes	= 1,
 		.colplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_JPEG_1X8,
+		.mbus_code	= V4L2_MBUS_FMT_JPEG_1X8,
 		.flags		= FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
 	}, {
 		.name		= "S5C73MX interleaved UYVY/JPEG",
@@ -200,7 +200,7 @@
 		.memplanes	= 2,
 		.colplanes	= 1,
 		.mdataplanes	= 0x2, /* plane 1 holds frame meta data */
-		.mbus_code	= MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8,
+		.mbus_code	= V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
 		.flags		= FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
 	},
 };
@@ -832,7 +832,6 @@
 	return -ENXIO;
 }
 
-#ifdef CONFIG_PM
 static int fimc_m2m_suspend(struct fimc_dev *fimc)
 {
 	unsigned long flags;
@@ -871,7 +870,6 @@
 
 	return 0;
 }
-#endif /* CONFIG_PM */
 
 static const struct of_device_id fimc_of_match[];
 
@@ -1039,7 +1037,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 static int fimc_runtime_resume(struct device *dev)
 {
 	struct fimc_dev *fimc =	dev_get_drvdata(dev);
@@ -1294,6 +1292,7 @@
 	.driver = {
 		.of_match_table = fimc_of_match,
 		.name		= FIMC_DRIVER_NAME,
+		.owner		= THIS_MODULE,
 		.pm     	= &fimc_pm_ops,
 	}
 };
diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
index 7328f08..6c75c6c 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.h
+++ b/drivers/media/platform/exynos4-is/fimc-core.h
@@ -579,8 +579,8 @@
 
 static inline bool fimc_user_defined_mbus_fmt(u32 code)
 {
-	return (code == MEDIA_BUS_FMT_JPEG_1X8 ||
-		code == MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8);
+	return (code == V4L2_MBUS_FMT_JPEG_1X8 ||
+		code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8);
 }
 
 /* Return the alpha component bit mask */
diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
index 7521aa5..371cad4 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c
+++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
@@ -81,7 +81,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
 static int fimc_is_i2c_runtime_suspend(struct device *dev)
 {
 	struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev);
@@ -133,6 +133,7 @@
 	.driver = {
 		.of_match_table = fimc_is_i2c_of_match,
 		.name		= "fimc-isp-i2c",
+		.owner		= THIS_MODULE,
 		.pm		= &fimc_is_i2c_pm_ops,
 	}
 };
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
index 49658ca..22162b2 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.c
+++ b/drivers/media/platform/exynos4-is/fimc-is.c
@@ -428,7 +428,8 @@
 	 * needed around for copying to the IS working memory every
 	 * time before the Cortex-A5 is restarted.
 	 */
-	release_firmware(is->fw.f_w);
+	if (is->fw.f_w)
+		release_firmware(is->fw.f_w);
 	is->fw.f_w = fw;
 done:
 	mutex_unlock(&is->lock);
@@ -813,9 +814,9 @@
 		return -ENOMEM;
 
 	is->irq = irq_of_parse_and_map(dev->of_node, 0);
-	if (!is->irq) {
+	if (is->irq < 0) {
 		dev_err(dev, "no irq found\n");
-		return -EINVAL;
+		return is->irq;
 	}
 
 	ret = fimc_is_get_clocks(is);
@@ -936,7 +937,8 @@
 	vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
 	fimc_is_put_clocks(is);
 	fimc_is_debugfs_remove(is);
-	release_firmware(is->fw.f_w);
+	if (is->fw.f_w)
+		release_firmware(is->fw.f_w);
 	fimc_is_free_cpu_memory(is);
 
 	return 0;
@@ -960,6 +962,7 @@
 	.driver = {
 		.of_match_table	= fimc_is_of_match,
 		.name		= FIMC_IS_DRV_NAME,
+		.owner		= THIS_MODULE,
 		.pm		= &fimc_is_pm_ops,
 	}
 };
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c
index 60c7449..be62d6b 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp.c
@@ -41,21 +41,21 @@
 		.depth		= { 8 },
 		.color		= FIMC_FMT_RAW8,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.mbus_code	= V4L2_MBUS_FMT_SGRBG8_1X8,
 	}, {
 		.name		= "RAW10 (GRBG)",
 		.fourcc		= V4L2_PIX_FMT_SGRBG10,
 		.depth		= { 10 },
 		.color		= FIMC_FMT_RAW10,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.mbus_code	= V4L2_MBUS_FMT_SGRBG10_1X10,
 	}, {
 		.name		= "RAW12 (GRBG)",
 		.fourcc		= V4L2_PIX_FMT_SGRBG12,
 		.depth		= { 12 },
 		.color		= FIMC_FMT_RAW12,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
+		.mbus_code	= V4L2_MBUS_FMT_SGRBG12_1X12,
 	},
 };
 
@@ -149,7 +149,7 @@
 
 		if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) {
 			mf->colorspace = V4L2_COLORSPACE_JPEG;
-			mf->code = MEDIA_BUS_FMT_YUV10_1X30;
+			mf->code = V4L2_MBUS_FMT_YUV10_1X30;
 		}
 	}
 
@@ -175,7 +175,7 @@
 				FIMC_ISP_SINK_WIDTH_MAX, 0,
 				&mf->height, FIMC_ISP_SINK_HEIGHT_MIN,
 				FIMC_ISP_SINK_HEIGHT_MAX, 0, 0);
-		mf->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+		mf->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	} else {
 		if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
 			format = v4l2_subdev_get_try_format(fh,
@@ -188,7 +188,7 @@
 		mf->height = format->height - FIMC_ISP_CAC_MARGIN_HEIGHT;
 
 		if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) {
-			mf->code = MEDIA_BUS_FMT_YUV10_1X30;
+			mf->code = V4L2_MBUS_FMT_YUV10_1X30;
 			mf->colorspace = V4L2_COLORSPACE_JPEG;
 		} else {
 			mf->code = format->code;
@@ -680,11 +680,11 @@
 				FIMC_ISP_CAC_MARGIN_WIDTH;
 	isp->sink_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT +
 				FIMC_ISP_CAC_MARGIN_HEIGHT;
-	isp->sink_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	isp->sink_fmt.code = V4L2_MBUS_FMT_SGRBG10_1X10;
 
 	isp->src_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH;
 	isp->src_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT;
-	isp->src_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	isp->src_fmt.code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	__is_set_frame_size(is, &isp->src_fmt);
 }
 
diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c
index 0477716..bc3ec7d 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c
@@ -112,24 +112,24 @@
 }
 
 static const u32 src_pixfmt_map[8][3] = {
-	{ MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR,
+	{ V4L2_MBUS_FMT_YUYV8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR,
 	  FLITE_REG_CIGCTRL_YUV422_1P },
-	{ MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB,
+	{ V4L2_MBUS_FMT_YVYU8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB,
 	  FLITE_REG_CIGCTRL_YUV422_1P },
-	{ MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY,
+	{ V4L2_MBUS_FMT_UYVY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY,
 	  FLITE_REG_CIGCTRL_YUV422_1P },
-	{ MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY,
+	{ V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY,
 	  FLITE_REG_CIGCTRL_YUV422_1P },
-	{ MEDIA_BUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 },
-	{ MEDIA_BUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 },
-	{ MEDIA_BUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 },
-	{ MEDIA_BUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) },
+	{ V4L2_MBUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 },
+	{ V4L2_MBUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 },
+	{ V4L2_MBUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 },
+	{ V4L2_MBUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) },
 };
 
 /* Set camera input pixel format and resolution */
 void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
 {
-	u32 pixelcode = f->fmt->mbus_code;
+	enum v4l2_mbus_pixelcode pixelcode = f->fmt->mbus_code;
 	int i = ARRAY_SIZE(src_pixfmt_map);
 	u32 cfg;
 
@@ -232,10 +232,10 @@
 static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
 {
 	static const u32 pixcode[4][2] = {
-		{ MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR },
-		{ MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CIODMAFMT_YCRYCB },
-		{ MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CIODMAFMT_CBYCRY },
-		{ MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY },
+		{ V4L2_MBUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR },
+		{ V4L2_MBUS_FMT_YVYU8_2X8, FLITE_REG_CIODMAFMT_YCRYCB },
+		{ V4L2_MBUS_FMT_UYVY8_2X8, FLITE_REG_CIODMAFMT_CBYCRY },
+		{ V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY },
 	};
 	u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
 	int i = ARRAY_SIZE(pixcode);
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index 2510f18..a97d235 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -48,7 +48,7 @@
 		.depth		= { 16 },
 		.color		= FIMC_FMT_YCBYCR422,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.flags		= FMT_FLAGS_YUV,
 	}, {
 		.name		= "YUV 4:2:2 packed, CbYCrY",
@@ -57,7 +57,7 @@
 		.depth		= { 16 },
 		.color		= FIMC_FMT_CBYCRY422,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_UYVY8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
 		.flags		= FMT_FLAGS_YUV,
 	}, {
 		.name		= "YUV 4:2:2 packed, CrYCbY",
@@ -66,7 +66,7 @@
 		.depth		= { 16 },
 		.color		= FIMC_FMT_CRYCBY422,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_VYUY8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_VYUY8_2X8,
 		.flags		= FMT_FLAGS_YUV,
 	}, {
 		.name		= "YUV 4:2:2 packed, YCrYCb",
@@ -75,7 +75,7 @@
 		.depth		= { 16 },
 		.color		= FIMC_FMT_YCRYCB422,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_YVYU8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YVYU8_2X8,
 		.flags		= FMT_FLAGS_YUV,
 	}, {
 		.name		= "RAW8 (GRBG)",
@@ -84,7 +84,7 @@
 		.depth		= { 8 },
 		.color		= FIMC_FMT_RAW8,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.mbus_code	= V4L2_MBUS_FMT_SGRBG8_1X8,
 		.flags		= FMT_FLAGS_RAW_BAYER,
 	}, {
 		.name		= "RAW10 (GRBG)",
@@ -93,7 +93,7 @@
 		.depth		= { 16 },
 		.color		= FIMC_FMT_RAW10,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.mbus_code	= V4L2_MBUS_FMT_SGRBG10_1X10,
 		.flags		= FMT_FLAGS_RAW_BAYER,
 	}, {
 		.name		= "RAW12 (GRBG)",
@@ -102,7 +102,7 @@
 		.depth		= { 16 },
 		.color		= FIMC_FMT_RAW12,
 		.memplanes	= 1,
-		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
+		.mbus_code	= V4L2_MBUS_FMT_SGRBG12_1X12,
 		.flags		= FMT_FLAGS_RAW_BAYER,
 	},
 };
@@ -1588,7 +1588,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 static int fimc_lite_runtime_resume(struct device *dev)
 {
 	struct fimc_lite *fimc = dev_get_drvdata(dev);
@@ -1720,6 +1720,7 @@
 	.driver = {
 		.of_match_table = flite_of_match,
 		.name		= FIMC_LITE_DRV_NAME,
+		.owner		= THIS_MODULE,
 		.pm		= &fimc_lite_pm_ops,
 	}
 };
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
index f3ed10b..0ad1b6f 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -538,9 +538,7 @@
 	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
 	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
 	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
 	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
-#endif
 	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
 	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
 	.vidioc_g_crop			= fimc_m2m_g_crop,
diff --git a/drivers/media/platform/exynos4-is/fimc-reg.c b/drivers/media/platform/exynos4-is/fimc-reg.c
index df0cbcb..2d77fd8 100644
--- a/drivers/media/platform/exynos4-is/fimc-reg.c
+++ b/drivers/media/platform/exynos4-is/fimc-reg.c
@@ -592,10 +592,10 @@
 };
 
 static const struct mbus_pixfmt_desc pix_desc[] = {
-	{ MEDIA_BUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 },
-	{ MEDIA_BUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 },
-	{ MEDIA_BUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 },
-	{ MEDIA_BUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 },
+	{ V4L2_MBUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 },
+	{ V4L2_MBUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 },
+	{ V4L2_MBUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 },
+	{ V4L2_MBUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 },
 };
 
 int fimc_hw_set_camera_source(struct fimc_dev *fimc,
@@ -689,11 +689,11 @@
 
 		/* TODO: add remaining supported formats. */
 		switch (vid_cap->ci_fmt.code) {
-		case MEDIA_BUS_FMT_VYUY8_2X8:
+		case V4L2_MBUS_FMT_VYUY8_2X8:
 			tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
 			break;
-		case MEDIA_BUS_FMT_JPEG_1X8:
-		case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8:
+		case V4L2_MBUS_FMT_JPEG_1X8:
+		case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
 			tmp = FIMC_REG_CSIIMGFMT_USER(1);
 			cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
 			break;
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index f315ef9..54c49d5 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -1469,6 +1469,7 @@
 	.driver = {
 		.of_match_table = of_match_ptr(fimc_md_of_match),
 		.name		= "s5p-fimc-md",
+		.owner		= THIS_MODULE,
 	}
 };
 
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
index 2504aa8..db6fd14 100644
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -238,34 +238,34 @@
  */
 struct csis_pix_format {
 	unsigned int pix_width_alignment;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	u32 fmt_reg;
 	u8 data_alignment;
 };
 
 static const struct csis_pix_format s5pcsis_formats[] = {
 	{
-		.code = MEDIA_BUS_FMT_VYUY8_2X8,
+		.code = V4L2_MBUS_FMT_VYUY8_2X8,
 		.fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT,
 		.data_alignment = 32,
 	}, {
-		.code = MEDIA_BUS_FMT_JPEG_1X8,
+		.code = V4L2_MBUS_FMT_JPEG_1X8,
 		.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
 		.data_alignment = 32,
 	}, {
-		.code = MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8,
+		.code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
 		.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
 		.data_alignment = 32,
 	}, {
-		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
+		.code = V4L2_MBUS_FMT_SGRBG8_1X8,
 		.fmt_reg = S5PCSIS_CFG_FMT_RAW8,
 		.data_alignment = 24,
 	}, {
-		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.code = V4L2_MBUS_FMT_SGRBG10_1X10,
 		.fmt_reg = S5PCSIS_CFG_FMT_RAW10,
 		.data_alignment = 24,
 	}, {
-		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.code = V4L2_MBUS_FMT_SGRBG12_1X12,
 		.fmt_reg = S5PCSIS_CFG_FMT_RAW12,
 		.data_alignment = 24,
 	}
@@ -978,7 +978,7 @@
 }
 #endif
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 static int s5pcsis_runtime_suspend(struct device *dev)
 {
 	return s5pcsis_pm_suspend(dev, true);
@@ -1041,6 +1041,7 @@
 	.driver		= {
 		.of_match_table = s5pcsis_of_match,
 		.name		= CSIS_DRIVER_NAME,
+		.owner		= THIS_MODULE,
 		.pm		= &s5pcsis_pm_ops,
 	},
 };
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index bbf4281..d5dc198 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -604,11 +604,10 @@
 {
 	strcpy(cap->driver, "viu");
 	strcpy(cap->card, "viu");
-	cap->device_caps =	V4L2_CAP_VIDEO_CAPTURE |
+	cap->capabilities =	V4L2_CAP_VIDEO_CAPTURE |
 				V4L2_CAP_STREAMING     |
 				V4L2_CAP_VIDEO_OVERLAY |
 				V4L2_CAP_READWRITE;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
@@ -1681,6 +1680,7 @@
 #endif
 	.driver = {
 		.name = DRV_NAME,
+		.owner = THIS_MODULE,
 		.of_match_table = mpc512x_viu_of_match,
 	},
 };
diff --git a/drivers/media/platform/indycam.c b/drivers/media/platform/indycam.c
new file mode 100644
index 0000000..f1d192b
--- /dev/null
+++ b/drivers/media/platform/indycam.c
@@ -0,0 +1,378 @@
+/*
+ *  indycam.c - Silicon Graphics IndyCam digital camera driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  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/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+/* IndyCam decodes stream of photons into digital image representation ;-) */
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+
+#include "indycam.h"
+
+#define INDYCAM_MODULE_VERSION "0.0.5"
+
+MODULE_DESCRIPTION("SGI IndyCam driver");
+MODULE_VERSION(INDYCAM_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+
+// #define INDYCAM_DEBUG
+
+#ifdef INDYCAM_DEBUG
+#define dprintk(x...) printk("IndyCam: " x);
+#define indycam_regdump(client) indycam_regdump_debug(client)
+#else
+#define dprintk(x...)
+#define indycam_regdump(client)
+#endif
+
+struct indycam {
+	struct v4l2_subdev sd;
+	u8 version;
+};
+
+static inline struct indycam *to_indycam(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct indycam, sd);
+}
+
+static const u8 initseq[] = {
+	INDYCAM_CONTROL_AGCENA,		/* INDYCAM_CONTROL */
+	INDYCAM_SHUTTER_60,		/* INDYCAM_SHUTTER */
+	INDYCAM_GAIN_DEFAULT,		/* INDYCAM_GAIN */
+	0x00,				/* INDYCAM_BRIGHTNESS (read-only) */
+	INDYCAM_RED_BALANCE_DEFAULT,	/* INDYCAM_RED_BALANCE */
+	INDYCAM_BLUE_BALANCE_DEFAULT,	/* INDYCAM_BLUE_BALANCE */
+	INDYCAM_RED_SATURATION_DEFAULT,	/* INDYCAM_RED_SATURATION */
+	INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */
+};
+
+/* IndyCam register handling */
+
+static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	if (reg == INDYCAM_REG_RESET) {
+		dprintk("indycam_read_reg(): "
+			"skipping write-only register %d\n", reg);
+		*value = 0;
+		return 0;
+	}
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+
+	if (ret < 0) {
+		printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, "
+		       "register = 0x%02x\n", reg);
+		return ret;
+	}
+
+	*value = (u8)ret;
+
+	return 0;
+}
+
+static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int err;
+
+	if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) {
+		dprintk("indycam_write_reg(): "
+			"skipping read-only register %d\n", reg);
+		return 0;
+	}
+
+	dprintk("Writing Reg %d = 0x%02x\n", reg, value);
+	err = i2c_smbus_write_byte_data(client, reg, value);
+
+	if (err) {
+		printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, "
+		       "register = 0x%02x, value = 0x%02x\n", reg, value);
+	}
+	return err;
+}
+
+static int indycam_write_block(struct v4l2_subdev *sd, u8 reg,
+			       u8 length, u8 *data)
+{
+	int i, err;
+
+	for (i = 0; i < length; i++) {
+		err = indycam_write_reg(sd, reg + i, data[i]);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+/* Helper functions */
+
+#ifdef INDYCAM_DEBUG
+static void indycam_regdump_debug(struct v4l2_subdev *sd)
+{
+	int i;
+	u8 val;
+
+	for (i = 0; i < 9; i++) {
+		indycam_read_reg(sd, i, &val);
+		dprintk("Reg %d = 0x%02x\n", i, val);
+	}
+}
+#endif
+
+static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct indycam *camera = to_indycam(sd);
+	u8 reg;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
+		if (ret)
+			return -EIO;
+		if (ctrl->id == V4L2_CID_AUTOGAIN)
+			ctrl->value = (reg & INDYCAM_CONTROL_AGCENA)
+				? 1 : 0;
+		else
+			ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL)
+				? 1 : 0;
+		break;
+	case V4L2_CID_EXPOSURE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, &reg);
+		if (ret)
+			return -EIO;
+		ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
+		break;
+	case V4L2_CID_GAIN:
+		ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, &reg);
+		if (ret)
+			return -EIO;
+		ctrl->value = (s32)reg;
+		break;
+	case V4L2_CID_RED_BALANCE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, &reg);
+		if (ret)
+			return -EIO;
+		ctrl->value = (s32)reg;
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, &reg);
+		if (ret)
+			return -EIO;
+		ctrl->value = (s32)reg;
+		break;
+	case INDYCAM_CONTROL_RED_SATURATION:
+		ret = indycam_read_reg(sd,
+				       INDYCAM_REG_RED_SATURATION, &reg);
+		if (ret)
+			return -EIO;
+		ctrl->value = (s32)reg;
+		break;
+	case INDYCAM_CONTROL_BLUE_SATURATION:
+		ret = indycam_read_reg(sd,
+				       INDYCAM_REG_BLUE_SATURATION, &reg);
+		if (ret)
+			return -EIO;
+		ctrl->value = (s32)reg;
+		break;
+	case V4L2_CID_GAMMA:
+		if (camera->version == CAMERA_VERSION_MOOSE) {
+			ret = indycam_read_reg(sd,
+					       INDYCAM_REG_GAMMA, &reg);
+			if (ret)
+				return -EIO;
+			ctrl->value = (s32)reg;
+		} else {
+			ctrl->value = INDYCAM_GAMMA_DEFAULT;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct indycam *camera = to_indycam(sd);
+	u8 reg;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
+		if (ret)
+			break;
+
+		if (ctrl->id == V4L2_CID_AUTOGAIN) {
+			if (ctrl->value)
+				reg |= INDYCAM_CONTROL_AGCENA;
+			else
+				reg &= ~INDYCAM_CONTROL_AGCENA;
+		} else {
+			if (ctrl->value)
+				reg |= INDYCAM_CONTROL_AWBCTL;
+			else
+				reg &= ~INDYCAM_CONTROL_AWBCTL;
+		}
+
+		ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg);
+		break;
+	case V4L2_CID_EXPOSURE:
+		reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
+		ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg);
+		break;
+	case V4L2_CID_GAIN:
+		ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value);
+		break;
+	case V4L2_CID_RED_BALANCE:
+		ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE,
+					ctrl->value);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE,
+					ctrl->value);
+		break;
+	case INDYCAM_CONTROL_RED_SATURATION:
+		ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION,
+					ctrl->value);
+		break;
+	case INDYCAM_CONTROL_BLUE_SATURATION:
+		ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION,
+					ctrl->value);
+		break;
+	case V4L2_CID_GAMMA:
+		if (camera->version == CAMERA_VERSION_MOOSE) {
+			ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA,
+						ctrl->value);
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/* I2C-interface */
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops indycam_core_ops = {
+	.g_ctrl = indycam_g_ctrl,
+	.s_ctrl = indycam_s_ctrl,
+};
+
+static const struct v4l2_subdev_ops indycam_ops = {
+	.core = &indycam_core_ops,
+};
+
+static int indycam_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	int err = 0;
+	struct indycam *camera;
+	struct v4l2_subdev *sd;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	camera = kzalloc(sizeof(struct indycam), GFP_KERNEL);
+	if (!camera)
+		return -ENOMEM;
+
+	sd = &camera->sd;
+	v4l2_i2c_subdev_init(sd, client, &indycam_ops);
+
+	camera->version = i2c_smbus_read_byte_data(client,
+						   INDYCAM_REG_VERSION);
+	if (camera->version != CAMERA_VERSION_INDY &&
+	    camera->version != CAMERA_VERSION_MOOSE) {
+		kfree(camera);
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "IndyCam v%d.%d detected\n",
+	       INDYCAM_VERSION_MAJOR(camera->version),
+	       INDYCAM_VERSION_MINOR(camera->version));
+
+	indycam_regdump(sd);
+
+	// initialize
+	err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq);
+	if (err) {
+		printk(KERN_ERR "IndyCam initialization failed\n");
+		kfree(camera);
+		return -EIO;
+	}
+
+	indycam_regdump(sd);
+
+	// white balance
+	err = indycam_write_reg(sd, INDYCAM_REG_CONTROL,
+			  INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
+	if (err) {
+		printk(KERN_ERR "IndyCam: White balancing camera failed\n");
+		kfree(camera);
+		return -EIO;
+	}
+
+	indycam_regdump(sd);
+
+	printk(KERN_INFO "IndyCam initialized\n");
+
+	return 0;
+}
+
+static int indycam_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_indycam(sd));
+	return 0;
+}
+
+static const struct i2c_device_id indycam_id[] = {
+	{ "indycam", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, indycam_id);
+
+static struct i2c_driver indycam_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "indycam",
+	},
+	.probe		= indycam_probe,
+	.remove		= indycam_remove,
+	.id_table	= indycam_id,
+};
+
+module_i2c_driver(indycam_driver);
diff --git a/drivers/media/platform/indycam.h b/drivers/media/platform/indycam.h
new file mode 100644
index 0000000..881f21c
--- /dev/null
+++ b/drivers/media/platform/indycam.h
@@ -0,0 +1,93 @@
+/*
+ *  indycam.h - Silicon Graphics IndyCam digital camera driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  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 _INDYCAM_H_
+#define _INDYCAM_H_
+
+/* I2C address for the Guinness Camera */
+#define INDYCAM_ADDR			0x56
+
+/* Camera version */
+#define CAMERA_VERSION_INDY		0x10	/* v1.0 */
+#define CAMERA_VERSION_MOOSE		0x12	/* v1.2 */
+#define INDYCAM_VERSION_MAJOR(x)	(((x) & 0xf0) >> 4)
+#define INDYCAM_VERSION_MINOR(x)	((x) & 0x0f)
+
+/* Register bus addresses */
+#define INDYCAM_REG_CONTROL		0x00
+#define INDYCAM_REG_SHUTTER		0x01
+#define INDYCAM_REG_GAIN		0x02
+#define INDYCAM_REG_BRIGHTNESS		0x03 /* read-only */
+#define INDYCAM_REG_RED_BALANCE		0x04
+#define INDYCAM_REG_BLUE_BALANCE	0x05
+#define INDYCAM_REG_RED_SATURATION	0x06
+#define INDYCAM_REG_BLUE_SATURATION	0x07
+#define INDYCAM_REG_GAMMA		0x08
+#define INDYCAM_REG_VERSION		0x0e /* read-only */
+#define INDYCAM_REG_RESET		0x0f /* write-only */
+
+#define INDYCAM_REG_LED			0x46
+#define INDYCAM_REG_ORIENTATION		0x47
+#define INDYCAM_REG_BUTTON		0x48
+
+/* Field definitions of registers */
+#define INDYCAM_CONTROL_AGCENA		(1<<0) /* automatic gain control */
+#define INDYCAM_CONTROL_AWBCTL		(1<<1) /* automatic white balance */
+						/* 2-3 are reserved */
+#define INDYCAM_CONTROL_EVNFLD		(1<<4)	/* read-only */
+
+#define INDYCAM_SHUTTER_10000		0x02	/* 1/10000 second */
+#define INDYCAM_SHUTTER_4000		0x04	/* 1/4000 second */
+#define INDYCAM_SHUTTER_2000		0x08	/* 1/2000 second */
+#define INDYCAM_SHUTTER_1000		0x10	/* 1/1000 second */
+#define INDYCAM_SHUTTER_500		0x20	/* 1/500 second */
+#define INDYCAM_SHUTTER_250		0x3f	/* 1/250 second */
+#define INDYCAM_SHUTTER_125		0x7e	/* 1/125 second */
+#define INDYCAM_SHUTTER_100		0x9e	/* 1/100 second */
+#define INDYCAM_SHUTTER_60		0x00	/* 1/60 second */
+
+#define INDYCAM_LED_ACTIVE			0x10
+#define INDYCAM_LED_INACTIVE			0x30
+#define INDYCAM_ORIENTATION_BOTTOM_TO_TOP	0x40
+#define INDYCAM_BUTTON_RELEASED			0x10
+
+/* Values for controls */
+#define INDYCAM_SHUTTER_MIN		0x00
+#define INDYCAM_SHUTTER_MAX		0xff
+#define INDYCAM_GAIN_MIN                0x00
+#define INDYCAM_GAIN_MAX                0xff
+#define INDYCAM_RED_BALANCE_MIN		0x00
+#define INDYCAM_RED_BALANCE_MAX		0xff
+#define INDYCAM_BLUE_BALANCE_MIN        0x00
+#define INDYCAM_BLUE_BALANCE_MAX        0xff
+#define INDYCAM_RED_SATURATION_MIN      0x00
+#define INDYCAM_RED_SATURATION_MAX      0xff
+#define INDYCAM_BLUE_SATURATION_MIN	0x00
+#define INDYCAM_BLUE_SATURATION_MAX	0xff
+#define INDYCAM_GAMMA_MIN		0x00
+#define INDYCAM_GAMMA_MAX		0xff
+
+#define INDYCAM_AGC_DEFAULT		1
+#define INDYCAM_AWB_DEFAULT		0
+#define INDYCAM_SHUTTER_DEFAULT		0xff
+#define INDYCAM_GAIN_DEFAULT		0x80
+#define INDYCAM_RED_BALANCE_DEFAULT	0x18
+#define INDYCAM_BLUE_BALANCE_DEFAULT	0xa4
+#define INDYCAM_RED_SATURATION_DEFAULT	0x80
+#define INDYCAM_BLUE_SATURATION_DEFAULT	0xc0
+#define INDYCAM_GAMMA_DEFAULT		0x80
+
+/* Driver interface definitions */
+
+#define INDYCAM_CONTROL_RED_SATURATION		(V4L2_CID_PRIVATE_BASE + 0)
+#define INDYCAM_CONTROL_BLUE_SATURATION		(V4L2_CID_PRIVATE_BASE + 1)
+
+#endif
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index b70c1ae..d36c507 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -1101,6 +1101,7 @@
 	.remove		= deinterlace_remove,
 	.driver		= {
 		.name	= MEM2MEM_NAME,
+		.owner	= THIS_MODULE,
 	},
 };
 module_platform_driver(deinterlace_pdrv);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 137ffa2..6895e12 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -106,61 +106,61 @@
 	__u32 pixelformat;
 	int bpp;   /* Bytes per pixel */
 	bool planar;
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 } mcam_formats[] = {
 	{
 		.desc		= "YUYV 4:2:2",
 		.pixelformat	= V4L2_PIX_FMT_YUYV,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp		= 2,
 		.planar		= false,
 	},
 	{
 		.desc		= "UYVY 4:2:2",
 		.pixelformat	= V4L2_PIX_FMT_UYVY,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp		= 2,
 		.planar		= false,
 	},
 	{
 		.desc		= "YUV 4:2:2 PLANAR",
 		.pixelformat	= V4L2_PIX_FMT_YUV422P,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp		= 2,
 		.planar		= true,
 	},
 	{
 		.desc		= "YUV 4:2:0 PLANAR",
 		.pixelformat	= V4L2_PIX_FMT_YUV420,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp		= 2,
 		.planar		= true,
 	},
 	{
 		.desc		= "YVU 4:2:0 PLANAR",
 		.pixelformat	= V4L2_PIX_FMT_YVU420,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp		= 2,
 		.planar		= true,
 	},
 	{
 		.desc		= "RGB 444",
 		.pixelformat	= V4L2_PIX_FMT_RGB444,
-		.mbus_code	= MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE,
+		.mbus_code	= V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
 		.bpp		= 2,
 		.planar		= false,
 	},
 	{
 		.desc		= "RGB 565",
 		.pixelformat	= V4L2_PIX_FMT_RGB565,
-		.mbus_code	= MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.mbus_code	= V4L2_MBUS_FMT_RGB565_2X8_LE,
 		.bpp		= 2,
 		.planar		= false,
 	},
 	{
 		.desc		= "Raw RGB Bayer",
 		.pixelformat	= V4L2_PIX_FMT_SBGGR8,
-		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.mbus_code	= V4L2_MBUS_FMT_SBGGR8_1X8,
 		.bpp		= 1,
 		.planar		= false,
 	},
@@ -190,7 +190,8 @@
 	.sizeimage	= VGA_WIDTH*VGA_HEIGHT*2,
 };
 
-static const u32 mcam_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
+static const enum v4l2_mbus_pixelcode mcam_def_mbus_code =
+					V4L2_MBUS_FMT_YUYV8_2X8;
 
 
 /*
@@ -1079,8 +1080,6 @@
 		*nbufs = minbufs;
 	if (cam->buffer_mode == B_DMA_contig)
 		alloc_ctxs[0] = cam->vb_alloc_ctx;
-	else if (cam->buffer_mode == B_DMA_sg)
-		alloc_ctxs[0] = cam->vb_alloc_ctx_sg;
 	return 0;
 }
 
@@ -1102,6 +1101,26 @@
 		mcam_read_setup(cam);
 }
 
+
+/*
+ * vb2 uses these to release the mutex when waiting in dqbuf.  I'm
+ * not actually sure we need to do this (I'm not sure that vb2_dqbuf() needs
+ * to be called with the mutex held), but better safe than sorry.
+ */
+static void mcam_vb_wait_prepare(struct vb2_queue *vq)
+{
+	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+
+	mutex_unlock(&cam->s_mutex);
+}
+
+static void mcam_vb_wait_finish(struct vb2_queue *vq)
+{
+	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+
+	mutex_lock(&cam->s_mutex);
+}
+
 /*
  * These need to be called with the mutex held from vb2
  */
@@ -1171,8 +1190,8 @@
 	.buf_queue		= mcam_vb_buf_queue,
 	.start_streaming	= mcam_vb_start_streaming,
 	.stop_streaming		= mcam_vb_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
+	.wait_prepare		= mcam_vb_wait_prepare,
+	.wait_finish		= mcam_vb_wait_finish,
 };
 
 
@@ -1200,12 +1219,17 @@
 static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
 {
 	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
 	struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
 	struct mcam_dma_desc *desc = mvb->dma_desc;
 	struct scatterlist *sg;
 	int i;
 
-	for_each_sg(sg_table->sgl, sg, sg_table->nents, i) {
+	mvb->dma_desc_nent = dma_map_sg(cam->dev, sg_table->sgl,
+			sg_table->nents, DMA_FROM_DEVICE);
+	if (mvb->dma_desc_nent <= 0)
+		return -EIO;  /* Not sure what's right here */
+	for_each_sg(sg_table->sgl, sg, mvb->dma_desc_nent, i) {
 		desc->dma_addr = sg_dma_address(sg);
 		desc->segment_len = sg_dma_len(sg);
 		desc++;
@@ -1213,6 +1237,16 @@
 	return 0;
 }
 
+static void mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
+{
+	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+	struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
+
+	if (sg_table)
+		dma_unmap_sg(cam->dev, sg_table->sgl,
+				sg_table->nents, DMA_FROM_DEVICE);
+}
+
 static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
 {
 	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
@@ -1229,11 +1263,12 @@
 	.buf_init		= mcam_vb_sg_buf_init,
 	.buf_prepare		= mcam_vb_sg_buf_prepare,
 	.buf_queue		= mcam_vb_buf_queue,
+	.buf_finish		= mcam_vb_sg_buf_finish,
 	.buf_cleanup		= mcam_vb_sg_buf_cleanup,
 	.start_streaming	= mcam_vb_start_streaming,
 	.stop_streaming		= mcam_vb_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
+	.wait_prepare		= mcam_vb_wait_prepare,
+	.wait_finish		= mcam_vb_wait_finish,
 };
 
 #endif /* MCAM_MODE_DMA_SG */
@@ -1245,7 +1280,6 @@
 	memset(vq, 0, sizeof(*vq));
 	vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	vq->drv_priv = cam;
-	vq->lock = &cam->s_mutex;
 	INIT_LIST_HEAD(&cam->buffers);
 	switch (cam->buffer_mode) {
 	case B_DMA_contig:
@@ -1253,12 +1287,10 @@
 		vq->ops = &mcam_vb2_ops;
 		vq->mem_ops = &vb2_dma_contig_memops;
 		vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
+		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
 		vq->io_modes = VB2_MMAP | VB2_USERPTR;
 		cam->dma_setup = mcam_ctlr_dma_contig;
 		cam->frame_complete = mcam_dma_contig_done;
-		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
-		if (IS_ERR(cam->vb_alloc_ctx))
-			return PTR_ERR(cam->vb_alloc_ctx);
 #endif
 		break;
 	case B_DMA_sg:
@@ -1269,9 +1301,6 @@
 		vq->io_modes = VB2_MMAP | VB2_USERPTR;
 		cam->dma_setup = mcam_ctlr_dma_sg;
 		cam->frame_complete = mcam_dma_sg_done;
-		cam->vb_alloc_ctx_sg = vb2_dma_sg_init_ctx(cam->dev);
-		if (IS_ERR(cam->vb_alloc_ctx_sg))
-			return PTR_ERR(cam->vb_alloc_ctx_sg);
 #endif
 		break;
 	case B_vmalloc:
@@ -1297,10 +1326,6 @@
 	if (cam->buffer_mode == B_DMA_contig)
 		vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
 #endif
-#ifdef MCAM_MODE_DMA_SG
-	if (cam->buffer_mode == B_DMA_sg)
-		vb2_dma_sg_cleanup_ctx(cam->vb_alloc_ctx_sg);
-#endif
 }
 
 
@@ -1389,9 +1414,9 @@
 {
 	strcpy(cap->driver, "marvell_ccic");
 	strcpy(cap->card, "marvell_ccic");
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+	cap->version = 1;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
 		V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 6ccfbb6..4dcdb69 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -176,7 +176,6 @@
 	/* DMA buffers - DMA modes */
 	struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS];
 	struct vb2_alloc_ctx *vb_alloc_ctx;
-	struct vb2_alloc_ctx *vb_alloc_ctx_sg;
 
 	/* Mode-specific ops, set at open time */
 	void (*dma_setup)(struct mcam_camera *cam);
@@ -184,7 +183,7 @@
 
 	/* Current operating parameters */
 	struct v4l2_pix_format pix_format;
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 
 	/* Locks */
 	struct mutex s_mutex; /* Access to this structure */
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 0ed9b3a..054507f 100644
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -512,6 +512,7 @@
 #endif
 	.driver = {
 		.name	= "mmp-camera",
+		.owner	= THIS_MODULE
 	}
 };
 
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/mem2mem_testdev.c
similarity index 81%
rename from drivers/media/platform/vim2m.c
rename to drivers/media/platform/mem2mem_testdev.c
index a3b6383..c1b03cf 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/mem2mem_testdev.c
@@ -31,11 +31,12 @@
 #include <media/v4l2-event.h>
 #include <media/videobuf2-vmalloc.h>
 
+#define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev"
+
 MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
 MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.1.1");
-MODULE_ALIAS("mem2mem_testdev");
 
 static unsigned debug;
 module_param(debug, uint, 0644);
@@ -51,7 +52,7 @@
 #define MEM2MEM_CAPTURE	(1 << 0)
 #define MEM2MEM_OUTPUT	(1 << 1)
 
-#define MEM2MEM_NAME		"vim2m"
+#define MEM2MEM_NAME		"m2m-testdev"
 
 /* Per queue */
 #define MEM2MEM_DEF_NUM_BUFS	VIDEO_MAX_FRAME
@@ -71,15 +72,15 @@
 	v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
 
 
-static void vim2m_dev_release(struct device *dev)
+static void m2mtest_dev_release(struct device *dev)
 {}
 
-static struct platform_device vim2m_pdev = {
+static struct platform_device m2mtest_pdev = {
 	.name		= MEM2MEM_NAME,
-	.dev.release	= vim2m_dev_release,
+	.dev.release	= m2mtest_dev_release,
 };
 
-struct vim2m_fmt {
+struct m2mtest_fmt {
 	char	*name;
 	u32	fourcc;
 	int	depth;
@@ -87,7 +88,7 @@
 	u32	types;
 };
 
-static struct vim2m_fmt formats[] = {
+static struct m2mtest_fmt formats[] = {
 	{
 		.name	= "RGB565 (BE)",
 		.fourcc	= V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
@@ -107,12 +108,12 @@
 #define NUM_FORMATS ARRAY_SIZE(formats)
 
 /* Per-queue, driver-specific private data */
-struct vim2m_q_data {
+struct m2mtest_q_data {
 	unsigned int		width;
 	unsigned int		height;
 	unsigned int		sizeimage;
 	unsigned int		sequence;
-	struct vim2m_fmt	*fmt;
+	struct m2mtest_fmt	*fmt;
 };
 
 enum {
@@ -123,9 +124,9 @@
 #define V4L2_CID_TRANS_TIME_MSEC	(V4L2_CID_USER_BASE + 0x1000)
 #define V4L2_CID_TRANS_NUM_BUFS		(V4L2_CID_USER_BASE + 0x1001)
 
-static struct vim2m_fmt *find_format(struct v4l2_format *f)
+static struct m2mtest_fmt *find_format(struct v4l2_format *f)
 {
-	struct vim2m_fmt *fmt;
+	struct m2mtest_fmt *fmt;
 	unsigned int k;
 
 	for (k = 0; k < NUM_FORMATS; k++) {
@@ -140,7 +141,7 @@
 	return &formats[k];
 }
 
-struct vim2m_dev {
+struct m2mtest_dev {
 	struct v4l2_device	v4l2_dev;
 	struct video_device	*vfd;
 
@@ -153,9 +154,9 @@
 	struct v4l2_m2m_dev	*m2m_dev;
 };
 
-struct vim2m_ctx {
+struct m2mtest_ctx {
 	struct v4l2_fh		fh;
-	struct vim2m_dev	*dev;
+	struct m2mtest_dev	*dev;
 
 	struct v4l2_ctrl_handler hdl;
 
@@ -176,15 +177,15 @@
 	enum v4l2_colorspace	colorspace;
 
 	/* Source and destination queue data */
-	struct vim2m_q_data   q_data[2];
+	struct m2mtest_q_data   q_data[2];
 };
 
-static inline struct vim2m_ctx *file2ctx(struct file *file)
+static inline struct m2mtest_ctx *file2ctx(struct file *file)
 {
-	return container_of(file->private_data, struct vim2m_ctx, fh);
+	return container_of(file->private_data, struct m2mtest_ctx, fh);
 }
 
-static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx,
+static struct m2mtest_q_data *get_q_data(struct m2mtest_ctx *ctx,
 					 enum v4l2_buf_type type)
 {
 	switch (type) {
@@ -199,12 +200,12 @@
 }
 
 
-static int device_process(struct vim2m_ctx *ctx,
+static int device_process(struct m2mtest_ctx *ctx,
 			  struct vb2_buffer *in_vb,
 			  struct vb2_buffer *out_vb)
 {
-	struct vim2m_dev *dev = ctx->dev;
-	struct vim2m_q_data *q_data;
+	struct m2mtest_dev *dev = ctx->dev;
+	struct m2mtest_q_data *q_data;
 	u8 *p_in, *p_out;
 	int x, y, t, w;
 	int tile_w, bytes_left;
@@ -333,7 +334,7 @@
 	return 0;
 }
 
-static void schedule_irq(struct vim2m_dev *dev, int msec_timeout)
+static void schedule_irq(struct m2mtest_dev *dev, int msec_timeout)
 {
 	dprintk(dev, "Scheduling a simulated irq\n");
 	mod_timer(&dev->timer, jiffies + msecs_to_jiffies(msec_timeout));
@@ -348,7 +349,7 @@
  */
 static int job_ready(void *priv)
 {
-	struct vim2m_ctx *ctx = priv;
+	struct m2mtest_ctx *ctx = priv;
 
 	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen
 	    || v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen) {
@@ -361,7 +362,7 @@
 
 static void job_abort(void *priv)
 {
-	struct vim2m_ctx *ctx = priv;
+	struct m2mtest_ctx *ctx = priv;
 
 	/* Will cancel the transaction in the next interrupt handler */
 	ctx->aborting = 1;
@@ -375,8 +376,8 @@
  */
 static void device_run(void *priv)
 {
-	struct vim2m_ctx *ctx = priv;
-	struct vim2m_dev *dev = ctx->dev;
+	struct m2mtest_ctx *ctx = priv;
+	struct m2mtest_dev *dev = ctx->dev;
 	struct vb2_buffer *src_buf, *dst_buf;
 
 	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
@@ -390,12 +391,12 @@
 
 static void device_isr(unsigned long priv)
 {
-	struct vim2m_dev *vim2m_dev = (struct vim2m_dev *)priv;
-	struct vim2m_ctx *curr_ctx;
+	struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv;
+	struct m2mtest_ctx *curr_ctx;
 	struct vb2_buffer *src_vb, *dst_vb;
 	unsigned long flags;
 
-	curr_ctx = v4l2_m2m_get_curr_priv(vim2m_dev->m2m_dev);
+	curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
 
 	if (NULL == curr_ctx) {
 		pr_err("Instance released before the end of transaction\n");
@@ -407,16 +408,16 @@
 
 	curr_ctx->num_processed++;
 
-	spin_lock_irqsave(&vim2m_dev->irqlock, flags);
+	spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
 	v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
 	v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
-	spin_unlock_irqrestore(&vim2m_dev->irqlock, flags);
+	spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
 
 	if (curr_ctx->num_processed == curr_ctx->translen
 	    || curr_ctx->aborting) {
 		dprintk(curr_ctx->dev, "Finishing transaction\n");
 		curr_ctx->num_processed = 0;
-		v4l2_m2m_job_finish(vim2m_dev->m2m_dev, curr_ctx->fh.m2m_ctx);
+		v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->fh.m2m_ctx);
 	} else {
 		device_run(curr_ctx);
 	}
@@ -440,7 +441,7 @@
 static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
 {
 	int i, num;
-	struct vim2m_fmt *fmt;
+	struct m2mtest_fmt *fmt;
 
 	num = 0;
 
@@ -479,10 +480,10 @@
 	return enum_fmt(f, MEM2MEM_OUTPUT);
 }
 
-static int vidioc_g_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
+static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
 {
 	struct vb2_queue *vq;
-	struct vim2m_q_data *q_data;
+	struct m2mtest_q_data *q_data;
 
 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 	if (!vq)
@@ -513,7 +514,7 @@
 	return vidioc_g_fmt(file2ctx(file), f);
 }
 
-static int vidioc_try_fmt(struct v4l2_format *f, struct vim2m_fmt *fmt)
+static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt)
 {
 	/* V4L2 specification suggests the driver corrects the format struct
 	 * if any of the dimensions is unsupported */
@@ -538,8 +539,8 @@
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 				  struct v4l2_format *f)
 {
-	struct vim2m_fmt *fmt;
-	struct vim2m_ctx *ctx = file2ctx(file);
+	struct m2mtest_fmt *fmt;
+	struct m2mtest_ctx *ctx = file2ctx(file);
 
 	fmt = find_format(f);
 	if (!fmt) {
@@ -560,8 +561,8 @@
 static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
 				  struct v4l2_format *f)
 {
-	struct vim2m_fmt *fmt;
-	struct vim2m_ctx *ctx = file2ctx(file);
+	struct m2mtest_fmt *fmt;
+	struct m2mtest_ctx *ctx = file2ctx(file);
 
 	fmt = find_format(f);
 	if (!fmt) {
@@ -580,9 +581,9 @@
 	return vidioc_try_fmt(f, fmt);
 }
 
-static int vidioc_s_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
+static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
 {
-	struct vim2m_q_data *q_data;
+	struct m2mtest_q_data *q_data;
 	struct vb2_queue *vq;
 
 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
@@ -626,7 +627,7 @@
 static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct vim2m_ctx *ctx = file2ctx(file);
+	struct m2mtest_ctx *ctx = file2ctx(file);
 	int ret;
 
 	ret = vidioc_try_fmt_vid_out(file, priv, f);
@@ -639,10 +640,10 @@
 	return ret;
 }
 
-static int vim2m_s_ctrl(struct v4l2_ctrl *ctrl)
+static int m2mtest_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct vim2m_ctx *ctx =
-		container_of(ctrl->handler, struct vim2m_ctx, hdl);
+	struct m2mtest_ctx *ctx =
+		container_of(ctrl->handler, struct m2mtest_ctx, hdl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_HFLIP:
@@ -675,12 +676,12 @@
 	return 0;
 }
 
-static const struct v4l2_ctrl_ops vim2m_ctrl_ops = {
-	.s_ctrl = vim2m_s_ctrl,
+static const struct v4l2_ctrl_ops m2mtest_ctrl_ops = {
+	.s_ctrl = m2mtest_s_ctrl,
 };
 
 
-static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
+static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
 	.vidioc_querycap	= vidioc_querycap,
 
 	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
@@ -697,9 +698,6 @@
 	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
 	.vidioc_qbuf		= v4l2_m2m_ioctl_qbuf,
 	.vidioc_dqbuf		= v4l2_m2m_ioctl_dqbuf,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
-#endif
 
 	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
 	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
@@ -713,13 +711,13 @@
  * Queue operations
  */
 
-static int vim2m_queue_setup(struct vb2_queue *vq,
+static int m2mtest_queue_setup(struct vb2_queue *vq,
 				const struct v4l2_format *fmt,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
-	struct vim2m_q_data *q_data;
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
+	struct m2mtest_q_data *q_data;
 	unsigned int size, count = *nbuffers;
 
 	q_data = get_q_data(ctx, vq->type);
@@ -743,10 +741,10 @@
 	return 0;
 }
 
-static int vim2m_buf_prepare(struct vb2_buffer *vb)
+static int m2mtest_buf_prepare(struct vb2_buffer *vb)
 {
-	struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	struct vim2m_q_data *q_data;
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct m2mtest_q_data *q_data;
 
 	dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
 
@@ -772,25 +770,25 @@
 	return 0;
 }
 
-static void vim2m_buf_queue(struct vb2_buffer *vb)
+static void m2mtest_buf_queue(struct vb2_buffer *vb)
 {
-	struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 
 	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 }
 
-static int vim2m_start_streaming(struct vb2_queue *q, unsigned count)
+static int m2mtest_start_streaming(struct vb2_queue *q, unsigned count)
 {
-	struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
-	struct vim2m_q_data *q_data = get_q_data(ctx, q->type);
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
+	struct m2mtest_q_data *q_data = get_q_data(ctx, q->type);
 
 	q_data->sequence = 0;
 	return 0;
 }
 
-static void vim2m_stop_streaming(struct vb2_queue *q)
+static void m2mtest_stop_streaming(struct vb2_queue *q)
 {
-	struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
 	struct vb2_buffer *vb;
 	unsigned long flags;
 
@@ -807,26 +805,26 @@
 	}
 }
 
-static struct vb2_ops vim2m_qops = {
-	.queue_setup	 = vim2m_queue_setup,
-	.buf_prepare	 = vim2m_buf_prepare,
-	.buf_queue	 = vim2m_buf_queue,
-	.start_streaming = vim2m_start_streaming,
-	.stop_streaming  = vim2m_stop_streaming,
+static struct vb2_ops m2mtest_qops = {
+	.queue_setup	 = m2mtest_queue_setup,
+	.buf_prepare	 = m2mtest_buf_prepare,
+	.buf_queue	 = m2mtest_buf_queue,
+	.start_streaming = m2mtest_start_streaming,
+	.stop_streaming  = m2mtest_stop_streaming,
 	.wait_prepare	 = vb2_ops_wait_prepare,
 	.wait_finish	 = vb2_ops_wait_finish,
 };
 
 static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
 {
-	struct vim2m_ctx *ctx = priv;
+	struct m2mtest_ctx *ctx = priv;
 	int ret;
 
 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 	src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
 	src_vq->drv_priv = ctx;
 	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-	src_vq->ops = &vim2m_qops;
+	src_vq->ops = &m2mtest_qops;
 	src_vq->mem_ops = &vb2_vmalloc_memops;
 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	src_vq->lock = &ctx->dev->dev_mutex;
@@ -839,7 +837,7 @@
 	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
 	dst_vq->drv_priv = ctx;
 	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-	dst_vq->ops = &vim2m_qops;
+	dst_vq->ops = &m2mtest_qops;
 	dst_vq->mem_ops = &vb2_vmalloc_memops;
 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	dst_vq->lock = &ctx->dev->dev_mutex;
@@ -847,8 +845,8 @@
 	return vb2_queue_init(dst_vq);
 }
 
-static const struct v4l2_ctrl_config vim2m_ctrl_trans_time_msec = {
-	.ops = &vim2m_ctrl_ops,
+static const struct v4l2_ctrl_config m2mtest_ctrl_trans_time_msec = {
+	.ops = &m2mtest_ctrl_ops,
 	.id = V4L2_CID_TRANS_TIME_MSEC,
 	.name = "Transaction Time (msec)",
 	.type = V4L2_CTRL_TYPE_INTEGER,
@@ -858,8 +856,8 @@
 	.step = 1,
 };
 
-static const struct v4l2_ctrl_config vim2m_ctrl_trans_num_bufs = {
-	.ops = &vim2m_ctrl_ops,
+static const struct v4l2_ctrl_config m2mtest_ctrl_trans_num_bufs = {
+	.ops = &m2mtest_ctrl_ops,
 	.id = V4L2_CID_TRANS_NUM_BUFS,
 	.name = "Buffers Per Transaction",
 	.type = V4L2_CTRL_TYPE_INTEGER,
@@ -872,10 +870,10 @@
 /*
  * File operations
  */
-static int vim2m_open(struct file *file)
+static int m2mtest_open(struct file *file)
 {
-	struct vim2m_dev *dev = video_drvdata(file);
-	struct vim2m_ctx *ctx = NULL;
+	struct m2mtest_dev *dev = video_drvdata(file);
+	struct m2mtest_ctx *ctx = NULL;
 	struct v4l2_ctrl_handler *hdl;
 	int rc = 0;
 
@@ -892,10 +890,10 @@
 	ctx->dev = dev;
 	hdl = &ctx->hdl;
 	v4l2_ctrl_handler_init(hdl, 4);
-	v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
-	v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
-	v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_time_msec, NULL);
-	v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_num_bufs, NULL);
+	v4l2_ctrl_new_std(hdl, &m2mtest_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(hdl, &m2mtest_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_time_msec, NULL);
+	v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_num_bufs, NULL);
 	if (hdl->error) {
 		rc = hdl->error;
 		v4l2_ctrl_handler_free(hdl);
@@ -935,10 +933,10 @@
 	return rc;
 }
 
-static int vim2m_release(struct file *file)
+static int m2mtest_release(struct file *file)
 {
-	struct vim2m_dev *dev = video_drvdata(file);
-	struct vim2m_ctx *ctx = file2ctx(file);
+	struct m2mtest_dev *dev = video_drvdata(file);
+	struct m2mtest_ctx *ctx = file2ctx(file);
 
 	dprintk(dev, "Releasing instance %p\n", ctx);
 
@@ -955,20 +953,20 @@
 	return 0;
 }
 
-static const struct v4l2_file_operations vim2m_fops = {
+static const struct v4l2_file_operations m2mtest_fops = {
 	.owner		= THIS_MODULE,
-	.open		= vim2m_open,
-	.release	= vim2m_release,
+	.open		= m2mtest_open,
+	.release	= m2mtest_release,
 	.poll		= v4l2_m2m_fop_poll,
 	.unlocked_ioctl	= video_ioctl2,
 	.mmap		= v4l2_m2m_fop_mmap,
 };
 
-static struct video_device vim2m_videodev = {
+static struct video_device m2mtest_videodev = {
 	.name		= MEM2MEM_NAME,
 	.vfl_dir	= VFL_DIR_M2M,
-	.fops		= &vim2m_fops,
-	.ioctl_ops	= &vim2m_ioctl_ops,
+	.fops		= &m2mtest_fops,
+	.ioctl_ops	= &m2mtest_ioctl_ops,
 	.minor		= -1,
 	.release	= video_device_release,
 };
@@ -979,9 +977,9 @@
 	.job_abort	= job_abort,
 };
 
-static int vim2m_probe(struct platform_device *pdev)
+static int m2mtest_probe(struct platform_device *pdev)
 {
-	struct vim2m_dev *dev;
+	struct m2mtest_dev *dev;
 	struct video_device *vfd;
 	int ret;
 
@@ -1005,7 +1003,7 @@
 		goto unreg_dev;
 	}
 
-	*vfd = vim2m_videodev;
+	*vfd = m2mtest_videodev;
 	vfd->lock = &dev->dev_mutex;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 
@@ -1016,7 +1014,7 @@
 	}
 
 	video_set_drvdata(vfd, dev);
-	snprintf(vfd->name, sizeof(vfd->name), "%s", vim2m_videodev.name);
+	snprintf(vfd->name, sizeof(vfd->name), "%s", m2mtest_videodev.name);
 	dev->vfd = vfd;
 	v4l2_info(&dev->v4l2_dev,
 			"Device registered as /dev/video%d\n", vfd->num);
@@ -1044,11 +1042,11 @@
 	return ret;
 }
 
-static int vim2m_remove(struct platform_device *pdev)
+static int m2mtest_remove(struct platform_device *pdev)
 {
-	struct vim2m_dev *dev = platform_get_drvdata(pdev);
+	struct m2mtest_dev *dev = platform_get_drvdata(pdev);
 
-	v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
+	v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
 	v4l2_m2m_release(dev->m2m_dev);
 	del_timer_sync(&dev->timer);
 	video_unregister_device(dev->vfd);
@@ -1057,34 +1055,35 @@
 	return 0;
 }
 
-static struct platform_driver vim2m_pdrv = {
-	.probe		= vim2m_probe,
-	.remove		= vim2m_remove,
+static struct platform_driver m2mtest_pdrv = {
+	.probe		= m2mtest_probe,
+	.remove		= m2mtest_remove,
 	.driver		= {
 		.name	= MEM2MEM_NAME,
+		.owner	= THIS_MODULE,
 	},
 };
 
-static void __exit vim2m_exit(void)
+static void __exit m2mtest_exit(void)
 {
-	platform_driver_unregister(&vim2m_pdrv);
-	platform_device_unregister(&vim2m_pdev);
+	platform_driver_unregister(&m2mtest_pdrv);
+	platform_device_unregister(&m2mtest_pdev);
 }
 
-static int __init vim2m_init(void)
+static int __init m2mtest_init(void)
 {
 	int ret;
 
-	ret = platform_device_register(&vim2m_pdev);
+	ret = platform_device_register(&m2mtest_pdev);
 	if (ret)
 		return ret;
 
-	ret = platform_driver_register(&vim2m_pdrv);
+	ret = platform_driver_register(&m2mtest_pdrv);
 	if (ret)
-		platform_device_unregister(&vim2m_pdev);
+		platform_device_unregister(&m2mtest_pdev);
 
 	return 0;
 }
 
-module_init(vim2m_init);
-module_exit(vim2m_exit);
+module_init(m2mtest_init);
+module_exit(m2mtest_exit);
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index 87314b7..4971ff2 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -402,8 +402,13 @@
 {
 	strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
 	strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
-	cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	/*
+	 * This is only a mem-to-mem video device. The capture and output
+	 * device capability flags are left only for backward compatibility
+	 * and are scheduled for removal.
+	 */
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+			    V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
 	return 0;
 }
 
@@ -1005,6 +1010,7 @@
 	.remove		= emmaprp_remove,
 	.driver		= {
 		.name	= MEM2MEM_NAME,
+		.owner	= THIS_MODULE,
 	},
 };
 module_platform_driver(emmaprp_pdrv);
diff --git a/drivers/media/platform/omap/Kconfig b/drivers/media/platform/omap/Kconfig
index 97c28fd..f0bc674 100644
--- a/drivers/media/platform/omap/Kconfig
+++ b/drivers/media/platform/omap/Kconfig
@@ -4,8 +4,7 @@
 config VIDEO_OMAP2_VOUT
 	tristate "OMAP2/OMAP3 V4L2-Display driver"
 	depends on m
-	depends on MMU
-	depends on ARCH_OMAP2 || ARCH_OMAP3
+	depends on ARCH_OMAP2 || ARCH_OMAP3 || (COMPILE_TEST && HAS_MMU)
 	select VIDEOBUF_GEN
 	select VIDEOBUF_DMA_CONTIG
 	select OMAP2_DSS if HAS_IOMEM && ARCH_OMAP2PLUS
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index ba2d8f9..64ab6fb 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -198,7 +198,7 @@
  * omap_vout_uservirt_to_phys: This inline function is used to convert user
  * space virtual address to physical address.
  */
-static unsigned long omap_vout_uservirt_to_phys(unsigned long virtp)
+static u32 omap_vout_uservirt_to_phys(u32 virtp)
 {
 	unsigned long physp = 0;
 	struct vm_area_struct *vma;
@@ -418,10 +418,10 @@
 	}
 
 	v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
-		"%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n"
+		"%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n"
 		"rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
 		"out_height=%d rotation_type=%d screen_width=%d\n",
-		__func__, ovl->is_enabled(ovl), &info.paddr, info.width, info.height,
+		__func__, ovl->is_enabled(ovl), info.paddr, info.width, info.height,
 		info.color_mode, info.rotation, info.mirror, info.pos_x,
 		info.pos_y, info.out_width, info.out_height, info.rotation_type,
 		info.screen_width);
@@ -794,7 +794,7 @@
 		vout->queued_buf_addr[vb->i] = (u8 *)
 			omap_vout_uservirt_to_phys(vb->baddr);
 	} else {
-		unsigned long addr, dma_addr;
+		u32 addr, dma_addr;
 		unsigned long size;
 
 		addr = (unsigned long) vout->buf_virt_addr[vb->i];
@@ -1054,9 +1054,8 @@
 	strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
 	strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
 	cap->bus_info[0] = '\0';
-	cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
+	cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
 		V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 
 	return 0;
 }
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 51c2129..72265e5 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -2380,6 +2380,7 @@
 	.remove = isp_remove,
 	.id_table = omap3isp_id_table,
 	.driver = {
+		.owner = THIS_MODULE,
 		.name = "omap3isp",
 		.pm	= &omap3isp_pm_ops,
 	},
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 587489a..81a9dc0 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -36,23 +36,23 @@
 		  unsigned int pad, enum v4l2_subdev_format_whence which);
 
 static const unsigned int ccdc_fmts[] = {
-	MEDIA_BUS_FMT_Y8_1X8,
-	MEDIA_BUS_FMT_Y10_1X10,
-	MEDIA_BUS_FMT_Y12_1X12,
-	MEDIA_BUS_FMT_SGRBG8_1X8,
-	MEDIA_BUS_FMT_SRGGB8_1X8,
-	MEDIA_BUS_FMT_SBGGR8_1X8,
-	MEDIA_BUS_FMT_SGBRG8_1X8,
-	MEDIA_BUS_FMT_SGRBG10_1X10,
-	MEDIA_BUS_FMT_SRGGB10_1X10,
-	MEDIA_BUS_FMT_SBGGR10_1X10,
-	MEDIA_BUS_FMT_SGBRG10_1X10,
-	MEDIA_BUS_FMT_SGRBG12_1X12,
-	MEDIA_BUS_FMT_SRGGB12_1X12,
-	MEDIA_BUS_FMT_SBGGR12_1X12,
-	MEDIA_BUS_FMT_SGBRG12_1X12,
-	MEDIA_BUS_FMT_YUYV8_2X8,
-	MEDIA_BUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_Y8_1X8,
+	V4L2_MBUS_FMT_Y10_1X10,
+	V4L2_MBUS_FMT_Y12_1X12,
+	V4L2_MBUS_FMT_SGRBG8_1X8,
+	V4L2_MBUS_FMT_SRGGB8_1X8,
+	V4L2_MBUS_FMT_SBGGR8_1X8,
+	V4L2_MBUS_FMT_SGBRG8_1X8,
+	V4L2_MBUS_FMT_SGRBG10_1X10,
+	V4L2_MBUS_FMT_SRGGB10_1X10,
+	V4L2_MBUS_FMT_SBGGR10_1X10,
+	V4L2_MBUS_FMT_SGBRG10_1X10,
+	V4L2_MBUS_FMT_SGRBG12_1X12,
+	V4L2_MBUS_FMT_SRGGB12_1X12,
+	V4L2_MBUS_FMT_SBGGR12_1X12,
+	V4L2_MBUS_FMT_SGBRG12_1X12,
+	V4L2_MBUS_FMT_YUYV8_2X8,
+	V4L2_MBUS_FMT_UYVY8_2X8,
 };
 
 /*
@@ -266,10 +266,10 @@
 		__ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
 				  V4L2_SUBDEV_FORMAT_ACTIVE);
 
-	if ((format->code != MEDIA_BUS_FMT_SGRBG10_1X10) &&
-	    (format->code != MEDIA_BUS_FMT_SRGGB10_1X10) &&
-	    (format->code != MEDIA_BUS_FMT_SBGGR10_1X10) &&
-	    (format->code != MEDIA_BUS_FMT_SGBRG10_1X10))
+	if ((format->code != V4L2_MBUS_FMT_SGRBG10_1X10) &&
+	    (format->code != V4L2_MBUS_FMT_SRGGB10_1X10) &&
+	    (format->code != V4L2_MBUS_FMT_SBGGR10_1X10) &&
+	    (format->code != V4L2_MBUS_FMT_SGBRG10_1X10))
 		return -EINVAL;
 
 	if (enable)
@@ -971,8 +971,8 @@
 
 	format = &ccdc->formats[CCDC_PAD_SINK];
 
-	if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
-	    format->code == MEDIA_BUS_FMT_UYVY8_2X8) {
+	if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+	    format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
 		/* According to the OMAP3 TRM the input mode only affects SYNC
 		 * mode, enabling BT.656 mode should take precedence. However,
 		 * in practice setting the input mode to YCbCr data on 8 bits
@@ -1020,7 +1020,7 @@
 	/* The CCDC_CFG.Y8POS bit is used in YCbCr8 input mode only. The
 	 * hardware seems to ignore it in all other input modes.
 	 */
-	if (format->code == MEDIA_BUS_FMT_UYVY8_2X8)
+	if (format->code == V4L2_MBUS_FMT_UYVY8_2X8)
 		isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
 			    ISPCCDC_CFG_Y8POS);
 	else
@@ -1168,9 +1168,9 @@
 
 	if (ccdc->bt656)
 		bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
-	else if (fmt_info->code == MEDIA_BUS_FMT_YUYV8_2X8)
+	else if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8)
 		bridge = ISPCTRL_PAR_BRIDGE_LENDIAN;
-	else if (fmt_info->code == MEDIA_BUS_FMT_UYVY8_2X8)
+	else if (fmt_info->code == V4L2_MBUS_FMT_UYVY8_2X8)
 		bridge = ISPCTRL_PAR_BRIDGE_BENDIAN;
 	else
 		bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
@@ -1199,16 +1199,16 @@
 
 	/* Mosaic filter */
 	switch (format->code) {
-	case MEDIA_BUS_FMT_SRGGB10_1X10:
-	case MEDIA_BUS_FMT_SRGGB12_1X12:
+	case V4L2_MBUS_FMT_SRGGB10_1X10:
+	case V4L2_MBUS_FMT_SRGGB12_1X12:
 		ccdc_pattern = ccdc_srggb_pattern;
 		break;
-	case MEDIA_BUS_FMT_SBGGR10_1X10:
-	case MEDIA_BUS_FMT_SBGGR12_1X12:
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+	case V4L2_MBUS_FMT_SBGGR12_1X12:
 		ccdc_pattern = ccdc_sbggr_pattern;
 		break;
-	case MEDIA_BUS_FMT_SGBRG10_1X10:
-	case MEDIA_BUS_FMT_SGBRG12_1X12:
+	case V4L2_MBUS_FMT_SGBRG10_1X10:
+	case V4L2_MBUS_FMT_SGBRG12_1X12:
 		ccdc_pattern = ccdc_sgbrg_pattern;
 		break;
 	default:
@@ -1267,7 +1267,7 @@
 	/* The CCDC outputs data in UYVY order by default. Swap bytes to get
 	 * YUYV.
 	 */
-	if (format->code == MEDIA_BUS_FMT_YUYV8_1X16)
+	if (format->code == V4L2_MBUS_FMT_YUYV8_1X16)
 		isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
 			    ISPCCDC_CFG_BSWD);
 	else
@@ -1967,7 +1967,7 @@
 		enum v4l2_subdev_format_whence which)
 {
 	const struct isp_format_info *info;
-	u32 pixelcode;
+	enum v4l2_mbus_pixelcode pixelcode;
 	unsigned int width = fmt->width;
 	unsigned int height = fmt->height;
 	struct v4l2_rect *crop;
@@ -1983,7 +1983,7 @@
 
 		/* If not found, use SGRBG10 as default */
 		if (i >= ARRAY_SIZE(ccdc_fmts))
-			fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+			fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 
 		/* Clamp the input size. */
 		fmt->width = clamp_t(u32, width, 32, 4096);
@@ -2007,19 +2007,19 @@
 		 * configured to pack bytes in BT.656, hiding the inaccuracy.
 		 * In all cases bytes can be swapped.
 		 */
-		if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
-		    fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) {
+		if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+		    fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) {
 			/* Use the user requested format if YUV. */
-			if (pixelcode == MEDIA_BUS_FMT_YUYV8_2X8 ||
-			    pixelcode == MEDIA_BUS_FMT_UYVY8_2X8 ||
-			    pixelcode == MEDIA_BUS_FMT_YUYV8_1X16 ||
-			    pixelcode == MEDIA_BUS_FMT_UYVY8_1X16)
+			if (pixelcode == V4L2_MBUS_FMT_YUYV8_2X8 ||
+			    pixelcode == V4L2_MBUS_FMT_UYVY8_2X8 ||
+			    pixelcode == V4L2_MBUS_FMT_YUYV8_1X16 ||
+			    pixelcode == V4L2_MBUS_FMT_UYVY8_1X16)
 				fmt->code = pixelcode;
 
-			if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8)
-				fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
-			else if (fmt->code == MEDIA_BUS_FMT_UYVY8_2X8)
-				fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
+			if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8)
+				fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
+			else if (fmt->code == V4L2_MBUS_FMT_UYVY8_2X8)
+				fmt->code = V4L2_MBUS_FMT_UYVY8_1X16;
 		}
 
 		/* Hardcode the output size to the crop rectangle size. */
@@ -2047,8 +2047,8 @@
 		fmt->code = info->truncated;
 
 		/* YUV formats are not supported by the video port. */
-		if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
-		    fmt->code == MEDIA_BUS_FMT_UYVY8_2X8)
+		if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+		    fmt->code == V4L2_MBUS_FMT_UYVY8_2X8)
 			fmt->code = 0;
 
 		/* The number of lines that can be clocked out from the video
@@ -2083,7 +2083,7 @@
 	 * to keep the Bayer pattern.
 	 */
 	info = omap3isp_video_format_info(sink->code);
-	if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) {
+	if (info->flavor != V4L2_MBUS_FMT_Y8_1X8) {
 		crop->left &= ~1;
 		crop->top &= ~1;
 	}
@@ -2103,7 +2103,7 @@
 			       sink->height - crop->top);
 
 	/* Odd width/height values don't make sense for Bayer formats. */
-	if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) {
+	if (info->flavor != V4L2_MBUS_FMT_Y8_1X8) {
 		crop->width &= ~1;
 		crop->height &= ~1;
 	}
@@ -2135,13 +2135,13 @@
 		format = __ccdc_get_format(ccdc, fh, code->pad,
 					   V4L2_SUBDEV_FORMAT_TRY);
 
-		if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
-		    format->code == MEDIA_BUS_FMT_UYVY8_2X8) {
+		if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+		    format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
 			/* In YUV mode the CCDC can swap bytes. */
 			if (code->index == 0)
-				code->code = MEDIA_BUS_FMT_YUYV8_1X16;
+				code->code = V4L2_MBUS_FMT_YUYV8_1X16;
 			else if (code->index == 1)
-				code->code = MEDIA_BUS_FMT_UYVY8_1X16;
+				code->code = V4L2_MBUS_FMT_UYVY8_1X16;
 			else
 				return -EINVAL;
 		} else {
@@ -2383,7 +2383,9 @@
  * return true if the combination is possible
  * return false otherwise
  */
-static bool ccdc_is_shiftable(u32 in, u32 out, unsigned int additional_shift)
+static bool ccdc_is_shiftable(enum v4l2_mbus_pixelcode in,
+			      enum v4l2_mbus_pixelcode out,
+			      unsigned int additional_shift)
 {
 	const struct isp_format_info *in_info, *out_info;
 
@@ -2450,7 +2452,7 @@
 	memset(&format, 0, sizeof(format));
 	format.pad = CCDC_PAD_SINK;
 	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	format.format.width = 4096;
 	format.format.height = 4096;
 	ccdc_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c
index f4aedb3..9cb49b3 100644
--- a/drivers/media/platform/omap3isp/ispccp2.c
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -289,10 +289,10 @@
 	u32 val, format;
 
 	switch (config->format) {
-	case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
 		format = ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP;
 		break;
-	case MEDIA_BUS_FMT_SGRBG10_1X10:
+	case V4L2_MBUS_FMT_SGRBG10_1X10:
 	default:
 		format = ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP;	/* RAW10+VP */
 		break;
@@ -438,7 +438,7 @@
 	u32 val, hwords;
 
 	if (sink_pixcode != source_pixcode &&
-	    sink_pixcode == MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8)
+	    sink_pixcode == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
 		dpcm_decompress = 1;
 
 	ccp2_pwr_cfg(ccp2);
@@ -604,8 +604,8 @@
  */
 
 static const unsigned int ccp2_fmts[] = {
-	MEDIA_BUS_FMT_SGRBG10_1X10,
-	MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
+	V4L2_MBUS_FMT_SGRBG10_1X10,
+	V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
 };
 
 /*
@@ -643,8 +643,8 @@
 
 	switch (pad) {
 	case CCP2_PAD_SINK:
-		if (fmt->code != MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8)
-			fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+		if (fmt->code != V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
+			fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 
 		if (ccp2->input == CCP2_INPUT_SENSOR) {
 			fmt->width = clamp_t(u32, fmt->width,
@@ -671,7 +671,7 @@
 		 */
 		format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK, which);
 		memcpy(fmt, format, sizeof(*fmt));
-		fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+		fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 		break;
 	}
 
@@ -808,7 +808,7 @@
 	memset(&format, 0, sizeof(format));
 	format.pad = CCP2_PAD_SINK;
 	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	format.format.width = 4096;
 	format.format.height = 4096;
 	ccp2_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c
index 09c686d..6530b25 100644
--- a/drivers/media/platform/omap3isp/ispcsi2.c
+++ b/drivers/media/platform/omap3isp/ispcsi2.c
@@ -78,15 +78,15 @@
 }
 
 static const unsigned int csi2_input_fmts[] = {
-	MEDIA_BUS_FMT_SGRBG10_1X10,
-	MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
-	MEDIA_BUS_FMT_SRGGB10_1X10,
-	MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
-	MEDIA_BUS_FMT_SBGGR10_1X10,
-	MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
-	MEDIA_BUS_FMT_SGBRG10_1X10,
-	MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
-	MEDIA_BUS_FMT_YUYV8_2X8,
+	V4L2_MBUS_FMT_SGRBG10_1X10,
+	V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+	V4L2_MBUS_FMT_SRGGB10_1X10,
+	V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
+	V4L2_MBUS_FMT_SBGGR10_1X10,
+	V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
+	V4L2_MBUS_FMT_SGBRG10_1X10,
+	V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
+	V4L2_MBUS_FMT_YUYV8_2X8,
 };
 
 /* To set the format on the CSI2 requires a mapping function that takes
@@ -171,19 +171,19 @@
 	int fmtidx, destidx, is_3630;
 
 	switch (fmt->code) {
-	case MEDIA_BUS_FMT_SGRBG10_1X10:
-	case MEDIA_BUS_FMT_SRGGB10_1X10:
-	case MEDIA_BUS_FMT_SBGGR10_1X10:
-	case MEDIA_BUS_FMT_SGBRG10_1X10:
+	case V4L2_MBUS_FMT_SGRBG10_1X10:
+	case V4L2_MBUS_FMT_SRGGB10_1X10:
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+	case V4L2_MBUS_FMT_SGBRG10_1X10:
 		fmtidx = 0;
 		break;
-	case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
-	case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
-	case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
-	case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
 		fmtidx = 1;
 		break;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		fmtidx = 2;
 		break;
 	default:
@@ -843,7 +843,7 @@
 		unsigned int pad, struct v4l2_mbus_framefmt *fmt,
 		enum v4l2_subdev_format_whence which)
 {
-	u32 pixelcode;
+	enum v4l2_mbus_pixelcode pixelcode;
 	struct v4l2_mbus_framefmt *format;
 	const struct isp_format_info *info;
 	unsigned int i;
@@ -858,7 +858,7 @@
 
 		/* If not found, use SGRBG10 as default */
 		if (i >= ARRAY_SIZE(csi2_input_fmts))
-			fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+			fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 
 		fmt->width = clamp_t(u32, fmt->width, 1, 8191);
 		fmt->height = clamp_t(u32, fmt->height, 1, 8191);
@@ -1029,7 +1029,7 @@
 	memset(&format, 0, sizeof(format));
 	format.pad = CSI2_PAD_SINK;
 	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	format.format.width = 4096;
 	format.format.height = 4096;
 	csi2_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c
index dd9eed4..605f57e 100644
--- a/drivers/media/platform/omap3isp/isppreview.c
+++ b/drivers/media/platform/omap3isp/isppreview.c
@@ -964,16 +964,18 @@
  * @prev: pointer to previewer private structure
  * @pixelcode: pixel code
  */
-static void preview_config_ycpos(struct isp_prev_device *prev, u32 pixelcode)
+static void
+preview_config_ycpos(struct isp_prev_device *prev,
+		     enum v4l2_mbus_pixelcode pixelcode)
 {
 	struct isp_device *isp = to_isp_device(prev);
 	enum preview_ycpos_mode mode;
 
 	switch (pixelcode) {
-	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case V4L2_MBUS_FMT_YUYV8_1X16:
 		mode = YCPOS_CrYCbY;
 		break;
-	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case V4L2_MBUS_FMT_UYVY8_1X16:
 		mode = YCPOS_YCrYCb;
 		break;
 	default:
@@ -1026,16 +1028,16 @@
 			    ISPPRV_PCR_WIDTH);
 
 	switch (info->flavor) {
-	case MEDIA_BUS_FMT_SGRBG8_1X8:
+	case V4L2_MBUS_FMT_SGRBG8_1X8:
 		prev->params.cfa_order = 0;
 		break;
-	case MEDIA_BUS_FMT_SRGGB8_1X8:
+	case V4L2_MBUS_FMT_SRGGB8_1X8:
 		prev->params.cfa_order = 1;
 		break;
-	case MEDIA_BUS_FMT_SBGGR8_1X8:
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
 		prev->params.cfa_order = 2;
 		break;
-	case MEDIA_BUS_FMT_SGBRG8_1X8:
+	case V4L2_MBUS_FMT_SGBRG8_1X8:
 		prev->params.cfa_order = 3;
 		break;
 	default:
@@ -1076,8 +1078,8 @@
 	unsigned int elv = prev->crop.top + prev->crop.height - 1;
 	u32 features;
 
-	if (format->code != MEDIA_BUS_FMT_Y8_1X8 &&
-	    format->code != MEDIA_BUS_FMT_Y10_1X10) {
+	if (format->code != V4L2_MBUS_FMT_Y8_1X8 &&
+	    format->code != V4L2_MBUS_FMT_Y10_1X10) {
 		sph -= 2;
 		eph += 2;
 		slv -= 2;
@@ -1707,21 +1709,21 @@
 
 /* previewer format descriptions */
 static const unsigned int preview_input_fmts[] = {
-	MEDIA_BUS_FMT_Y8_1X8,
-	MEDIA_BUS_FMT_SGRBG8_1X8,
-	MEDIA_BUS_FMT_SRGGB8_1X8,
-	MEDIA_BUS_FMT_SBGGR8_1X8,
-	MEDIA_BUS_FMT_SGBRG8_1X8,
-	MEDIA_BUS_FMT_Y10_1X10,
-	MEDIA_BUS_FMT_SGRBG10_1X10,
-	MEDIA_BUS_FMT_SRGGB10_1X10,
-	MEDIA_BUS_FMT_SBGGR10_1X10,
-	MEDIA_BUS_FMT_SGBRG10_1X10,
+	V4L2_MBUS_FMT_Y8_1X8,
+	V4L2_MBUS_FMT_SGRBG8_1X8,
+	V4L2_MBUS_FMT_SRGGB8_1X8,
+	V4L2_MBUS_FMT_SBGGR8_1X8,
+	V4L2_MBUS_FMT_SGBRG8_1X8,
+	V4L2_MBUS_FMT_Y10_1X10,
+	V4L2_MBUS_FMT_SGRBG10_1X10,
+	V4L2_MBUS_FMT_SRGGB10_1X10,
+	V4L2_MBUS_FMT_SBGGR10_1X10,
+	V4L2_MBUS_FMT_SGBRG10_1X10,
 };
 
 static const unsigned int preview_output_fmts[] = {
-	MEDIA_BUS_FMT_UYVY8_1X16,
-	MEDIA_BUS_FMT_YUYV8_1X16,
+	V4L2_MBUS_FMT_UYVY8_1X16,
+	V4L2_MBUS_FMT_YUYV8_1X16,
 };
 
 /*
@@ -1740,7 +1742,7 @@
 			       struct v4l2_mbus_framefmt *fmt,
 			       enum v4l2_subdev_format_whence which)
 {
-	u32 pixelcode;
+	enum v4l2_mbus_pixelcode pixelcode;
 	struct v4l2_rect *crop;
 	unsigned int i;
 
@@ -1772,7 +1774,7 @@
 
 		/* If not found, use SGRBG10 as default */
 		if (i >= ARRAY_SIZE(preview_input_fmts))
-			fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+			fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
 		break;
 
 	case PREV_PAD_SOURCE:
@@ -1780,13 +1782,13 @@
 		*fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
 
 		switch (pixelcode) {
-		case MEDIA_BUS_FMT_YUYV8_1X16:
-		case MEDIA_BUS_FMT_UYVY8_1X16:
+		case V4L2_MBUS_FMT_YUYV8_1X16:
+		case V4L2_MBUS_FMT_UYVY8_1X16:
 			fmt->code = pixelcode;
 			break;
 
 		default:
-			fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
+			fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
 			break;
 		}
 
@@ -1841,8 +1843,8 @@
 	 * and no columns in other modes. Increase the margins based on the sink
 	 * format.
 	 */
-	if (sink->code != MEDIA_BUS_FMT_Y8_1X8 &&
-	    sink->code != MEDIA_BUS_FMT_Y10_1X10) {
+	if (sink->code != V4L2_MBUS_FMT_Y8_1X8 &&
+	    sink->code != V4L2_MBUS_FMT_Y10_1X10) {
 		left += 2;
 		right -= 2;
 		top += 2;
@@ -2090,7 +2092,7 @@
 	memset(&format, 0, sizeof(format));
 	format.pad = PREV_PAD_SINK;
 	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
 	format.format.width = 4096;
 	format.format.height = 4096;
 	preview_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c
index 2b9bc48..05d1ace 100644
--- a/drivers/media/platform/omap3isp/ispresizer.c
+++ b/drivers/media/platform/omap3isp/ispresizer.c
@@ -198,16 +198,17 @@
  * @res: Device context.
  * @pixelcode: pixel code.
  */
-static void resizer_set_ycpos(struct isp_res_device *res, u32 pixelcode)
+static void resizer_set_ycpos(struct isp_res_device *res,
+			      enum v4l2_mbus_pixelcode pixelcode)
 {
 	struct isp_device *isp = to_isp_device(res);
 
 	switch (pixelcode) {
-	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case V4L2_MBUS_FMT_YUYV8_1X16:
 		isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
 			    ISPRSZ_CNT_YCPOS);
 		break;
-	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case V4L2_MBUS_FMT_UYVY8_1X16:
 		isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
 			    ISPRSZ_CNT_YCPOS);
 		break;
@@ -1347,8 +1348,8 @@
 
 /* resizer pixel formats */
 static const unsigned int resizer_formats[] = {
-	MEDIA_BUS_FMT_UYVY8_1X16,
-	MEDIA_BUS_FMT_YUYV8_1X16,
+	V4L2_MBUS_FMT_UYVY8_1X16,
+	V4L2_MBUS_FMT_YUYV8_1X16,
 };
 
 static unsigned int resizer_max_in_width(struct isp_res_device *res)
@@ -1384,9 +1385,9 @@
 
 	switch (pad) {
 	case RESZ_PAD_SINK:
-		if (fmt->code != MEDIA_BUS_FMT_YUYV8_1X16 &&
-		    fmt->code != MEDIA_BUS_FMT_UYVY8_1X16)
-			fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
+		if (fmt->code != V4L2_MBUS_FMT_YUYV8_1X16 &&
+		    fmt->code != V4L2_MBUS_FMT_UYVY8_1X16)
+			fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
 
 		fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH,
 				     resizer_max_in_width(res));
@@ -1570,7 +1571,7 @@
 	memset(&format, 0, sizeof(format));
 	format.pad = RESZ_PAD_SINK;
 	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.format.code = MEDIA_BUS_FMT_YUYV8_1X16;
+	format.format.code = V4L2_MBUS_FMT_YUYV8_1X16;
 	format.format.width = 4096;
 	format.format.height = 4096;
 	resizer_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index b463fe1..bc38c88 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -39,74 +39,74 @@
  * corresponding in-memory formats to the table below!!!
  */
 static struct isp_format_info formats[] = {
-	{ MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
-	  MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
+	{ V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+	  V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
 	  V4L2_PIX_FMT_GREY, 8, 1, },
-	{ MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10,
-	  MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y8_1X8,
+	{ V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
+	  V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
 	  V4L2_PIX_FMT_Y10, 10, 2, },
-	{ MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y10_1X10,
-	  MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y8_1X8,
+	{ V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
+	  V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
 	  V4L2_PIX_FMT_Y12, 12, 2, },
-	{ MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
-	  MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
+	{ V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+	  V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
 	  V4L2_PIX_FMT_SBGGR8, 8, 1, },
-	{ MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
-	  MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
+	{ V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+	  V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
 	  V4L2_PIX_FMT_SGBRG8, 8, 1, },
-	{ MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
-	  MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
+	{ V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+	  V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
 	  V4L2_PIX_FMT_SGRBG8, 8, 1, },
-	{ MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
-	  MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
+	{ V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+	  V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
 	  V4L2_PIX_FMT_SRGGB8, 8, 1, },
-	{ MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
-	  MEDIA_BUS_FMT_SBGGR10_1X10, 0,
+	{ V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
+	  V4L2_MBUS_FMT_SBGGR10_1X10, 0,
 	  V4L2_PIX_FMT_SBGGR10DPCM8, 8, 1, },
-	{ MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
-	  MEDIA_BUS_FMT_SGBRG10_1X10, 0,
+	{ V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
+	  V4L2_MBUS_FMT_SGBRG10_1X10, 0,
 	  V4L2_PIX_FMT_SGBRG10DPCM8, 8, 1, },
-	{ MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
-	  MEDIA_BUS_FMT_SGRBG10_1X10, 0,
+	{ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+	  V4L2_MBUS_FMT_SGRBG10_1X10, 0,
 	  V4L2_PIX_FMT_SGRBG10DPCM8, 8, 1, },
-	{ MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
-	  MEDIA_BUS_FMT_SRGGB10_1X10, 0,
+	{ V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
+	  V4L2_MBUS_FMT_SRGGB10_1X10, 0,
 	  V4L2_PIX_FMT_SRGGB10DPCM8, 8, 1, },
-	{ MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10,
-	  MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR8_1X8,
+	{ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
+	  V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
 	  V4L2_PIX_FMT_SBGGR10, 10, 2, },
-	{ MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10,
-	  MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG8_1X8,
+	{ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
+	  V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
 	  V4L2_PIX_FMT_SGBRG10, 10, 2, },
-	{ MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10,
-	  MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG8_1X8,
+	{ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
+	  V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
 	  V4L2_PIX_FMT_SGRBG10, 10, 2, },
-	{ MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
-	  MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8,
+	{ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
+	  V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
 	  V4L2_PIX_FMT_SRGGB10, 10, 2, },
-	{ MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR10_1X10,
-	  MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR8_1X8,
+	{ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
+	  V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
 	  V4L2_PIX_FMT_SBGGR12, 12, 2, },
-	{ MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG10_1X10,
-	  MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG8_1X8,
+	{ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
+	  V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
 	  V4L2_PIX_FMT_SGBRG12, 12, 2, },
-	{ MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG10_1X10,
-	  MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG8_1X8,
+	{ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
+	  V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
 	  V4L2_PIX_FMT_SGRBG12, 12, 2, },
-	{ MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10,
-	  MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB8_1X8,
+	{ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
+	  V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
 	  V4L2_PIX_FMT_SRGGB12, 12, 2, },
-	{ MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16,
-	  MEDIA_BUS_FMT_UYVY8_1X16, 0,
+	{ V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
+	  V4L2_MBUS_FMT_UYVY8_1X16, 0,
 	  V4L2_PIX_FMT_UYVY, 16, 2, },
-	{ MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16,
-	  MEDIA_BUS_FMT_YUYV8_1X16, 0,
+	{ V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
+	  V4L2_MBUS_FMT_YUYV8_1X16, 0,
 	  V4L2_PIX_FMT_YUYV, 16, 2, },
-	{ MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_UYVY8_2X8,
-	  MEDIA_BUS_FMT_UYVY8_2X8, 0,
+	{ V4L2_MBUS_FMT_UYVY8_2X8, V4L2_MBUS_FMT_UYVY8_2X8,
+	  V4L2_MBUS_FMT_UYVY8_2X8, 0,
 	  V4L2_PIX_FMT_UYVY, 8, 2, },
-	{ MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YUYV8_2X8,
-	  MEDIA_BUS_FMT_YUYV8_2X8, 0,
+	{ V4L2_MBUS_FMT_YUYV8_2X8, V4L2_MBUS_FMT_YUYV8_2X8,
+	  V4L2_MBUS_FMT_YUYV8_2X8, 0,
 	  V4L2_PIX_FMT_YUYV, 8, 2, },
 	/* Empty entry to catch the unsupported pixel code (0) used by the CCDC
 	 * module and avoid NULL pointer dereferences.
@@ -114,7 +114,8 @@
 	{ 0, }
 };
 
-const struct isp_format_info *omap3isp_video_format_info(u32 code)
+const struct isp_format_info *
+omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
 {
 	unsigned int i;
 
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 4071dd7..0b7efed 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -44,10 +44,10 @@
  * @bpp: Bytes per pixel (when stored in memory)
  */
 struct isp_format_info {
-	u32 code;
-	u32 truncated;
-	u32 uncompressed;
-	u32 flavor;
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_mbus_pixelcode truncated;
+	enum v4l2_mbus_pixelcode uncompressed;
+	enum v4l2_mbus_pixelcode flavor;
 	u32 pixelformat;
 	unsigned int width;
 	unsigned int bpp;
@@ -206,6 +206,6 @@
 struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
 
 const struct isp_format_info *
-omap3isp_video_format_info(u32 code);
+omap3isp_video_format_info(enum v4l2_mbus_pixelcode code);
 
 #endif /* OMAP3_ISP_VIDEO_H */
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index aa40c82..4f81b4c 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -1218,11 +1218,11 @@
 }
 
 /* Media bus pixel formats supported at the camif input */
-static const u32 camif_mbus_formats[] = {
-	MEDIA_BUS_FMT_YUYV8_2X8,
-	MEDIA_BUS_FMT_YVYU8_2X8,
-	MEDIA_BUS_FMT_UYVY8_2X8,
-	MEDIA_BUS_FMT_VYUY8_2X8,
+static const enum v4l2_mbus_pixelcode camif_mbus_formats[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
+	V4L2_MBUS_FMT_YVYU8_2X8,
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_VYUY8_2X8,
 };
 
 /*
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
index 2d5bd3a..b385747 100644
--- a/drivers/media/platform/s3c-camif/camif-core.c
+++ b/drivers/media/platform/s3c-camif/camif-core.c
@@ -256,7 +256,8 @@
 	v4l2_device_unregister_subdev(sd);
 	camif->sensor.sd = NULL;
 	i2c_unregister_device(client);
-	i2c_put_adapter(adapter);
+	if (adapter)
+		i2c_put_adapter(adapter);
 }
 
 static int camif_create_media_links(struct camif_dev *camif)
@@ -651,6 +652,7 @@
 	.id_table	= s3c_camif_driver_ids,
 	.driver = {
 		.name	= S3C_CAMIF_DRIVER_NAME,
+		.owner	= THIS_MODULE,
 		.pm	= &s3c_camif_pm_ops,
 	}
 };
diff --git a/drivers/media/platform/s3c-camif/camif-regs.c b/drivers/media/platform/s3c-camif/camif-regs.c
index 812fb3a..6e0c998 100644
--- a/drivers/media/platform/s3c-camif/camif-regs.c
+++ b/drivers/media/platform/s3c-camif/camif-regs.c
@@ -96,10 +96,10 @@
 }
 
 static const u32 src_pixfmt_map[8][2] = {
-	{ MEDIA_BUS_FMT_YUYV8_2X8, CISRCFMT_ORDER422_YCBYCR },
-	{ MEDIA_BUS_FMT_YVYU8_2X8, CISRCFMT_ORDER422_YCRYCB },
-	{ MEDIA_BUS_FMT_UYVY8_2X8, CISRCFMT_ORDER422_CBYCRY },
-	{ MEDIA_BUS_FMT_VYUY8_2X8, CISRCFMT_ORDER422_CRYCBY },
+	{ V4L2_MBUS_FMT_YUYV8_2X8, CISRCFMT_ORDER422_YCBYCR },
+	{ V4L2_MBUS_FMT_YVYU8_2X8, CISRCFMT_ORDER422_YCRYCB },
+	{ V4L2_MBUS_FMT_UYVY8_2X8, CISRCFMT_ORDER422_CBYCRY },
+	{ V4L2_MBUS_FMT_VYUY8_2X8, CISRCFMT_ORDER422_CRYCBY },
 };
 
 /* Set camera input pixel format and resolution */
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 47ba8fb..d79e214 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -297,8 +297,14 @@
 	strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1);
 	strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1);
 	cap->bus_info[0] = 0;
-	cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	cap->version = KERNEL_VERSION(1, 0, 0);
+	/*
+	 * This is only a mem-to-mem video device. The capture and output
+	 * device capability flags are left only for backward compatibility
+	 * and are scheduled for removal.
+	 */
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+			    V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
 	return 0;
 }
 
@@ -806,6 +812,7 @@
 	.id_table	= g2d_driver_ids,
 	.driver		= {
 		.name = G2D_NAME,
+		.owner = THIS_MODULE,
 		.of_match_table = exynos_g2d_match,
 	},
 };
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 12f7452..e525a7c 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -893,7 +893,7 @@
 			       unsigned long buffer, unsigned long size,
 			       struct s5p_jpeg_ctx *ctx)
 {
-	int c, components = 0, notfound;
+	int c, components, notfound;
 	unsigned int height, width, word, subsampling = 0;
 	long length;
 	struct s5p_jpeg_buffer jpeg_buffer;
@@ -1001,8 +1001,13 @@
 			sizeof(cap->card));
 	}
 	cap->bus_info[0] = 0;
-	cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	/*
+	 * This is only a mem-to-mem video device. The capture and output
+	 * device capability flags are left only for backward compatibility
+	 * and are scheduled for removal.
+	 */
+	cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M |
+			    V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
 	return 0;
 }
 
@@ -2627,7 +2632,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
 static int s5p_jpeg_runtime_suspend(struct device *dev)
 {
 	struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
@@ -2677,9 +2681,7 @@
 
 	return 0;
 }
-#endif /* CONFIG_PM */
 
-#ifdef CONFIG_PM_SLEEP
 static int s5p_jpeg_suspend(struct device *dev)
 {
 	if (pm_runtime_suspended(dev))
@@ -2695,7 +2697,6 @@
 
 	return s5p_jpeg_runtime_resume(dev);
 }
-#endif
 
 static const struct dev_pm_ops s5p_jpeg_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(s5p_jpeg_suspend, s5p_jpeg_resume)
@@ -2763,6 +2764,7 @@
 	.remove = s5p_jpeg_remove,
 	.driver = {
 		.of_match_table	= of_match_ptr(samsung_jpeg_match),
+		.owner		= THIS_MODULE,
 		.name		= S5P_JPEG_M2M_NAME,
 		.pm		= &s5p_jpeg_pm_ops,
 	},
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
index 83e01f3..51cb2dd 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
@@ -71,7 +71,6 @@
 #define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6	16
 #define S5P_FIMV_R2H_CMD_ERR_RET_V6		32
 
-#define S5P_FIMV_MFC_BUS_RESET_CTRL            0x7110
 #define S5P_FIMV_FW_VERSION_V6			0xf000
 
 #define S5P_FIMV_INSTANCE_ID_V6			0xf008
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index fbfdf03..165bc86 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -159,10 +159,6 @@
 	}
 	clear_bit(0, &dev->hw_lock);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
-
-	/* De-init MFC */
-	s5p_mfc_deinit_hw(dev);
-
 	/* Double check if there is at least one instance running.
 	 * If no instance is in memory than no firmware should be present */
 	if (dev->num_inst > 0) {
@@ -224,14 +220,11 @@
 	size_t dec_y_addr;
 	unsigned int frame_type;
 
-	/* Make sure we actually have a new frame before continuing. */
-	frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
-	if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED)
-		return;
 	dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
+	frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
 
 	/* Copy timestamp / timecode from decoded src to dst and set
-	   appropriate flags. */
+	   appropriate flags */
 	src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
 	list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
 		if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) {
@@ -257,11 +250,6 @@
 				dst_buf->b->v4l2_buf.flags |=
 						V4L2_BUF_FLAG_BFRAME;
 				break;
-			default:
-				/* Don't know how to handle
-				   S5P_FIMV_DECODE_FRAME_OTHER_FRAME. */
-				mfc_debug(2, "Unexpected frame type: %d\n",
-						frame_type);
 			}
 			break;
 		}
@@ -346,7 +334,8 @@
 		ctx->state = MFCINST_RES_CHANGE_INIT;
 		s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
 		wake_up_ctx(ctx, reason, err);
-		WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+		if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+			BUG();
 		s5p_mfc_clock_off();
 		s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
 		return;
@@ -418,7 +407,8 @@
 		clear_work_bit(ctx);
 	s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
 	wake_up_ctx(ctx, reason, err);
-	WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+	if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+		BUG();
 	s5p_mfc_clock_off();
 	/* if suspending, wake up device and do not try_run again*/
 	if (test_bit(0, &dev->enter_suspend))
@@ -465,7 +455,8 @@
 			break;
 		}
 	}
-	WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+	if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+		BUG();
 	s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
 	s5p_mfc_clock_off();
 	wake_up_dev(dev, reason, err);
@@ -519,7 +510,8 @@
 	}
 	s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
 	clear_work_bit(ctx);
-	WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+	if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+		BUG();
 	s5p_mfc_clock_off();
 	s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
 	wake_up_ctx(ctx, reason, err);
@@ -557,14 +549,16 @@
 		} else {
 			ctx->dpb_flush_flag = 0;
 		}
-		WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+		if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+			BUG();
 
 		s5p_mfc_clock_off();
 
 		wake_up(&ctx->queue);
 		s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
 	} else {
-		WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+		if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+			BUG();
 
 		s5p_mfc_clock_off();
 
@@ -641,7 +635,8 @@
 				mfc_err("post_frame_start() failed\n");
 			s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
 			wake_up_ctx(ctx, reason, err);
-			WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+			if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+				BUG();
 			s5p_mfc_clock_off();
 			s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
 		} else {
@@ -820,7 +815,7 @@
 		ret = -ENOENT;
 		goto err_queue_init;
 	}
-	q->mem_ops = &vb2_dma_contig_memops;
+	q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	ret = vb2_queue_init(q);
 	if (ret) {
@@ -842,7 +837,7 @@
 		ret = -ENOENT;
 		goto err_queue_init;
 	}
-	q->mem_ops = &vb2_dma_contig_memops;
+	q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	ret = vb2_queue_init(q);
 	if (ret) {
@@ -1289,17 +1284,11 @@
 			m_dev->int_cond, msecs_to_jiffies(MFC_INT_TIMEOUT));
 		if (ret == 0) {
 			mfc_err("Waiting for hardware to finish timed out\n");
-			clear_bit(0, &m_dev->enter_suspend);
 			return -EIO;
 		}
 	}
 
-	ret = s5p_mfc_sleep(m_dev);
-	if (ret) {
-		clear_bit(0, &m_dev->enter_suspend);
-		clear_bit(0, &m_dev->hw_lock);
-	}
-	return ret;
+	return s5p_mfc_sleep(m_dev);
 }
 
 static int s5p_mfc_resume(struct device *dev)
@@ -1313,7 +1302,7 @@
 }
 #endif
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 static int s5p_mfc_runtime_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -1516,6 +1505,7 @@
 	.id_table	= mfc_driver_ids,
 	.driver	= {
 		.name	= S5P_MFC_NAME,
+		.owner	= THIS_MODULE,
 		.pm	= &s5p_mfc_pm_ops,
 		.of_match_table = exynos_mfc_match,
 	},
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 15f7663..3e41ca1 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -237,6 +237,8 @@
 
 /**
  * struct s5p_mfc_priv_buf - represents internal used buffer
+ * @alloc:		allocation-specific context for each buffer
+ *			(videobuf2 allocator)
  * @ofs:		offset of each buffer, will be used for MFC
  * @virt:		kernel virtual address, only valid when the
  *			buffer accessed by driver
@@ -244,6 +246,7 @@
  * @size:		size of the buffer
  */
 struct s5p_mfc_priv_buf {
+	void		*alloc;
 	unsigned long	ofs;
 	void		*virt;
 	dma_addr_t	dma;
@@ -337,7 +340,6 @@
 	struct s5p_mfc_hw_cmds *mfc_cmds;
 	const struct s5p_mfc_regs *mfc_regs;
 	enum s5p_mfc_fw_ver fw_ver;
-	bool risc_on; /* indicates if RISC is on or off */
 };
 
 /**
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 40d8a03..0c885a8 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -129,25 +129,6 @@
 	return 0;
 }
 
-static int s5p_mfc_bus_reset(struct s5p_mfc_dev *dev)
-{
-	unsigned int status;
-	unsigned long timeout;
-
-	/* Reset */
-	mfc_write(dev, 0x1, S5P_FIMV_MFC_BUS_RESET_CTRL);
-	timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-	/* Check bus status */
-	do {
-		if (time_after(jiffies, timeout)) {
-			mfc_err("Timeout while resetting MFC.\n");
-			return -EIO;
-		}
-		status = mfc_read(dev, S5P_FIMV_MFC_BUS_RESET_CTRL);
-	} while ((status & 0x2) == 0);
-	return 0;
-}
-
 /* Reset the device */
 int s5p_mfc_reset(struct s5p_mfc_dev *dev)
 {
@@ -158,6 +139,12 @@
 	mfc_debug_enter();
 
 	if (IS_MFCV6_PLUS(dev)) {
+		/* Reset IP */
+		/*  except RISC, reset */
+		mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6);
+		/*  reset release */
+		mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET_V6);
+
 		/* Zero Initialization of MFC registers */
 		mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
 		mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
@@ -166,17 +153,8 @@
 		for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
 			mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
 
-		/* check bus reset control before reset */
-		if (dev->risc_on)
-			if (s5p_mfc_bus_reset(dev))
-				return -EIO;
-		/* Reset
-		 * set RISC_ON to 0 during power_on & wake_up.
-		 * V6 needs RISC_ON set to 0 during reset also.
-		 */
-		if ((!dev->risc_on) || (!IS_MFCV7_PLUS(dev)))
-			mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
-
+		/* Reset */
+		mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
 		mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
 		mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
 	} else {
@@ -248,7 +226,6 @@
 	/* 0. MFC reset */
 	mfc_debug(2, "MFC reset..\n");
 	s5p_mfc_clock_on();
-	dev->risc_on = 0;
 	ret = s5p_mfc_reset(dev);
 	if (ret) {
 		mfc_err("Failed to reset MFC - timeout\n");
@@ -261,10 +238,8 @@
 	s5p_mfc_clear_cmds(dev);
 	/* 3. Release reset signal to the RISC */
 	s5p_mfc_clean_dev_int_flags(dev);
-	if (IS_MFCV6_PLUS(dev)) {
-		dev->risc_on = 1;
+	if (IS_MFCV6_PLUS(dev))
 		mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
-	}
 	else
 		mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
 	mfc_debug(2, "Will now wait for completion of firmware transfer\n");
@@ -353,58 +328,6 @@
 	return ret;
 }
 
-static int s5p_mfc_v8_wait_wakeup(struct s5p_mfc_dev *dev)
-{
-	int ret;
-
-	/* Release reset signal to the RISC */
-	dev->risc_on = 1;
-	mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
-
-	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
-		mfc_err("Failed to reset MFCV8\n");
-		return -EIO;
-	}
-	mfc_debug(2, "Write command to wakeup MFCV8\n");
-	ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
-	if (ret) {
-		mfc_err("Failed to send command to MFCV8 - timeout\n");
-		return ret;
-	}
-
-	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
-		mfc_err("Failed to wakeup MFC\n");
-		return -EIO;
-	}
-	return ret;
-}
-
-static int s5p_mfc_wait_wakeup(struct s5p_mfc_dev *dev)
-{
-	int ret;
-
-	/* Send MFC wakeup command */
-	ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
-	if (ret) {
-		mfc_err("Failed to send command to MFC - timeout\n");
-		return ret;
-	}
-
-	/* Release reset signal to the RISC */
-	if (IS_MFCV6_PLUS(dev)) {
-		dev->risc_on = 1;
-		mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
-	} else {
-		mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
-	}
-
-	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
-		mfc_err("Failed to wakeup MFC\n");
-		return -EIO;
-	}
-	return ret;
-}
-
 int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
 {
 	int ret;
@@ -413,11 +336,9 @@
 	/* 0. MFC reset */
 	mfc_debug(2, "MFC reset..\n");
 	s5p_mfc_clock_on();
-	dev->risc_on = 0;
 	ret = s5p_mfc_reset(dev);
 	if (ret) {
 		mfc_err("Failed to reset MFC - timeout\n");
-		s5p_mfc_clock_off();
 		return ret;
 	}
 	mfc_debug(2, "Done MFC reset..\n");
@@ -426,16 +347,23 @@
 	/* 2. Initialize registers of channel I/F */
 	s5p_mfc_clear_cmds(dev);
 	s5p_mfc_clean_dev_int_flags(dev);
-	/* 3. Send MFC wakeup command and wait for completion*/
-	if (IS_MFCV8(dev))
-		ret = s5p_mfc_v8_wait_wakeup(dev);
-	else
-		ret = s5p_mfc_wait_wakeup(dev);
-
-	s5p_mfc_clock_off();
-	if (ret)
+	/* 3. Initialize firmware */
+	ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
+	if (ret) {
+		mfc_err("Failed to send command to MFC - timeout\n");
 		return ret;
-
+	}
+	/* 4. Release reset signal to the RISC */
+	if (IS_MFCV6_PLUS(dev))
+		mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+	else
+		mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+	mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
+	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
+		mfc_err("Failed to load firmware\n");
+		return -EIO;
+	}
+	s5p_mfc_clock_off();
 	dev->int_cond = 0;
 	if (dev->int_err != 0 || dev->int_type !=
 						S5P_MFC_R2H_CMD_WAKEUP_RET) {
@@ -468,6 +396,7 @@
 	}
 
 	set_work_bit_irqsave(ctx);
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
 	if (s5p_mfc_wait_for_done_ctx(ctx,
 		S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
@@ -493,6 +422,7 @@
 {
 	ctx->state = MFCINST_RETURN_INST;
 	set_work_bit_irqsave(ctx);
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
 	/* Wait until instance is returned or timeout occurred */
 	if (s5p_mfc_wait_for_done_ctx(ctx,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index c6c3452..a98fe02 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -269,13 +269,15 @@
 	strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1);
 	strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
 	cap->bus_info[0] = 0;
+	cap->version = KERNEL_VERSION(1, 0, 0);
 	/*
 	 * This is only a mem-to-mem video device. The capture and output
 	 * device capability flags are left only for backward compatibility
 	 * and are scheduled for removal.
 	 */
-	cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING |
+			    V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+			    V4L2_CAP_VIDEO_OUTPUT_MPLANE;
 	return 0;
 }
 
@@ -332,6 +334,7 @@
 						MFCINST_RES_CHANGE_END)) {
 		/* If the MFC is parsing the header,
 		 * so wait until it is finished */
+		s5p_mfc_clean_ctx_int_flags(ctx);
 		s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
 									0);
 	}
@@ -737,12 +740,12 @@
 		    ctx->state < MFCINST_ABORT) {
 			ctrl->val = ctx->pb_count;
 			break;
-		} else if (ctx->state != MFCINST_INIT &&
-				ctx->state != MFCINST_RES_CHANGE_END) {
+		} else if (ctx->state != MFCINST_INIT) {
 			v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
 			return -EINVAL;
 		}
 		/* Should wait for the header to be parsed */
+		s5p_mfc_clean_ctx_int_flags(ctx);
 		s5p_mfc_wait_for_done_ctx(ctx,
 				S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
 		if (ctx->state >= MFCINST_HEAD_PARSED &&
@@ -1054,6 +1057,7 @@
 		if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) {
 			ctx->state = MFCINST_FLUSH;
 			set_work_bit_irqsave(ctx);
+			s5p_mfc_clean_ctx_int_flags(ctx);
 			s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
 			if (s5p_mfc_wait_for_done_ctx(ctx,
 				S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index bd64f1d..a904a1c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -32,7 +32,7 @@
 #include "s5p_mfc_intr.h"
 #include "s5p_mfc_opr.h"
 
-#define DEF_SRC_FMT_ENC	V4L2_PIX_FMT_NV12M
+#define DEF_SRC_FMT_ENC	V4L2_PIX_FMT_NV12MT
 #define DEF_DST_FMT_ENC	V4L2_PIX_FMT_H264
 
 static struct s5p_mfc_fmt formats[] = {
@@ -67,7 +67,8 @@
 		.codec_mode	= S5P_MFC_CODEC_NONE,
 		.type		= MFC_FMT_RAW,
 		.num_planes	= 2,
-		.versions	= MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT,
+		.versions	= MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
+								MFC_V8_BIT,
 	},
 	{
 		.name		= "H264 Encoded Stream",
@@ -689,16 +690,6 @@
 		.step = 1,
 		.default_value = 0,
 	},
-	{
-		.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Minimum number of output bufs",
-		.minimum = 1,
-		.maximum = 32,
-		.step = 1,
-		.default_value = 1,
-		.is_volatile = 1,
-	},
 };
 
 #define NUM_CTRLS ARRAY_SIZE(controls)
@@ -947,13 +938,15 @@
 	strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1);
 	strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
 	cap->bus_info[0] = 0;
+	cap->version = KERNEL_VERSION(1, 0, 0);
 	/*
 	 * This is only a mem-to-mem video device. The capture and output
 	 * device capability flags are left only for backward compatibility
 	 * and are scheduled for removal.
 	 */
-	cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING |
+			    V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+			    V4L2_CAP_VIDEO_OUTPUT_MPLANE;
 	return 0;
 }
 
@@ -1144,11 +1137,6 @@
 		(reqbufs->memory != V4L2_MEMORY_USERPTR))
 		return -EINVAL;
 	if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-		if (reqbufs->count == 0) {
-			ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-			ctx->capture_state = QUEUE_FREE;
-			return ret;
-		}
 		if (ctx->capture_state != QUEUE_FREE) {
 			mfc_err("invalid capture state: %d\n",
 							ctx->capture_state);
@@ -1170,14 +1158,6 @@
 			return -ENOMEM;
 		}
 	} else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		if (reqbufs->count == 0) {
-			mfc_debug(2, "Freeing buffers\n");
-			ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-			s5p_mfc_hw_call_void(dev->mfc_ops, release_codec_buffers,
-					ctx);
-			ctx->output_state = QUEUE_FREE;
-			return ret;
-		}
 		if (ctx->output_state != QUEUE_FREE) {
 			mfc_err("invalid output state: %d\n",
 							ctx->output_state);
@@ -1644,39 +1624,8 @@
 	return ret;
 }
 
-static int s5p_mfc_enc_g_v_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
-	struct s5p_mfc_dev *dev = ctx->dev;
-
-	switch (ctrl->id) {
-	case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
-		if (ctx->state >= MFCINST_HEAD_PARSED &&
-		    ctx->state < MFCINST_ABORT) {
-			ctrl->val = ctx->pb_count;
-			break;
-		} else if (ctx->state != MFCINST_INIT) {
-			v4l2_err(&dev->v4l2_dev, "Encoding not initialised\n");
-			return -EINVAL;
-		}
-		/* Should wait for the header to be produced */
-		s5p_mfc_wait_for_done_ctx(ctx,
-				S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
-		if (ctx->state >= MFCINST_HEAD_PARSED &&
-		    ctx->state < MFCINST_ABORT) {
-			ctrl->val = ctx->pb_count;
-		} else {
-			v4l2_err(&dev->v4l2_dev, "Encoding not initialised\n");
-			return -EINVAL;
-		}
-		break;
-	}
-	return 0;
-}
-
 static const struct v4l2_ctrl_ops s5p_mfc_enc_ctrl_ops = {
 	.s_ctrl = s5p_mfc_enc_s_ctrl,
-	.g_volatile_ctrl = s5p_mfc_enc_g_v_ctrl,
 };
 
 static int vidioc_s_parm(struct file *file, void *priv,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index 0c4fcf2..7cf0796 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -1178,6 +1178,7 @@
 
 	s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
 }
 
@@ -1191,6 +1192,7 @@
 		last_frame = MFC_DEC_LAST_FRAME;
 		s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
 		dev->curr_ctx = ctx->num;
+		s5p_mfc_clean_ctx_int_flags(ctx);
 		s5p_mfc_decode_one_frame_v5(ctx, last_frame);
 		return 0;
 	}
@@ -1210,6 +1212,7 @@
 		ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
 		last_frame = MFC_DEC_LAST_FRAME;
 		mfc_debug(2, "Setting ctx->state to FINISHING\n");
@@ -1270,6 +1273,7 @@
 	s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	mfc_debug(2, "encoding buffer with index=%d state=%d\n",
 		  src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
 	s5p_mfc_encode_one_frame_v5(ctx);
@@ -1293,6 +1297,7 @@
 				0, temp_vb->b->v4l2_planes[0].bytesused);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	s5p_mfc_init_decode_v5(ctx);
 }
 
@@ -1312,6 +1317,7 @@
 	s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	s5p_mfc_init_encode_v5(ctx);
 }
 
@@ -1346,6 +1352,7 @@
 				0, temp_vb->b->v4l2_planes[0].bytesused);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
 	if (ret) {
 		mfc_err("Failed to alloc frame mem\n");
@@ -1389,8 +1396,6 @@
 	 * Now obtaining frames from MFC buffer
 	 */
 	s5p_mfc_clock_on();
-	s5p_mfc_clean_ctx_int_flags(ctx);
-
 	if (ctx->type == MFCINST_DECODER) {
 		s5p_mfc_set_dec_desc_buffer(ctx);
 		switch (ctx->state) {
@@ -1401,10 +1406,12 @@
 			ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
 			break;
 		case MFCINST_INIT:
+			s5p_mfc_clean_ctx_int_flags(ctx);
 			ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
 					ctx);
 			break;
 		case MFCINST_RETURN_INST:
+			s5p_mfc_clean_ctx_int_flags(ctx);
 			ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
 					ctx);
 			break;
@@ -1437,10 +1444,12 @@
 			ret = s5p_mfc_run_enc_frame(ctx);
 			break;
 		case MFCINST_INIT:
+			s5p_mfc_clean_ctx_int_flags(ctx);
 			ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
 					ctx);
 			break;
 		case MFCINST_RETURN_INST:
+			s5p_mfc_clean_ctx_int_flags(ctx);
 			ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
 					ctx);
 			break;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 9aea179..8798b14 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -1394,6 +1394,7 @@
 
 	if (flush) {
 		dev->curr_ctx = ctx->num;
+		s5p_mfc_clean_ctx_int_flags(ctx);
 		writel(ctx->inst_no, mfc_regs->instance_id);
 		s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev,
 				S5P_FIMV_H2R_CMD_FLUSH_V6, NULL);
@@ -1531,10 +1532,27 @@
 static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_buf *temp_vb;
+	unsigned long flags;
 
-	s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0);
+	spin_lock_irqsave(&dev->irqlock, flags);
+
+	/* Frames are being decoded */
+	if (list_empty(&ctx->src_queue)) {
+		mfc_debug(2, "No src buffers.\n");
+		spin_unlock_irqrestore(&dev->irqlock, flags);
+		return;
+	}
+	/* Get the next source buffer */
+	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+	temp_vb->flags |= MFC_BUF_FLAG_USED;
+	s5p_mfc_set_dec_stream_buffer_v6(ctx,
+			vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+
 	dev->curr_ctx = ctx->num;
-	s5p_mfc_decode_one_frame_v6(ctx, MFC_DEC_LAST_FRAME);
+	s5p_mfc_clean_ctx_int_flags(ctx);
+	s5p_mfc_decode_one_frame_v6(ctx, 1);
 }
 
 static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
@@ -1570,6 +1588,7 @@
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
 		last_frame = 1;
 		mfc_debug(2, "Setting ctx->state to FINISHING\n");
@@ -1626,6 +1645,7 @@
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	s5p_mfc_encode_one_frame_v6(ctx);
 
 	return 0;
@@ -1647,6 +1667,7 @@
 			temp_vb->b->v4l2_planes[0].bytesused);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	s5p_mfc_init_decode_v6(ctx);
 }
 
@@ -1666,6 +1687,7 @@
 	s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
 	spin_unlock_irqrestore(&dev->irqlock, flags);
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	s5p_mfc_init_encode_v6(ctx);
 }
 
@@ -1685,6 +1707,7 @@
 	}
 
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
 	if (ret) {
 		mfc_err("Failed to alloc frame mem.\n");
@@ -1699,6 +1722,7 @@
 	int ret;
 
 	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
 	ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
 	if (ret) {
 		mfc_err("Failed to alloc frame mem.\n");
@@ -1747,8 +1771,6 @@
 	 * Now obtaining frames from MFC buffer */
 
 	s5p_mfc_clock_on();
-	s5p_mfc_clean_ctx_int_flags(ctx);
-
 	if (ctx->type == MFCINST_DECODER) {
 		switch (ctx->state) {
 		case MFCINST_FINISHING:
@@ -1758,10 +1780,12 @@
 			ret = s5p_mfc_run_dec_frame(ctx);
 			break;
 		case MFCINST_INIT:
+			s5p_mfc_clean_ctx_int_flags(ctx);
 			ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
 					ctx);
 			break;
 		case MFCINST_RETURN_INST:
+			s5p_mfc_clean_ctx_int_flags(ctx);
 			ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
 					ctx);
 			break;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 5f97a33..826c489 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -13,7 +13,9 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
+#ifdef CONFIG_PM_RUNTIME
 #include <linux/pm_runtime.h>
+#endif
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_pm.h"
@@ -65,7 +67,7 @@
 	}
 
 	atomic_set(&pm->power, 0);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 	pm->device = &dev->plat_dev->dev;
 	pm_runtime_enable(pm->device);
 #endif
@@ -91,7 +93,7 @@
 	}
 	clk_unprepare(pm->clock_gate);
 	clk_put(pm->clock_gate);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 	pm_runtime_disable(pm->device);
 #endif
 }
@@ -118,7 +120,7 @@
 
 int s5p_mfc_power_on(void)
 {
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 	return pm_runtime_get_sync(pm->device);
 #else
 	atomic_set(&pm->power, 1);
@@ -128,7 +130,7 @@
 
 int s5p_mfc_power_off(void)
 {
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 	return pm_runtime_put_sync(pm->device);
 #else
 	atomic_set(&pm->power, 0);
diff --git a/drivers/media/platform/s5p-tv/Kconfig b/drivers/media/platform/s5p-tv/Kconfig
index 8f78739..c22aac6 100644
--- a/drivers/media/platform/s5p-tv/Kconfig
+++ b/drivers/media/platform/s5p-tv/Kconfig
@@ -8,8 +8,8 @@
 
 config VIDEO_SAMSUNG_S5P_TV
 	bool "Samsung TV driver for S5P platform"
-	depends on PM
-	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+	depends on PM_RUNTIME
+	depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
 	default n
 	---help---
 	  Say Y here to enable selecting the TV output devices for
diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c
index c78b0cf..1434ba4 100644
--- a/drivers/media/platform/s5p-tv/hdmi_drv.c
+++ b/drivers/media/platform/s5p-tv/hdmi_drv.c
@@ -660,7 +660,7 @@
 	memset(fmt, 0, sizeof(*fmt));
 	fmt->width = t->hact.end - t->hact.beg;
 	fmt->height = t->vact[0].end - t->vact[0].beg;
-	fmt->code = MEDIA_BUS_FMT_FIXED; /* means RGB888 */
+	fmt->code = V4L2_MBUS_FMT_FIXED; /* means RGB888 */
 	fmt->colorspace = V4L2_COLORSPACE_SRGB;
 	if (t->interlaced) {
 		fmt->field = V4L2_FIELD_INTERLACED;
@@ -1046,6 +1046,7 @@
 	.id_table = hdmi_driver_types,
 	.driver = {
 		.name = "s5p-hdmi",
+		.owner = THIS_MODULE,
 		.pm = &hdmi_pm_ops,
 	}
 };
diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c
index 2a9501d..bc08b5f 100644
--- a/drivers/media/platform/s5p-tv/mixer_drv.c
+++ b/drivers/media/platform/s5p-tv/mixer_drv.c
@@ -487,6 +487,7 @@
 	.remove = mxr_remove,
 	.driver = {
 		.name = MXR_DRIVER_NAME,
+		.owner = THIS_MODULE,
 		.pm = &mxr_pm_ops,
 	}
 };
diff --git a/drivers/media/platform/s5p-tv/sdo_drv.c b/drivers/media/platform/s5p-tv/sdo_drv.c
index 3621af9..72cf892 100644
--- a/drivers/media/platform/s5p-tv/sdo_drv.c
+++ b/drivers/media/platform/s5p-tv/sdo_drv.c
@@ -170,7 +170,7 @@
 	/* all modes are 720 pixels wide */
 	fmt->width = 720;
 	fmt->height = sdev->fmt->height;
-	fmt->code = MEDIA_BUS_FMT_FIXED;
+	fmt->code = V4L2_MBUS_FMT_FIXED;
 	fmt->field = V4L2_FIELD_INTERLACED;
 	fmt->colorspace = V4L2_COLORSPACE_JPEG;
 	return 0;
@@ -482,6 +482,7 @@
 	.remove = sdo_remove,
 	.driver = {
 		.name = "s5p-sdo",
+		.owner = THIS_MODULE,
 		.pm = &sdo_pm_ops,
 	}
 };
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index aaa1f6f..be3b3bc 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -1235,6 +1235,7 @@
 	.remove		= sh_veu_remove,
 	.driver		= {
 		.name	= "sh_veu",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 261f119..e5f1d4c 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -396,8 +396,7 @@
 	dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
 
 	strlcpy(cap->card, "SuperH VOU", sizeof(cap->card));
-	cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
 	return 0;
 }
 
@@ -681,7 +680,7 @@
 	struct sh_vou_geometry geo;
 	struct v4l2_mbus_framefmt mbfmt = {
 		/* Revisit: is this the correct code? */
-		.code = MEDIA_BUS_FMT_YUYV8_2X8,
+		.code = V4L2_MBUS_FMT_YUYV8_2X8,
 		.field = V4L2_FIELD_INTERLACED,
 		.colorspace = V4L2_COLORSPACE_SMPTE170M,
 	};
@@ -734,7 +733,7 @@
 	/* Sanity checks */
 	if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH ||
 	    (unsigned)mbfmt.height > img_height_max ||
-	    mbfmt.code != MEDIA_BUS_FMT_YUYV8_2X8)
+	    mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8)
 		return -EIO;
 
 	if (mbfmt.width != geo.output.width ||
@@ -944,7 +943,7 @@
 	struct sh_vou_geometry geo;
 	struct v4l2_mbus_framefmt mbfmt = {
 		/* Revisit: is this the correct code? */
-		.code = MEDIA_BUS_FMT_YUYV8_2X8,
+		.code = V4L2_MBUS_FMT_YUYV8_2X8,
 		.field = V4L2_FIELD_INTERLACED,
 		.colorspace = V4L2_COLORSPACE_SMPTE170M,
 	};
@@ -995,7 +994,7 @@
 	/* Sanity checks */
 	if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH ||
 	    (unsigned)mbfmt.height > img_height_max ||
-	    mbfmt.code != MEDIA_BUS_FMT_YUYV8_2X8)
+	    mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8)
 		return -EIO;
 
 	geo.output.width = mbfmt.width;
@@ -1450,6 +1449,7 @@
 	.remove  = sh_vou_remove,
 	.driver  = {
 		.name	= "sh-vou",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
index fa5bceb..aebae21 100644
--- a/drivers/media/platform/soc_camera/Kconfig
+++ b/drivers/media/platform/soc_camera/Kconfig
@@ -1,6 +1,6 @@
 config SOC_CAMERA
-	depends on !KERNEL_3_4
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_5
 	tristate "SoC camera support"
 	depends on m
 	depends on VIDEO_V4L2 && HAS_DMA && I2C
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 8efe403..c5291b0 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -105,25 +105,25 @@
 }
 
 static int configure_geometry(struct atmel_isi *isi, u32 width,
-			u32 height, u32 code)
+			u32 height, enum v4l2_mbus_pixelcode code)
 {
 	u32 cfg2, cr;
 
 	switch (code) {
 	/* YUV, including grey */
-	case MEDIA_BUS_FMT_Y8_1X8:
+	case V4L2_MBUS_FMT_Y8_1X8:
 		cr = ISI_CFG2_GRAYSCALE;
 		break;
-	case MEDIA_BUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
 		cr = ISI_CFG2_YCC_SWAP_MODE_3;
 		break;
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		cr = ISI_CFG2_YCC_SWAP_MODE_2;
 		break;
-	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
 		cr = ISI_CFG2_YCC_SWAP_MODE_1;
 		break;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		cr = ISI_CFG2_YCC_SWAP_DEFAULT;
 		break;
 	/* RGB, TODO */
@@ -645,7 +645,7 @@
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	int formats = 0, ret;
 	/* sensor format */
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	/* soc camera host format */
 	const struct soc_mbus_pixelfmt *fmt;
 
@@ -670,10 +670,10 @@
 	}
 
 	switch (code) {
-	case MEDIA_BUS_FMT_UYVY8_2X8:
-	case MEDIA_BUS_FMT_VYUY8_2X8:
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
 		formats++;
 		if (xlate) {
 			xlate->host_fmt	= &isi_camera_formats[0];
@@ -1068,6 +1068,7 @@
 	.remove		= atmel_isi_remove,
 	.driver		= {
 		.name = "atmel_isi",
+		.owner = THIS_MODULE,
 		.of_match_table = of_match_ptr(atmel_isi_of_match),
 	},
 };
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index ce72bd2..2347612 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -211,7 +211,7 @@
 
 /* prp configuration for a client-host fmt pair */
 struct mx2_fmt_cfg {
-	u32	in_fmt;
+	enum v4l2_mbus_pixelcode	in_fmt;
 	u32				out_fmt;
 	struct mx2_prp_cfg		cfg;
 };
@@ -309,7 +309,7 @@
 		}
 	},
 	{
-		.in_fmt		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.in_fmt		= V4L2_MBUS_FMT_UYVY8_2X8,
 		.out_fmt	= V4L2_PIX_FMT_YUYV,
 		.cfg		= {
 			.channel	= 1,
@@ -323,7 +323,7 @@
 		}
 	},
 	{
-		.in_fmt		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.in_fmt		= V4L2_MBUS_FMT_YUYV8_2X8,
 		.out_fmt	= V4L2_PIX_FMT_YUYV,
 		.cfg		= {
 			.channel	= 1,
@@ -337,7 +337,7 @@
 		}
 	},
 	{
-		.in_fmt		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.in_fmt		= V4L2_MBUS_FMT_YUYV8_2X8,
 		.out_fmt	= V4L2_PIX_FMT_YUV420,
 		.cfg		= {
 			.channel	= 2,
@@ -351,7 +351,7 @@
 		}
 	},
 	{
-		.in_fmt		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.in_fmt		= V4L2_MBUS_FMT_UYVY8_2X8,
 		.out_fmt	= V4L2_PIX_FMT_YUV420,
 		.cfg		= {
 			.channel	= 2,
@@ -366,7 +366,9 @@
 	},
 };
 
-static struct mx2_fmt_cfg *mx27_emma_prp_get_format(u32 in_fmt, u32 out_fmt)
+static struct mx2_fmt_cfg *mx27_emma_prp_get_format(
+					enum v4l2_mbus_pixelcode in_fmt,
+					u32 out_fmt)
 {
 	int i;
 
@@ -943,7 +945,7 @@
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	const struct soc_mbus_pixelfmt *fmt;
 	struct device *dev = icd->parent;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	int ret, formats = 0;
 
 	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -957,8 +959,8 @@
 		return 0;
 	}
 
-	if (code == MEDIA_BUS_FMT_YUYV8_2X8 ||
-	    code == MEDIA_BUS_FMT_UYVY8_2X8) {
+	if (code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+	    code == V4L2_MBUS_FMT_UYVY8_2X8) {
 		formats++;
 		if (xlate) {
 			/*
@@ -966,7 +968,7 @@
 			 * soc_mediabus.c
 			 */
 			xlate->host_fmt =
-				soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_1_5X8);
+				soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_1_5X8);
 			xlate->code	= code;
 			dev_dbg(dev, "Providing host format %s for sensor code %d\n",
 			       xlate->host_fmt->name, code);
@@ -974,11 +976,11 @@
 		}
 	}
 
-	if (code == MEDIA_BUS_FMT_UYVY8_2X8) {
+	if (code == V4L2_MBUS_FMT_UYVY8_2X8) {
 		formats++;
 		if (xlate) {
 			xlate->host_fmt =
-				soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_2X8);
+				soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_2X8);
 			xlate->code	= code;
 			dev_dbg(dev, "Providing host format %s for sensor code %d\n",
 				xlate->host_fmt->name, code);
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index a60c3bb..7696a87 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -656,7 +656,7 @@
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->parent;
 	int formats = 0, ret;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	const struct soc_mbus_pixelfmt *fmt;
 
 	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -677,7 +677,7 @@
 		return 0;
 
 	switch (code) {
-	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
 		formats++;
 		if (xlate) {
 			xlate->host_fmt	= &mx3_camera_formats[0];
@@ -687,7 +687,7 @@
 				mx3_camera_formats[0].name, code);
 		}
 		break;
-	case MEDIA_BUS_FMT_Y10_1X10:
+	case V4L2_MBUS_FMT_Y10_1X10:
 		formats++;
 		if (xlate) {
 			xlate->host_fmt	= &mx3_camera_formats[1];
@@ -1253,6 +1253,7 @@
 static struct platform_driver mx3_camera_driver = {
 	.driver		= {
 		.name	= MX3_CAM_DRV_NAME,
+		.owner	= THIS_MODULE,
 	},
 	.probe		= mx3_camera_probe,
 	.remove		= mx3_camera_remove,
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c
index e6b9328..74ce8b6 100644
--- a/drivers/media/platform/soc_camera/omap1_camera.c
+++ b/drivers/media/platform/soc_camera/omap1_camera.c
@@ -140,7 +140,7 @@
 /* buffer for one video frame */
 struct omap1_cam_buf {
 	struct videobuf_buffer		vb;
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	int				inwork;
 	struct scatterlist		*sgbuf;
 	int				sgcount;
@@ -980,7 +980,7 @@
 /* Duplicate standard formats based on host capability of byte swapping */
 static const struct soc_mbus_lookup omap1_cam_formats[] = {
 {
-	.code = MEDIA_BUS_FMT_UYVY8_2X8,
+	.code = V4L2_MBUS_FMT_UYVY8_2X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_YUYV,
 		.name			= "YUYV",
@@ -990,7 +990,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_VYUY8_2X8,
+	.code = V4L2_MBUS_FMT_VYUY8_2X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_YVYU,
 		.name			= "YVYU",
@@ -1000,7 +1000,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_YUYV8_2X8,
+	.code = V4L2_MBUS_FMT_YUYV8_2X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_UYVY,
 		.name			= "UYVY",
@@ -1010,7 +1010,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_YVYU8_2X8,
+	.code = V4L2_MBUS_FMT_YVYU8_2X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_VYUY,
 		.name			= "VYUY",
@@ -1020,7 +1020,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+	.code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB555,
 		.name			= "RGB555",
@@ -1030,7 +1030,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+	.code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB555X,
 		.name			= "RGB555X",
@@ -1040,7 +1040,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+	.code = V4L2_MBUS_FMT_RGB565_2X8_BE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB565,
 		.name			= "RGB565",
@@ -1050,7 +1050,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+	.code = V4L2_MBUS_FMT_RGB565_2X8_LE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB565X,
 		.name			= "RGB565X",
@@ -1068,7 +1068,7 @@
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->parent;
 	int formats = 0, ret;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	const struct soc_mbus_pixelfmt *fmt;
 
 	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -1088,14 +1088,14 @@
 		return 0;
 
 	switch (code) {
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_YVYU8_2X8:
-	case MEDIA_BUS_FMT_UYVY8_2X8:
-	case MEDIA_BUS_FMT_VYUY8_2X8:
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
-	case MEDIA_BUS_FMT_RGB565_2X8_BE:
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		formats++;
 		if (xlate) {
 			xlate->host_fmt	= soc_mbus_find_fmtdesc(code,
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index 951226a..66178fc 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -187,7 +187,7 @@
 struct pxa_buffer {
 	/* common v4l buffer stuff -- must be first */
 	struct videobuf_buffer		vb;
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	/* our descriptor lists for Y, U and V channels */
 	struct pxa_cam_dma		dmas[3];
 	int				inwork;
@@ -1253,7 +1253,7 @@
 	struct device *dev = icd->parent;
 	int formats = 0, ret;
 	struct pxa_cam *cam;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	const struct soc_mbus_pixelfmt *fmt;
 
 	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -1283,7 +1283,7 @@
 	}
 
 	switch (code) {
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		formats++;
 		if (xlate) {
 			xlate->host_fmt	= &pxa_camera_formats[0];
@@ -1292,11 +1292,11 @@
 			dev_dbg(dev, "Providing format %s using code %d\n",
 				pxa_camera_formats[0].name, code);
 		}
-	case MEDIA_BUS_FMT_VYUY8_2X8:
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_YVYU8_2X8:
-	case MEDIA_BUS_FMT_RGB565_2X8_LE:
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
 		if (xlate)
 			dev_dbg(dev, "Providing format %s packed\n",
 				fmt->name);
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 0c1f556..20defcb 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -64,30 +64,6 @@
 #define VNDMR_REG	0x58	/* Video n Data Mode Register */
 #define VNDMR2_REG	0x5C	/* Video n Data Mode Register 2 */
 #define VNUVAOF_REG	0x60	/* Video n UV Address Offset Register */
-#define VNC1A_REG	0x80	/* Video n Coefficient Set C1A Register */
-#define VNC1B_REG	0x84	/* Video n Coefficient Set C1B Register */
-#define VNC1C_REG	0x88	/* Video n Coefficient Set C1C Register */
-#define VNC2A_REG	0x90	/* Video n Coefficient Set C2A Register */
-#define VNC2B_REG	0x94	/* Video n Coefficient Set C2B Register */
-#define VNC2C_REG	0x98	/* Video n Coefficient Set C2C Register */
-#define VNC3A_REG	0xA0	/* Video n Coefficient Set C3A Register */
-#define VNC3B_REG	0xA4	/* Video n Coefficient Set C3B Register */
-#define VNC3C_REG	0xA8	/* Video n Coefficient Set C3C Register */
-#define VNC4A_REG	0xB0	/* Video n Coefficient Set C4A Register */
-#define VNC4B_REG	0xB4	/* Video n Coefficient Set C4B Register */
-#define VNC4C_REG	0xB8	/* Video n Coefficient Set C4C Register */
-#define VNC5A_REG	0xC0	/* Video n Coefficient Set C5A Register */
-#define VNC5B_REG	0xC4	/* Video n Coefficient Set C5B Register */
-#define VNC5C_REG	0xC8	/* Video n Coefficient Set C5C Register */
-#define VNC6A_REG	0xD0	/* Video n Coefficient Set C6A Register */
-#define VNC6B_REG	0xD4	/* Video n Coefficient Set C6B Register */
-#define VNC6C_REG	0xD8	/* Video n Coefficient Set C6C Register */
-#define VNC7A_REG	0xE0	/* Video n Coefficient Set C7A Register */
-#define VNC7B_REG	0xE4	/* Video n Coefficient Set C7B Register */
-#define VNC7C_REG	0xE8	/* Video n Coefficient Set C7C Register */
-#define VNC8A_REG	0xF0	/* Video n Coefficient Set C8A Register */
-#define VNC8B_REG	0xF4	/* Video n Coefficient Set C8B Register */
-#define VNC8C_REG	0xF8	/* Video n Coefficient Set C8C Register */
 
 /* Register bit fields for R-Car VIN */
 /* Video n Main Control Register bits */
@@ -130,7 +106,6 @@
 #define VNDMR2_VPS		(1 << 30)
 #define VNDMR2_HPS		(1 << 29)
 #define VNDMR2_FTEV		(1 << 17)
-#define VNDMR2_VLV(n)		((n & 0xf) << 12)
 
 #define VIN_MAX_WIDTH		2048
 #define VIN_MAX_HEIGHT		2048
@@ -142,324 +117,6 @@
 	RCAR_E1,
 };
 
-struct vin_coeff {
-	unsigned short xs_value;
-	u32 coeff_set[24];
-};
-
-static const struct vin_coeff vin_coeff_set[] = {
-	{ 0x0000, {
-		0x00000000,		0x00000000,		0x00000000,
-		0x00000000,		0x00000000,		0x00000000,
-		0x00000000,		0x00000000,		0x00000000,
-		0x00000000,		0x00000000,		0x00000000,
-		0x00000000,		0x00000000,		0x00000000,
-		0x00000000,		0x00000000,		0x00000000,
-		0x00000000,		0x00000000,		0x00000000,
-		0x00000000,		0x00000000,		0x00000000 },
-	},
-	{ 0x1000, {
-		0x000fa400,		0x000fa400,		0x09625902,
-		0x000003f8,		0x00000403,		0x3de0d9f0,
-		0x001fffed,		0x00000804,		0x3cc1f9c3,
-		0x001003de,		0x00000c01,		0x3cb34d7f,
-		0x002003d2,		0x00000c00,		0x3d24a92d,
-		0x00200bca,		0x00000bff,		0x3df600d2,
-		0x002013cc,		0x000007ff,		0x3ed70c7e,
-		0x00100fde,		0x00000000,		0x3f87c036 },
-	},
-	{ 0x1200, {
-		0x002ffff1,		0x002ffff1,		0x02a0a9c8,
-		0x002003e7,		0x001ffffa,		0x000185bc,
-		0x002007dc,		0x000003ff,		0x3e52859c,
-		0x00200bd4,		0x00000002,		0x3d53996b,
-		0x00100fd0,		0x00000403,		0x3d04ad2d,
-		0x00000bd5,		0x00000403,		0x3d35ace7,
-		0x3ff003e4,		0x00000801,		0x3dc674a1,
-		0x3fffe800,		0x00000800,		0x3e76f461 },
-	},
-	{ 0x1400, {
-		0x00100be3,		0x00100be3,		0x04d1359a,
-		0x00000fdb,		0x002003ed,		0x0211fd93,
-		0x00000fd6,		0x002003f4,		0x0002d97b,
-		0x000007d6,		0x002ffffb,		0x3e93b956,
-		0x3ff003da,		0x001003ff,		0x3db49926,
-		0x3fffefe9,		0x00100001,		0x3d655cee,
-		0x3fffd400,		0x00000003,		0x3d65f4b6,
-		0x000fb421,		0x00000402,		0x3dc6547e },
-	},
-	{ 0x1600, {
-		0x00000bdd,		0x00000bdd,		0x06519578,
-		0x3ff007da,		0x00000be3,		0x03c24973,
-		0x3ff003d9,		0x00000be9,		0x01b30d5f,
-		0x3ffff7df,		0x001003f1,		0x0003c542,
-		0x000fdfec,		0x001003f7,		0x3ec4711d,
-		0x000fc400,		0x002ffffd,		0x3df504f1,
-		0x001fa81a,		0x002ffc00,		0x3d957cc2,
-		0x002f8c3c,		0x00100000,		0x3db5c891 },
-	},
-	{ 0x1800, {
-		0x3ff003dc,		0x3ff003dc,		0x0791e558,
-		0x000ff7dd,		0x3ff007de,		0x05328554,
-		0x000fe7e3,		0x3ff00be2,		0x03232546,
-		0x000fd7ee,		0x000007e9,		0x0143bd30,
-		0x001fb800,		0x000007ee,		0x00044511,
-		0x002fa015,		0x000007f4,		0x3ef4bcee,
-		0x002f8832,		0x001003f9,		0x3e4514c7,
-		0x001f7853,		0x001003fd,		0x3de54c9f },
-	},
-	{ 0x1a00, {
-		0x000fefe0,		0x000fefe0,		0x08721d3c,
-		0x001fdbe7,		0x000ffbde,		0x0652a139,
-		0x001fcbf0,		0x000003df,		0x0463292e,
-		0x002fb3ff,		0x3ff007e3,		0x0293a91d,
-		0x002f9c12,		0x3ff00be7,		0x01241905,
-		0x001f8c29,		0x000007ed,		0x3fe470eb,
-		0x000f7c46,		0x000007f2,		0x3f04b8ca,
-		0x3fef7865,		0x000007f6,		0x3e74e4a8 },
-	},
-	{ 0x1c00, {
-		0x001fd3e9,		0x001fd3e9,		0x08f23d26,
-		0x002fbff3,		0x001fe3e4,		0x0712ad23,
-		0x002fa800,		0x000ff3e0,		0x05631d1b,
-		0x001f9810,		0x000ffbe1,		0x03b3890d,
-		0x000f8c23,		0x000003e3,		0x0233e8fa,
-		0x3fef843b,		0x000003e7,		0x00f430e4,
-		0x3fbf8456,		0x3ff00bea,		0x00046cc8,
-		0x3f8f8c72,		0x3ff00bef,		0x3f3490ac },
-	},
-	{ 0x1e00, {
-		0x001fbbf4,		0x001fbbf4,		0x09425112,
-		0x001fa800,		0x002fc7ed,		0x0792b110,
-		0x000f980e,		0x001fdbe6,		0x0613110a,
-		0x3fff8c20,		0x001fe7e3,		0x04a368fd,
-		0x3fcf8c33,		0x000ff7e2,		0x0343b8ed,
-		0x3f9f8c4a,		0x000fffe3,		0x0203f8da,
-		0x3f5f9c61,		0x000003e6,		0x00e428c5,
-		0x3f1fb07b,		0x000003eb,		0x3fe440af },
-	},
-	{ 0x2000, {
-		0x000fa400,		0x000fa400,		0x09625902,
-		0x3fff980c,		0x001fb7f5,		0x0812b0ff,
-		0x3fdf901c,		0x001fc7ed,		0x06b2fcfa,
-		0x3faf902d,		0x001fd3e8,		0x055348f1,
-		0x3f7f983f,		0x001fe3e5,		0x04038ce3,
-		0x3f3fa454,		0x001fefe3,		0x02e3c8d1,
-		0x3f0fb86a,		0x001ff7e4,		0x01c3e8c0,
-		0x3ecfd880,		0x000fffe6,		0x00c404ac },
-	},
-	{ 0x2200, {
-		0x3fdf9c0b,		0x3fdf9c0b,		0x09725cf4,
-		0x3fbf9818,		0x3fffa400,		0x0842a8f1,
-		0x3f8f9827,		0x000fb3f7,		0x0702f0ec,
-		0x3f5fa037,		0x000fc3ef,		0x05d330e4,
-		0x3f2fac49,		0x001fcfea,		0x04a364d9,
-		0x3effc05c,		0x001fdbe7,		0x038394ca,
-		0x3ecfdc6f,		0x001fe7e6,		0x0273b0bb,
-		0x3ea00083,		0x001fefe6,		0x0183c0a9 },
-	},
-	{ 0x2400, {
-		0x3f9fa014,		0x3f9fa014,		0x098260e6,
-		0x3f7f9c23,		0x3fcf9c0a,		0x08629ce5,
-		0x3f4fa431,		0x3fefa400,		0x0742d8e1,
-		0x3f1fb440,		0x3fffb3f8,		0x062310d9,
-		0x3eefc850,		0x000fbbf2,		0x050340d0,
-		0x3ecfe062,		0x000fcbec,		0x041364c2,
-		0x3ea00073,		0x001fd3ea,		0x03037cb5,
-		0x3e902086,		0x001fdfe8,		0x022388a5 },
-	},
-	{ 0x2600, {
-		0x3f5fa81e,		0x3f5fa81e,		0x096258da,
-		0x3f3fac2b,		0x3f8fa412,		0x088290d8,
-		0x3f0fbc38,		0x3fafa408,		0x0772c8d5,
-		0x3eefcc47,		0x3fcfa800,		0x0672f4ce,
-		0x3ecfe456,		0x3fefaffa,		0x05531cc6,
-		0x3eb00066,		0x3fffbbf3,		0x047334bb,
-		0x3ea01c77,		0x000fc7ee,		0x039348ae,
-		0x3ea04486,		0x000fd3eb,		0x02b350a1 },
-	},
-	{ 0x2800, {
-		0x3f2fb426,		0x3f2fb426,		0x094250ce,
-		0x3f0fc032,		0x3f4fac1b,		0x086284cd,
-		0x3eefd040,		0x3f7fa811,		0x0782acc9,
-		0x3ecfe84c,		0x3f9fa807,		0x06a2d8c4,
-		0x3eb0005b,		0x3fbfac00,		0x05b2f4bc,
-		0x3eb0186a,		0x3fdfb3fa,		0x04c308b4,
-		0x3eb04077,		0x3fefbbf4,		0x03f31ca8,
-		0x3ec06884,		0x000fbff2,		0x03031c9e },
-	},
-	{ 0x2a00, {
-		0x3f0fc42d,		0x3f0fc42d,		0x090240c4,
-		0x3eefd439,		0x3f2fb822,		0x08526cc2,
-		0x3edfe845,		0x3f4fb018,		0x078294bf,
-		0x3ec00051,		0x3f6fac0f,		0x06b2b4bb,
-		0x3ec0185f,		0x3f8fac07,		0x05e2ccb4,
-		0x3ec0386b,		0x3fafac00,		0x0502e8ac,
-		0x3ed05c77,		0x3fcfb3fb,		0x0432f0a3,
-		0x3ef08482,		0x3fdfbbf6,		0x0372f898 },
-	},
-	{ 0x2c00, {
-		0x3eefdc31,		0x3eefdc31,		0x08e238b8,
-		0x3edfec3d,		0x3f0fc828,		0x082258b9,
-		0x3ed00049,		0x3f1fc01e,		0x077278b6,
-		0x3ed01455,		0x3f3fb815,		0x06c294b2,
-		0x3ed03460,		0x3f5fb40d,		0x0602acac,
-		0x3ef0506c,		0x3f7fb006,		0x0542c0a4,
-		0x3f107476,		0x3f9fb400,		0x0472c89d,
-		0x3f309c80,		0x3fbfb7fc,		0x03b2cc94 },
-	},
-	{ 0x2e00, {
-		0x3eefec37,		0x3eefec37,		0x088220b0,
-		0x3ee00041,		0x3effdc2d,		0x07f244ae,
-		0x3ee0144c,		0x3f0fd023,		0x07625cad,
-		0x3ef02c57,		0x3f1fc81a,		0x06c274a9,
-		0x3f004861,		0x3f3fbc13,		0x060288a6,
-		0x3f20686b,		0x3f5fb80c,		0x05529c9e,
-		0x3f408c74,		0x3f6fb805,		0x04b2ac96,
-		0x3f80ac7e,		0x3f8fb800,		0x0402ac8e },
-	},
-	{ 0x3000, {
-		0x3ef0003a,		0x3ef0003a,		0x084210a6,
-		0x3ef01045,		0x3effec32,		0x07b228a7,
-		0x3f00284e,		0x3f0fdc29,		0x073244a4,
-		0x3f104058,		0x3f0fd420,		0x06a258a2,
-		0x3f305c62,		0x3f2fc818,		0x0612689d,
-		0x3f508069,		0x3f3fc011,		0x05728496,
-		0x3f80a072,		0x3f4fc00a,		0x04d28c90,
-		0x3fc0c07b,		0x3f6fbc04,		0x04429088 },
-	},
-	{ 0x3200, {
-		0x3f00103e,		0x3f00103e,		0x07f1fc9e,
-		0x3f102447,		0x3f000035,		0x0782149d,
-		0x3f203c4f,		0x3f0ff02c,		0x07122c9c,
-		0x3f405458,		0x3f0fe424,		0x06924099,
-		0x3f607061,		0x3f1fd41d,		0x06024c97,
-		0x3f909068,		0x3f2fcc16,		0x05726490,
-		0x3fc0b070,		0x3f3fc80f,		0x04f26c8a,
-		0x0000d077,		0x3f4fc409,		0x04627484 },
-	},
-	{ 0x3400, {
-		0x3f202040,		0x3f202040,		0x07a1e898,
-		0x3f303449,		0x3f100c38,		0x0741fc98,
-		0x3f504c50,		0x3f10002f,		0x06e21495,
-		0x3f706459,		0x3f1ff028,		0x06722492,
-		0x3fa08060,		0x3f1fe421,		0x05f2348f,
-		0x3fd09c67,		0x3f1fdc19,		0x05824c89,
-		0x0000bc6e,		0x3f2fd014,		0x04f25086,
-		0x0040dc74,		0x3f3fcc0d,		0x04825c7f },
-	},
-	{ 0x3600, {
-		0x3f403042,		0x3f403042,		0x0761d890,
-		0x3f504848,		0x3f301c3b,		0x0701f090,
-		0x3f805c50,		0x3f200c33,		0x06a2008f,
-		0x3fa07458,		0x3f10002b,		0x06520c8d,
-		0x3fd0905e,		0x3f1ff424,		0x05e22089,
-		0x0000ac65,		0x3f1fe81d,		0x05823483,
-		0x0030cc6a,		0x3f2fdc18,		0x04f23c81,
-		0x0080e871,		0x3f2fd412,		0x0482407c },
-	},
-	{ 0x3800, {
-		0x3f604043,		0x3f604043,		0x0721c88a,
-		0x3f80544a,		0x3f502c3c,		0x06d1d88a,
-		0x3fb06851,		0x3f301c35,		0x0681e889,
-		0x3fd08456,		0x3f30082f,		0x0611fc88,
-		0x00009c5d,		0x3f200027,		0x05d20884,
-		0x0030b863,		0x3f2ff421,		0x05621880,
-		0x0070d468,		0x3f2fe81b,		0x0502247c,
-		0x00c0ec6f,		0x3f2fe015,		0x04a22877 },
-	},
-	{ 0x3a00, {
-		0x3f904c44,		0x3f904c44,		0x06e1b884,
-		0x3fb0604a,		0x3f70383e,		0x0691c885,
-		0x3fe07451,		0x3f502c36,		0x0661d483,
-		0x00009055,		0x3f401831,		0x0601ec81,
-		0x0030a85b,		0x3f300c2a,		0x05b1f480,
-		0x0070c061,		0x3f300024,		0x0562047a,
-		0x00b0d867,		0x3f3ff41e,		0x05020c77,
-		0x00f0f46b,		0x3f2fec19,		0x04a21474 },
-	},
-	{ 0x3c00, {
-		0x3fb05c43,		0x3fb05c43,		0x06c1b07e,
-		0x3fe06c4b,		0x3f902c3f,		0x0681c081,
-		0x0000844f,		0x3f703838,		0x0631cc7d,
-		0x00309855,		0x3f602433,		0x05d1d47e,
-		0x0060b459,		0x3f50142e,		0x0581e47b,
-		0x00a0c85f,		0x3f400828,		0x0531f078,
-		0x00e0e064,		0x3f300021,		0x0501fc73,
-		0x00b0fc6a,		0x3f3ff41d,		0x04a20873 },
-	},
-	{ 0x3e00, {
-		0x3fe06444,		0x3fe06444,		0x0681a07a,
-		0x00007849,		0x3fc0503f,		0x0641b07a,
-		0x0020904d,		0x3fa0403a,		0x05f1c07a,
-		0x0060a453,		0x3f803034,		0x05c1c878,
-		0x0090b858,		0x3f70202f,		0x0571d477,
-		0x00d0d05d,		0x3f501829,		0x0531e073,
-		0x0110e462,		0x3f500825,		0x04e1e471,
-		0x01510065,		0x3f40001f,		0x04a1f06d },
-	},
-	{ 0x4000, {
-		0x00007044,		0x00007044,		0x06519476,
-		0x00208448,		0x3fe05c3f,		0x0621a476,
-		0x0050984d,		0x3fc04c3a,		0x05e1b075,
-		0x0080ac52,		0x3fa03c35,		0x05a1b875,
-		0x00c0c056,		0x3f803030,		0x0561c473,
-		0x0100d45b,		0x3f70202b,		0x0521d46f,
-		0x0140e860,		0x3f601427,		0x04d1d46e,
-		0x01810064,		0x3f500822,		0x0491dc6b },
-	},
-	{ 0x5000, {
-		0x0110a442,		0x0110a442,		0x0551545e,
-		0x0140b045,		0x00e0983f,		0x0531585f,
-		0x0160c047,		0x00c08c3c,		0x0511645e,
-		0x0190cc4a,		0x00908039,		0x04f1685f,
-		0x01c0dc4c,		0x00707436,		0x04d1705e,
-		0x0200e850,		0x00506833,		0x04b1785b,
-		0x0230f453,		0x00305c30,		0x0491805a,
-		0x02710056,		0x0010542d,		0x04718059 },
-	},
-	{ 0x6000, {
-		0x01c0bc40,		0x01c0bc40,		0x04c13052,
-		0x01e0c841,		0x01a0b43d,		0x04c13851,
-		0x0210cc44,		0x0180a83c,		0x04a13453,
-		0x0230d845,		0x0160a03a,		0x04913c52,
-		0x0260e047,		0x01409838,		0x04714052,
-		0x0280ec49,		0x01208c37,		0x04514c50,
-		0x02b0f44b,		0x01008435,		0x04414c50,
-		0x02d1004c,		0x00e07c33,		0x0431544f },
-	},
-	{ 0x7000, {
-		0x0230c83e,		0x0230c83e,		0x04711c4c,
-		0x0250d03f,		0x0210c43c,		0x0471204b,
-		0x0270d840,		0x0200b83c,		0x0451244b,
-		0x0290dc42,		0x01e0b43a,		0x0441244c,
-		0x02b0e443,		0x01c0b038,		0x0441284b,
-		0x02d0ec44,		0x01b0a438,		0x0421304a,
-		0x02f0f445,		0x0190a036,		0x04213449,
-		0x0310f847,		0x01709c34,		0x04213848 },
-	},
-	{ 0x8000, {
-		0x0280d03d,		0x0280d03d,		0x04310c48,
-		0x02a0d43e,		0x0270c83c,		0x04311047,
-		0x02b0dc3e,		0x0250c83a,		0x04311447,
-		0x02d0e040,		0x0240c03a,		0x04211446,
-		0x02e0e840,		0x0220bc39,		0x04111847,
-		0x0300e842,		0x0210b438,		0x04012445,
-		0x0310f043,		0x0200b037,		0x04012045,
-		0x0330f444,		0x01e0ac36,		0x03f12445 },
-	},
-	{ 0xefff, {
-		0x0340dc3a,		0x0340dc3a,		0x03b0ec40,
-		0x0340e03a,		0x0330e039,		0x03c0f03e,
-		0x0350e03b,		0x0330dc39,		0x03c0ec3e,
-		0x0350e43a,		0x0320dc38,		0x03c0f43e,
-		0x0360e43b,		0x0320d839,		0x03b0f03e,
-		0x0360e83b,		0x0310d838,		0x03c0fc3b,
-		0x0370e83b,		0x0310d439,		0x03a0f83d,
-		0x0370e83c,		0x0300d438,		0x03b0fc3c },
-	}
-};
-
 enum rcar_vin_state {
 	STOPPED = 0,
 	RUNNING,
@@ -504,9 +161,6 @@
 	/* Client output, as seen by the VIN */
 	unsigned int			width;
 	unsigned int			height;
-	/* User window from S_FMT */
-	unsigned int out_width;
-	unsigned int out_height;
 	/*
 	 * User window from S_CROP / G_CROP, produced by client cropping and
 	 * scaling, VIN scaling and VIN cropping, mapped back onto the client
@@ -618,16 +272,16 @@
 
 	/* input interface */
 	switch (icd->current_fmt->code) {
-	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case V4L2_MBUS_FMT_YUYV8_1X16:
 		/* BT.601/BT.1358 16bit YCbCr422 */
 		vnmc |= VNMC_INF_YUV16;
 		break;
-	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 		/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
 		vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
 			VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
 		break;
-	case MEDIA_BUS_FMT_YUYV10_2X10:
+	case V4L2_MBUS_FMT_YUYV10_2X10:
 		/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
 		vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
 			VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
@@ -678,7 +332,7 @@
 		vnmc |= VNMC_BPS;
 
 	/* progressive or interlaced mode */
-	interrupts = progressive ? VNIE_FIE : VNIE_EFE;
+	interrupts = progressive ? VNIE_FIE | VNIE_EFE : VNIE_EFE;
 
 	/* ack interrupts */
 	iowrite32(interrupts, priv->base + VNINTS_REG);
@@ -1013,60 +667,6 @@
 	/* VIN does not have "mclk" */
 }
 
-static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
-{
-	int i;
-	const struct vin_coeff *p_prev_set = NULL;
-	const struct vin_coeff *p_set = NULL;
-
-	/* Look for suitable coefficient values */
-	for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
-		p_prev_set = p_set;
-		p_set = &vin_coeff_set[i];
-
-		if (xs < p_set->xs_value)
-			break;
-	}
-
-	/* Use previous value if its XS value is closer */
-	if (p_prev_set && p_set &&
-	    xs - p_prev_set->xs_value < p_set->xs_value - xs)
-		p_set = p_prev_set;
-
-	/* Set coefficient registers */
-	iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG);
-	iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG);
-	iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG);
-
-	iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG);
-	iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG);
-	iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG);
-
-	iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG);
-	iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG);
-	iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG);
-
-	iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG);
-	iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG);
-	iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG);
-
-	iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG);
-	iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG);
-	iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG);
-
-	iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG);
-	iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG);
-	iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG);
-
-	iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG);
-	iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG);
-	iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG);
-
-	iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG);
-	iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG);
-	iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG);
-}
-
 /* rect is guaranteed to not exceed the scaled camera rectangle */
 static int rcar_vin_set_rect(struct soc_camera_device *icd)
 {
@@ -1076,7 +676,6 @@
 	unsigned int left_offset, top_offset;
 	unsigned char dsize = 0;
 	struct v4l2_rect *cam_subrect = &cam->subrect;
-	u32 value;
 
 	dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
 		icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
@@ -1096,64 +695,40 @@
 
 	/* Set Start/End Pixel/Line Pre-Clip */
 	iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
-	iowrite32((left_offset + cam_subrect->width - 1) << dsize,
+	iowrite32((left_offset + cam->width - 1) << dsize,
 		  priv->base + VNEPPRC_REG);
 	switch (priv->field) {
 	case V4L2_FIELD_INTERLACED:
 	case V4L2_FIELD_INTERLACED_TB:
 	case V4L2_FIELD_INTERLACED_BT:
 		iowrite32(top_offset / 2, priv->base + VNSLPRC_REG);
-		iowrite32((top_offset + cam_subrect->height) / 2 - 1,
+		iowrite32((top_offset + cam->height) / 2 - 1,
 			  priv->base + VNELPRC_REG);
 		break;
 	default:
 		iowrite32(top_offset, priv->base + VNSLPRC_REG);
-		iowrite32(top_offset + cam_subrect->height - 1,
+		iowrite32(top_offset + cam->height - 1,
 			  priv->base + VNELPRC_REG);
 		break;
 	}
 
-	/* Set scaling coefficient */
-	value = 0;
-	if (cam_subrect->height != cam->out_height)
-		value = (4096 * cam_subrect->height) / cam->out_height;
-	dev_dbg(icd->parent, "YS Value: %x\n", value);
-	iowrite32(value, priv->base + VNYS_REG);
-
-	value = 0;
-	if (cam_subrect->width != cam->out_width)
-		value = (4096 * cam_subrect->width) / cam->out_width;
-
-	/* Horizontal upscaling is up to double size */
-	if (0 < value && value < 2048)
-		value = 2048;
-
-	dev_dbg(icd->parent, "XS Value: %x\n", value);
-	iowrite32(value, priv->base + VNXS_REG);
-
-	/* Horizontal upscaling is carried out by scaling down from double size */
-	if (value < 4096)
-		value *= 2;
-
-	set_coeff(priv, value);
-
 	/* Set Start/End Pixel/Line Post-Clip */
 	iowrite32(0, priv->base + VNSPPOC_REG);
 	iowrite32(0, priv->base + VNSLPOC_REG);
-	iowrite32((cam->out_width - 1) << dsize, priv->base + VNEPPOC_REG);
+	iowrite32((cam_subrect->width - 1) << dsize, priv->base + VNEPPOC_REG);
 	switch (priv->field) {
 	case V4L2_FIELD_INTERLACED:
 	case V4L2_FIELD_INTERLACED_TB:
 	case V4L2_FIELD_INTERLACED_BT:
-		iowrite32(cam->out_height / 2 - 1,
+		iowrite32(cam_subrect->height / 2 - 1,
 			  priv->base + VNELPOC_REG);
 		break;
 	default:
-		iowrite32(cam->out_height - 1, priv->base + VNELPOC_REG);
+		iowrite32(cam_subrect->height - 1, priv->base + VNELPOC_REG);
 		break;
 	}
 
-	iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG);
+	iowrite32(ALIGN(cam->width, 0x10), priv->base + VNIS_REG);
 
 	return 0;
 }
@@ -1244,7 +819,7 @@
 	if (ret < 0 && ret != -ENOIOCTLCMD)
 		return ret;
 
-	val = VNDMR2_FTEV | VNDMR2_VLV(1);
+	val = priv->field == V4L2_FIELD_NONE ? VNDMR2_FTEV : 0;
 	if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
 		val |= VNDMR2_VPS;
 	if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
@@ -1305,14 +880,6 @@
 		.layout			= SOC_MBUS_LAYOUT_PLANAR_Y_C,
 	},
 	{
-		.fourcc			= V4L2_PIX_FMT_YUYV,
-		.name			= "YUYV",
-		.bits_per_sample	= 16,
-		.packing		= SOC_MBUS_PACKING_NONE,
-		.order			= SOC_MBUS_ORDER_LE,
-		.layout			= SOC_MBUS_LAYOUT_PACKED,
-	},
-	{
 		.fourcc			= V4L2_PIX_FMT_UYVY,
 		.name			= "UYVY",
 		.bits_per_sample	= 16,
@@ -1354,7 +921,7 @@
 	int ret, k, n;
 	int formats = 0;
 	struct rcar_vin_cam *cam;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	const struct soc_mbus_pixelfmt *fmt;
 
 	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -1432,8 +999,6 @@
 		cam->subrect = rect;
 		cam->width = mf.width;
 		cam->height = mf.height;
-		cam->out_width	= mf.width;
-		cam->out_height	= mf.height;
 
 		icd->host_priv = cam;
 	} else {
@@ -1445,9 +1010,9 @@
 		cam->extra_fmt = NULL;
 
 	switch (code) {
-	case MEDIA_BUS_FMT_YUYV8_1X16:
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_YUYV10_2X10:
+	case V4L2_MBUS_FMT_YUYV8_1X16:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YUYV10_2X10:
 		if (cam->extra_fmt)
 			break;
 
@@ -1694,9 +1259,6 @@
 	dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
 		vin_sub_width, pix->width, vin_sub_height, pix->height);
 
-	cam->out_width = pix->width;
-	cam->out_height = pix->height;
-
 	icd->current_fmt = xlate;
 
 	priv->field = field;
@@ -1748,12 +1310,8 @@
 	if (ret < 0)
 		return ret;
 
-	/* Adjust only if VIN cannot scale */
-	if (pix->width > mf.width * 2)
-		pix->width = mf.width * 2;
-	if (pix->height > mf.height * 3)
-		pix->height = mf.height * 3;
-
+	pix->width = mf.width;
+	pix->height = mf.height;
 	pix->field = mf.field;
 	pix->colorspace = mf.colorspace;
 
@@ -1837,8 +1395,6 @@
 
 #ifdef CONFIG_OF
 static struct of_device_id rcar_vin_of_table[] = {
-	{ .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
-	{ .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
 	{ .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
 	{ .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
 	{ .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
@@ -1987,6 +1543,7 @@
 	.remove		= rcar_vin_remove,
 	.driver		= {
 		.name		= DRV_NAME,
+		.owner		= THIS_MODULE,
 		.of_match_table	= of_match_ptr(rcar_vin_of_table),
 	},
 	.id_table	= rcar_vin_id_table,
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 8b27b3e..20ad4a5 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -149,7 +149,7 @@
 	/* Camera cropping rectangle */
 	struct v4l2_rect rect;
 	const struct soc_mbus_pixelfmt *extra_fmt;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 };
 
 static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb)
@@ -861,16 +861,16 @@
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
 		switch (cam->code) {
-		case MEDIA_BUS_FMT_UYVY8_2X8:
+		case V4L2_MBUS_FMT_UYVY8_2X8:
 			value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */
 			break;
-		case MEDIA_BUS_FMT_VYUY8_2X8:
+		case V4L2_MBUS_FMT_VYUY8_2X8:
 			value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */
 			break;
-		case MEDIA_BUS_FMT_YUYV8_2X8:
+		case V4L2_MBUS_FMT_YUYV8_2X8:
 			value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */
 			break;
-		case MEDIA_BUS_FMT_YVYU8_2X8:
+		case V4L2_MBUS_FMT_YVYU8_2X8:
 			value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */
 			break;
 		default:
@@ -1048,7 +1048,7 @@
 	int ret, k, n;
 	int formats = 0;
 	struct sh_mobile_ceu_cam *cam;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	const struct soc_mbus_pixelfmt *fmt;
 
 	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -1141,10 +1141,10 @@
 		cam->extra_fmt = NULL;
 
 	switch (code) {
-	case MEDIA_BUS_FMT_UYVY8_2X8:
-	case MEDIA_BUS_FMT_VYUY8_2X8:
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
 		if (cam->extra_fmt)
 			break;
 
@@ -2009,6 +2009,7 @@
 static struct platform_driver sh_mobile_ceu_driver = {
 	.driver		= {
 		.name	= "sh_mobile_ceu",
+		.owner	= THIS_MODULE,
 		.pm	= &sh_mobile_ceu_dev_pm_ops,
 		.of_match_table = sh_mobile_ceu_of_match,
 	},
diff --git a/drivers/media/platform/soc_camera/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c
index c4e7aa0..05dd21a 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_csi2.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c
@@ -59,28 +59,28 @@
 	switch (pdata->type) {
 	case SH_CSI2C:
 		switch (mf->code) {
-		case MEDIA_BUS_FMT_UYVY8_2X8:		/* YUV422 */
-		case MEDIA_BUS_FMT_YUYV8_1_5X8:		/* YUV420 */
-		case MEDIA_BUS_FMT_Y8_1X8:		/* RAW8 */
-		case MEDIA_BUS_FMT_SBGGR8_1X8:
-		case MEDIA_BUS_FMT_SGRBG8_1X8:
+		case V4L2_MBUS_FMT_UYVY8_2X8:		/* YUV422 */
+		case V4L2_MBUS_FMT_YUYV8_1_5X8:		/* YUV420 */
+		case V4L2_MBUS_FMT_Y8_1X8:		/* RAW8 */
+		case V4L2_MBUS_FMT_SBGGR8_1X8:
+		case V4L2_MBUS_FMT_SGRBG8_1X8:
 			break;
 		default:
 			/* All MIPI CSI-2 devices must support one of primary formats */
-			mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
+			mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
 		}
 		break;
 	case SH_CSI2I:
 		switch (mf->code) {
-		case MEDIA_BUS_FMT_Y8_1X8:		/* RAW8 */
-		case MEDIA_BUS_FMT_SBGGR8_1X8:
-		case MEDIA_BUS_FMT_SGRBG8_1X8:
-		case MEDIA_BUS_FMT_SBGGR10_1X10:	/* RAW10 */
-		case MEDIA_BUS_FMT_SBGGR12_1X12:	/* RAW12 */
+		case V4L2_MBUS_FMT_Y8_1X8:		/* RAW8 */
+		case V4L2_MBUS_FMT_SBGGR8_1X8:
+		case V4L2_MBUS_FMT_SGRBG8_1X8:
+		case V4L2_MBUS_FMT_SBGGR10_1X10:	/* RAW10 */
+		case V4L2_MBUS_FMT_SBGGR12_1X12:	/* RAW12 */
 			break;
 		default:
 			/* All MIPI CSI-2 devices must support one of primary formats */
-			mf->code = MEDIA_BUS_FMT_SBGGR8_1X8;
+			mf->code = V4L2_MBUS_FMT_SBGGR8_1X8;
 		}
 		break;
 	}
@@ -104,21 +104,21 @@
 		return -EINVAL;
 
 	switch (mf->code) {
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
 		tmp |= 0x1e;	/* YUV422 8 bit */
 		break;
-	case MEDIA_BUS_FMT_YUYV8_1_5X8:
+	case V4L2_MBUS_FMT_YUYV8_1_5X8:
 		tmp |= 0x18;	/* YUV420 8 bit */
 		break;
-	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
 		tmp |= 0x21;	/* RGB555 */
 		break;
-	case MEDIA_BUS_FMT_RGB565_2X8_BE:
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
 		tmp |= 0x22;	/* RGB565 */
 		break;
-	case MEDIA_BUS_FMT_Y8_1X8:
-	case MEDIA_BUS_FMT_SBGGR8_1X8:
-	case MEDIA_BUS_FMT_SGRBG8_1X8:
+	case V4L2_MBUS_FMT_Y8_1X8:
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
+	case V4L2_MBUS_FMT_SGRBG8_1X8:
 		tmp |= 0x2a;	/* RAW8 */
 		break;
 	default:
@@ -391,6 +391,7 @@
 	.probe	= sh_csi2_probe,
 	.driver	= {
 		.name	= "sh-mobile-csi2",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index b3db51c..8e61b97 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -460,7 +460,7 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	unsigned int i, fmts = 0, raw_fmts = 0;
 	int ret;
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 
 	while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code))
 		raw_fmts++;
@@ -2236,6 +2236,7 @@
 	.remove  = soc_camera_pdrv_remove,
 	.driver  = {
 		.name	= "soc-camera-pdrv",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c
index f535910..ceaddfb 100644
--- a/drivers/media/platform/soc_camera/soc_camera_platform.c
+++ b/drivers/media/platform/soc_camera/soc_camera_platform.c
@@ -62,7 +62,7 @@
 };
 
 static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
-					u32 *code)
+					enum v4l2_mbus_pixelcode *code)
 {
 	struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
 
@@ -180,6 +180,7 @@
 static struct platform_driver soc_camera_platform_driver = {
 	.driver		= {
 		.name	= "soc_camera_platform",
+		.owner	= THIS_MODULE,
 	},
 	.probe		= soc_camera_platform_probe,
 	.remove		= soc_camera_platform_remove,
diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c
index 1dbcd42..dc02dec 100644
--- a/drivers/media/platform/soc_camera/soc_mediabus.c
+++ b/drivers/media/platform/soc_camera/soc_mediabus.c
@@ -17,7 +17,7 @@
 
 static const struct soc_mbus_lookup mbus_fmt[] = {
 {
-	.code = MEDIA_BUS_FMT_YUYV8_2X8,
+	.code = V4L2_MBUS_FMT_YUYV8_2X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_YUYV,
 		.name			= "YUYV",
@@ -27,7 +27,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_YVYU8_2X8,
+	.code = V4L2_MBUS_FMT_YVYU8_2X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_YVYU,
 		.name			= "YVYU",
@@ -37,7 +37,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_UYVY8_2X8,
+	.code = V4L2_MBUS_FMT_UYVY8_2X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_UYVY,
 		.name			= "UYVY",
@@ -47,7 +47,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_VYUY8_2X8,
+	.code = V4L2_MBUS_FMT_VYUY8_2X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_VYUY,
 		.name			= "VYUY",
@@ -57,7 +57,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+	.code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB555,
 		.name			= "RGB555",
@@ -67,7 +67,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+	.code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB555X,
 		.name			= "RGB555X",
@@ -77,7 +77,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+	.code = V4L2_MBUS_FMT_RGB565_2X8_LE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB565,
 		.name			= "RGB565",
@@ -87,7 +87,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+	.code = V4L2_MBUS_FMT_RGB565_2X8_BE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB565X,
 		.name			= "RGB565X",
@@ -97,7 +97,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB666_1X18,
+	.code = V4L2_MBUS_FMT_RGB666_1X18,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB32,
 		.name			= "RGB666/32bpp",
@@ -106,7 +106,7 @@
 		.order			= SOC_MBUS_ORDER_LE,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB888_1X24,
+	.code = V4L2_MBUS_FMT_RGB888_1X24,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB32,
 		.name			= "RGB888/32bpp",
@@ -115,7 +115,7 @@
 		.order			= SOC_MBUS_ORDER_LE,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB888_2X12_BE,
+	.code = V4L2_MBUS_FMT_RGB888_2X12_BE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB32,
 		.name			= "RGB888/32bpp",
@@ -124,7 +124,7 @@
 		.order			= SOC_MBUS_ORDER_BE,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB888_2X12_LE,
+	.code = V4L2_MBUS_FMT_RGB888_2X12_LE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB32,
 		.name			= "RGB888/32bpp",
@@ -133,7 +133,7 @@
 		.order			= SOC_MBUS_ORDER_LE,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SBGGR8_1X8,
+	.code = V4L2_MBUS_FMT_SBGGR8_1X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SBGGR8,
 		.name			= "Bayer 8 BGGR",
@@ -143,7 +143,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SBGGR10_1X10,
+	.code = V4L2_MBUS_FMT_SBGGR10_1X10,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SBGGR10,
 		.name			= "Bayer 10 BGGR",
@@ -153,7 +153,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_Y8_1X8,
+	.code = V4L2_MBUS_FMT_Y8_1X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_GREY,
 		.name			= "Grey",
@@ -163,7 +163,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_Y10_1X10,
+	.code = V4L2_MBUS_FMT_Y10_1X10,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_Y10,
 		.name			= "Grey 10bit",
@@ -173,7 +173,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
+	.code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SBGGR10,
 		.name			= "Bayer 10 BGGR",
@@ -183,7 +183,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE,
+	.code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SBGGR10,
 		.name			= "Bayer 10 BGGR",
@@ -193,7 +193,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE,
+	.code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SBGGR10,
 		.name			= "Bayer 10 BGGR",
@@ -203,7 +203,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE,
+	.code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SBGGR10,
 		.name			= "Bayer 10 BGGR",
@@ -213,7 +213,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_JPEG_1X8,
+	.code = V4L2_MBUS_FMT_JPEG_1X8,
 	.fmt = {
 		.fourcc                 = V4L2_PIX_FMT_JPEG,
 		.name                   = "JPEG",
@@ -223,7 +223,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE,
+	.code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_RGB444,
 		.name			= "RGB444",
@@ -233,7 +233,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_YUYV8_1_5X8,
+	.code = V4L2_MBUS_FMT_YUYV8_1_5X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_YUV420,
 		.name			= "YUYV 4:2:0",
@@ -243,7 +243,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_YVYU8_1_5X8,
+	.code = V4L2_MBUS_FMT_YVYU8_1_5X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_YVU420,
 		.name			= "YVYU 4:2:0",
@@ -253,7 +253,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_UYVY8_1X16,
+	.code = V4L2_MBUS_FMT_UYVY8_1X16,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_UYVY,
 		.name			= "UYVY 16bit",
@@ -263,7 +263,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_VYUY8_1X16,
+	.code = V4L2_MBUS_FMT_VYUY8_1X16,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_VYUY,
 		.name			= "VYUY 16bit",
@@ -273,7 +273,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_YUYV8_1X16,
+	.code = V4L2_MBUS_FMT_YUYV8_1X16,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_YUYV,
 		.name			= "YUYV 16bit",
@@ -283,7 +283,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_YVYU8_1X16,
+	.code = V4L2_MBUS_FMT_YVYU8_1X16,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_YVYU,
 		.name			= "YVYU 16bit",
@@ -293,7 +293,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SGRBG8_1X8,
+	.code = V4L2_MBUS_FMT_SGRBG8_1X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SGRBG8,
 		.name			= "Bayer 8 GRBG",
@@ -303,7 +303,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
+	.code = V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SGRBG10DPCM8,
 		.name			= "Bayer 10 BGGR DPCM 8",
@@ -313,7 +313,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SGBRG10_1X10,
+	.code = V4L2_MBUS_FMT_SGBRG10_1X10,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SGBRG10,
 		.name			= "Bayer 10 GBRG",
@@ -323,7 +323,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SGRBG10_1X10,
+	.code = V4L2_MBUS_FMT_SGRBG10_1X10,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SGRBG10,
 		.name			= "Bayer 10 GRBG",
@@ -333,7 +333,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SRGGB10_1X10,
+	.code = V4L2_MBUS_FMT_SRGGB10_1X10,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SRGGB10,
 		.name			= "Bayer 10 RGGB",
@@ -343,7 +343,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SBGGR12_1X12,
+	.code = V4L2_MBUS_FMT_SBGGR12_1X12,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SBGGR12,
 		.name			= "Bayer 12 BGGR",
@@ -353,7 +353,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SGBRG12_1X12,
+	.code = V4L2_MBUS_FMT_SGBRG12_1X12,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SGBRG12,
 		.name			= "Bayer 12 GBRG",
@@ -363,7 +363,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SGRBG12_1X12,
+	.code = V4L2_MBUS_FMT_SGRBG12_1X12,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SGRBG12,
 		.name			= "Bayer 12 GRBG",
@@ -373,7 +373,7 @@
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
 }, {
-	.code = MEDIA_BUS_FMT_SRGGB12_1X12,
+	.code = V4L2_MBUS_FMT_SRGGB12_1X12,
 	.fmt = {
 		.fourcc			= V4L2_PIX_FMT_SRGGB12,
 		.name			= "Bayer 12 RGGB",
@@ -458,7 +458,7 @@
 EXPORT_SYMBOL(soc_mbus_image_size);
 
 const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
-	u32 code,
+	enum v4l2_mbus_pixelcode code,
 	const struct soc_mbus_lookup *lookup,
 	int n)
 {
@@ -473,7 +473,7 @@
 EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
 
 const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
-	u32 code)
+	enum v4l2_mbus_pixelcode code)
 {
 	return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
 }
diff --git a/drivers/media/platform/ti-vpe/csc.c b/drivers/media/platform/ti-vpe/csc.c
index bec6749..940df40 100644
--- a/drivers/media/platform/ti-vpe/csc.c
+++ b/drivers/media/platform/ti-vpe/csc.c
@@ -93,8 +93,12 @@
 {
 	struct device *dev = &csc->pdev->dev;
 
-#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, \
-	ioread32(csc->base + CSC_##r))
+	u32 read_reg(struct csc_data *csc, int offset)
+	{
+		return ioread32(csc->base + offset);
+	}
+
+#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(csc, CSC_##r))
 
 	DUMPREG(CSC00);
 	DUMPREG(CSC01);
@@ -185,7 +189,7 @@
 	csc->base = devm_ioremap_resource(&pdev->dev, csc->res);
 	if (IS_ERR(csc->base)) {
 		dev_err(&pdev->dev, "failed to ioremap\n");
-		return ERR_CAST(csc->base);
+		return csc->base;
 	}
 
 	return csc;
diff --git a/drivers/media/platform/ti-vpe/sc.c b/drivers/media/platform/ti-vpe/sc.c
index f82d1c7..6314171 100644
--- a/drivers/media/platform/ti-vpe/sc.c
+++ b/drivers/media/platform/ti-vpe/sc.c
@@ -24,8 +24,12 @@
 {
 	struct device *dev = &sc->pdev->dev;
 
-#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, \
-	ioread32(sc->base + CFG_##r))
+	u32 read_reg(struct sc_data *sc, int offset)
+	{
+		return ioread32(sc->base + offset);
+	}
+
+#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(sc, CFG_##r))
 
 	DUMPREG(SC0);
 	DUMPREG(SC1);
@@ -300,7 +304,7 @@
 	sc->base = devm_ioremap_resource(&pdev->dev, sc->res);
 	if (IS_ERR(sc->base)) {
 		dev_err(&pdev->dev, "failed to ioremap\n");
-		return ERR_CAST(sc->base);
+		return sc->base;
 	}
 
 	return sc;
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index d628d1a..9a081c2 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -2376,6 +2376,7 @@
 	.remove		= vpe_remove,
 	.driver		= {
 		.name	= VPE_MODULE_NAME,
+		.owner	= THIS_MODULE,
 		.of_match_table = vpe_of_match,
 	},
 };
diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c
index 5820e45..3cb2f35 100644
--- a/drivers/media/platform/timblogiw.c
+++ b/drivers/media/platform/timblogiw.c
@@ -857,6 +857,7 @@
 static struct platform_driver timblogiw_platform_driver = {
 	.driver = {
 		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
 	},
 	.probe		= timblogiw_probe,
 	.remove		= timblogiw_remove,
diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c
index 86989d8..ae6870c 100644
--- a/drivers/media/platform/via-camera.c
+++ b/drivers/media/platform/via-camera.c
@@ -101,7 +101,7 @@
 	 */
 	struct v4l2_pix_format sensor_format;
 	struct v4l2_pix_format user_format;
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 };
 
 /*
@@ -143,12 +143,12 @@
 	__u8 *desc;
 	__u32 pixelformat;
 	int bpp;   /* Bytes per pixel */
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 } via_formats[] = {
 	{
 		.desc		= "YUYV 4:2:2",
 		.pixelformat	= V4L2_PIX_FMT_YUYV,
-		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 		.bpp		= 2,
 	},
 	/* RGB444 and Bayer should be doable, but have never been
@@ -849,7 +849,7 @@
 	.sizeimage	= VGA_WIDTH * VGA_HEIGHT * 2,
 };
 
-static const u32 via_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
+static const enum v4l2_mbus_pixelcode via_def_mbus_code = V4L2_MBUS_FMT_YUYV8_2X8;
 
 static int viacam_enum_fmt_vid_cap(struct file *filp, void *priv,
 		struct v4l2_fmtdesc *fmt)
@@ -985,9 +985,9 @@
 {
 	strcpy(cap->driver, "via-camera");
 	strcpy(cap->card, "via-camera");
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+	cap->version = 1;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
 		V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
diff --git a/drivers/media/platform/vino.c b/drivers/media/platform/vino.c
new file mode 100644
index 0000000..91d44ea
--- /dev/null
+++ b/drivers/media/platform/vino.c
@@ -0,0 +1,4347 @@
+/*
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * Based on the previous version of the driver for 2.4 kernels by:
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *
+ * v4l2_device/v4l2_subdev conversion by:
+ * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this conversion is untested! Please contact the linux-media
+ * mailinglist if you can test this, together with the test results.
+ */
+
+/*
+ * TODO:
+ * - remove "mark pages reserved-hacks" from memory allocation code
+ *   and implement fault()
+ * - check decimation, calculating and reporting image size when
+ *   using decimation
+ * - implement read(), user mode buffers and overlay (?)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/time.h>
+#include <linux/kmod.h>
+
+#include <linux/i2c.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/mutex.h>
+
+#include <asm/paccess.h>
+#include <asm/io.h>
+#include <asm/sgi/ip22.h>
+#include <asm/sgi/mc.h>
+
+#include "vino.h"
+#include "saa7191.h"
+#include "indycam.h"
+
+/* Uncomment the following line to get lots and lots of (mostly useless)
+ * debug info.
+ * Note that the debug output also slows down the driver significantly */
+// #define VINO_DEBUG
+// #define VINO_DEBUG_INT
+
+#define VINO_MODULE_VERSION "0.0.7"
+
+MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
+MODULE_VERSION(VINO_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+#ifdef VINO_DEBUG
+#define dprintk(x...) printk("VINO: " x);
+#else
+#define dprintk(x...)
+#endif
+
+#define VINO_NO_CHANNEL			0
+#define VINO_CHANNEL_A			1
+#define VINO_CHANNEL_B			2
+
+#define VINO_PAL_WIDTH			768
+#define VINO_PAL_HEIGHT			576
+#define VINO_NTSC_WIDTH			640
+#define VINO_NTSC_HEIGHT		480
+
+#define VINO_MIN_WIDTH			32
+#define VINO_MIN_HEIGHT			32
+
+#define VINO_CLIPPING_START_ODD_D1	1
+#define VINO_CLIPPING_START_ODD_PAL	15
+#define VINO_CLIPPING_START_ODD_NTSC	12
+
+#define VINO_CLIPPING_START_EVEN_D1	2
+#define VINO_CLIPPING_START_EVEN_PAL	15
+#define VINO_CLIPPING_START_EVEN_NTSC	12
+
+#define VINO_INPUT_CHANNEL_COUNT	3
+
+/* the number is the index for vino_inputs */
+#define VINO_INPUT_NONE			-1
+#define VINO_INPUT_COMPOSITE		0
+#define VINO_INPUT_SVIDEO		1
+#define VINO_INPUT_D1			2
+
+#define VINO_PAGE_RATIO			(PAGE_SIZE / VINO_PAGE_SIZE)
+
+#define VINO_FIFO_THRESHOLD_DEFAULT	16
+
+#define VINO_FRAMEBUFFER_SIZE		((VINO_PAL_WIDTH \
+					  * VINO_PAL_HEIGHT * 4 \
+					  + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
+
+#define VINO_FRAMEBUFFER_COUNT_MAX	8
+
+#define VINO_FRAMEBUFFER_UNUSED		0
+#define VINO_FRAMEBUFFER_IN_USE		1
+#define VINO_FRAMEBUFFER_READY		2
+
+#define VINO_QUEUE_ERROR		-1
+#define VINO_QUEUE_MAGIC		0x20050125
+
+#define VINO_MEMORY_NONE		0
+#define VINO_MEMORY_MMAP		1
+#define VINO_MEMORY_USERPTR		2
+
+#define VINO_DUMMY_DESC_COUNT		4
+#define VINO_DESC_FETCH_DELAY		5	/* microseconds */
+
+#define VINO_MAX_FRAME_SKIP_COUNT	128
+
+/* the number is the index for vino_data_formats */
+#define VINO_DATA_FMT_NONE		-1
+#define VINO_DATA_FMT_GREY		0
+#define VINO_DATA_FMT_RGB332		1
+#define VINO_DATA_FMT_RGB32		2
+#define VINO_DATA_FMT_YUV		3
+
+#define VINO_DATA_FMT_COUNT		4
+
+/* the number is the index for vino_data_norms */
+#define VINO_DATA_NORM_NONE		-1
+#define VINO_DATA_NORM_NTSC		0
+#define VINO_DATA_NORM_PAL		1
+#define VINO_DATA_NORM_SECAM		2
+#define VINO_DATA_NORM_D1		3
+
+#define VINO_DATA_NORM_COUNT		4
+
+/* I2C controller flags */
+#define SGI_I2C_FORCE_IDLE		(0 << 0)
+#define SGI_I2C_NOT_IDLE		(1 << 0)
+#define SGI_I2C_WRITE			(0 << 1)
+#define SGI_I2C_READ			(1 << 1)
+#define SGI_I2C_RELEASE_BUS		(0 << 2)
+#define SGI_I2C_HOLD_BUS		(1 << 2)
+#define SGI_I2C_XFER_DONE		(0 << 4)
+#define SGI_I2C_XFER_BUSY		(1 << 4)
+#define SGI_I2C_ACK			(0 << 5)
+#define SGI_I2C_NACK			(1 << 5)
+#define SGI_I2C_BUS_OK			(0 << 7)
+#define SGI_I2C_BUS_ERR			(1 << 7)
+
+/* Internal data structure definitions */
+
+struct vino_input {
+	char *name;
+	v4l2_std_id std;
+};
+
+struct vino_clipping {
+	unsigned int left, right, top, bottom;
+};
+
+struct vino_data_format {
+	/* the description */
+	char *description;
+	/* bytes per pixel */
+	unsigned int bpp;
+	/* V4L2 fourcc code */
+	__u32 pixelformat;
+	/* V4L2 colorspace (duh!) */
+	enum v4l2_colorspace colorspace;
+};
+
+struct vino_data_norm {
+	char *description;
+	unsigned int width, height;
+	struct vino_clipping odd;
+	struct vino_clipping even;
+
+	v4l2_std_id std;
+	unsigned int fps_min, fps_max;
+	__u32 framelines;
+};
+
+struct vino_descriptor_table {
+	/* the number of PAGE_SIZE sized pages in the buffer */
+	unsigned int page_count;
+	/* virtual (kmalloc'd) pointers to the actual data
+	 * (in PAGE_SIZE chunks, used with mmap streaming) */
+	unsigned long *virtual;
+
+	/* cpu address for the VINO descriptor table
+	 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+	unsigned long *dma_cpu;
+	/* dma address for the VINO descriptor table
+	 * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+	dma_addr_t dma;
+};
+
+struct vino_framebuffer {
+	/* identifier nubmer */
+	unsigned int id;
+	/* the length of the whole buffer */
+	unsigned int size;
+	/* the length of actual data in buffer */
+	unsigned int data_size;
+	/* the data format */
+	unsigned int data_format;
+	/* the state of buffer data */
+	unsigned int state;
+	/* is the buffer mapped in user space? */
+	unsigned int map_count;
+	/* memory offset for mmap() */
+	unsigned int offset;
+	/* frame counter */
+	unsigned int frame_counter;
+	/* timestamp (written when image capture finishes) */
+	struct timeval timestamp;
+
+	struct vino_descriptor_table desc_table;
+
+	spinlock_t state_lock;
+};
+
+struct vino_framebuffer_fifo {
+	unsigned int length;
+
+	unsigned int used;
+	unsigned int head;
+	unsigned int tail;
+
+	unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX];
+};
+
+struct vino_framebuffer_queue {
+	unsigned int magic;
+
+	/* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
+	unsigned int type;
+	unsigned int length;
+
+	/* data field of in and out contain index numbers for buffer */
+	struct vino_framebuffer_fifo in;
+	struct vino_framebuffer_fifo out;
+
+	struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX];
+
+	spinlock_t queue_lock;
+	struct mutex queue_mutex;
+	wait_queue_head_t frame_wait_queue;
+};
+
+struct vino_interrupt_data {
+	struct timeval timestamp;
+	unsigned int frame_counter;
+	unsigned int skip_count;
+	unsigned int skip;
+};
+
+struct vino_channel_settings {
+	unsigned int channel;
+
+	int input;
+	unsigned int data_format;
+	unsigned int data_norm;
+	struct vino_clipping clipping;
+	unsigned int decimation;
+	unsigned int line_size;
+	unsigned int alpha;
+	unsigned int fps;
+	unsigned int framert_reg;
+
+	unsigned int fifo_threshold;
+
+	struct vino_framebuffer_queue fb_queue;
+
+	/* number of the current field */
+	unsigned int field;
+
+	/* read in progress */
+	int reading;
+	/* streaming is active */
+	int streaming;
+	/* the driver is currently processing the queue */
+	int capturing;
+
+	struct mutex mutex;
+	spinlock_t capture_lock;
+
+	unsigned int users;
+
+	struct vino_interrupt_data int_data;
+
+	/* V4L support */
+	struct video_device *vdev;
+};
+
+struct vino_settings {
+	struct v4l2_device v4l2_dev;
+	struct vino_channel_settings a;
+	struct vino_channel_settings b;
+
+	/* the channel which owns this client:
+	 * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
+	unsigned int decoder_owner;
+	struct v4l2_subdev *decoder;
+	unsigned int camera_owner;
+	struct v4l2_subdev *camera;
+
+	/* a lock for vino register access */
+	spinlock_t vino_lock;
+	/* a lock for channel input changes */
+	spinlock_t input_lock;
+
+	unsigned long dummy_page;
+	struct vino_descriptor_table dummy_desc_table;
+};
+
+/* Module parameters */
+
+/*
+ * Using vino_pixel_conversion the ABGR32-format pixels supplied
+ * by the VINO chip can be converted to more common formats
+ * like RGBA32 (or probably RGB24 in the future). This way we
+ * can give out data that can be specified correctly with
+ * the V4L2-definitions.
+ *
+ * The pixel format is specified as RGBA32 when no conversion
+ * is used.
+ *
+ * Note that this only affects the 32-bit bit depth.
+ *
+ * Use non-zero value to enable conversion.
+ */
+static int vino_pixel_conversion;
+
+module_param_named(pixelconv, vino_pixel_conversion, int, 0);
+
+MODULE_PARM_DESC(pixelconv,
+		 "enable pixel conversion (non-zero value enables)");
+
+/* Internal data structures */
+
+static struct sgi_vino *vino;
+
+static struct vino_settings *vino_drvdata;
+
+#define camera_call(o, f, args...) \
+	v4l2_subdev_call(vino_drvdata->camera, o, f, ##args)
+#define decoder_call(o, f, args...) \
+	v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args)
+
+static const char *vino_driver_name = "vino";
+static const char *vino_driver_description = "SGI VINO";
+static const char *vino_bus_name = "GIO64 bus";
+static const char *vino_vdev_name_a = "SGI VINO Channel A";
+static const char *vino_vdev_name_b = "SGI VINO Channel B";
+
+static void vino_capture_tasklet(unsigned long channel);
+
+DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A);
+DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B);
+
+static const struct vino_input vino_inputs[] = {
+	{
+		.name		= "Composite",
+		.std		= V4L2_STD_NTSC | V4L2_STD_PAL
+		| V4L2_STD_SECAM,
+	}, {
+		.name		= "S-Video",
+		.std		= V4L2_STD_NTSC | V4L2_STD_PAL
+		| V4L2_STD_SECAM,
+	}, {
+		.name		= "D1/IndyCam",
+		.std		= V4L2_STD_NTSC,
+	}
+};
+
+static const struct vino_data_format vino_data_formats[] = {
+	{
+		.description	= "8-bit greyscale",
+		.bpp		= 1,
+		.pixelformat	= V4L2_PIX_FMT_GREY,
+		.colorspace	= V4L2_COLORSPACE_SMPTE170M,
+	}, {
+		.description	= "8-bit dithered RGB 3-3-2",
+		.bpp		= 1,
+		.pixelformat	= V4L2_PIX_FMT_RGB332,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+	}, {
+		.description	= "32-bit RGB",
+		.bpp		= 4,
+		.pixelformat	= V4L2_PIX_FMT_RGB32,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+	}, {
+		.description	= "YUV 4:2:2",
+		.bpp		= 2,
+		.pixelformat	= V4L2_PIX_FMT_YUYV, // XXX: swapped?
+		.colorspace	= V4L2_COLORSPACE_SMPTE170M,
+	}
+};
+
+static const struct vino_data_norm vino_data_norms[] = {
+	{
+		.description	= "NTSC",
+		.std		= V4L2_STD_NTSC,
+		.fps_min	= 6,
+		.fps_max	= 30,
+		.framelines	= 525,
+		.width		= VINO_NTSC_WIDTH,
+		.height		= VINO_NTSC_HEIGHT,
+		.odd		= {
+			.top	= VINO_CLIPPING_START_ODD_NTSC,
+			.left	= 0,
+			.bottom	= VINO_CLIPPING_START_ODD_NTSC
+			+ VINO_NTSC_HEIGHT / 2 - 1,
+			.right	= VINO_NTSC_WIDTH,
+		},
+		.even		= {
+			.top	= VINO_CLIPPING_START_EVEN_NTSC,
+			.left	= 0,
+			.bottom	= VINO_CLIPPING_START_EVEN_NTSC
+			+ VINO_NTSC_HEIGHT / 2 - 1,
+			.right	= VINO_NTSC_WIDTH,
+		},
+	}, {
+		.description	= "PAL",
+		.std		= V4L2_STD_PAL,
+		.fps_min	= 5,
+		.fps_max	= 25,
+		.framelines	= 625,
+		.width		= VINO_PAL_WIDTH,
+		.height		= VINO_PAL_HEIGHT,
+		.odd		= {
+			.top	= VINO_CLIPPING_START_ODD_PAL,
+			.left	= 0,
+			.bottom	= VINO_CLIPPING_START_ODD_PAL
+			+ VINO_PAL_HEIGHT / 2 - 1,
+			.right	= VINO_PAL_WIDTH,
+		},
+		.even		= {
+			.top	= VINO_CLIPPING_START_EVEN_PAL,
+			.left	= 0,
+			.bottom	= VINO_CLIPPING_START_EVEN_PAL
+			+ VINO_PAL_HEIGHT / 2 - 1,
+			.right	= VINO_PAL_WIDTH,
+		},
+	}, {
+		.description	= "SECAM",
+		.std		= V4L2_STD_SECAM,
+		.fps_min	= 5,
+		.fps_max	= 25,
+		.framelines	= 625,
+		.width		= VINO_PAL_WIDTH,
+		.height		= VINO_PAL_HEIGHT,
+		.odd		= {
+			.top	= VINO_CLIPPING_START_ODD_PAL,
+			.left	= 0,
+			.bottom	= VINO_CLIPPING_START_ODD_PAL
+			+ VINO_PAL_HEIGHT / 2 - 1,
+			.right	= VINO_PAL_WIDTH,
+		},
+		.even		= {
+			.top	= VINO_CLIPPING_START_EVEN_PAL,
+			.left	= 0,
+			.bottom	= VINO_CLIPPING_START_EVEN_PAL
+			+ VINO_PAL_HEIGHT / 2 - 1,
+			.right	= VINO_PAL_WIDTH,
+		},
+	}, {
+		.description	= "NTSC/D1",
+		.std		= V4L2_STD_NTSC,
+		.fps_min	= 6,
+		.fps_max	= 30,
+		.framelines	= 525,
+		.width		= VINO_NTSC_WIDTH,
+		.height		= VINO_NTSC_HEIGHT,
+		.odd		= {
+			.top	= VINO_CLIPPING_START_ODD_D1,
+			.left	= 0,
+			.bottom	= VINO_CLIPPING_START_ODD_D1
+			+ VINO_NTSC_HEIGHT / 2 - 1,
+			.right	= VINO_NTSC_WIDTH,
+		},
+		.even		= {
+			.top	= VINO_CLIPPING_START_EVEN_D1,
+			.left	= 0,
+			.bottom	= VINO_CLIPPING_START_EVEN_D1
+			+ VINO_NTSC_HEIGHT / 2 - 1,
+			.right	= VINO_NTSC_WIDTH,
+		},
+	}
+};
+
+#define VINO_INDYCAM_V4L2_CONTROL_COUNT		9
+
+struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
+	{
+		.id = V4L2_CID_AUTOGAIN,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Automatic Gain Control",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = INDYCAM_AGC_DEFAULT,
+	}, {
+		.id = V4L2_CID_AUTO_WHITE_BALANCE,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Automatic White Balance",
+		.minimum = 0,
+		.maximum = 1,
+		.step = 1,
+		.default_value = INDYCAM_AWB_DEFAULT,
+	}, {
+		.id = V4L2_CID_GAIN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Gain",
+		.minimum = INDYCAM_GAIN_MIN,
+		.maximum = INDYCAM_GAIN_MAX,
+		.step = 1,
+		.default_value = INDYCAM_GAIN_DEFAULT,
+	}, {
+		.id = INDYCAM_CONTROL_RED_SATURATION,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red Saturation",
+		.minimum = INDYCAM_RED_SATURATION_MIN,
+		.maximum = INDYCAM_RED_SATURATION_MAX,
+		.step = 1,
+		.default_value = INDYCAM_RED_SATURATION_DEFAULT,
+	}, {
+		.id = INDYCAM_CONTROL_BLUE_SATURATION,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue Saturation",
+		.minimum = INDYCAM_BLUE_SATURATION_MIN,
+		.maximum = INDYCAM_BLUE_SATURATION_MAX,
+		.step = 1,
+		.default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
+	}, {
+		.id = V4L2_CID_RED_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red Balance",
+		.minimum = INDYCAM_RED_BALANCE_MIN,
+		.maximum = INDYCAM_RED_BALANCE_MAX,
+		.step = 1,
+		.default_value = INDYCAM_RED_BALANCE_DEFAULT,
+	}, {
+		.id = V4L2_CID_BLUE_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue Balance",
+		.minimum = INDYCAM_BLUE_BALANCE_MIN,
+		.maximum = INDYCAM_BLUE_BALANCE_MAX,
+		.step = 1,
+		.default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
+	}, {
+		.id = V4L2_CID_EXPOSURE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Shutter Control",
+		.minimum = INDYCAM_SHUTTER_MIN,
+		.maximum = INDYCAM_SHUTTER_MAX,
+		.step = 1,
+		.default_value = INDYCAM_SHUTTER_DEFAULT,
+	}, {
+		.id = V4L2_CID_GAMMA,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Gamma",
+		.minimum = INDYCAM_GAMMA_MIN,
+		.maximum = INDYCAM_GAMMA_MAX,
+		.step = 1,
+		.default_value = INDYCAM_GAMMA_DEFAULT,
+	}
+};
+
+#define VINO_SAA7191_V4L2_CONTROL_COUNT		9
+
+struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
+	{
+		.id = V4L2_CID_HUE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Hue",
+		.minimum = SAA7191_HUE_MIN,
+		.maximum = SAA7191_HUE_MAX,
+		.step = 1,
+		.default_value = SAA7191_HUE_DEFAULT,
+	}, {
+		.id = SAA7191_CONTROL_BANDPASS,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Luminance Bandpass",
+		.minimum = SAA7191_BANDPASS_MIN,
+		.maximum = SAA7191_BANDPASS_MAX,
+		.step = 1,
+		.default_value = SAA7191_BANDPASS_DEFAULT,
+	}, {
+		.id = SAA7191_CONTROL_BANDPASS_WEIGHT,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Luminance Bandpass Weight",
+		.minimum = SAA7191_BANDPASS_WEIGHT_MIN,
+		.maximum = SAA7191_BANDPASS_WEIGHT_MAX,
+		.step = 1,
+		.default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
+	}, {
+		.id = SAA7191_CONTROL_CORING,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "HF Luminance Coring",
+		.minimum = SAA7191_CORING_MIN,
+		.maximum = SAA7191_CORING_MAX,
+		.step = 1,
+		.default_value = SAA7191_CORING_DEFAULT,
+	}, {
+		.id = SAA7191_CONTROL_FORCE_COLOUR,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "Force Colour",
+		.minimum = SAA7191_FORCE_COLOUR_MIN,
+		.maximum = SAA7191_FORCE_COLOUR_MAX,
+		.step = 1,
+		.default_value = SAA7191_FORCE_COLOUR_DEFAULT,
+	}, {
+		.id = SAA7191_CONTROL_CHROMA_GAIN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Chrominance Gain Control",
+		.minimum = SAA7191_CHROMA_GAIN_MIN,
+		.maximum = SAA7191_CHROMA_GAIN_MAX,
+		.step = 1,
+		.default_value = SAA7191_CHROMA_GAIN_DEFAULT,
+	}, {
+		.id = SAA7191_CONTROL_VTRC,
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.name = "VTR Time Constant",
+		.minimum = SAA7191_VTRC_MIN,
+		.maximum = SAA7191_VTRC_MAX,
+		.step = 1,
+		.default_value = SAA7191_VTRC_DEFAULT,
+	}, {
+		.id = SAA7191_CONTROL_LUMA_DELAY,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Luminance Delay Compensation",
+		.minimum = SAA7191_LUMA_DELAY_MIN,
+		.maximum = SAA7191_LUMA_DELAY_MAX,
+		.step = 1,
+		.default_value = SAA7191_LUMA_DELAY_DEFAULT,
+	}, {
+		.id = SAA7191_CONTROL_VNR,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Vertical Noise Reduction",
+		.minimum = SAA7191_VNR_MIN,
+		.maximum = SAA7191_VNR_MAX,
+		.step = 1,
+		.default_value = SAA7191_VNR_DEFAULT,
+	}
+};
+
+/* VINO framebuffer/DMA descriptor management */
+
+static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
+					       unsigned int count)
+{
+	unsigned int i;
+
+	dprintk("vino_free_buffer_with_count(): count = %d\n", count);
+
+	for (i = 0; i < count; i++) {
+		ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
+		dma_unmap_single(NULL,
+				 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+				 PAGE_SIZE, DMA_FROM_DEVICE);
+		free_page(fb->desc_table.virtual[i]);
+	}
+
+	dma_free_coherent(NULL,
+			  VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
+			  sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
+			  fb->desc_table.dma);
+	kfree(fb->desc_table.virtual);
+
+	memset(fb, 0, sizeof(struct vino_framebuffer));
+}
+
+static void vino_free_buffer(struct vino_framebuffer *fb)
+{
+	vino_free_buffer_with_count(fb, fb->desc_table.page_count);
+}
+
+static int vino_allocate_buffer(struct vino_framebuffer *fb,
+				unsigned int size)
+{
+	unsigned int count, i, j;
+	int ret = 0;
+
+	dprintk("vino_allocate_buffer():\n");
+
+	if (size < 1)
+		return -EINVAL;
+
+	memset(fb, 0, sizeof(struct vino_framebuffer));
+
+	count = ((size / PAGE_SIZE) + 4) & ~3;
+
+	dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
+		size, count);
+
+	/* allocate memory for table with virtual (page) addresses */
+	fb->desc_table.virtual =
+		kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+	if (!fb->desc_table.virtual)
+		return -ENOMEM;
+
+	/* allocate memory for table with dma addresses
+	 * (has space for four extra descriptors) */
+	fb->desc_table.dma_cpu =
+		dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+				   sizeof(dma_addr_t), &fb->desc_table.dma,
+				   GFP_KERNEL | GFP_DMA);
+	if (!fb->desc_table.dma_cpu) {
+		ret = -ENOMEM;
+		goto out_free_virtual;
+	}
+
+	/* allocate pages for the buffer and acquire the according
+	 * dma addresses */
+	for (i = 0; i < count; i++) {
+		dma_addr_t dma_data_addr;
+
+		fb->desc_table.virtual[i] =
+			get_zeroed_page(GFP_KERNEL | GFP_DMA);
+		if (!fb->desc_table.virtual[i]) {
+			ret = -ENOBUFS;
+			break;
+		}
+
+		dma_data_addr =
+			dma_map_single(NULL,
+				       (void *)fb->desc_table.virtual[i],
+				       PAGE_SIZE, DMA_FROM_DEVICE);
+
+		for (j = 0; j < VINO_PAGE_RATIO; j++) {
+			fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+				dma_data_addr + VINO_PAGE_SIZE * j;
+		}
+
+		SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
+	}
+
+	/* page_count needs to be set anyway, because the descriptor table has
+	 * been allocated according to this number */
+	fb->desc_table.page_count = count;
+
+	if (ret) {
+		/* the descriptor with index i doesn't contain
+		 * a valid address yet */
+		vino_free_buffer_with_count(fb, i);
+		return ret;
+	}
+
+	//fb->size = size;
+	fb->size = count * PAGE_SIZE;
+	fb->data_format = VINO_DATA_FMT_NONE;
+
+	/* set the dma stop-bit for the last (count+1)th descriptor */
+	fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+	return 0;
+
+ out_free_virtual:
+	kfree(fb->desc_table.virtual);
+	return ret;
+}
+
+#if 0
+/* user buffers not fully implemented yet */
+static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
+				     void *user,
+				     unsigned int size)
+{
+	unsigned int count, i, j;
+	int ret = 0;
+
+	dprintk("vino_prepare_user_buffer():\n");
+
+	if (size < 1)
+		return -EINVAL;
+
+	memset(fb, 0, sizeof(struct vino_framebuffer));
+
+	count = ((size / PAGE_SIZE)) & ~3;
+
+	dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
+		size, count);
+
+	/* allocate memory for table with virtual (page) addresses */
+	fb->desc_table.virtual = (unsigned long *)
+		kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+	if (!fb->desc_table.virtual)
+		return -ENOMEM;
+
+	/* allocate memory for table with dma addresses
+	 * (has space for four extra descriptors) */
+	fb->desc_table.dma_cpu =
+		dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+				   sizeof(dma_addr_t), &fb->desc_table.dma,
+				   GFP_KERNEL | GFP_DMA);
+	if (!fb->desc_table.dma_cpu) {
+		ret = -ENOMEM;
+		goto out_free_virtual;
+	}
+
+	/* allocate pages for the buffer and acquire the according
+	 * dma addresses */
+	for (i = 0; i < count; i++) {
+		dma_addr_t dma_data_addr;
+
+		fb->desc_table.virtual[i] =
+			get_zeroed_page(GFP_KERNEL | GFP_DMA);
+		if (!fb->desc_table.virtual[i]) {
+			ret = -ENOBUFS;
+			break;
+		}
+
+		dma_data_addr =
+			dma_map_single(NULL,
+				       (void *)fb->desc_table.virtual[i],
+				       PAGE_SIZE, DMA_FROM_DEVICE);
+
+		for (j = 0; j < VINO_PAGE_RATIO; j++) {
+			fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+				dma_data_addr + VINO_PAGE_SIZE * j;
+		}
+
+		SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
+	}
+
+	/* page_count needs to be set anyway, because the descriptor table has
+	 * been allocated according to this number */
+	fb->desc_table.page_count = count;
+
+	if (ret) {
+		/* the descriptor with index i doesn't contain
+		 * a valid address yet */
+		vino_free_buffer_with_count(fb, i);
+		return ret;
+	}
+
+	//fb->size = size;
+	fb->size = count * PAGE_SIZE;
+
+	/* set the dma stop-bit for the last (count+1)th descriptor */
+	fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+	return 0;
+
+ out_free_virtual:
+	kfree(fb->desc_table.virtual);
+	return ret;
+}
+#endif
+
+static void vino_sync_buffer(struct vino_framebuffer *fb)
+{
+	int i;
+
+	dprintk("vino_sync_buffer():\n");
+
+	for (i = 0; i < fb->desc_table.page_count; i++)
+		dma_sync_single_for_cpu(NULL,
+					fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+					PAGE_SIZE, DMA_FROM_DEVICE);
+}
+
+/* Framebuffer fifo functions (need to be locked externally) */
+
+static inline void vino_fifo_init(struct vino_framebuffer_fifo *f,
+			   unsigned int length)
+{
+	f->length = 0;
+	f->used = 0;
+	f->head = 0;
+	f->tail = 0;
+
+	if (length > VINO_FRAMEBUFFER_COUNT_MAX)
+		length = VINO_FRAMEBUFFER_COUNT_MAX;
+
+	f->length = length;
+}
+
+/* returns true/false */
+static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f,
+				   unsigned int id)
+{
+	unsigned int i;
+
+	for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
+		if (f->data[i] == id)
+			return 1;
+	}
+
+	return 0;
+}
+
+#if 0
+/* returns true/false */
+static inline int vino_fifo_full(struct vino_framebuffer_fifo *f)
+{
+	return (f->used == f->length);
+}
+#endif
+
+static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
+{
+	return f->used;
+}
+
+static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
+{
+	if (id >= f->length) {
+		return VINO_QUEUE_ERROR;
+	}
+
+	if (vino_fifo_has_id(f, id)) {
+		return VINO_QUEUE_ERROR;
+	}
+
+	if (f->used < f->length) {
+		f->data[f->tail] = id;
+		f->tail = (f->tail + 1) % f->length;
+		f->used++;
+	} else {
+		return VINO_QUEUE_ERROR;
+	}
+
+	return 0;
+}
+
+static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
+{
+	if (f->used > 0) {
+		*id = f->data[f->head];
+	} else {
+		return VINO_QUEUE_ERROR;
+	}
+
+	return 0;
+}
+
+static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
+{
+	if (f->used > 0) {
+		*id = f->data[f->head];
+		f->head = (f->head + 1) % f->length;
+		f->used--;
+	} else {
+		return VINO_QUEUE_ERROR;
+	}
+
+	return 0;
+}
+
+/* Framebuffer queue functions */
+
+/* execute with queue_lock locked */
+static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
+				       unsigned int length)
+{
+	unsigned int i;
+
+	q->length = 0;
+	memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
+	memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
+	for (i = 0; i < length; i++) {
+		dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
+			i);
+		vino_free_buffer(q->buffer[i]);
+		kfree(q->buffer[i]);
+	}
+
+	q->type = VINO_MEMORY_NONE;
+	q->magic = 0;
+}
+
+static void vino_queue_free(struct vino_framebuffer_queue *q)
+{
+	dprintk("vino_queue_free():\n");
+
+	if (q->magic != VINO_QUEUE_MAGIC)
+		return;
+	if (q->type != VINO_MEMORY_MMAP)
+		return;
+
+	mutex_lock(&q->queue_mutex);
+
+	vino_queue_free_with_count(q, q->length);
+
+	mutex_unlock(&q->queue_mutex);
+}
+
+static int vino_queue_init(struct vino_framebuffer_queue *q,
+			   unsigned int *length)
+{
+	unsigned int i;
+	int ret = 0;
+
+	dprintk("vino_queue_init(): length = %d\n", *length);
+
+	if (q->magic == VINO_QUEUE_MAGIC) {
+		dprintk("vino_queue_init(): queue already initialized!\n");
+		return -EINVAL;
+	}
+
+	if (q->type != VINO_MEMORY_NONE) {
+		dprintk("vino_queue_init(): queue already initialized!\n");
+		return -EINVAL;
+	}
+
+	if (*length < 1)
+		return -EINVAL;
+
+	mutex_lock(&q->queue_mutex);
+
+	if (*length > VINO_FRAMEBUFFER_COUNT_MAX)
+		*length = VINO_FRAMEBUFFER_COUNT_MAX;
+
+	q->length = 0;
+
+	for (i = 0; i < *length; i++) {
+		dprintk("vino_queue_init(): allocating buffer %d\n", i);
+		q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
+				       GFP_KERNEL);
+		if (!q->buffer[i]) {
+			dprintk("vino_queue_init(): kmalloc() failed\n");
+			ret = -ENOMEM;
+			break;
+		}
+
+		ret = vino_allocate_buffer(q->buffer[i],
+					   VINO_FRAMEBUFFER_SIZE);
+		if (ret) {
+			kfree(q->buffer[i]);
+			dprintk("vino_queue_init(): "
+				"vino_allocate_buffer() failed\n");
+			break;
+		}
+
+		q->buffer[i]->id = i;
+		if (i > 0) {
+			q->buffer[i]->offset = q->buffer[i - 1]->offset +
+				q->buffer[i - 1]->size;
+		} else {
+			q->buffer[i]->offset = 0;
+		}
+
+		spin_lock_init(&q->buffer[i]->state_lock);
+
+		dprintk("vino_queue_init(): buffer = %d, offset = %d, "
+			"size = %d\n", i, q->buffer[i]->offset,
+			q->buffer[i]->size);
+	}
+
+	if (ret) {
+		vino_queue_free_with_count(q, i);
+		*length = 0;
+	} else {
+		q->length = *length;
+		vino_fifo_init(&q->in, q->length);
+		vino_fifo_init(&q->out, q->length);
+		q->type = VINO_MEMORY_MMAP;
+		q->magic = VINO_QUEUE_MAGIC;
+	}
+
+	mutex_unlock(&q->queue_mutex);
+
+	return ret;
+}
+
+static struct vino_framebuffer *vino_queue_add(struct
+					       vino_framebuffer_queue *q,
+					       unsigned int id)
+{
+	struct vino_framebuffer *ret = NULL;
+	unsigned int total;
+	unsigned long flags;
+
+	dprintk("vino_queue_add(): id = %d\n", id);
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return ret;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0)
+		goto out;
+
+	if (id >= q->length)
+		goto out;
+
+	/* not needed?: if (vino_fifo_full(&q->out)) {
+		goto out;
+		}*/
+	/* check that outgoing queue isn't already full
+	 * (or that it won't become full) */
+	total = vino_fifo_get_used(&q->in) +
+		vino_fifo_get_used(&q->out);
+	if (total >= q->length)
+		goto out;
+
+	if (vino_fifo_enqueue(&q->in, id))
+		goto out;
+
+	ret = q->buffer[id];
+
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+static struct vino_framebuffer *vino_queue_transfer(struct
+						    vino_framebuffer_queue *q)
+{
+	struct vino_framebuffer *ret = NULL;
+	struct vino_framebuffer *fb;
+	int id;
+	unsigned long flags;
+
+	dprintk("vino_queue_transfer():\n");
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return ret;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0)
+		goto out;
+
+	// now this actually removes an entry from the incoming queue
+	if (vino_fifo_dequeue(&q->in, &id)) {
+		goto out;
+	}
+
+	dprintk("vino_queue_transfer(): id = %d\n", id);
+	fb = q->buffer[id];
+
+	// we have already checked that the outgoing queue is not full, but...
+	if (vino_fifo_enqueue(&q->out, id)) {
+		printk(KERN_ERR "vino_queue_transfer(): "
+		       "outgoing queue is full, this shouldn't happen!\n");
+		goto out;
+	}
+
+	ret = fb;
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+/* returns true/false */
+static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
+					unsigned int id)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return ret;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0)
+		goto out;
+
+	ret = vino_fifo_has_id(&q->in, id);
+
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+/* returns true/false */
+static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
+					unsigned int id)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return ret;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0)
+		goto out;
+
+	ret = vino_fifo_has_id(&q->out, id);
+
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
+				   unsigned int *used)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return VINO_QUEUE_ERROR;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0) {
+		ret = VINO_QUEUE_ERROR;
+		goto out;
+	}
+
+	*used = vino_fifo_get_used(&q->in);
+
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
+				   unsigned int *used)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return VINO_QUEUE_ERROR;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0) {
+		ret = VINO_QUEUE_ERROR;
+		goto out;
+	}
+
+	*used = vino_fifo_get_used(&q->out);
+
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+#if 0
+static int vino_queue_get_total(struct vino_framebuffer_queue *q,
+				unsigned int *total)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return VINO_QUEUE_ERROR;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0) {
+		ret = VINO_QUEUE_ERROR;
+		goto out;
+	}
+
+	*total = vino_fifo_get_used(&q->in) +
+		vino_fifo_get_used(&q->out);
+
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+#endif
+
+static struct vino_framebuffer *vino_queue_peek(struct
+						vino_framebuffer_queue *q,
+						unsigned int *id)
+{
+	struct vino_framebuffer *ret = NULL;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return ret;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0)
+		goto out;
+
+	if (vino_fifo_peek(&q->in, id)) {
+		goto out;
+	}
+
+	ret = q->buffer[*id];
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+static struct vino_framebuffer *vino_queue_remove(struct
+						  vino_framebuffer_queue *q,
+						  unsigned int *id)
+{
+	struct vino_framebuffer *ret = NULL;
+	unsigned long flags;
+	dprintk("vino_queue_remove():\n");
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return ret;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0)
+		goto out;
+
+	if (vino_fifo_dequeue(&q->out, id)) {
+		goto out;
+	}
+
+	dprintk("vino_queue_remove(): id = %d\n", *id);
+	ret = q->buffer[*id];
+out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+static struct
+vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
+					unsigned int id)
+{
+	struct vino_framebuffer *ret = NULL;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return ret;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+
+	if (q->length == 0)
+		goto out;
+
+	if (id >= q->length)
+		goto out;
+
+	ret = q->buffer[id];
+ out:
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
+{
+	unsigned int length = 0;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return length;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+	length = q->length;
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return length;
+}
+
+static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
+{
+	unsigned int i;
+	int ret = 0;
+	unsigned long flags;
+
+	if (q->magic != VINO_QUEUE_MAGIC) {
+		return ret;
+	}
+
+	spin_lock_irqsave(&q->queue_lock, flags);
+	for (i = 0; i < q->length; i++) {
+		if (q->buffer[i]->map_count > 0) {
+			ret = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+
+	return ret;
+}
+
+/* VINO functions */
+
+/* execute with input_lock locked */
+static void vino_update_line_size(struct vino_channel_settings *vcs)
+{
+	unsigned int w = vcs->clipping.right - vcs->clipping.left;
+	unsigned int d = vcs->decimation;
+	unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
+	unsigned int lsize;
+
+	dprintk("update_line_size(): before: w = %d, d = %d, "
+		"line_size = %d\n", w, d, vcs->line_size);
+
+	/* line size must be multiple of 8 bytes */
+	lsize = (bpp * (w / d)) & ~7;
+	w = (lsize / bpp) * d;
+
+	vcs->clipping.right = vcs->clipping.left + w;
+	vcs->line_size = lsize;
+
+	dprintk("update_line_size(): after: w = %d, d = %d, "
+		"line_size = %d\n", w, d, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_set_clipping(struct vino_channel_settings *vcs,
+			      unsigned int x, unsigned int y,
+			      unsigned int w, unsigned int h)
+{
+	unsigned int maxwidth, maxheight;
+	unsigned int d;
+
+	maxwidth = vino_data_norms[vcs->data_norm].width;
+	maxheight = vino_data_norms[vcs->data_norm].height;
+	d = vcs->decimation;
+
+	y &= ~1;	/* odd/even fields */
+
+	if (x > maxwidth) {
+		x = 0;
+	}
+	if (y > maxheight) {
+		y = 0;
+	}
+
+	if (((w / d) < VINO_MIN_WIDTH)
+	    || ((h / d) < VINO_MIN_HEIGHT)) {
+		w = VINO_MIN_WIDTH * d;
+		h = VINO_MIN_HEIGHT * d;
+	}
+
+	if ((x + w) > maxwidth) {
+		w = maxwidth - x;
+		if ((w / d) < VINO_MIN_WIDTH)
+			x = maxwidth - VINO_MIN_WIDTH * d;
+	}
+	if ((y + h) > maxheight) {
+		h = maxheight - y;
+		if ((h / d) < VINO_MIN_HEIGHT)
+			y = maxheight - VINO_MIN_HEIGHT * d;
+	}
+
+	vcs->clipping.left = x;
+	vcs->clipping.top = y;
+	vcs->clipping.right = x + w;
+	vcs->clipping.bottom = y + h;
+
+	vino_update_line_size(vcs);
+
+	dprintk("clipping %d, %d, %d, %d / %d - %d\n",
+		vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
+		vcs->clipping.bottom, vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static inline void vino_set_default_clipping(struct vino_channel_settings *vcs)
+{
+	vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
+			  vino_data_norms[vcs->data_norm].height);
+}
+
+/* execute with input_lock locked */
+static void vino_set_scaling(struct vino_channel_settings *vcs,
+			     unsigned int w, unsigned int h)
+{
+	unsigned int x, y, curw, curh, d;
+
+	x = vcs->clipping.left;
+	y = vcs->clipping.top;
+	curw = vcs->clipping.right - vcs->clipping.left;
+	curh = vcs->clipping.bottom - vcs->clipping.top;
+
+	d = max(curw / w, curh / h);
+
+	dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
+		w, h, curw, curh, d);
+
+	if (d < 1) {
+		d = 1;
+	} else if (d > 8) {
+		d = 8;
+	}
+
+	vcs->decimation = d;
+	vino_set_clipping(vcs, x, y, w * d, h * d);
+
+	dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
+		vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
+		vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static inline void vino_set_default_scaling(struct vino_channel_settings *vcs)
+{
+	vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
+			 vcs->clipping.bottom - vcs->clipping.top);
+}
+
+/* execute with input_lock locked */
+static void vino_set_framerate(struct vino_channel_settings *vcs,
+			       unsigned int fps)
+{
+	unsigned int mask;
+
+	switch (vcs->data_norm) {
+	case VINO_DATA_NORM_NTSC:
+	case VINO_DATA_NORM_D1:
+		fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
+
+		if (fps < vino_data_norms[vcs->data_norm].fps_min)
+			fps = vino_data_norms[vcs->data_norm].fps_min;
+		if (fps > vino_data_norms[vcs->data_norm].fps_max)
+			fps = vino_data_norms[vcs->data_norm].fps_max;
+
+		switch (fps) {
+		case 6:
+			mask = 0x003;
+			break;
+		case 12:
+			mask = 0x0c3;
+			break;
+		case 18:
+			mask = 0x333;
+			break;
+		case 24:
+			mask = 0x3ff;
+			break;
+		case 30:
+			mask = 0xfff;
+			break;
+		default:
+			mask = VINO_FRAMERT_FULL;
+		}
+		vcs->framert_reg = VINO_FRAMERT_RT(mask);
+		break;
+	case VINO_DATA_NORM_PAL:
+	case VINO_DATA_NORM_SECAM:
+		fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
+
+		if (fps < vino_data_norms[vcs->data_norm].fps_min)
+			fps = vino_data_norms[vcs->data_norm].fps_min;
+		if (fps > vino_data_norms[vcs->data_norm].fps_max)
+			fps = vino_data_norms[vcs->data_norm].fps_max;
+
+		switch (fps) {
+		case 5:
+			mask = 0x003;
+			break;
+		case 10:
+			mask = 0x0c3;
+			break;
+		case 15:
+			mask = 0x333;
+			break;
+		case 20:
+			mask = 0x0ff;
+			break;
+		case 25:
+			mask = 0x3ff;
+			break;
+		default:
+			mask = VINO_FRAMERT_FULL;
+		}
+		vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
+		break;
+	}
+
+	vcs->fps = fps;
+}
+
+/* execute with input_lock locked */
+static inline void vino_set_default_framerate(struct
+					      vino_channel_settings *vcs)
+{
+	vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
+}
+
+/* VINO I2C bus functions */
+
+struct i2c_algo_sgi_data {
+	void *data;	/* private data for lowlevel routines */
+	unsigned (*getctrl)(void *data);
+	void (*setctrl)(void *data, unsigned val);
+	unsigned (*rdata)(void *data);
+	void (*wdata)(void *data, unsigned val);
+
+	int xfer_timeout;
+	int ack_timeout;
+};
+
+static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
+{
+	int i;
+
+	for (i = 0; i < adap->xfer_timeout; i++) {
+		if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int wait_ack(struct i2c_algo_sgi_data *adap)
+{
+	int i;
+
+	if (wait_xfer_done(adap))
+		return -ETIMEDOUT;
+	for (i = 0; i < adap->ack_timeout; i++) {
+		if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int force_idle(struct i2c_algo_sgi_data *adap)
+{
+	int i;
+
+	adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE);
+	for (i = 0; i < adap->xfer_timeout; i++) {
+		if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0)
+			goto out;
+		udelay(1);
+	}
+	return -ETIMEDOUT;
+out:
+	if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR)
+		return -EIO;
+	return 0;
+}
+
+static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
+		      int rd)
+{
+	if (rd)
+		adap->setctrl(adap->data, SGI_I2C_NOT_IDLE);
+	/* Check if bus is idle, eventually force it to do so */
+	if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE)
+		if (force_idle(adap))
+			return -EIO;
+	/* Write out the i2c chip address and specify operation */
+	adap->setctrl(adap->data,
+		      SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
+	if (rd)
+		addr |= 1;
+	adap->wdata(adap->data, addr);
+	if (wait_ack(adap))
+		return -EIO;
+	return 0;
+}
+
+static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+		    unsigned int len)
+{
+	int i;
+
+	adap->setctrl(adap->data,
+		      SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
+	for (i = 0; i < len; i++) {
+		if (wait_xfer_done(adap))
+			return -EIO;
+		buf[i] = adap->rdata(adap->data);
+	}
+	adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
+
+	return 0;
+
+}
+
+static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+		     unsigned int len)
+{
+	int i;
+
+	/* We are already in write state */
+	for (i = 0; i < len; i++) {
+		adap->wdata(adap->data, buf[i]);
+		if (wait_ack(adap))
+			return -EIO;
+	}
+	return 0;
+}
+
+static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+		    int num)
+{
+	struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
+	struct i2c_msg *p;
+	int i, err = 0;
+
+	for (i = 0; !err && i < num; i++) {
+		p = &msgs[i];
+		err = do_address(adap, p->addr, p->flags & I2C_M_RD);
+		if (err || !p->len)
+			continue;
+		if (p->flags & I2C_M_RD)
+			err = i2c_read(adap, p->buf, p->len);
+		else
+			err = i2c_write(adap, p->buf, p->len);
+	}
+
+	return (err < 0) ? err : i;
+}
+
+static u32 sgi_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm sgi_algo = {
+	.master_xfer	= sgi_xfer,
+	.functionality	= sgi_func,
+};
+
+static unsigned i2c_vino_getctrl(void *data)
+{
+	return vino->i2c_control;
+}
+
+static void i2c_vino_setctrl(void *data, unsigned val)
+{
+	vino->i2c_control = val;
+}
+
+static unsigned i2c_vino_rdata(void *data)
+{
+	return vino->i2c_data;
+}
+
+static void i2c_vino_wdata(void *data, unsigned val)
+{
+	vino->i2c_data = val;
+}
+
+static struct i2c_algo_sgi_data i2c_sgi_vino_data = {
+	.getctrl = &i2c_vino_getctrl,
+	.setctrl = &i2c_vino_setctrl,
+	.rdata   = &i2c_vino_rdata,
+	.wdata   = &i2c_vino_wdata,
+	.xfer_timeout = 200,
+	.ack_timeout  = 1000,
+};
+
+static struct i2c_adapter vino_i2c_adapter = {
+	.name			= "VINO I2C bus",
+	.algo			= &sgi_algo,
+	.algo_data		= &i2c_sgi_vino_data,
+	.owner 			= THIS_MODULE,
+};
+
+/*
+ * Prepare VINO for DMA transfer...
+ * (execute only with vino_lock and input_lock locked)
+ */
+static int vino_dma_setup(struct vino_channel_settings *vcs,
+			  struct vino_framebuffer *fb)
+{
+	u32 ctrl, intr;
+	struct sgi_vino_channel *ch;
+	const struct vino_data_norm *norm;
+
+	dprintk("vino_dma_setup():\n");
+
+	vcs->field = 0;
+	fb->frame_counter = 0;
+
+	ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+	norm = &vino_data_norms[vcs->data_norm];
+
+	ch->page_index = 0;
+	ch->line_count = 0;
+
+	/* VINO line size register is set 8 bytes less than actual */
+	ch->line_size = vcs->line_size - 8;
+
+	/* let VINO know where to transfer data */
+	ch->start_desc_tbl = fb->desc_table.dma;
+	ch->next_4_desc = fb->desc_table.dma;
+
+	/* give vino time to fetch the first four descriptors, 5 usec
+	 * should be more than enough time */
+	udelay(VINO_DESC_FETCH_DELAY);
+
+	dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n",
+		ch->start_desc_tbl, ch->next_4_desc);
+
+	/* set the alpha register */
+	ch->alpha = vcs->alpha;
+
+	/* set clipping registers */
+	ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
+		VINO_CLIP_EVEN(norm->even.top +
+			       vcs->clipping.top / 2) |
+		VINO_CLIP_X(vcs->clipping.left);
+	ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
+				     vcs->clipping.bottom / 2 - 1) |
+		VINO_CLIP_EVEN(norm->even.top +
+			       vcs->clipping.bottom / 2 - 1) |
+		VINO_CLIP_X(vcs->clipping.right);
+
+	/* set the size of actual content in the buffer (DECIMATION !) */
+	fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
+			 vcs->decimation) *
+		((vcs->clipping.bottom - vcs->clipping.top) /
+		 vcs->decimation) *
+		vino_data_formats[vcs->data_format].bpp;
+
+	ch->frame_rate = vcs->framert_reg;
+
+	ctrl = vino->control;
+	intr = vino->intr_status;
+
+	if (vcs->channel == VINO_CHANNEL_A) {
+		/* All interrupt conditions for this channel was cleared
+		 * so clear the interrupt status register and enable
+		 * interrupts */
+		intr &=	~VINO_INTSTAT_A;
+		ctrl |= VINO_CTRL_A_INT;
+
+		/* enable synchronization */
+		ctrl |= VINO_CTRL_A_SYNC_ENBL;
+
+		/* enable frame assembly */
+		ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
+
+		/* set decimation used */
+		if (vcs->decimation < 2)
+			ctrl &= ~VINO_CTRL_A_DEC_ENBL;
+		else {
+			ctrl |= VINO_CTRL_A_DEC_ENBL;
+			ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
+			ctrl |= (vcs->decimation - 1) <<
+				VINO_CTRL_A_DEC_SCALE_SHIFT;
+		}
+
+		/* select input interface */
+		if (vcs->input == VINO_INPUT_D1)
+			ctrl |= VINO_CTRL_A_SELECT;
+		else
+			ctrl &= ~VINO_CTRL_A_SELECT;
+
+		/* palette */
+		ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
+			  VINO_CTRL_A_DITHER);
+	} else {
+		intr &= ~VINO_INTSTAT_B;
+		ctrl |= VINO_CTRL_B_INT;
+
+		ctrl |= VINO_CTRL_B_SYNC_ENBL;
+		ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
+
+		if (vcs->decimation < 2)
+			ctrl &= ~VINO_CTRL_B_DEC_ENBL;
+		else {
+			ctrl |= VINO_CTRL_B_DEC_ENBL;
+			ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
+			ctrl |= (vcs->decimation - 1) <<
+				VINO_CTRL_B_DEC_SCALE_SHIFT;
+
+		}
+		if (vcs->input == VINO_INPUT_D1)
+			ctrl |= VINO_CTRL_B_SELECT;
+		else
+			ctrl &= ~VINO_CTRL_B_SELECT;
+
+		ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
+			  VINO_CTRL_B_DITHER);
+	}
+
+	/* set palette */
+	fb->data_format = vcs->data_format;
+
+	switch (vcs->data_format) {
+		case VINO_DATA_FMT_GREY:
+			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+				VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
+			break;
+		case VINO_DATA_FMT_RGB32:
+			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+				VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
+			break;
+		case VINO_DATA_FMT_YUV:
+			/* nothing needs to be done */
+			break;
+		case VINO_DATA_FMT_RGB332:
+			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+				VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
+				VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
+			break;
+	}
+
+	vino->intr_status = intr;
+	vino->control = ctrl;
+
+	return 0;
+}
+
+/* (execute only with vino_lock locked) */
+static inline void vino_dma_start(struct vino_channel_settings *vcs)
+{
+	u32 ctrl = vino->control;
+
+	dprintk("vino_dma_start():\n");
+	ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+		VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
+	vino->control = ctrl;
+}
+
+/* (execute only with vino_lock locked) */
+static inline void vino_dma_stop(struct vino_channel_settings *vcs)
+{
+	u32 ctrl = vino->control;
+
+	ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
+		~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
+	ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
+		~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT;
+	vino->control = ctrl;
+	dprintk("vino_dma_stop():\n");
+}
+
+/*
+ * Load dummy page to descriptor registers. This prevents generating of
+ * spurious interrupts. (execute only with vino_lock locked)
+ */
+static void vino_clear_interrupt(struct vino_channel_settings *vcs)
+{
+	struct sgi_vino_channel *ch;
+
+	ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+
+	ch->page_index = 0;
+	ch->line_count = 0;
+
+	ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
+	ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
+
+	udelay(VINO_DESC_FETCH_DELAY);
+	dprintk("channel %c clear interrupt condition\n",
+	       (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
+}
+
+static int vino_capture(struct vino_channel_settings *vcs,
+			struct vino_framebuffer *fb)
+{
+	int err = 0;
+	unsigned long flags, flags2;
+
+	spin_lock_irqsave(&fb->state_lock, flags);
+
+	if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+		err = -EBUSY;
+	fb->state = VINO_FRAMEBUFFER_IN_USE;
+
+	spin_unlock_irqrestore(&fb->state_lock, flags);
+
+	if (err)
+		return err;
+
+	spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
+
+	vino_dma_setup(vcs, fb);
+	vino_dma_start(vcs);
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
+	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+	return err;
+}
+
+static
+struct vino_framebuffer *vino_capture_enqueue(struct
+					      vino_channel_settings *vcs,
+					      unsigned int index)
+{
+	struct vino_framebuffer *fb;
+	unsigned long flags;
+
+	dprintk("vino_capture_enqueue():\n");
+
+	spin_lock_irqsave(&vcs->capture_lock, flags);
+
+	fb = vino_queue_add(&vcs->fb_queue, index);
+	if (fb == NULL) {
+		dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
+			"queue full?\n");
+		goto out;
+	}
+out:
+	spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+	return fb;
+}
+
+static int vino_capture_next(struct vino_channel_settings *vcs, int start)
+{
+	struct vino_framebuffer *fb;
+	unsigned int incoming, id;
+	int err = 0;
+	unsigned long flags;
+
+	dprintk("vino_capture_next():\n");
+
+	spin_lock_irqsave(&vcs->capture_lock, flags);
+
+	if (start) {
+		/* start capture only if capture isn't in progress already */
+		if (vcs->capturing) {
+			spin_unlock_irqrestore(&vcs->capture_lock, flags);
+			return 0;
+		}
+
+	} else {
+		/* capture next frame:
+		 * stop capture if capturing is not set */
+		if (!vcs->capturing) {
+			spin_unlock_irqrestore(&vcs->capture_lock, flags);
+			return 0;
+		}
+	}
+
+	err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+	if (err) {
+		dprintk("vino_capture_next(): vino_queue_get_incoming() "
+			"failed\n");
+		err = -EINVAL;
+		goto out;
+	}
+	if (incoming == 0) {
+		dprintk("vino_capture_next(): no buffers available\n");
+		goto out;
+	}
+
+	fb = vino_queue_peek(&vcs->fb_queue, &id);
+	if (fb == NULL) {
+		dprintk("vino_capture_next(): vino_queue_peek() failed\n");
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (start) {
+		vcs->capturing = 1;
+	}
+
+	spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+	err = vino_capture(vcs, fb);
+
+	return err;
+
+out:
+	vcs->capturing = 0;
+	spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+	return err;
+}
+
+static inline int vino_is_capturing(struct vino_channel_settings *vcs)
+{
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vcs->capture_lock, flags);
+
+	ret = vcs->capturing;
+
+	spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+	return ret;
+}
+
+/* waits until a frame is captured */
+static int vino_wait_for_frame(struct vino_channel_settings *vcs)
+{
+	wait_queue_t wait;
+	int err = 0;
+
+	dprintk("vino_wait_for_frame():\n");
+
+	init_waitqueue_entry(&wait, current);
+	/* add ourselves into wait queue */
+	add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+
+	/* to ensure that schedule_timeout will return immediately
+	 * if VINO interrupt was triggered meanwhile */
+	schedule_timeout_interruptible(msecs_to_jiffies(100));
+
+	if (signal_pending(current))
+		err = -EINTR;
+
+	remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+
+	dprintk("vino_wait_for_frame(): waiting for frame %s\n",
+		err ? "failed" : "ok");
+
+	return err;
+}
+
+/* the function assumes that PAGE_SIZE % 4 == 0 */
+static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
+	unsigned char *pageptr;
+	unsigned int page, i;
+	unsigned char a;
+
+	for (page = 0; page < fb->desc_table.page_count; page++) {
+		pageptr = (unsigned char *)fb->desc_table.virtual[page];
+
+		for (i = 0; i < PAGE_SIZE; i += 4) {
+			a = pageptr[0];
+			pageptr[0] = pageptr[3];
+			pageptr[1] = pageptr[2];
+			pageptr[2] = pageptr[1];
+			pageptr[3] = a;
+			pageptr += 4;
+		}
+	}
+}
+
+/* checks if the buffer is in correct state and syncs data */
+static int vino_check_buffer(struct vino_channel_settings *vcs,
+			     struct vino_framebuffer *fb)
+{
+	int err = 0;
+	unsigned long flags;
+
+	dprintk("vino_check_buffer():\n");
+
+	spin_lock_irqsave(&fb->state_lock, flags);
+	switch (fb->state) {
+	case VINO_FRAMEBUFFER_IN_USE:
+		err = -EIO;
+		break;
+	case VINO_FRAMEBUFFER_READY:
+		vino_sync_buffer(fb);
+		fb->state = VINO_FRAMEBUFFER_UNUSED;
+		break;
+	default:
+		err = -EINVAL;
+	}
+	spin_unlock_irqrestore(&fb->state_lock, flags);
+
+	if (!err) {
+		if (vino_pixel_conversion
+		    && (fb->data_format == VINO_DATA_FMT_RGB32)) {
+			vino_convert_to_rgba(fb);
+		}
+	} else if (err && (err != -EINVAL)) {
+		dprintk("vino_check_buffer(): buffer not ready\n");
+
+		spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+		vino_dma_stop(vcs);
+		vino_clear_interrupt(vcs);
+		spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+	}
+
+	return err;
+}
+
+/* forcefully terminates capture */
+static void vino_capture_stop(struct vino_channel_settings *vcs)
+{
+	unsigned int incoming = 0, outgoing = 0, id;
+	unsigned long flags, flags2;
+
+	dprintk("vino_capture_stop():\n");
+
+	spin_lock_irqsave(&vcs->capture_lock, flags);
+
+	/* unset capturing to stop queue processing */
+	vcs->capturing = 0;
+
+	spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
+
+	vino_dma_stop(vcs);
+	vino_clear_interrupt(vcs);
+
+	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
+
+	/* remove all items from the queue */
+	if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+		dprintk("vino_capture_stop(): "
+			"vino_queue_get_incoming() failed\n");
+		goto out;
+	}
+	while (incoming > 0) {
+		vino_queue_transfer(&vcs->fb_queue);
+
+		if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+			dprintk("vino_capture_stop(): "
+				"vino_queue_get_incoming() failed\n");
+			goto out;
+		}
+	}
+
+	if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+		dprintk("vino_capture_stop(): "
+			"vino_queue_get_outgoing() failed\n");
+		goto out;
+	}
+	while (outgoing > 0) {
+		vino_queue_remove(&vcs->fb_queue, &id);
+
+		if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+			dprintk("vino_capture_stop(): "
+				"vino_queue_get_outgoing() failed\n");
+			goto out;
+		}
+	}
+
+out:
+	spin_unlock_irqrestore(&vcs->capture_lock, flags);
+}
+
+#if 0
+static int vino_capture_failed(struct vino_channel_settings *vcs)
+{
+	struct vino_framebuffer *fb;
+	unsigned long flags;
+	unsigned int i;
+	int ret;
+
+	dprintk("vino_capture_failed():\n");
+
+	spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+
+	vino_dma_stop(vcs);
+	vino_clear_interrupt(vcs);
+
+	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+	ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
+	if (ret == VINO_QUEUE_ERROR) {
+		dprintk("vino_queue_get_incoming() failed\n");
+		return -EINVAL;
+	}
+	if (i == 0) {
+		/* no buffers to process */
+		return 0;
+	}
+
+	fb = vino_queue_peek(&vcs->fb_queue, &i);
+	if (fb == NULL) {
+		dprintk("vino_queue_peek() failed\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&fb->state_lock, flags);
+	if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
+		fb->state = VINO_FRAMEBUFFER_UNUSED;
+		vino_queue_transfer(&vcs->fb_queue);
+		vino_queue_remove(&vcs->fb_queue, &i);
+		/* we should actually discard the newest frame,
+		 * but who cares ... */
+	}
+	spin_unlock_irqrestore(&fb->state_lock, flags);
+
+	return 0;
+}
+#endif
+
+static void vino_skip_frame(struct vino_channel_settings *vcs)
+{
+	struct vino_framebuffer *fb;
+	unsigned long flags;
+	unsigned int id;
+
+	spin_lock_irqsave(&vcs->capture_lock, flags);
+	fb = vino_queue_peek(&vcs->fb_queue, &id);
+	if (!fb) {
+		spin_unlock_irqrestore(&vcs->capture_lock, flags);
+		dprintk("vino_skip_frame(): vino_queue_peek() failed!\n");
+		return;
+	}
+	spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+	spin_lock_irqsave(&fb->state_lock, flags);
+	fb->state = VINO_FRAMEBUFFER_UNUSED;
+	spin_unlock_irqrestore(&fb->state_lock, flags);
+
+	vino_capture_next(vcs, 0);
+}
+
+static void vino_frame_done(struct vino_channel_settings *vcs)
+{
+	struct vino_framebuffer *fb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vcs->capture_lock, flags);
+	fb = vino_queue_transfer(&vcs->fb_queue);
+	if (!fb) {
+		spin_unlock_irqrestore(&vcs->capture_lock, flags);
+		dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
+		return;
+	}
+	spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+	fb->frame_counter = vcs->int_data.frame_counter;
+	memcpy(&fb->timestamp, &vcs->int_data.timestamp,
+	       sizeof(struct timeval));
+
+	spin_lock_irqsave(&fb->state_lock, flags);
+	if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+		fb->state = VINO_FRAMEBUFFER_READY;
+	spin_unlock_irqrestore(&fb->state_lock, flags);
+
+	wake_up(&vcs->fb_queue.frame_wait_queue);
+
+	vino_capture_next(vcs, 0);
+}
+
+static void vino_capture_tasklet(unsigned long channel) {
+	struct vino_channel_settings *vcs;
+
+	vcs = (channel == VINO_CHANNEL_A)
+		? &vino_drvdata->a : &vino_drvdata->b;
+
+	if (vcs->int_data.skip)
+		vcs->int_data.skip_count++;
+
+	if (vcs->int_data.skip && (vcs->int_data.skip_count
+				   <= VINO_MAX_FRAME_SKIP_COUNT)) {
+		vino_skip_frame(vcs);
+	} else {
+		vcs->int_data.skip_count = 0;
+		vino_frame_done(vcs);
+	}
+}
+
+static irqreturn_t vino_interrupt(int irq, void *dev_id)
+{
+	u32 ctrl, intr;
+	unsigned int fc_a, fc_b;
+	int handled_a = 0, skip_a = 0, done_a = 0;
+	int handled_b = 0, skip_b = 0, done_b = 0;
+
+#ifdef VINO_DEBUG_INT
+	int loop = 0;
+	unsigned int line_count = vino->a.line_count,
+		page_index = vino->a.page_index,
+		field_counter = vino->a.field_counter,
+		start_desc_tbl = vino->a.start_desc_tbl,
+		next_4_desc = vino->a.next_4_desc;
+	unsigned int line_count_2,
+		page_index_2,
+		field_counter_2,
+		start_desc_tbl_2,
+		next_4_desc_2;
+#endif
+
+	spin_lock(&vino_drvdata->vino_lock);
+
+	while ((intr = vino->intr_status)) {
+		fc_a = vino->a.field_counter >> 1;
+		fc_b = vino->b.field_counter >> 1;
+
+		/* handle error-interrupts in some special way ?
+		 * --> skips frames */
+		if (intr & VINO_INTSTAT_A) {
+			if (intr & VINO_INTSTAT_A_EOF) {
+				vino_drvdata->a.field++;
+				if (vino_drvdata->a.field > 1) {
+					vino_dma_stop(&vino_drvdata->a);
+					vino_clear_interrupt(&vino_drvdata->a);
+					vino_drvdata->a.field = 0;
+					done_a = 1;
+				} else {
+					if (vino->a.page_index
+					    != vino_drvdata->a.line_size) {
+						vino->a.line_count = 0;
+						vino->a.page_index =
+							vino_drvdata->
+							a.line_size;
+						vino->a.next_4_desc =
+							vino->a.start_desc_tbl;
+					}
+				}
+				dprintk("channel A end-of-field "
+					"interrupt: %04x\n", intr);
+			} else {
+				vino_dma_stop(&vino_drvdata->a);
+				vino_clear_interrupt(&vino_drvdata->a);
+				vino_drvdata->a.field = 0;
+				skip_a = 1;
+				dprintk("channel A error interrupt: %04x\n",
+					intr);
+			}
+
+#ifdef VINO_DEBUG_INT
+			line_count_2 = vino->a.line_count;
+			page_index_2 = vino->a.page_index;
+			field_counter_2 = vino->a.field_counter;
+			start_desc_tbl_2 = vino->a.start_desc_tbl;
+			next_4_desc_2 = vino->a.next_4_desc;
+
+			printk("intr = %04x, loop = %d, field = %d\n",
+			       intr, loop, vino_drvdata->a.field);
+			printk("1- line count = %04d, page index = %04d, "
+			       "start = %08x, next = %08x\n"
+			       "   fieldc = %d, framec = %d\n",
+			       line_count, page_index, start_desc_tbl,
+			       next_4_desc, field_counter, fc_a);
+			printk("12-line count = %04d, page index = %04d, "
+			       "   start = %08x, next = %08x\n",
+			       line_count_2, page_index_2, start_desc_tbl_2,
+			       next_4_desc_2);
+
+			if (done_a)
+				printk("\n");
+#endif
+		}
+
+		if (intr & VINO_INTSTAT_B) {
+			if (intr & VINO_INTSTAT_B_EOF) {
+				vino_drvdata->b.field++;
+				if (vino_drvdata->b.field > 1) {
+					vino_dma_stop(&vino_drvdata->b);
+					vino_clear_interrupt(&vino_drvdata->b);
+					vino_drvdata->b.field = 0;
+					done_b = 1;
+				}
+				dprintk("channel B end-of-field "
+					"interrupt: %04x\n", intr);
+			} else {
+				vino_dma_stop(&vino_drvdata->b);
+				vino_clear_interrupt(&vino_drvdata->b);
+				vino_drvdata->b.field = 0;
+				skip_b = 1;
+				dprintk("channel B error interrupt: %04x\n",
+					intr);
+			}
+		}
+
+		/* Always remember to clear interrupt status.
+		 * Disable VINO interrupts while we do this. */
+		ctrl = vino->control;
+		vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT);
+		vino->intr_status = ~intr;
+		vino->control = ctrl;
+
+		spin_unlock(&vino_drvdata->vino_lock);
+
+		if ((!handled_a) && (done_a || skip_a)) {
+			if (!skip_a) {
+				v4l2_get_timestamp(
+					&vino_drvdata->a.int_data.timestamp);
+				vino_drvdata->a.int_data.frame_counter = fc_a;
+			}
+			vino_drvdata->a.int_data.skip = skip_a;
+
+			dprintk("channel A %s, interrupt: %d\n",
+				skip_a ? "skipping frame" : "frame done",
+				intr);
+			tasklet_hi_schedule(&vino_tasklet_a);
+			handled_a = 1;
+		}
+
+		if ((!handled_b) && (done_b || skip_b)) {
+			if (!skip_b) {
+				v4l2_get_timestamp(
+					&vino_drvdata->b.int_data.timestamp);
+				vino_drvdata->b.int_data.frame_counter = fc_b;
+			}
+			vino_drvdata->b.int_data.skip = skip_b;
+
+			dprintk("channel B %s, interrupt: %d\n",
+				skip_b ? "skipping frame" : "frame done",
+				intr);
+			tasklet_hi_schedule(&vino_tasklet_b);
+			handled_b = 1;
+		}
+
+#ifdef VINO_DEBUG_INT
+		loop++;
+#endif
+		spin_lock(&vino_drvdata->vino_lock);
+	}
+
+	spin_unlock(&vino_drvdata->vino_lock);
+
+	return IRQ_HANDLED;
+}
+
+/* VINO video input management */
+
+static int vino_get_saa7191_input(int input)
+{
+	switch (input) {
+	case VINO_INPUT_COMPOSITE:
+		return SAA7191_INPUT_COMPOSITE;
+	case VINO_INPUT_SVIDEO:
+		return SAA7191_INPUT_SVIDEO;
+	default:
+		printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
+		       "invalid input!\n");
+		return -1;
+	}
+}
+
+/* execute with input_lock locked */
+static int vino_is_input_owner(struct vino_channel_settings *vcs)
+{
+	switch(vcs->input) {
+	case VINO_INPUT_COMPOSITE:
+	case VINO_INPUT_SVIDEO:
+		return vino_drvdata->decoder_owner == vcs->channel;
+	case VINO_INPUT_D1:
+		return vino_drvdata->camera_owner == vcs->channel;
+	default:
+		return 0;
+	}
+}
+
+static int vino_acquire_input(struct vino_channel_settings *vcs)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	dprintk("vino_acquire_input():\n");
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	/* First try D1 and then SAA7191 */
+	if (vino_drvdata->camera
+	    && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) {
+		vino_drvdata->camera_owner = vcs->channel;
+		vcs->input = VINO_INPUT_D1;
+		vcs->data_norm = VINO_DATA_NORM_D1;
+	} else if (vino_drvdata->decoder
+		   && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) {
+		int input;
+		int data_norm = 0;
+		v4l2_std_id norm;
+
+		input = VINO_INPUT_COMPOSITE;
+
+		ret = decoder_call(video, s_routing,
+				vino_get_saa7191_input(input), 0, 0);
+		if (ret) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+		/* Don't hold spinlocks while auto-detecting norm
+		 * as it may take a while... */
+
+		ret = decoder_call(video, querystd, &norm);
+		if (!ret) {
+			for (data_norm = 0; data_norm < 3; data_norm++) {
+				if (vino_data_norms[data_norm].std & norm)
+					break;
+			}
+			if (data_norm == 3)
+				data_norm = VINO_DATA_NORM_PAL;
+			ret = decoder_call(video, s_std, norm);
+		}
+
+		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+		if (ret) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		vino_drvdata->decoder_owner = vcs->channel;
+
+		vcs->input = input;
+		vcs->data_norm = data_norm;
+	} else {
+		vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
+			vino_drvdata->b.input : vino_drvdata->a.input;
+		vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
+			vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
+	}
+
+	if (vcs->input == VINO_INPUT_NONE) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	vino_set_default_clipping(vcs);
+	vino_set_default_scaling(vcs);
+	vino_set_default_framerate(vcs);
+
+	dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return ret;
+}
+
+static int vino_set_input(struct vino_channel_settings *vcs, int input)
+{
+	struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+		&vino_drvdata->b : &vino_drvdata->a;
+	unsigned long flags;
+	int ret = 0;
+
+	dprintk("vino_set_input():\n");
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	if (vcs->input == input)
+		goto out;
+
+	switch (input) {
+	case VINO_INPUT_COMPOSITE:
+	case VINO_INPUT_SVIDEO:
+		if (!vino_drvdata->decoder) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) {
+			vino_drvdata->decoder_owner = vcs->channel;
+		}
+
+		if (vino_drvdata->decoder_owner == vcs->channel) {
+			int data_norm = 0;
+			v4l2_std_id norm;
+
+			ret = decoder_call(video, s_routing,
+					vino_get_saa7191_input(input), 0, 0);
+			if (ret) {
+				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
+				ret = -EINVAL;
+				goto out;
+			}
+
+			spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+			/* Don't hold spinlocks while auto-detecting norm
+			 * as it may take a while... */
+
+			ret = decoder_call(video, querystd, &norm);
+			if (!ret) {
+				for (data_norm = 0; data_norm < 3; data_norm++) {
+					if (vino_data_norms[data_norm].std & norm)
+						break;
+				}
+				if (data_norm == 3)
+					data_norm = VINO_DATA_NORM_PAL;
+				ret = decoder_call(video, s_std, norm);
+			}
+
+			spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+			if (ret) {
+				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
+				ret = -EINVAL;
+				goto out;
+			}
+
+			vcs->input = input;
+			vcs->data_norm = data_norm;
+		} else {
+			if (input != vcs2->input) {
+				ret = -EBUSY;
+				goto out;
+			}
+
+			vcs->input = input;
+			vcs->data_norm = vcs2->data_norm;
+		}
+
+		if (vino_drvdata->camera_owner == vcs->channel) {
+			/* Transfer the ownership or release the input */
+			if (vcs2->input == VINO_INPUT_D1) {
+				vino_drvdata->camera_owner = vcs2->channel;
+			} else {
+				vino_drvdata->camera_owner = VINO_NO_CHANNEL;
+			}
+		}
+		break;
+	case VINO_INPUT_D1:
+		if (!vino_drvdata->camera) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (vino_drvdata->camera_owner == VINO_NO_CHANNEL)
+			vino_drvdata->camera_owner = vcs->channel;
+
+		if (vino_drvdata->decoder_owner == vcs->channel) {
+			/* Transfer the ownership or release the input */
+			if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+				 (vcs2->input == VINO_INPUT_SVIDEO)) {
+				vino_drvdata->decoder_owner = vcs2->channel;
+			} else {
+				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
+			}
+		}
+
+		vcs->input = input;
+		vcs->data_norm = VINO_DATA_NORM_D1;
+		break;
+	default:
+		ret = -EINVAL;
+		goto out;
+	}
+
+	vino_set_default_clipping(vcs);
+	vino_set_default_scaling(vcs);
+	vino_set_default_framerate(vcs);
+
+	dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return ret;
+}
+
+static void vino_release_input(struct vino_channel_settings *vcs)
+{
+	struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+		&vino_drvdata->b : &vino_drvdata->a;
+	unsigned long flags;
+
+	dprintk("vino_release_input():\n");
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	/* Release ownership of the channel
+	 * and if the other channel takes input from
+	 * the same source, transfer the ownership */
+	if (vino_drvdata->camera_owner == vcs->channel) {
+		if (vcs2->input == VINO_INPUT_D1) {
+			vino_drvdata->camera_owner = vcs2->channel;
+		} else {
+			vino_drvdata->camera_owner = VINO_NO_CHANNEL;
+		}
+	} else if (vino_drvdata->decoder_owner == vcs->channel) {
+		if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+			 (vcs2->input == VINO_INPUT_SVIDEO)) {
+			vino_drvdata->decoder_owner = vcs2->channel;
+		} else {
+			vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
+		}
+	}
+	vcs->input = VINO_INPUT_NONE;
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+}
+
+/* execute with input_lock locked */
+static int vino_set_data_norm(struct vino_channel_settings *vcs,
+			      unsigned int data_norm,
+			      unsigned long *flags)
+{
+	int err = 0;
+
+	if (data_norm == vcs->data_norm)
+		return 0;
+
+	switch (vcs->input) {
+	case VINO_INPUT_D1:
+		/* only one "norm" supported */
+		if (data_norm != VINO_DATA_NORM_D1)
+			return -EINVAL;
+		break;
+	case VINO_INPUT_COMPOSITE:
+	case VINO_INPUT_SVIDEO: {
+		v4l2_std_id norm;
+
+		if ((data_norm != VINO_DATA_NORM_PAL)
+		    && (data_norm != VINO_DATA_NORM_NTSC)
+		    && (data_norm != VINO_DATA_NORM_SECAM))
+			return -EINVAL;
+
+		spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
+
+		/* Don't hold spinlocks while setting norm
+		 * as it may take a while... */
+
+		norm = vino_data_norms[data_norm].std;
+		err = decoder_call(video, s_std, norm);
+
+		spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
+
+		if (err)
+			goto out;
+
+		vcs->data_norm = data_norm;
+
+		vino_set_default_clipping(vcs);
+		vino_set_default_scaling(vcs);
+		vino_set_default_framerate(vcs);
+		break;
+	}
+	default:
+		return -EINVAL;
+	}
+
+out:
+	return err;
+}
+
+/* V4L2 helper functions */
+
+static int vino_find_data_format(__u32 pixelformat)
+{
+	int i;
+
+	for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
+		if (vino_data_formats[i].pixelformat == pixelformat)
+			return i;
+	}
+
+	return VINO_DATA_FMT_NONE;
+}
+
+static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
+{
+	int input = VINO_INPUT_NONE;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+	if (vino_drvdata->decoder && vino_drvdata->camera) {
+		switch (index) {
+		case 0:
+			input = VINO_INPUT_COMPOSITE;
+			break;
+		case 1:
+			input = VINO_INPUT_SVIDEO;
+			break;
+		case 2:
+			input = VINO_INPUT_D1;
+			break;
+		}
+	} else if (vino_drvdata->decoder) {
+		switch (index) {
+		case 0:
+			input = VINO_INPUT_COMPOSITE;
+			break;
+		case 1:
+			input = VINO_INPUT_SVIDEO;
+			break;
+		}
+	} else if (vino_drvdata->camera) {
+		switch (index) {
+		case 0:
+			input = VINO_INPUT_D1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return input;
+}
+
+/* execute with input_lock locked */
+static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
+{
+	__u32 index = 0;
+	// FIXME: detect when no inputs available
+
+	if (vino_drvdata->decoder && vino_drvdata->camera) {
+		switch (vcs->input) {
+		case VINO_INPUT_COMPOSITE:
+			index = 0;
+			break;
+		case VINO_INPUT_SVIDEO:
+			index = 1;
+			break;
+		case VINO_INPUT_D1:
+			index = 2;
+			break;
+		}
+	} else if (vino_drvdata->decoder) {
+		switch (vcs->input) {
+		case VINO_INPUT_COMPOSITE:
+			index = 0;
+			break;
+		case VINO_INPUT_SVIDEO:
+			index = 1;
+			break;
+		}
+	} else if (vino_drvdata->camera) {
+		switch (vcs->input) {
+		case VINO_INPUT_D1:
+			index = 0;
+			break;
+		}
+	}
+
+	return index;
+}
+
+/* V4L2 ioctls */
+
+static int vino_querycap(struct file *file, void *__fh,
+		struct v4l2_capability *cap)
+{
+	memset(cap, 0, sizeof(struct v4l2_capability));
+
+	strcpy(cap->driver, vino_driver_name);
+	strcpy(cap->card, vino_driver_description);
+	strcpy(cap->bus_info, vino_bus_name);
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_STREAMING;
+	// V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
+	return 0;
+}
+
+static int vino_enum_input(struct file *file, void *__fh,
+			       struct v4l2_input *i)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	__u32 index = i->index;
+	int input;
+	dprintk("requested index = %d\n", index);
+
+	input = vino_int_enum_input(vcs, index);
+	if (input == VINO_INPUT_NONE)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	i->std = vino_inputs[input].std;
+	strcpy(i->name, vino_inputs[input].name);
+
+	if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
+		decoder_call(video, g_input_status, &i->status);
+	return 0;
+}
+
+static int vino_g_input(struct file *file, void *__fh,
+			     unsigned int *i)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	__u32 index;
+	int input;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+	input = vcs->input;
+	index = vino_find_input_index(vcs);
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	dprintk("input = %d\n", input);
+
+	if (input == VINO_INPUT_NONE) {
+		return -EINVAL;
+	}
+
+	*i = index;
+
+	return 0;
+}
+
+static int vino_s_input(struct file *file, void *__fh,
+			     unsigned int i)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	int input;
+	dprintk("requested input = %d\n", i);
+
+	input = vino_int_enum_input(vcs, i);
+	if (input == VINO_INPUT_NONE)
+		return -EINVAL;
+
+	return vino_set_input(vcs, input);
+}
+
+static int vino_querystd(struct file *file, void *__fh,
+			      v4l2_std_id *std)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	int err = 0;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	switch (vcs->input) {
+	case VINO_INPUT_D1:
+		*std = vino_inputs[vcs->input].std;
+		break;
+	case VINO_INPUT_COMPOSITE:
+	case VINO_INPUT_SVIDEO: {
+		decoder_call(video, querystd, std);
+		break;
+	}
+	default:
+		err = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return err;
+}
+
+static int vino_g_std(struct file *file, void *__fh,
+			   v4l2_std_id *std)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	*std = vino_data_norms[vcs->data_norm].std;
+	dprintk("current standard = %d\n", vcs->data_norm);
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return 0;
+}
+
+static int vino_s_std(struct file *file, void *__fh,
+			   v4l2_std_id std)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	if (!vino_is_input_owner(vcs)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* check if the standard is valid for the current input */
+	if (std & vino_inputs[vcs->input].std) {
+		dprintk("standard accepted\n");
+
+		/* change the video norm for SAA7191
+		 * and accept NTSC for D1 (do nothing) */
+
+		if (vcs->input == VINO_INPUT_D1)
+			goto out;
+
+		if (std & V4L2_STD_PAL) {
+			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
+						 &flags);
+		} else if (std & V4L2_STD_NTSC) {
+			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC,
+						 &flags);
+		} else if (std & V4L2_STD_SECAM) {
+			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM,
+						 &flags);
+		} else {
+			ret = -EINVAL;
+		}
+
+		if (ret) {
+			ret = -EINVAL;
+		}
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return ret;
+}
+
+static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
+			      struct v4l2_fmtdesc *fd)
+{
+	dprintk("format index = %d\n", fd->index);
+
+	if (fd->index >= VINO_DATA_FMT_COUNT)
+		return -EINVAL;
+	dprintk("format name = %s\n", vino_data_formats[fd->index].description);
+
+	fd->pixelformat = vino_data_formats[fd->index].pixelformat;
+	strcpy(fd->description, vino_data_formats[fd->index].description);
+	return 0;
+}
+
+static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
+			     struct v4l2_format *f)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	struct vino_channel_settings tempvcs;
+	unsigned long flags;
+	struct v4l2_pix_format *pf = &f->fmt.pix;
+
+	dprintk("requested: w = %d, h = %d\n",
+			pf->width, pf->height);
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+	memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	tempvcs.data_format = vino_find_data_format(pf->pixelformat);
+	if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
+		tempvcs.data_format = VINO_DATA_FMT_GREY;
+		pf->pixelformat =
+			vino_data_formats[tempvcs.data_format].
+			pixelformat;
+	}
+
+	/* data format must be set before clipping/scaling */
+	vino_set_scaling(&tempvcs, pf->width, pf->height);
+
+	dprintk("data format = %s\n",
+			vino_data_formats[tempvcs.data_format].description);
+
+	pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
+		tempvcs.decimation;
+	pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+		tempvcs.decimation;
+
+	pf->field = V4L2_FIELD_INTERLACED;
+	pf->bytesperline = tempvcs.line_size;
+	pf->sizeimage = tempvcs.line_size *
+		(tempvcs.clipping.bottom - tempvcs.clipping.top) /
+		tempvcs.decimation;
+	pf->colorspace =
+		vino_data_formats[tempvcs.data_format].colorspace;
+
+	return 0;
+}
+
+static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
+			   struct v4l2_format *f)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	struct v4l2_pix_format *pf = &f->fmt.pix;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	pf->width = (vcs->clipping.right - vcs->clipping.left) /
+		vcs->decimation;
+	pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
+		vcs->decimation;
+	pf->pixelformat =
+		vino_data_formats[vcs->data_format].pixelformat;
+
+	pf->field = V4L2_FIELD_INTERLACED;
+	pf->bytesperline = vcs->line_size;
+	pf->sizeimage = vcs->line_size *
+		(vcs->clipping.bottom - vcs->clipping.top) /
+		vcs->decimation;
+	pf->colorspace =
+		vino_data_formats[vcs->data_format].colorspace;
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+	return 0;
+}
+
+static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
+			   struct v4l2_format *f)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	int data_format;
+	unsigned long flags;
+	struct v4l2_pix_format *pf = &f->fmt.pix;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	data_format = vino_find_data_format(pf->pixelformat);
+
+	if (data_format == VINO_DATA_FMT_NONE) {
+		vcs->data_format = VINO_DATA_FMT_GREY;
+		pf->pixelformat =
+			vino_data_formats[vcs->data_format].
+			pixelformat;
+	} else {
+		vcs->data_format = data_format;
+	}
+
+	/* data format must be set before clipping/scaling */
+	vino_set_scaling(vcs, pf->width, pf->height);
+
+	dprintk("data format = %s\n",
+	       vino_data_formats[vcs->data_format].description);
+
+	pf->width = vcs->clipping.right - vcs->clipping.left;
+	pf->height = vcs->clipping.bottom - vcs->clipping.top;
+
+	pf->field = V4L2_FIELD_INTERLACED;
+	pf->bytesperline = vcs->line_size;
+	pf->sizeimage = vcs->line_size *
+		(vcs->clipping.bottom - vcs->clipping.top) /
+		vcs->decimation;
+	pf->colorspace =
+		vino_data_formats[vcs->data_format].colorspace;
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+	return 0;
+}
+
+static int vino_cropcap(struct file *file, void *__fh,
+			     struct v4l2_cropcap *ccap)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	const struct vino_data_norm *norm;
+	unsigned long flags;
+
+	switch (ccap->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+		norm = &vino_data_norms[vcs->data_norm];
+
+		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+		ccap->bounds.left = 0;
+		ccap->bounds.top = 0;
+		ccap->bounds.width = norm->width;
+		ccap->bounds.height = norm->height;
+		memcpy(&ccap->defrect, &ccap->bounds,
+		       sizeof(struct v4l2_rect));
+
+		ccap->pixelaspect.numerator = 1;
+		ccap->pixelaspect.denominator = 1;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vino_g_crop(struct file *file, void *__fh,
+			    struct v4l2_crop *c)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+
+	switch (c->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+		c->c.left = vcs->clipping.left;
+		c->c.top = vcs->clipping.top;
+		c->c.width = vcs->clipping.right - vcs->clipping.left;
+		c->c.height = vcs->clipping.bottom - vcs->clipping.top;
+
+		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vino_s_crop(struct file *file, void *__fh,
+			    const struct v4l2_crop *c)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+
+	switch (c->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+		vino_set_clipping(vcs, c->c.left, c->c.top,
+				  c->c.width, c->c.height);
+
+		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vino_g_parm(struct file *file, void *__fh,
+			    struct v4l2_streamparm *sp)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	struct v4l2_captureparm *cp = &sp->parm.capture;
+
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->timeperframe.numerator = 1;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	cp->timeperframe.denominator = vcs->fps;
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	/* TODO: cp->readbuffers = xxx; */
+
+	return 0;
+}
+
+static int vino_s_parm(struct file *file, void *__fh,
+			    struct v4l2_streamparm *sp)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	struct v4l2_captureparm *cp = &sp->parm.capture;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	if ((cp->timeperframe.numerator == 0) ||
+	    (cp->timeperframe.denominator == 0)) {
+		/* reset framerate */
+		vino_set_default_framerate(vcs);
+	} else {
+		vino_set_framerate(vcs, cp->timeperframe.denominator /
+				   cp->timeperframe.numerator);
+	}
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return 0;
+}
+
+static int vino_reqbufs(struct file *file, void *__fh,
+			     struct v4l2_requestbuffers *rb)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+
+	if (vcs->reading)
+		return -EBUSY;
+
+	/* TODO: check queue type */
+	if (rb->memory != V4L2_MEMORY_MMAP) {
+		dprintk("type not mmap\n");
+		return -EINVAL;
+	}
+
+	dprintk("count = %d\n", rb->count);
+	if (rb->count > 0) {
+		if (vino_is_capturing(vcs)) {
+			dprintk("busy, capturing\n");
+			return -EBUSY;
+		}
+
+		if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
+			dprintk("busy, buffers still mapped\n");
+			return -EBUSY;
+		} else {
+			vcs->streaming = 0;
+			vino_queue_free(&vcs->fb_queue);
+			vino_queue_init(&vcs->fb_queue, &rb->count);
+		}
+	} else {
+		vcs->streaming = 0;
+		vino_capture_stop(vcs);
+		vino_queue_free(&vcs->fb_queue);
+	}
+
+	return 0;
+}
+
+static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
+					struct vino_framebuffer *fb,
+					struct v4l2_buffer *b)
+{
+	if (vino_queue_outgoing_contains(&vcs->fb_queue,
+					 fb->id)) {
+		b->flags &= ~V4L2_BUF_FLAG_QUEUED;
+		b->flags |= V4L2_BUF_FLAG_DONE;
+	} else if (vino_queue_incoming_contains(&vcs->fb_queue,
+				       fb->id)) {
+		b->flags &= ~V4L2_BUF_FLAG_DONE;
+		b->flags |= V4L2_BUF_FLAG_QUEUED;
+	} else {
+		b->flags &= ~(V4L2_BUF_FLAG_DONE |
+			      V4L2_BUF_FLAG_QUEUED);
+	}
+
+	b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
+
+	if (fb->map_count > 0)
+		b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+	b->flags &= ~V4L2_BUF_FLAG_TIMESTAMP_MASK;
+	b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+
+	b->index = fb->id;
+	b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
+		V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
+	b->m.offset = fb->offset;
+	b->bytesused = fb->data_size;
+	b->length = fb->size;
+	b->field = V4L2_FIELD_INTERLACED;
+	b->sequence = fb->frame_counter;
+	memcpy(&b->timestamp, &fb->timestamp,
+	       sizeof(struct timeval));
+	// b->input ?
+
+	dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
+		fb->id, fb->size, fb->data_size, fb->offset);
+}
+
+static int vino_querybuf(struct file *file, void *__fh,
+			      struct v4l2_buffer *b)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	struct vino_framebuffer *fb;
+
+	if (vcs->reading)
+		return -EBUSY;
+
+	/* TODO: check queue type */
+	if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
+		dprintk("invalid index = %d\n",
+		       b->index);
+		return -EINVAL;
+	}
+
+	fb = vino_queue_get_buffer(&vcs->fb_queue,
+				   b->index);
+	if (fb == NULL) {
+		dprintk("vino_queue_get_buffer() failed");
+		return -EINVAL;
+	}
+
+	vino_v4l2_get_buffer_status(vcs, fb, b);
+
+	return 0;
+}
+
+static int vino_qbuf(struct file *file, void *__fh,
+			  struct v4l2_buffer *b)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	struct vino_framebuffer *fb;
+	int ret;
+
+	if (vcs->reading)
+		return -EBUSY;
+
+	/* TODO: check queue type */
+	if (b->memory != V4L2_MEMORY_MMAP) {
+		dprintk("type not mmap\n");
+		return -EINVAL;
+	}
+
+	fb = vino_capture_enqueue(vcs, b->index);
+	if (fb == NULL)
+		return -EINVAL;
+
+	vino_v4l2_get_buffer_status(vcs, fb, b);
+
+	if (vcs->streaming) {
+		ret = vino_capture_next(vcs, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int vino_dqbuf(struct file *file, void *__fh,
+			   struct v4l2_buffer *b)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned int nonblocking = file->f_flags & O_NONBLOCK;
+	struct vino_framebuffer *fb;
+	unsigned int incoming, outgoing;
+	int err;
+
+	if (vcs->reading)
+		return -EBUSY;
+
+	/* TODO: check queue type */
+
+	err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+	if (err) {
+		dprintk("vino_queue_get_incoming() failed\n");
+		return -EINVAL;
+	}
+	err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
+	if (err) {
+		dprintk("vino_queue_get_outgoing() failed\n");
+		return -EINVAL;
+	}
+
+	dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
+
+	if (outgoing == 0) {
+		if (incoming == 0) {
+			dprintk("no incoming or outgoing buffers\n");
+			return -EINVAL;
+		}
+		if (nonblocking) {
+			dprintk("non-blocking I/O was selected and "
+				"there are no buffers to dequeue\n");
+			return -EAGAIN;
+		}
+
+		err = vino_wait_for_frame(vcs);
+		if (err) {
+			err = vino_wait_for_frame(vcs);
+			if (err) {
+				/* interrupted or no frames captured because of
+				 * frame skipping */
+				/* vino_capture_failed(vcs); */
+				return -EIO;
+			}
+		}
+	}
+
+	fb = vino_queue_remove(&vcs->fb_queue, &b->index);
+	if (fb == NULL) {
+		dprintk("vino_queue_remove() failed\n");
+		return -EINVAL;
+	}
+
+	err = vino_check_buffer(vcs, fb);
+
+	vino_v4l2_get_buffer_status(vcs, fb, b);
+
+	if (err)
+		return -EIO;
+
+	return 0;
+}
+
+static int vino_streamon(struct file *file, void *__fh,
+		enum v4l2_buf_type i)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned int incoming;
+	int ret;
+	if (vcs->reading)
+		return -EBUSY;
+
+	if (vcs->streaming)
+		return 0;
+
+	// TODO: check queue type
+
+	if (vino_queue_get_length(&vcs->fb_queue) < 1) {
+		dprintk("no buffers allocated\n");
+		return -EINVAL;
+	}
+
+	ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+	if (ret) {
+		dprintk("vino_queue_get_incoming() failed\n");
+		return -EINVAL;
+	}
+
+	vcs->streaming = 1;
+
+	if (incoming > 0) {
+		ret = vino_capture_next(vcs, 1);
+		if (ret) {
+			vcs->streaming = 0;
+
+			dprintk("couldn't start capture\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int vino_streamoff(struct file *file, void *__fh,
+		enum v4l2_buf_type i)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	if (vcs->reading)
+		return -EBUSY;
+
+	if (!vcs->streaming)
+		return 0;
+
+	vcs->streaming = 0;
+	vino_capture_stop(vcs);
+
+	return 0;
+}
+
+static int vino_queryctrl(struct file *file, void *__fh,
+			       struct v4l2_queryctrl *queryctrl)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	int i;
+	int err = 0;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	switch (vcs->input) {
+	case VINO_INPUT_D1:
+		for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+			if (vino_indycam_v4l2_controls[i].id ==
+			    queryctrl->id) {
+				memcpy(queryctrl,
+				       &vino_indycam_v4l2_controls[i],
+				       sizeof(struct v4l2_queryctrl));
+				queryctrl->reserved[0] = 0;
+				goto found;
+			}
+		}
+
+		err =  -EINVAL;
+		break;
+	case VINO_INPUT_COMPOSITE:
+	case VINO_INPUT_SVIDEO:
+		for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+			if (vino_saa7191_v4l2_controls[i].id ==
+			    queryctrl->id) {
+				memcpy(queryctrl,
+				       &vino_saa7191_v4l2_controls[i],
+				       sizeof(struct v4l2_queryctrl));
+				queryctrl->reserved[0] = 0;
+				goto found;
+			}
+		}
+
+		err =  -EINVAL;
+		break;
+	default:
+		err =  -EINVAL;
+	}
+
+ found:
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return err;
+}
+
+static int vino_g_ctrl(struct file *file, void *__fh,
+			    struct v4l2_control *control)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	int i;
+	int err = 0;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	switch (vcs->input) {
+	case VINO_INPUT_D1: {
+		err = -EINVAL;
+		for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+			if (vino_indycam_v4l2_controls[i].id == control->id) {
+				err = 0;
+				break;
+			}
+		}
+
+		if (err)
+			goto out;
+
+		err = camera_call(core, g_ctrl, control);
+		if (err)
+			err = -EINVAL;
+		break;
+	}
+	case VINO_INPUT_COMPOSITE:
+	case VINO_INPUT_SVIDEO: {
+		err = -EINVAL;
+		for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+			if (vino_saa7191_v4l2_controls[i].id == control->id) {
+				err = 0;
+				break;
+			}
+		}
+
+		if (err)
+			goto out;
+
+		err = decoder_call(core, g_ctrl, control);
+		if (err)
+			err = -EINVAL;
+		break;
+	}
+	default:
+		err =  -EINVAL;
+	}
+
+out:
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return err;
+}
+
+static int vino_s_ctrl(struct file *file, void *__fh,
+			    struct v4l2_control *control)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	int i;
+	int err = 0;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	if (!vino_is_input_owner(vcs)) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	switch (vcs->input) {
+	case VINO_INPUT_D1: {
+		err = -EINVAL;
+		for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+			if (vino_indycam_v4l2_controls[i].id == control->id) {
+				err = 0;
+				break;
+			}
+		}
+		if (err)
+			goto out;
+		if (control->value < vino_indycam_v4l2_controls[i].minimum ||
+		    control->value > vino_indycam_v4l2_controls[i].maximum) {
+			err = -ERANGE;
+			goto out;
+		}
+		err = camera_call(core, s_ctrl, control);
+		if (err)
+			err = -EINVAL;
+		break;
+	}
+	case VINO_INPUT_COMPOSITE:
+	case VINO_INPUT_SVIDEO: {
+		err = -EINVAL;
+		for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+			if (vino_saa7191_v4l2_controls[i].id == control->id) {
+				err = 0;
+				break;
+			}
+		}
+		if (err)
+			goto out;
+		if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
+		    control->value > vino_saa7191_v4l2_controls[i].maximum) {
+			err = -ERANGE;
+			goto out;
+		}
+
+		err = decoder_call(core, s_ctrl, control);
+		if (err)
+			err = -EINVAL;
+		break;
+	}
+	default:
+		err =  -EINVAL;
+	}
+
+out:
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+	return err;
+}
+
+/* File operations */
+
+static int vino_open(struct file *file)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	int ret = 0;
+	dprintk("open(): channel = %c\n",
+	       (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
+
+	mutex_lock(&vcs->mutex);
+
+	if (vcs->users) {
+		dprintk("open(): driver busy\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = vino_acquire_input(vcs);
+	if (ret) {
+		dprintk("open(): vino_acquire_input() failed\n");
+		goto out;
+	}
+
+	vcs->users++;
+
+ out:
+	mutex_unlock(&vcs->mutex);
+
+	dprintk("open(): %s!\n", ret ? "failed" : "complete");
+
+	return ret;
+}
+
+static int vino_close(struct file *file)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	dprintk("close():\n");
+
+	mutex_lock(&vcs->mutex);
+
+	vcs->users--;
+
+	if (!vcs->users) {
+		vino_release_input(vcs);
+
+		/* stop DMA and free buffers */
+		vino_capture_stop(vcs);
+		vino_queue_free(&vcs->fb_queue);
+	}
+
+	mutex_unlock(&vcs->mutex);
+
+	return 0;
+}
+
+static void vino_vm_open(struct vm_area_struct *vma)
+{
+	struct vino_framebuffer *fb = vma->vm_private_data;
+
+	fb->map_count++;
+	dprintk("vino_vm_open(): count = %d\n", fb->map_count);
+}
+
+static void vino_vm_close(struct vm_area_struct *vma)
+{
+	struct vino_framebuffer *fb = vma->vm_private_data;
+
+	fb->map_count--;
+	dprintk("vino_vm_close(): count = %d\n", fb->map_count);
+}
+
+static const struct vm_operations_struct vino_vm_ops = {
+	.open	= vino_vm_open,
+	.close	= vino_vm_close,
+};
+
+static int vino_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+
+	unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+	struct vino_framebuffer *fb = NULL;
+	unsigned int i, length;
+	int ret = 0;
+
+	dprintk("mmap():\n");
+
+	// TODO: reject mmap if already mapped
+
+	if (mutex_lock_interruptible(&vcs->mutex))
+		return -EINTR;
+
+	if (vcs->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	// TODO: check queue type
+
+	if (!(vma->vm_flags & VM_WRITE)) {
+		dprintk("mmap(): app bug: PROT_WRITE please\n");
+		ret = -EINVAL;
+		goto out;
+	}
+	if (!(vma->vm_flags & VM_SHARED)) {
+		dprintk("mmap(): app bug: MAP_SHARED please\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* find the correct buffer using offset */
+	length = vino_queue_get_length(&vcs->fb_queue);
+	if (length == 0) {
+		dprintk("mmap(): queue not initialized\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	for (i = 0; i < length; i++) {
+		fb = vino_queue_get_buffer(&vcs->fb_queue, i);
+		if (fb == NULL) {
+			dprintk("mmap(): vino_queue_get_buffer() failed\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (fb->offset == offset)
+			goto found;
+	}
+
+	dprintk("mmap(): invalid offset = %lu\n", offset);
+	ret = -EINVAL;
+	goto out;
+
+found:
+	dprintk("mmap(): buffer = %d\n", i);
+
+	if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
+		dprintk("mmap(): failed: size = %lu > %lu\n",
+			size, fb->desc_table.page_count * PAGE_SIZE);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	for (i = 0; i < fb->desc_table.page_count; i++) {
+		unsigned long pfn =
+			virt_to_phys((void *)fb->desc_table.virtual[i]) >>
+			PAGE_SHIFT;
+
+		if (size < PAGE_SIZE)
+			break;
+
+		// protection was: PAGE_READONLY
+		if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
+				    vma->vm_page_prot)) {
+			dprintk("mmap(): remap_pfn_range() failed\n");
+			ret = -EAGAIN;
+			goto out;
+		}
+
+		start += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	fb->map_count = 1;
+
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+	vma->vm_flags &= ~VM_IO;
+	vma->vm_private_data = fb;
+	vma->vm_file = file;
+	vma->vm_ops = &vino_vm_ops;
+
+out:
+	mutex_unlock(&vcs->mutex);
+
+	return ret;
+}
+
+static unsigned int vino_poll(struct file *file, poll_table *pt)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned int outgoing;
+	unsigned int ret = 0;
+
+	// lock mutex (?)
+	// TODO: this has to be corrected for different read modes
+
+	dprintk("poll():\n");
+
+	if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+		dprintk("poll(): vino_queue_get_outgoing() failed\n");
+		ret = POLLERR;
+		goto error;
+	}
+	if (outgoing > 0)
+		goto over;
+
+	poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
+
+	if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+		dprintk("poll(): vino_queue_get_outgoing() failed\n");
+		ret = POLLERR;
+		goto error;
+	}
+
+over:
+	dprintk("poll(): data %savailable\n",
+		(outgoing > 0) ? "" : "not ");
+
+	if (outgoing > 0)
+		ret = POLLIN | POLLRDNORM;
+
+error:
+	return ret;
+}
+
+static long vino_ioctl(struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	long ret;
+
+	if (mutex_lock_interruptible(&vcs->mutex))
+		return -EINTR;
+
+	ret = video_ioctl2(file, cmd, arg);
+
+	mutex_unlock(&vcs->mutex);
+
+	return ret;
+}
+
+/* Initialization and cleanup */
+
+/* __initdata */
+static int vino_init_stage;
+
+const struct v4l2_ioctl_ops vino_ioctl_ops = {
+	.vidioc_enum_fmt_vid_cap     = vino_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap 	     = vino_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap  	     = vino_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap	     = vino_try_fmt_vid_cap,
+	.vidioc_querycap    	     = vino_querycap,
+	.vidioc_enum_input   	     = vino_enum_input,
+	.vidioc_g_input      	     = vino_g_input,
+	.vidioc_s_input      	     = vino_s_input,
+	.vidioc_g_std 		     = vino_g_std,
+	.vidioc_s_std 		     = vino_s_std,
+	.vidioc_querystd             = vino_querystd,
+	.vidioc_cropcap      	     = vino_cropcap,
+	.vidioc_s_crop       	     = vino_s_crop,
+	.vidioc_g_crop       	     = vino_g_crop,
+	.vidioc_s_parm 		     = vino_s_parm,
+	.vidioc_g_parm 		     = vino_g_parm,
+	.vidioc_reqbufs              = vino_reqbufs,
+	.vidioc_querybuf             = vino_querybuf,
+	.vidioc_qbuf                 = vino_qbuf,
+	.vidioc_dqbuf                = vino_dqbuf,
+	.vidioc_streamon             = vino_streamon,
+	.vidioc_streamoff            = vino_streamoff,
+	.vidioc_queryctrl            = vino_queryctrl,
+	.vidioc_g_ctrl               = vino_g_ctrl,
+	.vidioc_s_ctrl               = vino_s_ctrl,
+};
+
+static const struct v4l2_file_operations vino_fops = {
+	.owner		= THIS_MODULE,
+	.open		= vino_open,
+	.release	= vino_close,
+	.unlocked_ioctl	= vino_ioctl,
+	.mmap		= vino_mmap,
+	.poll		= vino_poll,
+};
+
+static struct video_device vdev_template = {
+	.name		= "NOT SET",
+	.fops		= &vino_fops,
+	.ioctl_ops 	= &vino_ioctl_ops,
+	.tvnorms 	= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+};
+
+static void vino_module_cleanup(int stage)
+{
+	switch(stage) {
+	case 11:
+		video_unregister_device(vino_drvdata->b.vdev);
+		vino_drvdata->b.vdev = NULL;
+	case 10:
+		video_unregister_device(vino_drvdata->a.vdev);
+		vino_drvdata->a.vdev = NULL;
+	case 9:
+		i2c_del_adapter(&vino_i2c_adapter);
+	case 8:
+		free_irq(SGI_VINO_IRQ, NULL);
+	case 7:
+		if (vino_drvdata->b.vdev) {
+			video_device_release(vino_drvdata->b.vdev);
+			vino_drvdata->b.vdev = NULL;
+		}
+	case 6:
+		if (vino_drvdata->a.vdev) {
+			video_device_release(vino_drvdata->a.vdev);
+			vino_drvdata->a.vdev = NULL;
+		}
+	case 5:
+		/* all entries in dma_cpu dummy table have the same address */
+		dma_unmap_single(NULL,
+				 vino_drvdata->dummy_desc_table.dma_cpu[0],
+				 PAGE_SIZE, DMA_FROM_DEVICE);
+		dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
+				  * sizeof(dma_addr_t),
+				  (void *)vino_drvdata->
+				  dummy_desc_table.dma_cpu,
+				  vino_drvdata->dummy_desc_table.dma);
+	case 4:
+		free_page(vino_drvdata->dummy_page);
+	case 3:
+		v4l2_device_unregister(&vino_drvdata->v4l2_dev);
+	case 2:
+		kfree(vino_drvdata);
+	case 1:
+		iounmap(vino);
+	case 0:
+		break;
+	default:
+		dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
+			stage);
+	}
+}
+
+static int vino_probe(void)
+{
+	unsigned long rev_id;
+
+	if (ip22_is_fullhouse()) {
+		printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
+		return -ENODEV;
+	}
+
+	if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
+		printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
+		return -ENODEV;
+	}
+
+	vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
+	if (!vino) {
+		printk(KERN_ERR "VINO: ioremap() failed\n");
+		return -EIO;
+	}
+	vino_init_stage++;
+
+	if (get_dbe(rev_id, &(vino->rev_id))) {
+		printk(KERN_ERR "Failed to read VINO revision register\n");
+		vino_module_cleanup(vino_init_stage);
+		return -ENODEV;
+	}
+
+	if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
+		printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
+		       rev_id);
+		vino_module_cleanup(vino_init_stage);
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id));
+
+	return 0;
+}
+
+static int vino_init(void)
+{
+	dma_addr_t dma_dummy_address;
+	int err;
+	int i;
+
+	vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
+	if (!vino_drvdata) {
+		vino_module_cleanup(vino_init_stage);
+		return -ENOMEM;
+	}
+	vino_init_stage++;
+	strlcpy(vino_drvdata->v4l2_dev.name, "vino",
+			sizeof(vino_drvdata->v4l2_dev.name));
+	err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
+	if (err)
+		return err;
+	vino_init_stage++;
+
+	/* create a dummy dma descriptor */
+	vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	if (!vino_drvdata->dummy_page) {
+		vino_module_cleanup(vino_init_stage);
+		return -ENOMEM;
+	}
+	vino_init_stage++;
+
+	// TODO: use page_count in dummy_desc_table
+
+	vino_drvdata->dummy_desc_table.dma_cpu =
+		dma_alloc_coherent(NULL,
+		VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
+		&vino_drvdata->dummy_desc_table.dma,
+		GFP_KERNEL | GFP_DMA);
+	if (!vino_drvdata->dummy_desc_table.dma_cpu) {
+		vino_module_cleanup(vino_init_stage);
+		return -ENOMEM;
+	}
+	vino_init_stage++;
+
+	dma_dummy_address = dma_map_single(NULL,
+					   (void *)vino_drvdata->dummy_page,
+					PAGE_SIZE, DMA_FROM_DEVICE);
+	for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
+		vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
+	}
+
+	/* initialize VINO */
+
+	vino->control = 0;
+	vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+	vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+	udelay(VINO_DESC_FETCH_DELAY);
+
+	vino->intr_status = 0;
+
+	vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+	vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+
+	return 0;
+}
+
+static int vino_init_channel_settings(struct vino_channel_settings *vcs,
+				 unsigned int channel, const char *name)
+{
+	vcs->channel = channel;
+	vcs->input = VINO_INPUT_NONE;
+	vcs->alpha = 0;
+	vcs->users = 0;
+	vcs->data_format = VINO_DATA_FMT_GREY;
+	vcs->data_norm = VINO_DATA_NORM_NTSC;
+	vcs->decimation = 1;
+	vino_set_default_clipping(vcs);
+	vino_set_default_framerate(vcs);
+
+	vcs->capturing = 0;
+
+	mutex_init(&vcs->mutex);
+	spin_lock_init(&vcs->capture_lock);
+
+	mutex_init(&vcs->fb_queue.queue_mutex);
+	spin_lock_init(&vcs->fb_queue.queue_lock);
+	init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
+
+	vcs->vdev = video_device_alloc();
+	if (!vcs->vdev) {
+		vino_module_cleanup(vino_init_stage);
+		return -ENOMEM;
+	}
+	vino_init_stage++;
+
+	memcpy(vcs->vdev, &vdev_template,
+	       sizeof(struct video_device));
+	strcpy(vcs->vdev->name, name);
+	vcs->vdev->release = video_device_release;
+	vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
+
+	video_set_drvdata(vcs->vdev, vcs);
+
+	return 0;
+}
+
+static int __init vino_module_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "SGI VINO driver version %s\n",
+	       VINO_MODULE_VERSION);
+
+	ret = vino_probe();
+	if (ret)
+		return ret;
+
+	ret = vino_init();
+	if (ret)
+		return ret;
+
+	/* initialize data structures */
+
+	spin_lock_init(&vino_drvdata->vino_lock);
+	spin_lock_init(&vino_drvdata->input_lock);
+
+	ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
+				    vino_vdev_name_a);
+	if (ret)
+		return ret;
+
+	ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
+				    vino_vdev_name_b);
+	if (ret)
+		return ret;
+
+	/* initialize hardware and register V4L devices */
+
+	ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
+		vino_driver_description, NULL);
+	if (ret) {
+		printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
+		       SGI_VINO_IRQ);
+		vino_module_cleanup(vino_init_stage);
+		return -EAGAIN;
+	}
+	vino_init_stage++;
+
+	ret = i2c_add_adapter(&vino_i2c_adapter);
+	if (ret) {
+		printk(KERN_ERR "VINO I2C bus registration failed\n");
+		vino_module_cleanup(vino_init_stage);
+		return ret;
+	}
+	i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
+	vino_init_stage++;
+
+	ret = video_register_device(vino_drvdata->a.vdev,
+				    VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		printk(KERN_ERR "VINO channel A Video4Linux-device "
+		       "registration failed\n");
+		vino_module_cleanup(vino_init_stage);
+		return -EINVAL;
+	}
+	vino_init_stage++;
+
+	ret = video_register_device(vino_drvdata->b.vdev,
+				    VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		printk(KERN_ERR "VINO channel B Video4Linux-device "
+		       "registration failed\n");
+		vino_module_cleanup(vino_init_stage);
+		return -EINVAL;
+	}
+	vino_init_stage++;
+
+	vino_drvdata->decoder =
+		v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
+			       "saa7191", 0, I2C_ADDRS(0x45));
+	vino_drvdata->camera =
+		v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
+			       "indycam", 0, I2C_ADDRS(0x2b));
+
+	dprintk("init complete!\n");
+
+	return 0;
+}
+
+static void __exit vino_module_exit(void)
+{
+	dprintk("exiting, stage = %d ...\n", vino_init_stage);
+	vino_module_cleanup(vino_init_stage);
+	dprintk("cleanup complete, exit!\n");
+}
+
+module_init(vino_module_init);
+module_exit(vino_module_exit);
diff --git a/drivers/media/platform/vino.h b/drivers/media/platform/vino.h
new file mode 100644
index 0000000..de2d615
--- /dev/null
+++ b/drivers/media/platform/vino.h
@@ -0,0 +1,138 @@
+/*
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se>
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ */
+
+#ifndef _VINO_H_
+#define _VINO_H_
+
+#define VINO_BASE	0x00080000	/* Vino is in the EISA address space,
+					 * but it is not an EISA bus card */
+#define VINO_PAGE_SIZE	4096
+
+struct sgi_vino_channel {
+	u32 _pad_alpha;
+	volatile u32 alpha;
+
+#define VINO_CLIP_X(x)		((x) & 0x3ff)		/* bits 0:9 */
+#define VINO_CLIP_ODD(x)	(((x) & 0x1ff) << 10)	/* bits 10:18 */
+#define VINO_CLIP_EVEN(x)	(((x) & 0x1ff) << 19)	/* bits 19:27 */
+	u32 _pad_clip_start;
+	volatile u32 clip_start;
+	u32 _pad_clip_end;
+	volatile u32 clip_end;
+
+#define VINO_FRAMERT_FULL	0xfff
+#define VINO_FRAMERT_PAL	(1<<0)			/* 0=NTSC 1=PAL */
+#define VINO_FRAMERT_RT(x)	(((x) & 0xfff) << 1)	/* bits 1:12 */
+	u32 _pad_frame_rate;
+	volatile u32 frame_rate;
+
+	u32 _pad_field_counter;
+	volatile u32 field_counter;
+	u32 _pad_line_size;
+	volatile u32 line_size;
+	u32 _pad_line_count;
+	volatile u32 line_count;
+	u32 _pad_page_index;
+	volatile u32 page_index;
+	u32 _pad_next_4_desc;
+	volatile u32 next_4_desc;
+	u32 _pad_start_desc_tbl;
+	volatile u32 start_desc_tbl;
+
+#define VINO_DESC_JUMP		(1<<30)
+#define VINO_DESC_STOP		(1<<31)
+#define VINO_DESC_VALID		(1<<32)
+	u32 _pad_desc_0;
+	volatile u32 desc_0;
+	u32 _pad_desc_1;
+	volatile u32 desc_1;
+	u32 _pad_desc_2;
+	volatile u32 desc_2;
+	u32 _pad_Bdesc_3;
+	volatile u32 desc_3;
+
+	u32 _pad_fifo_thres;
+	volatile u32 fifo_thres;
+	u32 _pad_fifo_read;
+	volatile u32 fifo_read;
+	u32 _pad_fifo_write;
+	volatile u32 fifo_write;
+};
+
+struct sgi_vino {
+#define VINO_CHIP_ID		0xb
+#define VINO_REV_NUM(x)		((x) & 0x0f)
+#define VINO_ID_VALUE(x)	(((x) & 0xf0) >> 4)
+	u32 _pad_rev_id;
+	volatile u32 rev_id;
+
+#define VINO_CTRL_LITTLE_ENDIAN		(1<<0)
+#define VINO_CTRL_A_EOF_INT		(1<<1)	/* Field transferred int */
+#define VINO_CTRL_A_FIFO_INT		(1<<2)	/* FIFO overflow int */
+#define VINO_CTRL_A_EOD_INT		(1<<3)	/* End of desc table int */
+#define VINO_CTRL_A_INT			(VINO_CTRL_A_EOF_INT | \
+					 VINO_CTRL_A_FIFO_INT | \
+					 VINO_CTRL_A_EOD_INT)
+#define VINO_CTRL_B_EOF_INT		(1<<4)	/* Field transferred int */
+#define VINO_CTRL_B_FIFO_INT		(1<<5)	/* FIFO overflow int */
+#define VINO_CTRL_B_EOD_INT		(1<<6)	/* End of desc table int */
+#define VINO_CTRL_B_INT			(VINO_CTRL_B_EOF_INT | \
+					 VINO_CTRL_B_FIFO_INT | \
+					 VINO_CTRL_B_EOD_INT)
+#define VINO_CTRL_A_DMA_ENBL		(1<<7)
+#define VINO_CTRL_A_INTERLEAVE_ENBL	(1<<8)
+#define VINO_CTRL_A_SYNC_ENBL		(1<<9)
+#define VINO_CTRL_A_SELECT		(1<<10)	/* 1=D1 0=Philips */
+#define VINO_CTRL_A_RGB			(1<<11)	/* 1=RGB 0=YUV */
+#define VINO_CTRL_A_LUMA_ONLY		(1<<12)
+#define VINO_CTRL_A_DEC_ENBL		(1<<13)	/* Decimation */
+#define VINO_CTRL_A_DEC_SCALE_MASK	0x1c000	/* bits 14:17 */
+#define VINO_CTRL_A_DEC_SCALE_SHIFT	(14)
+#define VINO_CTRL_A_DEC_HOR_ONLY	(1<<17)	/* Horizontal only */
+#define VINO_CTRL_A_DITHER		(1<<18)	/* 24 -> 8 bit dither */
+#define VINO_CTRL_B_DMA_ENBL		(1<<19)
+#define VINO_CTRL_B_INTERLEAVE_ENBL	(1<<20)
+#define VINO_CTRL_B_SYNC_ENBL		(1<<21)
+#define VINO_CTRL_B_SELECT		(1<<22)	/* 1=D1 0=Philips */
+#define VINO_CTRL_B_RGB			(1<<23)	/* 1=RGB 0=YUV */
+#define VINO_CTRL_B_LUMA_ONLY		(1<<24)
+#define VINO_CTRL_B_DEC_ENBL		(1<<25)	/* Decimation */
+#define VINO_CTRL_B_DEC_SCALE_MASK	0x1c000000	/* bits 26:28 */
+#define VINO_CTRL_B_DEC_SCALE_SHIFT	(26)
+#define VINO_CTRL_B_DEC_HOR_ONLY	(1<<29)	/* Decimation horizontal only */
+#define VINO_CTRL_B_DITHER		(1<<30)	/* ChanB 24 -> 8 bit dither */
+	u32 _pad_control;
+	volatile u32 control;
+
+#define VINO_INTSTAT_A_EOF		(1<<0)	/* Field transferred int */
+#define VINO_INTSTAT_A_FIFO		(1<<1)	/* FIFO overflow int */
+#define VINO_INTSTAT_A_EOD		(1<<2)	/* End of desc table int */
+#define VINO_INTSTAT_A			(VINO_INTSTAT_A_EOF | \
+					 VINO_INTSTAT_A_FIFO | \
+					 VINO_INTSTAT_A_EOD)
+#define VINO_INTSTAT_B_EOF		(1<<3)	/* Field transferred int */
+#define VINO_INTSTAT_B_FIFO		(1<<4)	/* FIFO overflow int */
+#define VINO_INTSTAT_B_EOD		(1<<5)	/* End of desc table int */
+#define VINO_INTSTAT_B			(VINO_INTSTAT_B_EOF | \
+					 VINO_INTSTAT_B_FIFO | \
+					 VINO_INTSTAT_B_EOD)
+	u32 _pad_intr_status;
+	volatile u32 intr_status;
+
+	u32 _pad_i2c_control;
+	volatile u32 i2c_control;
+	u32 _pad_i2c_data;
+	volatile u32 i2c_data;
+
+	struct sgi_vino_channel a;
+	struct sgi_vino_channel b;
+};
+
+#endif
diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig
index c03e09c..0d2d7c1 100644
--- a/drivers/media/platform/vivid/Kconfig
+++ b/drivers/media/platform/vivid/Kconfig
@@ -1,12 +1,9 @@
 config VIDEO_VIVID
 	tristate "Virtual Video Test Driver"
 	depends on m
-	depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FB
+	depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
 	depends on FONT_SUPPORT
 	depends on FONT_8x16
-	depends on FB_CFB_FILLRECT
-	depends on FB_CFB_COPYAREA
-	depends on FB_CFB_IMAGEBLIT
 	select VIDEOBUF2_VMALLOC
 	default n
 	---help---
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index a7e033a..2c61a62 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -100,9 +100,11 @@
 			   "\t\t    bit 0=crop, 1=compose, 2=scale,\n"
 			   "\t\t    -1=user-controlled (default)");
 
-static unsigned multiplanar[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 1 };
+static unsigned multiplanar[VIVID_MAX_DEVS];
 module_param_array(multiplanar, uint, NULL, 0444);
-MODULE_PARM_DESC(multiplanar, " 1 (default) creates a single planar device, 2 creates a multiplanar device.");
+MODULE_PARM_DESC(multiplanar, " 0 (default) is alternating single and multiplanar devices,\n"
+			      "\t\t    1 is single planar devices,\n"
+			      "\t\t    2 is multiplanar devices");
 
 /* Default: video + vbi-cap (raw and sliced) + radio rx + radio tx + sdr + vbi-out + vid-out */
 static unsigned node_types[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 0x1d3d };
@@ -195,6 +197,20 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7
 };
 
+void vivid_lock(struct vb2_queue *vq)
+{
+	struct vivid_dev *dev = vb2_get_drv_priv(vq);
+
+	mutex_lock(&dev->mutex);
+}
+
+void vivid_unlock(struct vb2_queue *vq)
+{
+	struct vivid_dev *dev = vb2_get_drv_priv(vq);
+
+	mutex_unlock(&dev->mutex);
+}
+
 static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *cap)
 {
@@ -572,7 +588,7 @@
 	.vidioc_querybuf		= vb2_ioctl_querybuf,
 	.vidioc_qbuf			= vb2_ioctl_qbuf,
 	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
-	.vidioc_expbuf			= vb2_ioctl_expbuf,
+/* Not yet	.vidioc_expbuf		= vb2_ioctl_expbuf,*/
 	.vidioc_streamon		= vb2_ioctl_streamon,
 	.vidioc_streamoff		= vb2_ioctl_streamoff,
 
@@ -653,7 +669,10 @@
 	/* start detecting feature set */
 
 	/* do we use single- or multi-planar? */
-	dev->multiplanar = multiplanar[inst] > 1;
+	if (multiplanar[inst] == 0)
+		dev->multiplanar = inst & 1;
+	else
+		dev->multiplanar = multiplanar[inst] > 1;
 	v4l2_info(&dev->v4l2_dev, "using %splanar format API\n",
 			dev->multiplanar ? "multi" : "single ");
 
@@ -1004,7 +1023,6 @@
 		q->mem_ops = &vb2_vmalloc_memops;
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 2;
-		q->lock = &dev->mutex;
 
 		ret = vb2_queue_init(q);
 		if (ret)
@@ -1023,7 +1041,6 @@
 		q->mem_ops = &vb2_vmalloc_memops;
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 2;
-		q->lock = &dev->mutex;
 
 		ret = vb2_queue_init(q);
 		if (ret)
@@ -1042,7 +1059,6 @@
 		q->mem_ops = &vb2_vmalloc_memops;
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 2;
-		q->lock = &dev->mutex;
 
 		ret = vb2_queue_init(q);
 		if (ret)
@@ -1061,7 +1077,6 @@
 		q->mem_ops = &vb2_vmalloc_memops;
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 2;
-		q->lock = &dev->mutex;
 
 		ret = vb2_queue_init(q);
 		if (ret)
@@ -1079,7 +1094,6 @@
 		q->mem_ops = &vb2_vmalloc_memops;
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 8;
-		q->lock = &dev->mutex;
 
 		ret = vb2_queue_init(q);
 		if (ret)
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 4b497df..811c286 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -116,17 +116,6 @@
 	CUSTOM_DV_TIMINGS,
 };
 
-enum vivid_colorspace {
-	VIVID_CS_170M,
-	VIVID_CS_709,
-	VIVID_CS_SRGB,
-	VIVID_CS_ADOBERGB,
-	VIVID_CS_2020,
-	VIVID_CS_240M,
-	VIVID_CS_SYS_M,
-	VIVID_CS_SYS_BG,
-};
-
 #define VIVID_INVALID_SIGNAL(mode) \
 	((mode) == NO_SIGNAL || (mode) == NO_LOCK || (mode) == OUT_OF_RANGE)
 
@@ -329,8 +318,6 @@
 	v4l2_std_id			std_out;
 	struct v4l2_dv_timings		dv_timings_out;
 	u32				colorspace_out;
-	u32				ycbcr_enc_out;
-	u32				quantization_out;
 	u32				service_set_out;
 	u32				bytesperline_out[2];
 	unsigned			tv_field_out;
@@ -527,4 +514,7 @@
 	return dev->output_type[dev->output] == HDMI;
 }
 
+void vivid_lock(struct vb2_queue *vq);
+void vivid_unlock(struct vb2_queue *vq);
+
 #endif
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 857e786..d5cbf00 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -40,9 +40,6 @@
 #define VIVID_CID_STRING		(VIVID_CID_CUSTOM_BASE + 5)
 #define VIVID_CID_BITMASK		(VIVID_CID_CUSTOM_BASE + 6)
 #define VIVID_CID_INTMENU		(VIVID_CID_CUSTOM_BASE + 7)
-#define VIVID_CID_U32_ARRAY		(VIVID_CID_CUSTOM_BASE + 8)
-#define VIVID_CID_U16_MATRIX		(VIVID_CID_CUSTOM_BASE + 9)
-#define VIVID_CID_U8_4D_ARRAY		(VIVID_CID_CUSTOM_BASE + 10)
 
 #define VIVID_CID_VIVID_BASE		(0x00f00000 | 0xf000)
 #define VIVID_CID_VIVID_CLASS		(0x00f00000 | 1)
@@ -62,21 +59,19 @@
 #define VIVID_CID_DV_TIMINGS_ASPECT_RATIO	(VIVID_CID_VIVID_BASE + 23)
 #define VIVID_CID_TSTAMP_SRC		(VIVID_CID_VIVID_BASE + 24)
 #define VIVID_CID_COLORSPACE		(VIVID_CID_VIVID_BASE + 25)
-#define VIVID_CID_YCBCR_ENC		(VIVID_CID_VIVID_BASE + 26)
-#define VIVID_CID_QUANTIZATION		(VIVID_CID_VIVID_BASE + 27)
-#define VIVID_CID_LIMITED_RGB_RANGE	(VIVID_CID_VIVID_BASE + 28)
-#define VIVID_CID_ALPHA_MODE		(VIVID_CID_VIVID_BASE + 29)
-#define VIVID_CID_HAS_CROP_CAP		(VIVID_CID_VIVID_BASE + 30)
-#define VIVID_CID_HAS_COMPOSE_CAP	(VIVID_CID_VIVID_BASE + 31)
-#define VIVID_CID_HAS_SCALER_CAP	(VIVID_CID_VIVID_BASE + 32)
-#define VIVID_CID_HAS_CROP_OUT		(VIVID_CID_VIVID_BASE + 33)
-#define VIVID_CID_HAS_COMPOSE_OUT	(VIVID_CID_VIVID_BASE + 34)
-#define VIVID_CID_HAS_SCALER_OUT	(VIVID_CID_VIVID_BASE + 35)
-#define VIVID_CID_LOOP_VIDEO		(VIVID_CID_VIVID_BASE + 36)
-#define VIVID_CID_SEQ_WRAP		(VIVID_CID_VIVID_BASE + 37)
-#define VIVID_CID_TIME_WRAP		(VIVID_CID_VIVID_BASE + 38)
-#define VIVID_CID_MAX_EDID_BLOCKS	(VIVID_CID_VIVID_BASE + 39)
-#define VIVID_CID_PERCENTAGE_FILL	(VIVID_CID_VIVID_BASE + 40)
+#define VIVID_CID_LIMITED_RGB_RANGE	(VIVID_CID_VIVID_BASE + 26)
+#define VIVID_CID_ALPHA_MODE		(VIVID_CID_VIVID_BASE + 27)
+#define VIVID_CID_HAS_CROP_CAP		(VIVID_CID_VIVID_BASE + 28)
+#define VIVID_CID_HAS_COMPOSE_CAP	(VIVID_CID_VIVID_BASE + 29)
+#define VIVID_CID_HAS_SCALER_CAP	(VIVID_CID_VIVID_BASE + 30)
+#define VIVID_CID_HAS_CROP_OUT		(VIVID_CID_VIVID_BASE + 31)
+#define VIVID_CID_HAS_COMPOSE_OUT	(VIVID_CID_VIVID_BASE + 32)
+#define VIVID_CID_HAS_SCALER_OUT	(VIVID_CID_VIVID_BASE + 33)
+#define VIVID_CID_LOOP_VIDEO		(VIVID_CID_VIVID_BASE + 34)
+#define VIVID_CID_SEQ_WRAP		(VIVID_CID_VIVID_BASE + 35)
+#define VIVID_CID_TIME_WRAP		(VIVID_CID_VIVID_BASE + 36)
+#define VIVID_CID_MAX_EDID_BLOCKS	(VIVID_CID_VIVID_BASE + 37)
+#define VIVID_CID_PERCENTAGE_FILL	(VIVID_CID_VIVID_BASE + 38)
 
 #define VIVID_CID_STD_SIGNAL_MODE	(VIVID_CID_VIVID_BASE + 60)
 #define VIVID_CID_STANDARD		(VIVID_CID_VIVID_BASE + 61)
@@ -168,42 +163,6 @@
 	.step = 1,
 };
 
-static const struct v4l2_ctrl_config vivid_ctrl_u32_array = {
-	.ops = &vivid_user_gen_ctrl_ops,
-	.id = VIVID_CID_U32_ARRAY,
-	.name = "U32 1 Element Array",
-	.type = V4L2_CTRL_TYPE_U32,
-	.def = 0x18,
-	.min = 0x10,
-	.max = 0x20000,
-	.step = 1,
-	.dims = { 1 },
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_u16_matrix = {
-	.ops = &vivid_user_gen_ctrl_ops,
-	.id = VIVID_CID_U16_MATRIX,
-	.name = "U16 8x16 Matrix",
-	.type = V4L2_CTRL_TYPE_U16,
-	.def = 0x18,
-	.min = 0x10,
-	.max = 0x2000,
-	.step = 1,
-	.dims = { 8, 16 },
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_u8_4d_array = {
-	.ops = &vivid_user_gen_ctrl_ops,
-	.id = VIVID_CID_U8_4D_ARRAY,
-	.name = "U8 2x3x4x5 Array",
-	.type = V4L2_CTRL_TYPE_U8,
-	.def = 0x18,
-	.min = 0x10,
-	.max = 0x20,
-	.step = 1,
-	.dims = { 2, 3, 4, 5 },
-};
-
 static const char * const vivid_ctrl_menu_strings[] = {
 	"Menu Item 0 (Skipped)",
 	"Menu Item 1",
@@ -335,16 +294,6 @@
 
 static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	static const u32 colorspaces[] = {
-		V4L2_COLORSPACE_SMPTE170M,
-		V4L2_COLORSPACE_REC709,
-		V4L2_COLORSPACE_SRGB,
-		V4L2_COLORSPACE_ADOBERGB,
-		V4L2_COLORSPACE_BT2020,
-		V4L2_COLORSPACE_SMPTE240M,
-		V4L2_COLORSPACE_470_SYSTEM_M,
-		V4L2_COLORSPACE_470_SYSTEM_BG,
-	};
 	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
 	unsigned i;
 
@@ -354,21 +303,7 @@
 		tpg_s_pattern(&dev->tpg, ctrl->val);
 		break;
 	case VIVID_CID_COLORSPACE:
-		tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]);
-		vivid_send_source_change(dev, TV);
-		vivid_send_source_change(dev, SVID);
-		vivid_send_source_change(dev, HDMI);
-		vivid_send_source_change(dev, WEBCAM);
-		break;
-	case VIVID_CID_YCBCR_ENC:
-		tpg_s_ycbcr_enc(&dev->tpg, ctrl->val);
-		vivid_send_source_change(dev, TV);
-		vivid_send_source_change(dev, SVID);
-		vivid_send_source_change(dev, HDMI);
-		vivid_send_source_change(dev, WEBCAM);
-		break;
-	case VIVID_CID_QUANTIZATION:
-		tpg_s_quantization(&dev->tpg, ctrl->val);
+		tpg_s_colorspace(&dev->tpg, ctrl->val);
 		vivid_send_source_change(dev, TV);
 		vivid_send_source_change(dev, SVID);
 		vivid_send_source_change(dev, HDMI);
@@ -688,14 +623,15 @@
 };
 
 static const char * const vivid_ctrl_colorspace_strings[] = {
+	"",
 	"SMPTE 170M",
-	"REC 709",
-	"sRGB",
-	"AdobeRGB",
-	"BT.2020",
 	"SMPTE 240M",
+	"REC 709",
+	"", /* Skip Bt878 entry */
 	"470 System M",
 	"470 System BG",
+	"", /* Skip JPEG entry */
+	"sRGB",
 	NULL,
 };
 
@@ -704,47 +640,11 @@
 	.id = VIVID_CID_COLORSPACE,
 	.name = "Colorspace",
 	.type = V4L2_CTRL_TYPE_MENU,
-	.max = 7,
-	.def = 2,
-	.qmenu = vivid_ctrl_colorspace_strings,
-};
-
-static const char * const vivid_ctrl_ycbcr_enc_strings[] = {
-	"Default",
-	"ITU-R 601",
-	"Rec. 709",
-	"xvYCC 601",
-	"xvYCC 709",
-	"sYCC",
-	"BT.2020 Non-Constant Luminance",
-	"BT.2020 Constant Luminance",
-	"SMPTE 240M",
-	NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
-	.ops = &vivid_vid_cap_ctrl_ops,
-	.id = VIVID_CID_YCBCR_ENC,
-	.name = "Y'CbCr Encoding",
-	.type = V4L2_CTRL_TYPE_MENU,
+	.min = 1,
 	.max = 8,
-	.qmenu = vivid_ctrl_ycbcr_enc_strings,
-};
-
-static const char * const vivid_ctrl_quantization_strings[] = {
-	"Default",
-	"Full Range",
-	"Limited Range",
-	NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_quantization = {
-	.ops = &vivid_vid_cap_ctrl_ops,
-	.id = VIVID_CID_QUANTIZATION,
-	.name = "Quantization",
-	.type = V4L2_CTRL_TYPE_MENU,
-	.max = 2,
-	.qmenu = vivid_ctrl_quantization_strings,
+	.menu_skip_mask = (1 << 4) | (1 << 7),
+	.def = 8,
+	.qmenu = vivid_ctrl_colorspace_strings,
 };
 
 static const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
@@ -823,12 +723,8 @@
 				dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
 			else
 				dev->colorspace_out = V4L2_COLORSPACE_REC709;
-			dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
 		} else {
 			dev->colorspace_out = V4L2_COLORSPACE_SRGB;
-			dev->quantization_out = dev->dvi_d_out ?
-					V4L2_QUANTIZATION_LIM_RANGE :
-					V4L2_QUANTIZATION_DEFAULT;
 		}
 		if (dev->loop_video)
 			vivid_send_source_change(dev, HDMI);
@@ -896,15 +792,15 @@
 		dev->start_streaming_error = true;
 		break;
 	case VIVID_CID_QUEUE_ERROR:
-		if (vb2_start_streaming_called(&dev->vb_vid_cap_q))
+		if (dev->vb_vid_cap_q.start_streaming_called)
 			vb2_queue_error(&dev->vb_vid_cap_q);
-		if (vb2_start_streaming_called(&dev->vb_vbi_cap_q))
+		if (dev->vb_vbi_cap_q.start_streaming_called)
 			vb2_queue_error(&dev->vb_vbi_cap_q);
-		if (vb2_start_streaming_called(&dev->vb_vid_out_q))
+		if (dev->vb_vid_out_q.start_streaming_called)
 			vb2_queue_error(&dev->vb_vid_out_q);
-		if (vb2_start_streaming_called(&dev->vb_vbi_out_q))
+		if (dev->vb_vbi_out_q.start_streaming_called)
 			vb2_queue_error(&dev->vb_vbi_out_q);
-		if (vb2_start_streaming_called(&dev->vb_sdr_cap_q))
+		if (dev->vb_sdr_cap_q.start_streaming_called)
 			vb2_queue_error(&dev->vb_sdr_cap_q);
 		break;
 	case VIVID_CID_SEQ_WRAP:
@@ -1326,9 +1222,6 @@
 	dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
 	dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
 	dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
-	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
-	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
-	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);
 
 	if (dev->has_vid_cap) {
 		/* Image Processing Controls */
@@ -1365,8 +1258,6 @@
 		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
 		dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
 			&vivid_ctrl_colorspace, NULL);
-		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
-		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
 		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
 	}
 
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index 4af55f1..8c5d661 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -297,8 +297,8 @@
 	.buf_queue		= sdr_cap_buf_queue,
 	.start_streaming	= sdr_cap_start_streaming,
 	.stop_streaming		= sdr_cap_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
+	.wait_prepare		= vivid_unlock,
+	.wait_finish		= vivid_lock,
 };
 
 int vivid_sdr_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band)
diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.c b/drivers/media/platform/vivid/vivid-tpg-colors.c
index 424aa7a..2adddc0 100644
--- a/drivers/media/platform/vivid/vivid-tpg-colors.c
+++ b/drivers/media/platform/vivid/vivid-tpg-colors.c
@@ -12,7 +12,7 @@
  * This source also contains the code used to generate the tpg_csc_colors
  * table. Run the following command to compile it:
  *
- *	gcc vivid-tpg-colors.c -DCOMPILE_APP -o gen-colors -lm
+ *	gcc vivid-colors.c -DCOMPILE_APP -o gen-colors -lm
  *
  * and run the utility.
  *
@@ -78,542 +78,22 @@
 #ifndef COMPILE_APP
 
 /* Generated table */
-const unsigned short tpg_rec709_to_linear[255 * 16 + 1] = {
-	   0,    0,    0,    1,    1,    1,    1,    2,    2,    2,    2,    2,    3,    3,    3,    3,
-	   4,    4,    4,    4,    4,    5,    5,    5,    5,    6,    6,    6,    6,    6,    7,    7,
-	   7,    7,    8,    8,    8,    8,    8,    9,    9,    9,    9,   10,   10,   10,   10,   10,
-	  11,   11,   11,   11,   12,   12,   12,   12,   12,   13,   13,   13,   13,   14,   14,   14,
-	  14,   14,   15,   15,   15,   15,   16,   16,   16,   16,   16,   17,   17,   17,   17,   18,
-	  18,   18,   18,   18,   19,   19,   19,   19,   20,   20,   20,   20,   20,   21,   21,   21,
-	  21,   22,   22,   22,   22,   22,   23,   23,   23,   23,   24,   24,   24,   24,   24,   25,
-	  25,   25,   25,   26,   26,   26,   26,   26,   27,   27,   27,   27,   28,   28,   28,   28,
-	  28,   29,   29,   29,   29,   30,   30,   30,   30,   30,   31,   31,   31,   31,   32,   32,
-	  32,   32,   32,   33,   33,   33,   33,   34,   34,   34,   34,   34,   35,   35,   35,   35,
-	  36,   36,   36,   36,   36,   37,   37,   37,   37,   38,   38,   38,   38,   38,   39,   39,
-	  39,   39,   40,   40,   40,   40,   40,   41,   41,   41,   41,   42,   42,   42,   42,   42,
-	  43,   43,   43,   43,   44,   44,   44,   44,   44,   45,   45,   45,   45,   46,   46,   46,
-	  46,   46,   47,   47,   47,   47,   48,   48,   48,   48,   48,   49,   49,   49,   49,   50,
-	  50,   50,   50,   50,   51,   51,   51,   51,   52,   52,   52,   52,   52,   53,   53,   53,
-	  53,   54,   54,   54,   54,   54,   55,   55,   55,   55,   56,   56,   56,   56,   56,   57,
-	  57,   57,   57,   58,   58,   58,   58,   58,   59,   59,   59,   59,   60,   60,   60,   60,
-	  60,   61,   61,   61,   61,   62,   62,   62,   62,   62,   63,   63,   63,   63,   64,   64,
-	  64,   64,   64,   65,   65,   65,   65,   66,   66,   66,   66,   66,   67,   67,   67,   67,
-	  68,   68,   68,   68,   68,   69,   69,   69,   69,   70,   70,   70,   70,   70,   71,   71,
-	  71,   71,   72,   72,   72,   72,   72,   73,   73,   73,   73,   73,   74,   74,   74,   74,
-	  74,   75,   75,   75,   75,   76,   76,   76,   76,   76,   77,   77,   77,   77,   78,   78,
-	  78,   78,   79,   79,   79,   79,   79,   80,   80,   80,   80,   81,   81,   81,   81,   82,
-	  82,   82,   82,   82,   83,   83,   83,   83,   84,   84,   84,   84,   85,   85,   85,   85,
-	  86,   86,   86,   86,   87,   87,   87,   87,   88,   88,   88,   88,   89,   89,   89,   89,
-	  90,   90,   90,   90,   91,   91,   91,   91,   92,   92,   92,   92,   93,   93,   93,   93,
-	  94,   94,   94,   94,   95,   95,   95,   95,   96,   96,   96,   96,   97,   97,   97,   97,
-	  98,   98,   98,   98,   99,   99,   99,   99,  100,  100,  100,  101,  101,  101,  101,  102,
-	 102,  102,  102,  103,  103,  103,  103,  104,  104,  104,  105,  105,  105,  105,  106,  106,
-	 106,  106,  107,  107,  107,  107,  108,  108,  108,  109,  109,  109,  109,  110,  110,  110,
-	 111,  111,  111,  111,  112,  112,  112,  112,  113,  113,  113,  114,  114,  114,  114,  115,
-	 115,  115,  116,  116,  116,  116,  117,  117,  117,  118,  118,  118,  118,  119,  119,  119,
-	 120,  120,  120,  120,  121,  121,  121,  122,  122,  122,  123,  123,  123,  123,  124,  124,
-	 124,  125,  125,  125,  125,  126,  126,  126,  127,  127,  127,  128,  128,  128,  128,  129,
-	 129,  129,  130,  130,  130,  131,  131,  131,  132,  132,  132,  132,  133,  133,  133,  134,
-	 134,  134,  135,  135,  135,  136,  136,  136,  136,  137,  137,  137,  138,  138,  138,  139,
-	 139,  139,  140,  140,  140,  141,  141,  141,  142,  142,  142,  142,  143,  143,  143,  144,
-	 144,  144,  145,  145,  145,  146,  146,  146,  147,  147,  147,  148,  148,  148,  149,  149,
-	 149,  150,  150,  150,  151,  151,  151,  152,  152,  152,  153,  153,  153,  154,  154,  154,
-	 155,  155,  155,  156,  156,  156,  157,  157,  157,  158,  158,  158,  159,  159,  159,  160,
-	 160,  160,  161,  161,  161,  162,  162,  162,  163,  163,  163,  164,  164,  164,  165,  165,
-	 165,  166,  166,  167,  167,  167,  168,  168,  168,  169,  169,  169,  170,  170,  170,  171,
-	 171,  171,  172,  172,  172,  173,  173,  174,  174,  174,  175,  175,  175,  176,  176,  176,
-	 177,  177,  177,  178,  178,  179,  179,  179,  180,  180,  180,  181,  181,  181,  182,  182,
-	 183,  183,  183,  184,  184,  184,  185,  185,  186,  186,  186,  187,  187,  187,  188,  188,
-	 188,  189,  189,  190,  190,  190,  191,  191,  191,  192,  192,  193,  193,  193,  194,  194,
-	 194,  195,  195,  196,  196,  196,  197,  197,  198,  198,  198,  199,  199,  199,  200,  200,
-	 201,  201,  201,  202,  202,  203,  203,  203,  204,  204,  204,  205,  205,  206,  206,  206,
-	 207,  207,  208,  208,  208,  209,  209,  210,  210,  210,  211,  211,  212,  212,  212,  213,
-	 213,  214,  214,  214,  215,  215,  216,  216,  216,  217,  217,  218,  218,  218,  219,  219,
-	 220,  220,  220,  221,  221,  222,  222,  222,  223,  223,  224,  224,  224,  225,  225,  226,
-	 226,  227,  227,  227,  228,  228,  229,  229,  229,  230,  230,  231,  231,  232,  232,  232,
-	 233,  233,  234,  234,  234,  235,  235,  236,  236,  237,  237,  237,  238,  238,  239,  239,
-	 240,  240,  240,  241,  241,  242,  242,  243,  243,  243,  244,  244,  245,  245,  246,  246,
-	 246,  247,  247,  248,  248,  249,  249,  249,  250,  250,  251,  251,  252,  252,  252,  253,
-	 253,  254,  254,  255,  255,  256,  256,  256,  257,  257,  258,  258,  259,  259,  260,  260,
-	 260,  261,  261,  262,  262,  263,  263,  264,  264,  264,  265,  265,  266,  266,  267,  267,
-	 268,  268,  269,  269,  269,  270,  270,  271,  271,  272,  272,  273,  273,  274,  274,  274,
-	 275,  275,  276,  276,  277,  277,  278,  278,  279,  279,  279,  280,  280,  281,  281,  282,
-	 282,  283,  283,  284,  284,  285,  285,  286,  286,  286,  287,  287,  288,  288,  289,  289,
-	 290,  290,  291,  291,  292,  292,  293,  293,  294,  294,  295,  295,  295,  296,  296,  297,
-	 297,  298,  298,  299,  299,  300,  300,  301,  301,  302,  302,  303,  303,  304,  304,  305,
-	 305,  306,  306,  307,  307,  308,  308,  309,  309,  309,  310,  310,  311,  311,  312,  312,
-	 313,  313,  314,  314,  315,  315,  316,  316,  317,  317,  318,  318,  319,  319,  320,  320,
-	 321,  321,  322,  322,  323,  323,  324,  324,  325,  325,  326,  326,  327,  327,  328,  328,
-	 329,  329,  330,  330,  331,  331,  332,  332,  333,  333,  334,  335,  335,  336,  336,  337,
-	 337,  338,  338,  339,  339,  340,  340,  341,  341,  342,  342,  343,  343,  344,  344,  345,
-	 345,  346,  346,  347,  347,  348,  348,  349,  349,  350,  351,  351,  352,  352,  353,  353,
-	 354,  354,  355,  355,  356,  356,  357,  357,  358,  358,  359,  360,  360,  361,  361,  362,
-	 362,  363,  363,  364,  364,  365,  365,  366,  366,  367,  368,  368,  369,  369,  370,  370,
-	 371,  371,  372,  372,  373,  373,  374,  375,  375,  376,  376,  377,  377,  378,  378,  379,
-	 379,  380,  381,  381,  382,  382,  383,  383,  384,  384,  385,  386,  386,  387,  387,  388,
-	 388,  389,  389,  390,  391,  391,  392,  392,  393,  393,  394,  394,  395,  396,  396,  397,
-	 397,  398,  398,  399,  399,  400,  401,  401,  402,  402,  403,  403,  404,  405,  405,  406,
-	 406,  407,  407,  408,  409,  409,  410,  410,  411,  411,  412,  413,  413,  414,  414,  415,
-	 415,  416,  417,  417,  418,  418,  419,  419,  420,  421,  421,  422,  422,  423,  424,  424,
-	 425,  425,  426,  426,  427,  428,  428,  429,  429,  430,  431,  431,  432,  432,  433,  433,
-	 434,  435,  435,  436,  436,  437,  438,  438,  439,  439,  440,  441,  441,  442,  442,  443,
-	 444,  444,  445,  445,  446,  447,  447,  448,  448,  449,  450,  450,  451,  451,  452,  453,
-	 453,  454,  454,  455,  456,  456,  457,  457,  458,  459,  459,  460,  460,  461,  462,  462,
-	 463,  463,  464,  465,  465,  466,  467,  467,  468,  468,  469,  470,  470,  471,  471,  472,
-	 473,  473,  474,  475,  475,  476,  476,  477,  478,  478,  479,  480,  480,  481,  481,  482,
-	 483,  483,  484,  485,  485,  486,  486,  487,  488,  488,  489,  490,  490,  491,  491,  492,
-	 493,  493,  494,  495,  495,  496,  497,  497,  498,  498,  499,  500,  500,  501,  502,  502,
-	 503,  504,  504,  505,  505,  506,  507,  507,  508,  509,  509,  510,  511,  511,  512,  513,
-	 513,  514,  514,  515,  516,  516,  517,  518,  518,  519,  520,  520,  521,  522,  522,  523,
-	 524,  524,  525,  526,  526,  527,  528,  528,  529,  529,  530,  531,  531,  532,  533,  533,
-	 534,  535,  535,  536,  537,  537,  538,  539,  539,  540,  541,  541,  542,  543,  543,  544,
-	 545,  545,  546,  547,  547,  548,  549,  549,  550,  551,  551,  552,  553,  553,  554,  555,
-	 555,  556,  557,  557,  558,  559,  560,  560,  561,  562,  562,  563,  564,  564,  565,  566,
-	 566,  567,  568,  568,  569,  570,  570,  571,  572,  572,  573,  574,  575,  575,  576,  577,
-	 577,  578,  579,  579,  580,  581,  581,  582,  583,  584,  584,  585,  586,  586,  587,  588,
-	 588,  589,  590,  590,  591,  592,  593,  593,  594,  595,  595,  596,  597,  598,  598,  599,
-	 600,  600,  601,  602,  602,  603,  604,  605,  605,  606,  607,  607,  608,  609,  610,  610,
-	 611,  612,  612,  613,  614,  615,  615,  616,  617,  617,  618,  619,  620,  620,  621,  622,
-	 622,  623,  624,  625,  625,  626,  627,  627,  628,  629,  630,  630,  631,  632,  632,  633,
-	 634,  635,  635,  636,  637,  638,  638,  639,  640,  640,  641,  642,  643,  643,  644,  645,
-	 646,  646,  647,  648,  649,  649,  650,  651,  652,  652,  653,  654,  654,  655,  656,  657,
-	 657,  658,  659,  660,  660,  661,  662,  663,  663,  664,  665,  666,  666,  667,  668,  669,
-	 669,  670,  671,  672,  672,  673,  674,  675,  675,  676,  677,  678,  678,  679,  680,  681,
-	 681,  682,  683,  684,  684,  685,  686,  687,  687,  688,  689,  690,  690,  691,  692,  693,
-	 694,  694,  695,  696,  697,  697,  698,  699,  700,  700,  701,  702,  703,  703,  704,  705,
-	 706,  707,  707,  708,  709,  710,  710,  711,  712,  713,  714,  714,  715,  716,  717,  717,
-	 718,  719,  720,  720,  721,  722,  723,  724,  724,  725,  726,  727,  728,  728,  729,  730,
-	 731,  731,  732,  733,  734,  735,  735,  736,  737,  738,  739,  739,  740,  741,  742,  742,
-	 743,  744,  745,  746,  746,  747,  748,  749,  750,  750,  751,  752,  753,  754,  754,  755,
-	 756,  757,  758,  758,  759,  760,  761,  762,  762,  763,  764,  765,  766,  766,  767,  768,
-	 769,  770,  771,  771,  772,  773,  774,  775,  775,  776,  777,  778,  779,  779,  780,  781,
-	 782,  783,  783,  784,  785,  786,  787,  788,  788,  789,  790,  791,  792,  793,  793,  794,
-	 795,  796,  797,  797,  798,  799,  800,  801,  802,  802,  803,  804,  805,  806,  807,  807,
-	 808,  809,  810,  811,  812,  812,  813,  814,  815,  816,  817,  817,  818,  819,  820,  821,
-	 822,  822,  823,  824,  825,  826,  827,  827,  828,  829,  830,  831,  832,  832,  833,  834,
-	 835,  836,  837,  838,  838,  839,  840,  841,  842,  843,  843,  844,  845,  846,  847,  848,
-	 849,  849,  850,  851,  852,  853,  854,  855,  855,  856,  857,  858,  859,  860,  861,  861,
-	 862,  863,  864,  865,  866,  867,  867,  868,  869,  870,  871,  872,  873,  873,  874,  875,
-	 876,  877,  878,  879,  880,  880,  881,  882,  883,  884,  885,  886,  887,  887,  888,  889,
-	 890,  891,  892,  893,  894,  894,  895,  896,  897,  898,  899,  900,  901,  901,  902,  903,
-	 904,  905,  906,  907,  908,  909,  909,  910,  911,  912,  913,  914,  915,  916,  916,  917,
-	 918,  919,  920,  921,  922,  923,  924,  925,  925,  926,  927,  928,  929,  930,  931,  932,
-	 933,  933,  934,  935,  936,  937,  938,  939,  940,  941,  942,  942,  943,  944,  945,  946,
-	 947,  948,  949,  950,  951,  952,  952,  953,  954,  955,  956,  957,  958,  959,  960,  961,
-	 962,  962,  963,  964,  965,  966,  967,  968,  969,  970,  971,  972,  973,  973,  974,  975,
-	 976,  977,  978,  979,  980,  981,  982,  983,  984,  985,  985,  986,  987,  988,  989,  990,
-	 991,  992,  993,  994,  995,  996,  997,  998,  998,  999, 1000, 1001, 1002, 1003, 1004, 1005,
-	1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020,
-	1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1030, 1031, 1032, 1033, 1034, 1035,
-	1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1050,
-	1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066,
-	1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1078, 1079, 1080, 1081,
-	1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097,
-	1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113,
-	1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129,
-	1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145,
-	1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
-	1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177,
-	1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1193, 1194,
-	1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210,
-	1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1223, 1224, 1225, 1226, 1227,
-	1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243,
-	1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260,
-	1261, 1262, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277,
-	1278, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1295,
-	1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1309, 1310, 1311, 1312,
-	1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329,
-	1330, 1331, 1332, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1345, 1346, 1347,
-	1348, 1349, 1350, 1351, 1352, 1353, 1354, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364,
-	1365, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1377, 1378, 1379, 1380, 1381, 1382,
-	1383, 1384, 1385, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1396, 1397, 1398, 1399, 1400,
-	1401, 1402, 1403, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1414, 1415, 1416, 1417, 1418,
-	1419, 1420, 1421, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1431, 1432, 1433, 1434, 1435, 1436,
-	1437, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1448, 1449, 1450, 1451, 1452, 1453, 1455,
-	1456, 1457, 1458, 1459, 1460, 1461, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1471, 1472, 1473,
-	1474, 1475, 1476, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1486, 1487, 1488, 1489, 1490, 1491,
-	1493, 1494, 1495, 1496, 1497, 1498, 1500, 1501, 1502, 1503, 1504, 1505, 1507, 1508, 1509, 1510,
-	1511, 1512, 1514, 1515, 1516, 1517, 1518, 1519, 1521, 1522, 1523, 1524, 1525, 1527, 1528, 1529,
-	1530, 1531, 1532, 1534, 1535, 1536, 1537, 1538, 1540, 1541, 1542, 1543, 1544, 1545, 1547, 1548,
-	1549, 1550, 1551, 1553, 1554, 1555, 1556, 1557, 1559, 1560, 1561, 1562, 1563, 1564, 1566, 1567,
-	1568, 1569, 1570, 1572, 1573, 1574, 1575, 1576, 1578, 1579, 1580, 1581, 1582, 1584, 1585, 1586,
-	1587, 1588, 1590, 1591, 1592, 1593, 1594, 1596, 1597, 1598, 1599, 1601, 1602, 1603, 1604, 1605,
-	1607, 1608, 1609, 1610, 1611, 1613, 1614, 1615, 1616, 1617, 1619, 1620, 1621, 1622, 1624, 1625,
-	1626, 1627, 1628, 1630, 1631, 1632, 1633, 1635, 1636, 1637, 1638, 1639, 1641, 1642, 1643, 1644,
-	1646, 1647, 1648, 1649, 1650, 1652, 1653, 1654, 1655, 1657, 1658, 1659, 1660, 1662, 1663, 1664,
-	1665, 1667, 1668, 1669, 1670, 1671, 1673, 1674, 1675, 1676, 1678, 1679, 1680, 1681, 1683, 1684,
-	1685, 1686, 1688, 1689, 1690, 1691, 1693, 1694, 1695, 1696, 1698, 1699, 1700, 1701, 1703, 1704,
-	1705, 1706, 1708, 1709, 1710, 1711, 1713, 1714, 1715, 1716, 1718, 1719, 1720, 1721, 1723, 1724,
-	1725, 1726, 1728, 1729, 1730, 1731, 1733, 1734, 1735, 1737, 1738, 1739, 1740, 1742, 1743, 1744,
-	1745, 1747, 1748, 1749, 1750, 1752, 1753, 1754, 1756, 1757, 1758, 1759, 1761, 1762, 1763, 1764,
-	1766, 1767, 1768, 1770, 1771, 1772, 1773, 1775, 1776, 1777, 1778, 1780, 1781, 1782, 1784, 1785,
-	1786, 1787, 1789, 1790, 1791, 1793, 1794, 1795, 1796, 1798, 1799, 1800, 1802, 1803, 1804, 1806,
-	1807, 1808, 1809, 1811, 1812, 1813, 1815, 1816, 1817, 1818, 1820, 1821, 1822, 1824, 1825, 1826,
-	1828, 1829, 1830, 1831, 1833, 1834, 1835, 1837, 1838, 1839, 1841, 1842, 1843, 1844, 1846, 1847,
-	1848, 1850, 1851, 1852, 1854, 1855, 1856, 1858, 1859, 1860, 1862, 1863, 1864, 1865, 1867, 1868,
-	1869, 1871, 1872, 1873, 1875, 1876, 1877, 1879, 1880, 1881, 1883, 1884, 1885, 1887, 1888, 1889,
-	1891, 1892, 1893, 1894, 1896, 1897, 1898, 1900, 1901, 1902, 1904, 1905, 1906, 1908, 1909, 1910,
-	1912, 1913, 1914, 1916, 1917, 1918, 1920, 1921, 1922, 1924, 1925, 1926, 1928, 1929, 1930, 1932,
-	1933, 1935, 1936, 1937, 1939, 1940, 1941, 1943, 1944, 1945, 1947, 1948, 1949, 1951, 1952, 1953,
-	1955, 1956, 1957, 1959, 1960, 1961, 1963, 1964, 1965, 1967, 1968, 1970, 1971, 1972, 1974, 1975,
-	1976, 1978, 1979, 1980, 1982, 1983, 1984, 1986, 1987, 1989, 1990, 1991, 1993, 1994, 1995, 1997,
-	1998, 1999, 2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017, 2019,
-	2020, 2021, 2023, 2024, 2026, 2027, 2028, 2030, 2031, 2032, 2034, 2035, 2037, 2038, 2039, 2041,
-	2042, 2043, 2045, 2046, 2048, 2049, 2050, 2052, 2053, 2055, 2056, 2057, 2059, 2060, 2061, 2063,
-	2064, 2066, 2067, 2068, 2070, 2071, 2073, 2074, 2075, 2077, 2078, 2080, 2081, 2082, 2084, 2085,
-	2087, 2088, 2089, 2091, 2092, 2094, 2095, 2096, 2098, 2099, 2101, 2102, 2103, 2105, 2106, 2108,
-	2109, 2110, 2112, 2113, 2115, 2116, 2117, 2119, 2120, 2122, 2123, 2124, 2126, 2127, 2129, 2130,
-	2132, 2133, 2134, 2136, 2137, 2139, 2140, 2141, 2143, 2144, 2146, 2147, 2149, 2150, 2151, 2153,
-	2154, 2156, 2157, 2159, 2160, 2161, 2163, 2164, 2166, 2167, 2169, 2170, 2171, 2173, 2174, 2176,
-	2177, 2179, 2180, 2181, 2183, 2184, 2186, 2187, 2189, 2190, 2191, 2193, 2194, 2196, 2197, 2199,
-	2200, 2202, 2203, 2204, 2206, 2207, 2209, 2210, 2212, 2213, 2214, 2216, 2217, 2219, 2220, 2222,
-	2223, 2225, 2226, 2228, 2229, 2230, 2232, 2233, 2235, 2236, 2238, 2239, 2241, 2242, 2243, 2245,
-	2246, 2248, 2249, 2251, 2252, 2254, 2255, 2257, 2258, 2260, 2261, 2262, 2264, 2265, 2267, 2268,
-	2270, 2271, 2273, 2274, 2276, 2277, 2279, 2280, 2282, 2283, 2284, 2286, 2287, 2289, 2290, 2292,
-	2293, 2295, 2296, 2298, 2299, 2301, 2302, 2304, 2305, 2307, 2308, 2310, 2311, 2312, 2314, 2315,
-	2317, 2318, 2320, 2321, 2323, 2324, 2326, 2327, 2329, 2330, 2332, 2333, 2335, 2336, 2338, 2339,
-	2341, 2342, 2344, 2345, 2347, 2348, 2350, 2351, 2353, 2354, 2356, 2357, 2359, 2360, 2362, 2363,
-	2365, 2366, 2368, 2369, 2371, 2372, 2374, 2375, 2377, 2378, 2380, 2381, 2383, 2384, 2386, 2387,
-	2389, 2390, 2392, 2393, 2395, 2396, 2398, 2399, 2401, 2402, 2404, 2405, 2407, 2408, 2410, 2411,
-	2413, 2414, 2416, 2417, 2419, 2420, 2422, 2423, 2425, 2426, 2428, 2429, 2431, 2433, 2434, 2436,
-	2437, 2439, 2440, 2442, 2443, 2445, 2446, 2448, 2449, 2451, 2452, 2454, 2455, 2457, 2458, 2460,
-	2462, 2463, 2465, 2466, 2468, 2469, 2471, 2472, 2474, 2475, 2477, 2478, 2480, 2481, 2483, 2485,
-	2486, 2488, 2489, 2491, 2492, 2494, 2495, 2497, 2498, 2500, 2502, 2503, 2505, 2506, 2508, 2509,
-	2511, 2512, 2514, 2515, 2517, 2519, 2520, 2522, 2523, 2525, 2526, 2528, 2529, 2531, 2533, 2534,
-	2536, 2537, 2539, 2540, 2542, 2543, 2545, 2547, 2548, 2550, 2551, 2553, 2554, 2556, 2557, 2559,
-	2561, 2562, 2564, 2565, 2567, 2568, 2570, 2572, 2573, 2575, 2576, 2578, 2579, 2581, 2583, 2584,
-	2586, 2587, 2589, 2590, 2592, 2594, 2595, 2597, 2598, 2600, 2601, 2603, 2605, 2606, 2608, 2609,
-	2611, 2613, 2614, 2616, 2617, 2619, 2620, 2622, 2624, 2625, 2627, 2628, 2630, 2632, 2633, 2635,
-	2636, 2638, 2640, 2641, 2643, 2644, 2646, 2647, 2649, 2651, 2652, 2654, 2655, 2657, 2659, 2660,
-	2662, 2663, 2665, 2667, 2668, 2670, 2671, 2673, 2675, 2676, 2678, 2679, 2681, 2683, 2684, 2686,
-	2687, 2689, 2691, 2692, 2694, 2696, 2697, 2699, 2700, 2702, 2704, 2705, 2707, 2708, 2710, 2712,
-	2713, 2715, 2716, 2718, 2720, 2721, 2723, 2725, 2726, 2728, 2729, 2731, 2733, 2734, 2736, 2738,
-	2739, 2741, 2742, 2744, 2746, 2747, 2749, 2751, 2752, 2754, 2755, 2757, 2759, 2760, 2762, 2764,
-	2765, 2767, 2769, 2770, 2772, 2773, 2775, 2777, 2778, 2780, 2782, 2783, 2785, 2787, 2788, 2790,
-	2791, 2793, 2795, 2796, 2798, 2800, 2801, 2803, 2805, 2806, 2808, 2810, 2811, 2813, 2814, 2816,
-	2818, 2819, 2821, 2823, 2824, 2826, 2828, 2829, 2831, 2833, 2834, 2836, 2838, 2839, 2841, 2843,
-	2844, 2846, 2848, 2849, 2851, 2853, 2854, 2856, 2857, 2859, 2861, 2862, 2864, 2866, 2867, 2869,
-	2871, 2872, 2874, 2876, 2877, 2879, 2881, 2882, 2884, 2886, 2888, 2889, 2891, 2893, 2894, 2896,
-	2898, 2899, 2901, 2903, 2904, 2906, 2908, 2909, 2911, 2913, 2914, 2916, 2918, 2919, 2921, 2923,
-	2924, 2926, 2928, 2929, 2931, 2933, 2935, 2936, 2938, 2940, 2941, 2943, 2945, 2946, 2948, 2950,
-	2951, 2953, 2955, 2956, 2958, 2960, 2962, 2963, 2965, 2967, 2968, 2970, 2972, 2973, 2975, 2977,
-	2979, 2980, 2982, 2984, 2985, 2987, 2989, 2990, 2992, 2994, 2996, 2997, 2999, 3001, 3002, 3004,
-	3006, 3008, 3009, 3011, 3013, 3014, 3016, 3018, 3020, 3021, 3023, 3025, 3026, 3028, 3030, 3032,
-	3033, 3035, 3037, 3038, 3040, 3042, 3044, 3045, 3047, 3049, 3050, 3052, 3054, 3056, 3057, 3059,
-	3061, 3063, 3064, 3066, 3068, 3069, 3071, 3073, 3075, 3076, 3078, 3080, 3082, 3083, 3085, 3087,
-	3089, 3090, 3092, 3094, 3095, 3097, 3099, 3101, 3102, 3104, 3106, 3108, 3109, 3111, 3113, 3115,
-	3116, 3118, 3120, 3122, 3123, 3125, 3127, 3129, 3130, 3132, 3134, 3136, 3137, 3139, 3141, 3143,
-	3144, 3146, 3148, 3150, 3151, 3153, 3155, 3157, 3158, 3160, 3162, 3164, 3165, 3167, 3169, 3171,
-	3172, 3174, 3176, 3178, 3179, 3181, 3183, 3185, 3187, 3188, 3190, 3192, 3194, 3195, 3197, 3199,
-	3201, 3202, 3204, 3206, 3208, 3209, 3211, 3213, 3215, 3217, 3218, 3220, 3222, 3224, 3225, 3227,
-	3229, 3231, 3233, 3234, 3236, 3238, 3240, 3241, 3243, 3245, 3247, 3249, 3250, 3252, 3254, 3256,
-	3258, 3259, 3261, 3263, 3265, 3266, 3268, 3270, 3272, 3274, 3275, 3277, 3279, 3281, 3283, 3284,
-	3286, 3288, 3290, 3292, 3293, 3295, 3297, 3299, 3301, 3302, 3304, 3306, 3308, 3310, 3311, 3313,
-	3315, 3317, 3319, 3320, 3322, 3324, 3326, 3328, 3329, 3331, 3333, 3335, 3337, 3338, 3340, 3342,
-	3344, 3346, 3348, 3349, 3351, 3353, 3355, 3357, 3358, 3360, 3362, 3364, 3366, 3368, 3369, 3371,
-	3373, 3375, 3377, 3378, 3380, 3382, 3384, 3386, 3388, 3389, 3391, 3393, 3395, 3397, 3399, 3400,
-	3402, 3404, 3406, 3408, 3410, 3411, 3413, 3415, 3417, 3419, 3421, 3422, 3424, 3426, 3428, 3430,
-	3432, 3433, 3435, 3437, 3439, 3441, 3443, 3444, 3446, 3448, 3450, 3452, 3454, 3455, 3457, 3459,
-	3461, 3463, 3465, 3467, 3468, 3470, 3472, 3474, 3476, 3478, 3480, 3481, 3483, 3485, 3487, 3489,
-	3491, 3492, 3494, 3496, 3498, 3500, 3502, 3504, 3506, 3507, 3509, 3511, 3513, 3515, 3517, 3519,
-	3520, 3522, 3524, 3526, 3528, 3530, 3532, 3533, 3535, 3537, 3539, 3541, 3543, 3545, 3547, 3548,
-	3550, 3552, 3554, 3556, 3558, 3560, 3562, 3563, 3565, 3567, 3569, 3571, 3573, 3575, 3577, 3578,
-	3580, 3582, 3584, 3586, 3588, 3590, 3592, 3594, 3595, 3597, 3599, 3601, 3603, 3605, 3607, 3609,
-	3611, 3612, 3614, 3616, 3618, 3620, 3622, 3624, 3626, 3628, 3629, 3631, 3633, 3635, 3637, 3639,
-	3641, 3643, 3645, 3647, 3648, 3650, 3652, 3654, 3656, 3658, 3660, 3662, 3664, 3666, 3667, 3669,
-	3671, 3673, 3675, 3677, 3679, 3681, 3683, 3685, 3687, 3688, 3690, 3692, 3694, 3696, 3698, 3700,
-	3702, 3704, 3706, 3708, 3710, 3711, 3713, 3715, 3717, 3719, 3721, 3723, 3725, 3727, 3729, 3731,
-	3733, 3735, 3736, 3738, 3740, 3742, 3744, 3746, 3748, 3750, 3752, 3754, 3756, 3758, 3760, 3762,
-	3764, 3765, 3767, 3769, 3771, 3773, 3775, 3777, 3779, 3781, 3783, 3785, 3787, 3789, 3791, 3793,
-	3795, 3796, 3798, 3800, 3802, 3804, 3806, 3808, 3810, 3812, 3814, 3816, 3818, 3820, 3822, 3824,
-	3826, 3828, 3830, 3832, 3833, 3835, 3837, 3839, 3841, 3843, 3845, 3847, 3849, 3851, 3853, 3855,
-	3857, 3859, 3861, 3863, 3865, 3867, 3869, 3871, 3873, 3875, 3877, 3879, 3881, 3883, 3884, 3886,
-	3888, 3890, 3892, 3894, 3896, 3898, 3900, 3902, 3904, 3906, 3908, 3910, 3912, 3914, 3916, 3918,
-	3920, 3922, 3924, 3926, 3928, 3930, 3932, 3934, 3936, 3938, 3940, 3942, 3944, 3946, 3948, 3950,
-	3952, 3954, 3956, 3958, 3960, 3962, 3964, 3966, 3968, 3970, 3972, 3974, 3976, 3978, 3980, 3982,
-	3984, 3986, 3988, 3990, 3992, 3994, 3996, 3998, 4000, 4002, 4004, 4006, 4008, 4010, 4012, 4014,
-	4016, 4018, 4020, 4022, 4024, 4026, 4028, 4030, 4032, 4034, 4036, 4038, 4040, 4042, 4044, 4046,
-	4048, 4050, 4052, 4054, 4056, 4058, 4060, 4062, 4064, 4066, 4068, 4070, 4072, 4074, 4076, 4078,
-	4080,
-};
-
-/* Generated table */
-const unsigned short tpg_linear_to_rec709[255 * 16 + 1] = {
-	   0,    5,    9,   14,   18,   22,   27,   32,   36,   41,   45,   50,   54,   59,   63,   68,
-	  72,   77,   81,   86,   90,   95,   99,  104,  108,  113,  117,  122,  126,  131,  135,  139,
-	 144,  149,  153,  158,  162,  167,  171,  176,  180,  185,  189,  194,  198,  203,  207,  212,
-	 216,  221,  225,  230,  234,  239,  243,  248,  252,  257,  261,  266,  270,  275,  279,  284,
-	 288,  293,  297,  302,  306,  311,  315,  320,  324,  328,  334,  338,  343,  347,  352,  356,
-	 360,  365,  369,  373,  377,  381,  386,  390,  394,  398,  402,  406,  410,  414,  418,  422,
-	 426,  430,  433,  437,  441,  445,  449,  452,  456,  460,  464,  467,  471,  475,  478,  482,
-	 485,  489,  492,  496,  499,  503,  506,  510,  513,  517,  520,  524,  527,  530,  534,  537,
-	 540,  544,  547,  550,  554,  557,  560,  563,  566,  570,  573,  576,  579,  582,  586,  589,
-	 592,  595,  598,  601,  604,  607,  610,  613,  616,  619,  622,  625,  628,  631,  634,  637,
-	 640,  643,  646,  649,  652,  655,  658,  660,  663,  666,  669,  672,  675,  677,  680,  683,
-	 686,  689,  691,  694,  697,  700,  702,  705,  708,  711,  713,  716,  719,  721,  724,  727,
-	 729,  732,  735,  737,  740,  743,  745,  748,  750,  753,  756,  758,  761,  763,  766,  768,
-	 771,  773,  776,  779,  781,  784,  786,  789,  791,  794,  796,  799,  801,  803,  806,  808,
-	 811,  813,  816,  818,  821,  823,  825,  828,  830,  833,  835,  837,  840,  842,  844,  847,
-	 849,  851,  854,  856,  858,  861,  863,  865,  868,  870,  872,  875,  877,  879,  881,  884,
-	 886,  888,  891,  893,  895,  897,  900,  902,  904,  906,  908,  911,  913,  915,  917,  919,
-	 922,  924,  926,  928,  930,  933,  935,  937,  939,  941,  943,  946,  948,  950,  952,  954,
-	 956,  958,  960,  963,  965,  967,  969,  971,  973,  975,  977,  979,  981,  984,  986,  988,
-	 990,  992,  994,  996,  998, 1000, 1002, 1004, 1006, 1008, 1010, 1012, 1014, 1016, 1018, 1020,
-	1022, 1024, 1026, 1028, 1030, 1032, 1034, 1036, 1038, 1040, 1042, 1044, 1046, 1048, 1050, 1052,
-	1054, 1056, 1058, 1060, 1062, 1064, 1066, 1068, 1069, 1071, 1073, 1075, 1077, 1079, 1081, 1083,
-	1085, 1087, 1089, 1090, 1092, 1094, 1096, 1098, 1100, 1102, 1104, 1106, 1107, 1109, 1111, 1113,
-	1115, 1117, 1119, 1120, 1122, 1124, 1126, 1128, 1130, 1131, 1133, 1135, 1137, 1139, 1141, 1142,
-	1144, 1146, 1148, 1150, 1151, 1153, 1155, 1157, 1159, 1160, 1162, 1164, 1166, 1168, 1169, 1171,
-	1173, 1175, 1176, 1178, 1180, 1182, 1184, 1185, 1187, 1189, 1191, 1192, 1194, 1196, 1198, 1199,
-	1201, 1203, 1204, 1206, 1208, 1210, 1211, 1213, 1215, 1217, 1218, 1220, 1222, 1223, 1225, 1227,
-	1228, 1230, 1232, 1234, 1235, 1237, 1239, 1240, 1242, 1244, 1245, 1247, 1249, 1250, 1252, 1254,
-	1255, 1257, 1259, 1260, 1262, 1264, 1265, 1267, 1269, 1270, 1272, 1274, 1275, 1277, 1279, 1280,
-	1282, 1283, 1285, 1287, 1288, 1290, 1292, 1293, 1295, 1296, 1298, 1300, 1301, 1303, 1305, 1306,
-	1308, 1309, 1311, 1313, 1314, 1316, 1317, 1319, 1321, 1322, 1324, 1325, 1327, 1328, 1330, 1332,
-	1333, 1335, 1336, 1338, 1339, 1341, 1343, 1344, 1346, 1347, 1349, 1350, 1352, 1354, 1355, 1357,
-	1358, 1360, 1361, 1363, 1364, 1366, 1367, 1369, 1371, 1372, 1374, 1375, 1377, 1378, 1380, 1381,
-	1383, 1384, 1386, 1387, 1389, 1390, 1392, 1393, 1395, 1396, 1398, 1399, 1401, 1402, 1404, 1405,
-	1407, 1408, 1410, 1411, 1413, 1414, 1416, 1417, 1419, 1420, 1422, 1423, 1425, 1426, 1428, 1429,
-	1431, 1432, 1434, 1435, 1437, 1438, 1440, 1441, 1442, 1444, 1445, 1447, 1448, 1450, 1451, 1453,
-	1454, 1456, 1457, 1458, 1460, 1461, 1463, 1464, 1466, 1467, 1469, 1470, 1471, 1473, 1474, 1476,
-	1477, 1479, 1480, 1481, 1483, 1484, 1486, 1487, 1489, 1490, 1491, 1493, 1494, 1496, 1497, 1498,
-	1500, 1501, 1503, 1504, 1505, 1507, 1508, 1510, 1511, 1512, 1514, 1515, 1517, 1518, 1519, 1521,
-	1522, 1524, 1525, 1526, 1528, 1529, 1531, 1532, 1533, 1535, 1536, 1537, 1539, 1540, 1542, 1543,
-	1544, 1546, 1547, 1548, 1550, 1551, 1553, 1554, 1555, 1557, 1558, 1559, 1561, 1562, 1563, 1565,
-	1566, 1567, 1569, 1570, 1571, 1573, 1574, 1576, 1577, 1578, 1580, 1581, 1582, 1584, 1585, 1586,
-	1588, 1589, 1590, 1592, 1593, 1594, 1596, 1597, 1598, 1600, 1601, 1602, 1603, 1605, 1606, 1607,
-	1609, 1610, 1611, 1613, 1614, 1615, 1617, 1618, 1619, 1621, 1622, 1623, 1624, 1626, 1627, 1628,
-	1630, 1631, 1632, 1634, 1635, 1636, 1637, 1639, 1640, 1641, 1643, 1644, 1645, 1647, 1648, 1649,
-	1650, 1652, 1653, 1654, 1655, 1657, 1658, 1659, 1661, 1662, 1663, 1664, 1666, 1667, 1668, 1670,
-	1671, 1672, 1673, 1675, 1676, 1677, 1678, 1680, 1681, 1682, 1683, 1685, 1686, 1687, 1688, 1690,
-	1691, 1692, 1693, 1695, 1696, 1697, 1698, 1700, 1701, 1702, 1703, 1705, 1706, 1707, 1708, 1710,
-	1711, 1712, 1713, 1715, 1716, 1717, 1718, 1720, 1721, 1722, 1723, 1724, 1726, 1727, 1728, 1729,
-	1731, 1732, 1733, 1734, 1736, 1737, 1738, 1739, 1740, 1742, 1743, 1744, 1745, 1746, 1748, 1749,
-	1750, 1751, 1753, 1754, 1755, 1756, 1757, 1759, 1760, 1761, 1762, 1763, 1765, 1766, 1767, 1768,
-	1769, 1771, 1772, 1773, 1774, 1775, 1777, 1778, 1779, 1780, 1781, 1783, 1784, 1785, 1786, 1787,
-	1788, 1790, 1791, 1792, 1793, 1794, 1796, 1797, 1798, 1799, 1800, 1801, 1803, 1804, 1805, 1806,
-	1807, 1809, 1810, 1811, 1812, 1813, 1814, 1816, 1817, 1818, 1819, 1820, 1821, 1823, 1824, 1825,
-	1826, 1827, 1828, 1829, 1831, 1832, 1833, 1834, 1835, 1836, 1838, 1839, 1840, 1841, 1842, 1843,
-	1845, 1846, 1847, 1848, 1849, 1850, 1851, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1861, 1862,
-	1863, 1864, 1865, 1866, 1867, 1868, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1878, 1879, 1880,
-	1881, 1882, 1883, 1884, 1885, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1896, 1897, 1898,
-	1899, 1900, 1901, 1902, 1903, 1904, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1916,
-	1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1927, 1928, 1929, 1930, 1931, 1932, 1933,
-	1934, 1935, 1936, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1950, 1951,
-	1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1963, 1964, 1965, 1966, 1967, 1968,
-	1969, 1970, 1971, 1972, 1973, 1974, 1975, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985,
-	1986, 1987, 1988, 1989, 1990, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-	2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
-	2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2031, 2032, 2033, 2034, 2035, 2036,
-	2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052,
-	2053, 2054, 2055, 2056, 2057, 2058, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069,
-	2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085,
-	2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101,
-	2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117,
-	2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133,
-	2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149,
-	2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165,
-	2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180,
-	2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196,
-	2197, 2198, 2199, 2200, 2201, 2202, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211,
-	2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2224, 2225, 2226,
-	2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2241,
-	2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257,
-	2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2271,
-	2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2283, 2284, 2285, 2286,
-	2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2295, 2296, 2297, 2298, 2299, 2300, 2301,
-	2302, 2303, 2304, 2305, 2306, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316,
-	2317, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2327, 2328, 2329, 2330,
-	2331, 2332, 2333, 2334, 2335, 2336, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345,
-	2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2354, 2355, 2356, 2357, 2358, 2359,
-	2360, 2361, 2362, 2363, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2371, 2372, 2373,
-	2374, 2375, 2376, 2377, 2378, 2379, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2386, 2387,
-	2388, 2389, 2390, 2391, 2392, 2393, 2394, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2401,
-	2402, 2403, 2404, 2405, 2406, 2407, 2408, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2415,
-	2416, 2417, 2418, 2419, 2420, 2421, 2422, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2428, 2429,
-	2430, 2431, 2432, 2433, 2434, 2435, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2441, 2442, 2443,
-	2444, 2445, 2446, 2447, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2453, 2454, 2455, 2456, 2457,
-	2458, 2459, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2465, 2466, 2467, 2468, 2469, 2470, 2471,
-	2471, 2472, 2473, 2474, 2475, 2476, 2477, 2477, 2478, 2479, 2480, 2481, 2482, 2482, 2483, 2484,
-	2485, 2486, 2487, 2488, 2488, 2489, 2490, 2491, 2492, 2493, 2493, 2494, 2495, 2496, 2497, 2498,
-	2499, 2499, 2500, 2501, 2502, 2503, 2504, 2504, 2505, 2506, 2507, 2508, 2509, 2509, 2510, 2511,
-	2512, 2513, 2514, 2514, 2515, 2516, 2517, 2518, 2519, 2519, 2520, 2521, 2522, 2523, 2524, 2524,
-	2525, 2526, 2527, 2528, 2529, 2529, 2530, 2531, 2532, 2533, 2534, 2534, 2535, 2536, 2537, 2538,
-	2539, 2539, 2540, 2541, 2542, 2543, 2544, 2544, 2545, 2546, 2547, 2548, 2548, 2549, 2550, 2551,
-	2552, 2553, 2553, 2554, 2555, 2556, 2557, 2558, 2558, 2559, 2560, 2561, 2562, 2562, 2563, 2564,
-	2565, 2566, 2567, 2567, 2568, 2569, 2570, 2571, 2571, 2572, 2573, 2574, 2575, 2576, 2576, 2577,
-	2578, 2579, 2580, 2580, 2581, 2582, 2583, 2584, 2584, 2585, 2586, 2587, 2588, 2589, 2589, 2590,
-	2591, 2592, 2593, 2593, 2594, 2595, 2596, 2597, 2597, 2598, 2599, 2600, 2601, 2601, 2602, 2603,
-	2604, 2605, 2605, 2606, 2607, 2608, 2609, 2610, 2610, 2611, 2612, 2613, 2614, 2614, 2615, 2616,
-	2617, 2618, 2618, 2619, 2620, 2621, 2622, 2622, 2623, 2624, 2625, 2626, 2626, 2627, 2628, 2629,
-	2630, 2630, 2631, 2632, 2633, 2634, 2634, 2635, 2636, 2637, 2637, 2638, 2639, 2640, 2641, 2641,
-	2642, 2643, 2644, 2645, 2645, 2646, 2647, 2648, 2649, 2649, 2650, 2651, 2652, 2653, 2653, 2654,
-	2655, 2656, 2656, 2657, 2658, 2659, 2660, 2660, 2661, 2662, 2663, 2664, 2664, 2665, 2666, 2667,
-	2668, 2668, 2669, 2670, 2671, 2671, 2672, 2673, 2674, 2675, 2675, 2676, 2677, 2678, 2678, 2679,
-	2680, 2681, 2682, 2682, 2683, 2684, 2685, 2686, 2686, 2687, 2688, 2689, 2689, 2690, 2691, 2692,
-	2693, 2693, 2694, 2695, 2696, 2696, 2697, 2698, 2699, 2700, 2700, 2701, 2702, 2703, 2703, 2704,
-	2705, 2706, 2706, 2707, 2708, 2709, 2710, 2710, 2711, 2712, 2713, 2713, 2714, 2715, 2716, 2717,
-	2717, 2718, 2719, 2720, 2720, 2721, 2722, 2723, 2723, 2724, 2725, 2726, 2727, 2727, 2728, 2729,
-	2730, 2730, 2731, 2732, 2733, 2733, 2734, 2735, 2736, 2736, 2737, 2738, 2739, 2740, 2740, 2741,
-	2742, 2743, 2743, 2744, 2745, 2746, 2746, 2747, 2748, 2749, 2749, 2750, 2751, 2752, 2752, 2753,
-	2754, 2755, 2755, 2756, 2757, 2758, 2759, 2759, 2760, 2761, 2762, 2762, 2763, 2764, 2765, 2765,
-	2766, 2767, 2768, 2768, 2769, 2770, 2771, 2771, 2772, 2773, 2774, 2774, 2775, 2776, 2777, 2777,
-	2778, 2779, 2780, 2780, 2781, 2782, 2783, 2783, 2784, 2785, 2786, 2786, 2787, 2788, 2789, 2789,
-	2790, 2791, 2792, 2792, 2793, 2794, 2795, 2795, 2796, 2797, 2798, 2798, 2799, 2800, 2801, 2801,
-	2802, 2803, 2804, 2804, 2805, 2806, 2807, 2807, 2808, 2809, 2810, 2810, 2811, 2812, 2813, 2813,
-	2814, 2815, 2815, 2816, 2817, 2818, 2818, 2819, 2820, 2821, 2821, 2822, 2823, 2824, 2824, 2825,
-	2826, 2827, 2827, 2828, 2829, 2830, 2830, 2831, 2832, 2832, 2833, 2834, 2835, 2835, 2836, 2837,
-	2838, 2838, 2839, 2840, 2841, 2841, 2842, 2843, 2844, 2844, 2845, 2846, 2846, 2847, 2848, 2849,
-	2849, 2850, 2851, 2852, 2852, 2853, 2854, 2855, 2855, 2856, 2857, 2857, 2858, 2859, 2860, 2860,
-	2861, 2862, 2863, 2863, 2864, 2865, 2865, 2866, 2867, 2868, 2868, 2869, 2870, 2871, 2871, 2872,
-	2873, 2873, 2874, 2875, 2876, 2876, 2877, 2878, 2879, 2879, 2880, 2881, 2881, 2882, 2883, 2884,
-	2884, 2885, 2886, 2886, 2887, 2888, 2889, 2889, 2890, 2891, 2892, 2892, 2893, 2894, 2894, 2895,
-	2896, 2897, 2897, 2898, 2899, 2899, 2900, 2901, 2902, 2902, 2903, 2904, 2904, 2905, 2906, 2907,
-	2907, 2908, 2909, 2909, 2910, 2911, 2912, 2912, 2913, 2914, 2914, 2915, 2916, 2917, 2917, 2918,
-	2919, 2919, 2920, 2921, 2922, 2922, 2923, 2924, 2924, 2925, 2926, 2927, 2927, 2928, 2929, 2929,
-	2930, 2931, 2932, 2932, 2933, 2934, 2934, 2935, 2936, 2937, 2937, 2938, 2939, 2939, 2940, 2941,
-	2941, 2942, 2943, 2944, 2944, 2945, 2946, 2946, 2947, 2948, 2949, 2949, 2950, 2951, 2951, 2952,
-	2953, 2953, 2954, 2955, 2956, 2956, 2957, 2958, 2958, 2959, 2960, 2961, 2961, 2962, 2963, 2963,
-	2964, 2965, 2965, 2966, 2967, 2968, 2968, 2969, 2970, 2970, 2971, 2972, 2972, 2973, 2974, 2975,
-	2975, 2976, 2977, 2977, 2978, 2979, 2979, 2980, 2981, 2982, 2982, 2983, 2984, 2984, 2985, 2986,
-	2986, 2987, 2988, 2988, 2989, 2990, 2991, 2991, 2992, 2993, 2993, 2994, 2995, 2995, 2996, 2997,
-	2998, 2998, 2999, 3000, 3000, 3001, 3002, 3002, 3003, 3004, 3004, 3005, 3006, 3006, 3007, 3008,
-	3009, 3009, 3010, 3011, 3011, 3012, 3013, 3013, 3014, 3015, 3015, 3016, 3017, 3018, 3018, 3019,
-	3020, 3020, 3021, 3022, 3022, 3023, 3024, 3024, 3025, 3026, 3026, 3027, 3028, 3029, 3029, 3030,
-	3031, 3031, 3032, 3033, 3033, 3034, 3035, 3035, 3036, 3037, 3037, 3038, 3039, 3039, 3040, 3041,
-	3042, 3042, 3043, 3044, 3044, 3045, 3046, 3046, 3047, 3048, 3048, 3049, 3050, 3050, 3051, 3052,
-	3052, 3053, 3054, 3054, 3055, 3056, 3056, 3057, 3058, 3059, 3059, 3060, 3061, 3061, 3062, 3063,
-	3063, 3064, 3065, 3065, 3066, 3067, 3067, 3068, 3069, 3069, 3070, 3071, 3071, 3072, 3073, 3073,
-	3074, 3075, 3075, 3076, 3077, 3077, 3078, 3079, 3079, 3080, 3081, 3081, 3082, 3083, 3084, 3084,
-	3085, 3086, 3086, 3087, 3088, 3088, 3089, 3090, 3090, 3091, 3092, 3092, 3093, 3094, 3094, 3095,
-	3096, 3096, 3097, 3098, 3098, 3099, 3100, 3100, 3101, 3102, 3102, 3103, 3104, 3104, 3105, 3106,
-	3106, 3107, 3108, 3108, 3109, 3110, 3110, 3111, 3112, 3112, 3113, 3114, 3114, 3115, 3116, 3116,
-	3117, 3118, 3118, 3119, 3120, 3120, 3121, 3122, 3122, 3123, 3124, 3124, 3125, 3126, 3126, 3127,
-	3128, 3128, 3129, 3130, 3130, 3131, 3132, 3132, 3133, 3134, 3134, 3135, 3135, 3136, 3137, 3137,
-	3138, 3139, 3139, 3140, 3141, 3141, 3142, 3143, 3143, 3144, 3145, 3145, 3146, 3147, 3147, 3148,
-	3149, 3149, 3150, 3151, 3151, 3152, 3153, 3153, 3154, 3155, 3155, 3156, 3157, 3157, 3158, 3159,
-	3159, 3160, 3160, 3161, 3162, 3162, 3163, 3164, 3164, 3165, 3166, 3166, 3167, 3168, 3168, 3169,
-	3170, 3170, 3171, 3172, 3172, 3173, 3174, 3174, 3175, 3175, 3176, 3177, 3177, 3178, 3179, 3179,
-	3180, 3181, 3181, 3182, 3183, 3183, 3184, 3185, 3185, 3186, 3187, 3187, 3188, 3188, 3189, 3190,
-	3190, 3191, 3192, 3192, 3193, 3194, 3194, 3195, 3196, 3196, 3197, 3198, 3198, 3199, 3199, 3200,
-	3201, 3201, 3202, 3203, 3203, 3204, 3205, 3205, 3206, 3207, 3207, 3208, 3209, 3209, 3210, 3210,
-	3211, 3212, 3212, 3213, 3214, 3214, 3215, 3216, 3216, 3217, 3218, 3218, 3219, 3219, 3220, 3221,
-	3221, 3222, 3223, 3223, 3224, 3225, 3225, 3226, 3227, 3227, 3228, 3228, 3229, 3230, 3230, 3231,
-	3232, 3232, 3233, 3234, 3234, 3235, 3235, 3236, 3237, 3237, 3238, 3239, 3239, 3240, 3241, 3241,
-	3242, 3242, 3243, 3244, 3244, 3245, 3246, 3246, 3247, 3248, 3248, 3249, 3249, 3250, 3251, 3251,
-	3252, 3253, 3253, 3254, 3255, 3255, 3256, 3256, 3257, 3258, 3258, 3259, 3260, 3260, 3261, 3262,
-	3262, 3263, 3263, 3264, 3265, 3265, 3266, 3267, 3267, 3268, 3268, 3269, 3270, 3270, 3271, 3272,
-	3272, 3273, 3274, 3274, 3275, 3275, 3276, 3277, 3277, 3278, 3279, 3279, 3280, 3280, 3281, 3282,
-	3282, 3283, 3284, 3284, 3285, 3285, 3286, 3287, 3287, 3288, 3289, 3289, 3290, 3290, 3291, 3292,
-	3292, 3293, 3294, 3294, 3295, 3295, 3296, 3297, 3297, 3298, 3299, 3299, 3300, 3300, 3301, 3302,
-	3302, 3303, 3304, 3304, 3305, 3305, 3306, 3307, 3307, 3308, 3309, 3309, 3310, 3310, 3311, 3312,
-	3312, 3313, 3314, 3314, 3315, 3315, 3316, 3317, 3317, 3318, 3319, 3319, 3320, 3320, 3321, 3322,
-	3322, 3323, 3323, 3324, 3325, 3325, 3326, 3327, 3327, 3328, 3328, 3329, 3330, 3330, 3331, 3332,
-	3332, 3333, 3333, 3334, 3335, 3335, 3336, 3336, 3337, 3338, 3338, 3339, 3340, 3340, 3341, 3341,
-	3342, 3343, 3343, 3344, 3345, 3345, 3346, 3346, 3347, 3348, 3348, 3349, 3349, 3350, 3351, 3351,
-	3352, 3352, 3353, 3354, 3354, 3355, 3356, 3356, 3357, 3357, 3358, 3359, 3359, 3360, 3360, 3361,
-	3362, 3362, 3363, 3364, 3364, 3365, 3365, 3366, 3367, 3367, 3368, 3368, 3369, 3370, 3370, 3371,
-	3371, 3372, 3373, 3373, 3374, 3375, 3375, 3376, 3376, 3377, 3378, 3378, 3379, 3379, 3380, 3381,
-	3381, 3382, 3382, 3383, 3384, 3384, 3385, 3385, 3386, 3387, 3387, 3388, 3389, 3389, 3390, 3390,
-	3391, 3392, 3392, 3393, 3393, 3394, 3395, 3395, 3396, 3396, 3397, 3398, 3398, 3399, 3399, 3400,
-	3401, 3401, 3402, 3402, 3403, 3404, 3404, 3405, 3405, 3406, 3407, 3407, 3408, 3408, 3409, 3410,
-	3410, 3411, 3411, 3412, 3413, 3413, 3414, 3414, 3415, 3416, 3416, 3417, 3418, 3418, 3419, 3419,
-	3420, 3421, 3421, 3422, 3422, 3423, 3424, 3424, 3425, 3425, 3426, 3427, 3427, 3428, 3428, 3429,
-	3430, 3430, 3431, 3431, 3432, 3433, 3433, 3434, 3434, 3435, 3435, 3436, 3437, 3437, 3438, 3438,
-	3439, 3440, 3440, 3441, 3441, 3442, 3443, 3443, 3444, 3444, 3445, 3446, 3446, 3447, 3447, 3448,
-	3449, 3449, 3450, 3450, 3451, 3452, 3452, 3453, 3453, 3454, 3455, 3455, 3456, 3456, 3457, 3458,
-	3458, 3459, 3459, 3460, 3461, 3461, 3462, 3462, 3463, 3463, 3464, 3465, 3465, 3466, 3466, 3467,
-	3468, 3468, 3469, 3469, 3470, 3471, 3471, 3472, 3472, 3473, 3474, 3474, 3475, 3475, 3476, 3476,
-	3477, 3478, 3478, 3479, 3479, 3480, 3481, 3481, 3482, 3482, 3483, 3484, 3484, 3485, 3485, 3486,
-	3486, 3487, 3488, 3488, 3489, 3489, 3490, 3491, 3491, 3492, 3492, 3493, 3494, 3494, 3495, 3495,
-	3496, 3496, 3497, 3498, 3498, 3499, 3499, 3500, 3501, 3501, 3502, 3502, 3503, 3504, 3504, 3505,
-	3505, 3506, 3506, 3507, 3508, 3508, 3509, 3509, 3510, 3511, 3511, 3512, 3512, 3513, 3513, 3514,
-	3515, 3515, 3516, 3516, 3517, 3518, 3518, 3519, 3519, 3520, 3520, 3521, 3522, 3522, 3523, 3523,
-	3524, 3525, 3525, 3526, 3526, 3527, 3527, 3528, 3529, 3529, 3530, 3530, 3531, 3531, 3532, 3533,
-	3533, 3534, 3534, 3535, 3536, 3536, 3537, 3537, 3538, 3538, 3539, 3540, 3540, 3541, 3541, 3542,
-	3542, 3543, 3544, 3544, 3545, 3545, 3546, 3547, 3547, 3548, 3548, 3549, 3549, 3550, 3551, 3551,
-	3552, 3552, 3553, 3553, 3554, 3555, 3555, 3556, 3556, 3557, 3557, 3558, 3559, 3559, 3560, 3560,
-	3561, 3561, 3562, 3563, 3563, 3564, 3564, 3565, 3566, 3566, 3567, 3567, 3568, 3568, 3569, 3570,
-	3570, 3571, 3571, 3572, 3572, 3573, 3574, 3574, 3575, 3575, 3576, 3576, 3577, 3578, 3578, 3579,
-	3579, 3580, 3580, 3581, 3582, 3582, 3583, 3583, 3584, 3584, 3585, 3586, 3586, 3587, 3587, 3588,
-	3588, 3589, 3590, 3590, 3591, 3591, 3592, 3592, 3593, 3594, 3594, 3595, 3595, 3596, 3596, 3597,
-	3597, 3598, 3599, 3599, 3600, 3600, 3601, 3601, 3602, 3603, 3603, 3604, 3604, 3605, 3605, 3606,
-	3607, 3607, 3608, 3608, 3609, 3609, 3610, 3611, 3611, 3612, 3612, 3613, 3613, 3614, 3615, 3615,
-	3616, 3616, 3617, 3617, 3618, 3618, 3619, 3620, 3620, 3621, 3621, 3622, 3622, 3623, 3624, 3624,
-	3625, 3625, 3626, 3626, 3627, 3627, 3628, 3629, 3629, 3630, 3630, 3631, 3631, 3632, 3633, 3633,
-	3634, 3634, 3635, 3635, 3636, 3636, 3637, 3638, 3638, 3639, 3639, 3640, 3640, 3641, 3642, 3642,
-	3643, 3643, 3644, 3644, 3645, 3645, 3646, 3647, 3647, 3648, 3648, 3649, 3649, 3650, 3650, 3651,
-	3652, 3652, 3653, 3653, 3654, 3654, 3655, 3656, 3656, 3657, 3657, 3658, 3658, 3659, 3659, 3660,
-	3661, 3661, 3662, 3662, 3663, 3663, 3664, 3664, 3665, 3666, 3666, 3667, 3667, 3668, 3668, 3669,
-	3669, 3670, 3671, 3671, 3672, 3672, 3673, 3673, 3674, 3674, 3675, 3676, 3676, 3677, 3677, 3678,
-	3678, 3679, 3679, 3680, 3681, 3681, 3682, 3682, 3683, 3683, 3684, 3684, 3685, 3686, 3686, 3687,
-	3687, 3688, 3688, 3689, 3689, 3690, 3691, 3691, 3692, 3692, 3693, 3693, 3694, 3694, 3695, 3695,
-	3696, 3697, 3697, 3698, 3698, 3699, 3699, 3700, 3700, 3701, 3702, 3702, 3703, 3703, 3704, 3704,
-	3705, 3705, 3706, 3707, 3707, 3708, 3708, 3709, 3709, 3710, 3710, 3711, 3711, 3712, 3713, 3713,
-	3714, 3714, 3715, 3715, 3716, 3716, 3717, 3717, 3718, 3719, 3719, 3720, 3720, 3721, 3721, 3722,
-	3722, 3723, 3724, 3724, 3725, 3725, 3726, 3726, 3727, 3727, 3728, 3728, 3729, 3730, 3730, 3731,
-	3731, 3732, 3732, 3733, 3733, 3734, 3734, 3735, 3736, 3736, 3737, 3737, 3738, 3738, 3739, 3739,
-	3740, 3740, 3741, 3742, 3742, 3743, 3743, 3744, 3744, 3745, 3745, 3746, 3746, 3747, 3748, 3748,
-	3749, 3749, 3750, 3750, 3751, 3751, 3752, 3752, 3753, 3753, 3754, 3755, 3755, 3756, 3756, 3757,
-	3757, 3758, 3758, 3759, 3759, 3760, 3761, 3761, 3762, 3762, 3763, 3763, 3764, 3764, 3765, 3765,
-	3766, 3766, 3767, 3768, 3768, 3769, 3769, 3770, 3770, 3771, 3771, 3772, 3772, 3773, 3773, 3774,
-	3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3781, 3781, 3782, 3782, 3783,
-	3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3789, 3789, 3790, 3790, 3791, 3791,
-	3792, 3792, 3793, 3793, 3794, 3794, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800,
-	3800, 3801, 3801, 3802, 3802, 3803, 3804, 3804, 3805, 3805, 3806, 3806, 3807, 3807, 3808, 3808,
-	3809, 3809, 3810, 3811, 3811, 3812, 3812, 3813, 3813, 3814, 3814, 3815, 3815, 3816, 3816, 3817,
-	3817, 3818, 3819, 3819, 3820, 3820, 3821, 3821, 3822, 3822, 3823, 3823, 3824, 3824, 3825, 3825,
-	3826, 3826, 3827, 3828, 3828, 3829, 3829, 3830, 3830, 3831, 3831, 3832, 3832, 3833, 3833, 3834,
-	3834, 3835, 3835, 3836, 3837, 3837, 3838, 3838, 3839, 3839, 3840, 3840, 3841, 3841, 3842, 3842,
-	3843, 3843, 3844, 3844, 3845, 3846, 3846, 3847, 3847, 3848, 3848, 3849, 3849, 3850, 3850, 3851,
-	3851, 3852, 3852, 3853, 3853, 3854, 3855, 3855, 3856, 3856, 3857, 3857, 3858, 3858, 3859, 3859,
-	3860, 3860, 3861, 3861, 3862, 3862, 3863, 3863, 3864, 3864, 3865, 3866, 3866, 3867, 3867, 3868,
-	3868, 3869, 3869, 3870, 3870, 3871, 3871, 3872, 3872, 3873, 3873, 3874, 3874, 3875, 3876, 3876,
-	3877, 3877, 3878, 3878, 3879, 3879, 3880, 3880, 3881, 3881, 3882, 3882, 3883, 3883, 3884, 3884,
-	3885, 3885, 3886, 3886, 3887, 3888, 3888, 3889, 3889, 3890, 3890, 3891, 3891, 3892, 3892, 3893,
-	3893, 3894, 3894, 3895, 3895, 3896, 3896, 3897, 3897, 3898, 3898, 3899, 3900, 3900, 3901, 3901,
-	3902, 3902, 3903, 3903, 3904, 3904, 3905, 3905, 3906, 3906, 3907, 3907, 3908, 3908, 3909, 3909,
-	3910, 3910, 3911, 3911, 3912, 3912, 3913, 3914, 3914, 3915, 3915, 3916, 3916, 3917, 3917, 3918,
-	3918, 3919, 3919, 3920, 3920, 3921, 3921, 3922, 3922, 3923, 3923, 3924, 3924, 3925, 3925, 3926,
-	3926, 3927, 3927, 3928, 3929, 3929, 3930, 3930, 3931, 3931, 3932, 3932, 3933, 3933, 3934, 3934,
-	3935, 3935, 3936, 3936, 3937, 3937, 3938, 3938, 3939, 3939, 3940, 3940, 3941, 3941, 3942, 3942,
-	3943, 3943, 3944, 3944, 3945, 3945, 3946, 3947, 3947, 3948, 3948, 3949, 3949, 3950, 3950, 3951,
-	3951, 3952, 3952, 3953, 3953, 3954, 3954, 3955, 3955, 3956, 3956, 3957, 3957, 3958, 3958, 3959,
-	3959, 3960, 3960, 3961, 3961, 3962, 3962, 3963, 3963, 3964, 3964, 3965, 3965, 3966, 3966, 3967,
-	3967, 3968, 3969, 3969, 3970, 3970, 3971, 3971, 3972, 3972, 3973, 3973, 3974, 3974, 3975, 3975,
-	3976, 3976, 3977, 3977, 3978, 3978, 3979, 3979, 3980, 3980, 3981, 3981, 3982, 3982, 3983, 3983,
-	3984, 3984, 3985, 3985, 3986, 3986, 3987, 3987, 3988, 3988, 3989, 3989, 3990, 3990, 3991, 3991,
-	3992, 3992, 3993, 3993, 3994, 3994, 3995, 3995, 3996, 3996, 3997, 3997, 3998, 3998, 3999, 3999,
-	4000, 4001, 4001, 4002, 4002, 4003, 4003, 4004, 4004, 4005, 4005, 4006, 4006, 4007, 4007, 4008,
-	4008, 4009, 4009, 4010, 4010, 4011, 4011, 4012, 4012, 4013, 4013, 4014, 4014, 4015, 4015, 4016,
-	4016, 4017, 4017, 4018, 4018, 4019, 4019, 4020, 4020, 4021, 4021, 4022, 4022, 4023, 4023, 4024,
-	4024, 4025, 4025, 4026, 4026, 4027, 4027, 4028, 4028, 4029, 4029, 4030, 4030, 4031, 4031, 4032,
-	4032, 4033, 4033, 4034, 4034, 4035, 4035, 4036, 4036, 4037, 4037, 4038, 4038, 4039, 4039, 4040,
-	4040, 4041, 4041, 4042, 4042, 4043, 4043, 4044, 4044, 4045, 4045, 4046, 4046, 4047, 4047, 4048,
-	4048, 4049, 4049, 4050, 4050, 4051, 4051, 4052, 4052, 4053, 4053, 4054, 4054, 4055, 4055, 4056,
-	4056, 4057, 4057, 4058, 4058, 4059, 4059, 4060, 4060, 4061, 4061, 4062, 4062, 4063, 4063, 4064,
-	4064, 4065, 4065, 4066, 4066, 4067, 4067, 4068, 4068, 4069, 4069, 4070, 4070, 4071, 4071, 4072,
-	4072, 4073, 4073, 4074, 4074, 4075, 4075, 4076, 4076, 4077, 4077, 4078, 4078, 4079, 4079, 4080,
-	4080,
-};
-
-/* Generated table */
-const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][TPG_COLOR_CSC_BLACK + 1] = {
-	[V4L2_COLORSPACE_SMPTE170M][0] = { 2939, 2939, 2939 },
-	[V4L2_COLORSPACE_SMPTE170M][1] = { 2953, 2963, 586 },
-	[V4L2_COLORSPACE_SMPTE170M][2] = { 0, 2967, 2937 },
-	[V4L2_COLORSPACE_SMPTE170M][3] = { 88, 2990, 575 },
-	[V4L2_COLORSPACE_SMPTE170M][4] = { 3016, 259, 2933 },
-	[V4L2_COLORSPACE_SMPTE170M][5] = { 3030, 405, 558 },
-	[V4L2_COLORSPACE_SMPTE170M][6] = { 478, 428, 2931 },
-	[V4L2_COLORSPACE_SMPTE170M][7] = { 547, 547, 547 },
+const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = {
+	[V4L2_COLORSPACE_SMPTE170M][0] = { 2953, 2939, 2939 },
+	[V4L2_COLORSPACE_SMPTE170M][1] = { 2954, 2963, 585 },
+	[V4L2_COLORSPACE_SMPTE170M][2] = { 84, 2967, 2937 },
+	[V4L2_COLORSPACE_SMPTE170M][3] = { 93, 2990, 575 },
+	[V4L2_COLORSPACE_SMPTE170M][4] = { 3030, 259, 2933 },
+	[V4L2_COLORSPACE_SMPTE170M][5] = { 3031, 406, 557 },
+	[V4L2_COLORSPACE_SMPTE170M][6] = { 544, 428, 2931 },
+	[V4L2_COLORSPACE_SMPTE170M][7] = { 551, 547, 547 },
 	[V4L2_COLORSPACE_SMPTE240M][0] = { 2926, 2926, 2926 },
-	[V4L2_COLORSPACE_SMPTE240M][1] = { 2941, 2950, 546 },
-	[V4L2_COLORSPACE_SMPTE240M][2] = { 0, 2954, 2924 },
-	[V4L2_COLORSPACE_SMPTE240M][3] = { 78, 2978, 536 },
-	[V4L2_COLORSPACE_SMPTE240M][4] = { 3004, 230, 2920 },
-	[V4L2_COLORSPACE_SMPTE240M][5] = { 3018, 363, 518 },
-	[V4L2_COLORSPACE_SMPTE240M][6] = { 437, 387, 2918 },
+	[V4L2_COLORSPACE_SMPTE240M][1] = { 2926, 2926, 857 },
+	[V4L2_COLORSPACE_SMPTE240M][2] = { 1594, 2901, 2901 },
+	[V4L2_COLORSPACE_SMPTE240M][3] = { 1594, 2901, 774 },
+	[V4L2_COLORSPACE_SMPTE240M][4] = { 2484, 618, 2858 },
+	[V4L2_COLORSPACE_SMPTE240M][5] = { 2484, 618, 617 },
+	[V4L2_COLORSPACE_SMPTE240M][6] = { 507, 507, 2832 },
 	[V4L2_COLORSPACE_SMPTE240M][7] = { 507, 507, 507 },
 	[V4L2_COLORSPACE_REC709][0] = { 2939, 2939, 2939 },
 	[V4L2_COLORSPACE_REC709][1] = { 2939, 2939, 547 },
@@ -623,21 +103,21 @@
 	[V4L2_COLORSPACE_REC709][5] = { 2939, 547, 547 },
 	[V4L2_COLORSPACE_REC709][6] = { 547, 547, 2939 },
 	[V4L2_COLORSPACE_REC709][7] = { 547, 547, 547 },
-	[V4L2_COLORSPACE_470_SYSTEM_M][0] = { 2892, 2988, 2807 },
-	[V4L2_COLORSPACE_470_SYSTEM_M][1] = { 2846, 3070, 843 },
+	[V4L2_COLORSPACE_470_SYSTEM_M][0] = { 2894, 2988, 2808 },
+	[V4L2_COLORSPACE_470_SYSTEM_M][1] = { 2847, 3070, 843 },
 	[V4L2_COLORSPACE_470_SYSTEM_M][2] = { 1656, 2962, 2783 },
 	[V4L2_COLORSPACE_470_SYSTEM_M][3] = { 1572, 3045, 763 },
-	[V4L2_COLORSPACE_470_SYSTEM_M][4] = { 2476, 229, 2742 },
-	[V4L2_COLORSPACE_470_SYSTEM_M][5] = { 2420, 672, 614 },
+	[V4L2_COLORSPACE_470_SYSTEM_M][4] = { 2477, 229, 2743 },
+	[V4L2_COLORSPACE_470_SYSTEM_M][5] = { 2422, 672, 614 },
 	[V4L2_COLORSPACE_470_SYSTEM_M][6] = { 725, 63, 2718 },
 	[V4L2_COLORSPACE_470_SYSTEM_M][7] = { 534, 561, 509 },
 	[V4L2_COLORSPACE_470_SYSTEM_BG][0] = { 2939, 2939, 2939 },
-	[V4L2_COLORSPACE_470_SYSTEM_BG][1] = { 2939, 2939, 464 },
+	[V4L2_COLORSPACE_470_SYSTEM_BG][1] = { 2939, 2939, 621 },
 	[V4L2_COLORSPACE_470_SYSTEM_BG][2] = { 786, 2939, 2939 },
-	[V4L2_COLORSPACE_470_SYSTEM_BG][3] = { 786, 2939, 464 },
-	[V4L2_COLORSPACE_470_SYSTEM_BG][4] = { 2879, 547, 2956 },
+	[V4L2_COLORSPACE_470_SYSTEM_BG][3] = { 786, 2939, 621 },
+	[V4L2_COLORSPACE_470_SYSTEM_BG][4] = { 2879, 547, 2923 },
 	[V4L2_COLORSPACE_470_SYSTEM_BG][5] = { 2879, 547, 547 },
-	[V4L2_COLORSPACE_470_SYSTEM_BG][6] = { 547, 547, 2956 },
+	[V4L2_COLORSPACE_470_SYSTEM_BG][6] = { 547, 547, 2923 },
 	[V4L2_COLORSPACE_470_SYSTEM_BG][7] = { 547, 547, 547 },
 	[V4L2_COLORSPACE_SRGB][0] = { 3056, 3056, 3056 },
 	[V4L2_COLORSPACE_SRGB][1] = { 3056, 3056, 800 },
@@ -647,22 +127,6 @@
 	[V4L2_COLORSPACE_SRGB][5] = { 3056, 800, 800 },
 	[V4L2_COLORSPACE_SRGB][6] = { 800, 800, 3056 },
 	[V4L2_COLORSPACE_SRGB][7] = { 800, 800, 800 },
-	[V4L2_COLORSPACE_ADOBERGB][0] = { 3033, 3033, 3033 },
-	[V4L2_COLORSPACE_ADOBERGB][1] = { 3033, 3033, 1063 },
-	[V4L2_COLORSPACE_ADOBERGB][2] = { 1828, 3033, 3033 },
-	[V4L2_COLORSPACE_ADOBERGB][3] = { 1828, 3033, 1063 },
-	[V4L2_COLORSPACE_ADOBERGB][4] = { 2633, 851, 2979 },
-	[V4L2_COLORSPACE_ADOBERGB][5] = { 2633, 851, 851 },
-	[V4L2_COLORSPACE_ADOBERGB][6] = { 851, 851, 2979 },
-	[V4L2_COLORSPACE_ADOBERGB][7] = { 851, 851, 851 },
-	[V4L2_COLORSPACE_BT2020][0] = { 2939, 2939, 2939 },
-	[V4L2_COLORSPACE_BT2020][1] = { 2877, 2923, 1058 },
-	[V4L2_COLORSPACE_BT2020][2] = { 1837, 2840, 2916 },
-	[V4L2_COLORSPACE_BT2020][3] = { 1734, 2823, 993 },
-	[V4L2_COLORSPACE_BT2020][4] = { 2427, 961, 2812 },
-	[V4L2_COLORSPACE_BT2020][5] = { 2351, 912, 648 },
-	[V4L2_COLORSPACE_BT2020][6] = { 792, 618, 2788 },
-	[V4L2_COLORSPACE_BT2020][7] = { 547, 547, 547 },
 };
 
 #else
@@ -674,40 +138,29 @@
 #include <stdlib.h>
 
 static const double rec709_to_ntsc1953[3][3] = {
-	{ 0.6689794, 0.2678309, 0.0323187 },
-	{ 0.0184901, 1.0742442, -0.0602820 },
-	{ 0.0162259, 0.0431716, 0.8549253 }
+	{ 0.6698, 0.2678,  0.0323 },
+	{ 0.0185, 1.0742, -0.0603 },
+	{ 0.0162, 0.0432,  0.8551 }
 };
 
 static const double rec709_to_ebu[3][3] = {
-	{ 0.9578221, 0.0421779, -0.0000000 },
-	{ -0.0000000, 1.0000000, 0.0000000 },
-	{ -0.0000000, -0.0119367, 1.0119367 }
+	{ 0.9578, 0.0422, 0      },
+	{ 0     , 1     , 0      },
+	{ 0     , 0.0118, 0.9882 }
 };
 
 static const double rec709_to_170m[3][3] = {
-	{ 1.0653640, -0.0553900, -0.0099740 },
-	{ -0.0196361, 1.0363630, -0.0167269 },
-	{ 0.0016327, 0.0044133, 0.9939540 },
+	{  1.0654, -0.0554, -0.0010 },
+	{ -0.0196,  1.0364, -0.0167 },
+	{  0.0016,  0.0044,  0.9940 }
 };
 
 static const double rec709_to_240m[3][3] = {
-	{ 1.0653640, -0.0553900, -0.0099740 },
-	{ -0.0196361, 1.0363630, -0.0167269 },
-	{ 0.0016327, 0.0044133, 0.9939540 },
+	{ 0.7151, 0.2849, 0      },
+	{ 0.0179, 0.9821, 0      },
+	{ 0.0177, 0.0472, 0.9350 }
 };
 
-static const double rec709_to_adobergb[3][3] = {
-	{ 0.7151627, 0.2848373, -0.0000000 },
-	{ 0.0000000, 1.0000000, 0.0000000 },
-	{ -0.0000000, 0.0411705, 0.9588295 },
-};
-
-static const double rec709_to_bt2020[3][3] = {
-	{ 0.6274524, 0.3292485, 0.0432991 },
-	{ 0.0691092, 0.9195311, 0.0113597 },
-	{ 0.0163976, 0.0880301, 0.8955723 },
-};
 
 static void mult_matrix(double *r, double *g, double *b, const double m[3][3])
 {
@@ -723,18 +176,7 @@
 
 static double transfer_srgb_to_rgb(double v)
 {
-	if (v < -0.04045)
-		return pow((-v + 0.055) / 1.055, 2.4);
-	return (v <= 0.04045) ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4);
-}
-
-static double transfer_rgb_to_srgb(double v)
-{
-	if (v <= -0.0031308)
-		return -1.055 * pow(-v, 1.0 / 2.4) + 0.055;
-	if (v <= 0.0031308)
-		return v * 12.92;
-	return 1.055 * pow(v, 1.0 / 2.4) - 0.055;
+	return (v <= 0.03928) ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4);
 }
 
 static double transfer_rgb_to_smpte240m(double v)
@@ -744,21 +186,9 @@
 
 static double transfer_rgb_to_rec709(double v)
 {
-	if (v <= -0.018)
-		return -1.099 * pow(-v, 0.45) + 0.099;
 	return (v < 0.018) ? v * 4.5 : 1.099 * pow(v, 0.45) - 0.099;
 }
 
-static double transfer_rec709_to_rgb(double v)
-{
-	return (v < 0.081) ? v / 4.5 : pow((v + 0.099) / 1.099, 1.0 / 0.45);
-}
-
-static double transfer_rgb_to_adobergb(double v)
-{
-	return pow(v, 1.0 / 2.19921875);
-}
-
 static double transfer_srgb_to_rec709(double v)
 {
 	return transfer_rgb_to_rec709(transfer_srgb_to_rgb(v));
@@ -766,8 +196,6 @@
 
 static void csc(enum v4l2_colorspace colorspace, double *r, double *g, double *b)
 {
-	int clamp = 1;
-
 	/* Convert the primaries of Rec. 709 Linear RGB */
 	switch (colorspace) {
 	case V4L2_COLORSPACE_SMPTE240M:
@@ -794,29 +222,15 @@
 		*b = transfer_srgb_to_rgb(*b);
 		mult_matrix(r, g, b, rec709_to_ntsc1953);
 		break;
-	case V4L2_COLORSPACE_ADOBERGB:
-		*r = transfer_srgb_to_rgb(*r);
-		*g = transfer_srgb_to_rgb(*g);
-		*b = transfer_srgb_to_rgb(*b);
-		mult_matrix(r, g, b, rec709_to_adobergb);
-		break;
-	case V4L2_COLORSPACE_BT2020:
-		*r = transfer_srgb_to_rgb(*r);
-		*g = transfer_srgb_to_rgb(*g);
-		*b = transfer_srgb_to_rgb(*b);
-		mult_matrix(r, g, b, rec709_to_bt2020);
-		break;
 	case V4L2_COLORSPACE_SRGB:
 	case V4L2_COLORSPACE_REC709:
 	default:
 		break;
 	}
 
-	if (clamp) {
-		*r = ((*r) < 0) ? 0 : (((*r) > 1) ? 1 : (*r));
-		*g = ((*g) < 0) ? 0 : (((*g) > 1) ? 1 : (*g));
-		*b = ((*b) < 0) ? 0 : (((*b) > 1) ? 1 : (*b));
-	}
+	*r = ((*r) < 0) ? 0 : (((*r) > 1) ? 1 : (*r));
+	*g = ((*g) < 0) ? 0 : (((*g) > 1) ? 1 : (*g));
+	*b = ((*b) < 0) ? 0 : (((*b) > 1) ? 1 : (*b));
 
 	/* Encode to gamma corrected colorspace */
 	switch (colorspace) {
@@ -828,18 +242,12 @@
 	case V4L2_COLORSPACE_SMPTE170M:
 	case V4L2_COLORSPACE_470_SYSTEM_M:
 	case V4L2_COLORSPACE_470_SYSTEM_BG:
-	case V4L2_COLORSPACE_BT2020:
 		*r = transfer_rgb_to_rec709(*r);
 		*g = transfer_rgb_to_rec709(*g);
 		*b = transfer_rgb_to_rec709(*b);
 		break;
 	case V4L2_COLORSPACE_SRGB:
 		break;
-	case V4L2_COLORSPACE_ADOBERGB:
-		*r = transfer_rgb_to_adobergb(*r);
-		*g = transfer_rgb_to_adobergb(*g);
-		*b = transfer_rgb_to_adobergb(*b);
-		break;
 	case V4L2_COLORSPACE_REC709:
 	default:
 		*r = transfer_srgb_to_rec709(*r);
@@ -861,8 +269,6 @@
 		V4L2_COLORSPACE_470_SYSTEM_BG,
 		0,
 		V4L2_COLORSPACE_SRGB,
-		V4L2_COLORSPACE_ADOBERGB,
-		V4L2_COLORSPACE_BT2020,
 	};
 	static const char * const colorspace_names[] = {
 		"",
@@ -874,39 +280,13 @@
 		"V4L2_COLORSPACE_470_SYSTEM_BG",
 		"",
 		"V4L2_COLORSPACE_SRGB",
-		"V4L2_COLORSPACE_ADOBERGB",
-		"V4L2_COLORSPACE_BT2020",
 	};
 	int i;
 	int c;
 
 	printf("/* Generated table */\n");
-	printf("const unsigned short tpg_rec709_to_linear[255 * 16 + 1] = {");
-	for (i = 0; i <= 255 * 16; i++) {
-		if (i % 16 == 0)
-			printf("\n\t");
-		printf("%4d,%s",
-			(int)(0.5 + 16.0 * 255.0 *
-				transfer_rec709_to_rgb(i / (16.0 * 255.0))),
-			i % 16 == 15 || i == 255 * 16 ? "" : " ");
-	}
-	printf("\n};\n\n");
-
-	printf("/* Generated table */\n");
-	printf("const unsigned short tpg_linear_to_rec709[255 * 16 + 1] = {");
-	for (i = 0; i <= 255 * 16; i++) {
-		if (i % 16 == 0)
-			printf("\n\t");
-		printf("%4d,%s",
-			(int)(0.5 + 16.0 * 255.0 *
-				transfer_rgb_to_rec709(i / (16.0 * 255.0))),
-			i % 16 == 15 || i == 255 * 16 ? "" : " ");
-	}
-	printf("\n};\n\n");
-
-	printf("/* Generated table */\n");
-	printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][TPG_COLOR_CSC_BLACK + 1] = {\n");
-	for (c = 0; c <= V4L2_COLORSPACE_BT2020; c++) {
+	printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = {\n");
+	for (c = 0; c <= V4L2_COLORSPACE_SRGB; c++) {
 		for (i = 0; i <= TPG_COLOR_CSC_BLACK; i++) {
 			double r, g, b;
 
diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.h b/drivers/media/platform/vivid/vivid-tpg-colors.h
index 2c33335..a2678fb 100644
--- a/drivers/media/platform/vivid/vivid-tpg-colors.h
+++ b/drivers/media/platform/vivid/vivid-tpg-colors.h
@@ -59,8 +59,6 @@
 };
 
 extern const struct color tpg_colors[TPG_COLOR_MAX];
-extern const unsigned short tpg_rec709_to_linear[255 * 16 + 1];
-extern const unsigned short tpg_linear_to_rec709[255 * 16 + 1];
-extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][TPG_COLOR_CSC_BLACK + 1];
+extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1];
 
 #endif
diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index fc9c653..0c6fa53 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -136,7 +136,7 @@
 		tpg->black_line[plane] = vzalloc(max_w * pixelsz);
 		if (!tpg->black_line[plane])
 			return -ENOMEM;
-		tpg->random_line[plane] = vzalloc(max_w * 2 * pixelsz);
+		tpg->random_line[plane] = vzalloc(max_w * pixelsz);
 		if (!tpg->random_line[plane])
 			return -ENOMEM;
 	}
@@ -296,193 +296,127 @@
 	}
 }
 
-static inline int rec709_to_linear(int v)
+static u16 color_to_y(struct tpg_data *tpg, int r, int g, int b)
 {
-	v = clamp(v, 0, 0xff0);
-	return tpg_rec709_to_linear[v];
-}
-
-static inline int linear_to_rec709(int v)
-{
-	v = clamp(v, 0, 0xff0);
-	return tpg_linear_to_rec709[v];
-}
-
-static void rgb2ycbcr(const int m[3][3], int r, int g, int b,
-			int y_offset, int *y, int *cb, int *cr)
-{
-	*y  = ((m[0][0] * r + m[0][1] * g + m[0][2] * b) >> 16) + (y_offset << 4);
-	*cb = ((m[1][0] * r + m[1][1] * g + m[1][2] * b) >> 16) + (128 << 4);
-	*cr = ((m[2][0] * r + m[2][1] * g + m[2][2] * b) >> 16) + (128 << 4);
-}
-
-static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b,
-			   int *y, int *cb, int *cr)
-{
-#define COEFF(v, r) ((int)(0.5 + (v) * (r) * 256.0))
-
-	static const int bt601[3][3] = {
-		{ COEFF(0.299, 219),  COEFF(0.587, 219),  COEFF(0.114, 219)  },
-		{ COEFF(-0.169, 224), COEFF(-0.331, 224), COEFF(0.5, 224)    },
-		{ COEFF(0.5, 224),    COEFF(-0.419, 224), COEFF(-0.081, 224) },
-	};
-	static const int bt601_full[3][3] = {
-		{ COEFF(0.299, 255),  COEFF(0.587, 255),  COEFF(0.114, 255)  },
-		{ COEFF(-0.169, 255), COEFF(-0.331, 255), COEFF(0.5, 255)    },
-		{ COEFF(0.5, 255),    COEFF(-0.419, 255), COEFF(-0.081, 255) },
-	};
-	static const int rec709[3][3] = {
-		{ COEFF(0.2126, 219),  COEFF(0.7152, 219),  COEFF(0.0722, 219)  },
-		{ COEFF(-0.1146, 224), COEFF(-0.3854, 224), COEFF(0.5, 224)     },
-		{ COEFF(0.5, 224),     COEFF(-0.4542, 224), COEFF(-0.0458, 224) },
-	};
-	static const int rec709_full[3][3] = {
-		{ COEFF(0.2126, 255),  COEFF(0.7152, 255),  COEFF(0.0722, 255)  },
-		{ COEFF(-0.1146, 255), COEFF(-0.3854, 255), COEFF(0.5, 255)     },
-		{ COEFF(0.5, 255),     COEFF(-0.4542, 255), COEFF(-0.0458, 255) },
-	};
-	static const int smpte240m[3][3] = {
-		{ COEFF(0.212, 219),  COEFF(0.701, 219),  COEFF(0.087, 219)  },
-		{ COEFF(-0.116, 224), COEFF(-0.384, 224), COEFF(0.5, 224)    },
-		{ COEFF(0.5, 224),    COEFF(-0.445, 224), COEFF(-0.055, 224) },
-	};
-	static const int bt2020[3][3] = {
-		{ COEFF(0.2726, 219),  COEFF(0.6780, 219),  COEFF(0.0593, 219)  },
-		{ COEFF(-0.1396, 224), COEFF(-0.3604, 224), COEFF(0.5, 224)     },
-		{ COEFF(0.5, 224),     COEFF(-0.4629, 224), COEFF(-0.0405, 224) },
-	};
-	bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
-	int lin_y, yc;
-
-	switch (tpg->real_ycbcr_enc) {
-	case V4L2_YCBCR_ENC_601:
-	case V4L2_YCBCR_ENC_XV601:
-	case V4L2_YCBCR_ENC_SYCC:
-		rgb2ycbcr(full ? bt601_full : bt601, r, g, b, 16, y, cb, cr);
-		break;
-	case V4L2_YCBCR_ENC_BT2020:
-		rgb2ycbcr(bt2020, r, g, b, 16, y, cb, cr);
-		break;
-	case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
-		lin_y = (COEFF(0.2627, 255) * rec709_to_linear(r) +
-			 COEFF(0.6780, 255) * rec709_to_linear(g) +
-			 COEFF(0.0593, 255) * rec709_to_linear(b)) >> 16;
-		yc = linear_to_rec709(lin_y);
-		*y = (yc * 219) / 255 + (16 << 4);
-		if (b <= yc)
-			*cb = (((b - yc) * COEFF(1.0 / 1.9404, 224)) >> 16) + (128 << 4);
-		else
-			*cb = (((b - yc) * COEFF(1.0 / 1.5816, 224)) >> 16) + (128 << 4);
-		if (r <= yc)
-			*cr = (((r - yc) * COEFF(1.0 / 1.7184, 224)) >> 16) + (128 << 4);
-		else
-			*cr = (((r - yc) * COEFF(1.0 / 0.9936, 224)) >> 16) + (128 << 4);
-		break;
-	case V4L2_YCBCR_ENC_SMPTE240M:
-		rgb2ycbcr(smpte240m, r, g, b, 16, y, cb, cr);
-		break;
-	case V4L2_YCBCR_ENC_709:
-	case V4L2_YCBCR_ENC_XV709:
+	switch (tpg->colorspace) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		return ((16829 * r + 33039 * g + 6416 * b + 16 * 32768) >> 16) + (16 << 4);
+	case V4L2_COLORSPACE_SMPTE240M:
+		return ((11932 * r + 39455 * g + 4897 * b + 16 * 32768) >> 16) + (16 << 4);
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SRGB:
 	default:
-		rgb2ycbcr(full ? rec709_full : rec709, r, g, b, 0, y, cb, cr);
-		break;
+		return ((11966 * r + 40254 * g + 4064 * b + 16 * 32768) >> 16) + (16 << 4);
 	}
 }
 
-static void ycbcr2rgb(const int m[3][3], int y, int cb, int cr,
-			int y_offset, int *r, int *g, int *b)
+static u16 color_to_cb(struct tpg_data *tpg, int r, int g, int b)
 {
-	y -= y_offset << 4;
+	switch (tpg->colorspace) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		return ((-9714 * r - 19070 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4);
+	case V4L2_COLORSPACE_SMPTE240M:
+		return ((-6684 * r - 22100 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4);
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SRGB:
+	default:
+		return ((-6596 * r - 22189 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4);
+	}
+}
+
+static u16 color_to_cr(struct tpg_data *tpg, int r, int g, int b)
+{
+	switch (tpg->colorspace) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		return ((28784 * r - 24103 * g - 4681 * b + 16 * 32768) >> 16) + (128 << 4);
+	case V4L2_COLORSPACE_SMPTE240M:
+		return ((28784 * r - 25606 * g - 3178 * b + 16 * 32768) >> 16) + (128 << 4);
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SRGB:
+	default:
+		return ((28784 * r - 26145 * g - 2639 * b + 16 * 32768) >> 16) + (128 << 4);
+	}
+}
+
+static u16 ycbcr_to_r(struct tpg_data *tpg, int y, int cb, int cr)
+{
+	int r;
+
+	y -= 16 << 4;
 	cb -= 128 << 4;
 	cr -= 128 << 4;
-	*r = m[0][0] * y + m[0][1] * cb + m[0][2] * cr;
-	*g = m[1][0] * y + m[1][1] * cb + m[1][2] * cr;
-	*b = m[2][0] * y + m[2][1] * cb + m[2][2] * cr;
-	*r = clamp(*r >> 12, 0, 0xff0);
-	*g = clamp(*g >> 12, 0, 0xff0);
-	*b = clamp(*b >> 12, 0, 0xff0);
-}
-
-static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr,
-			   int *r, int *g, int *b)
-{
-#undef COEFF
-#define COEFF(v, r) ((int)(0.5 + (v) * ((255.0 * 255.0 * 16.0) / (r))))
-	static const int bt601[3][3] = {
-		{ COEFF(1, 219), COEFF(0, 224),       COEFF(1.4020, 224)  },
-		{ COEFF(1, 219), COEFF(-0.3441, 224), COEFF(-0.7141, 224) },
-		{ COEFF(1, 219), COEFF(1.7720, 224),  COEFF(0, 224)       },
-	};
-	static const int bt601_full[3][3] = {
-		{ COEFF(1, 255), COEFF(0, 255),       COEFF(1.4020, 255)  },
-		{ COEFF(1, 255), COEFF(-0.3441, 255), COEFF(-0.7141, 255) },
-		{ COEFF(1, 255), COEFF(1.7720, 255),  COEFF(0, 255)       },
-	};
-	static const int rec709[3][3] = {
-		{ COEFF(1, 219), COEFF(0, 224),       COEFF(1.5748, 224)  },
-		{ COEFF(1, 219), COEFF(-0.1873, 224), COEFF(-0.4681, 224) },
-		{ COEFF(1, 219), COEFF(1.8556, 224),  COEFF(0, 224)       },
-	};
-	static const int rec709_full[3][3] = {
-		{ COEFF(1, 255), COEFF(0, 255),       COEFF(1.5748, 255)  },
-		{ COEFF(1, 255), COEFF(-0.1873, 255), COEFF(-0.4681, 255) },
-		{ COEFF(1, 255), COEFF(1.8556, 255),  COEFF(0, 255)       },
-	};
-	static const int smpte240m[3][3] = {
-		{ COEFF(1, 219), COEFF(0, 224),       COEFF(1.5756, 224)  },
-		{ COEFF(1, 219), COEFF(-0.2253, 224), COEFF(-0.4767, 224) },
-		{ COEFF(1, 219), COEFF(1.8270, 224),  COEFF(0, 224)       },
-	};
-	static const int bt2020[3][3] = {
-		{ COEFF(1, 219), COEFF(0, 224),       COEFF(1.4746, 224)  },
-		{ COEFF(1, 219), COEFF(-0.1646, 224), COEFF(-0.5714, 224) },
-		{ COEFF(1, 219), COEFF(1.8814, 224),  COEFF(0, 224)       },
-	};
-	bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
-	int lin_r, lin_g, lin_b, lin_y;
-
-	switch (tpg->real_ycbcr_enc) {
-	case V4L2_YCBCR_ENC_601:
-	case V4L2_YCBCR_ENC_XV601:
-	case V4L2_YCBCR_ENC_SYCC:
-		ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, 16, r, g, b);
+	switch (tpg->colorspace) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		r = 4769 * y + 6537 * cr;
 		break;
-	case V4L2_YCBCR_ENC_BT2020:
-		ycbcr2rgb(bt2020, y, cb, cr, 16, r, g, b);
+	case V4L2_COLORSPACE_SMPTE240M:
+		r = 4769 * y + 7376 * cr;
 		break;
-	case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
-		y -= 16 << 4;
-		cb -= 128 << 4;
-		cr -= 128 << 4;
-
-		if (cb <= 0)
-			*b = COEFF(1.0, 219) * y + COEFF(1.9404, 224) * cb;
-		else
-			*b = COEFF(1.0, 219) * y + COEFF(1.5816, 224) * cb;
-		*b = *b >> 12;
-		if (cr <= 0)
-			*r = COEFF(1.0, 219) * y + COEFF(1.7184, 224) * cr;
-		else
-			*r = COEFF(1.0, 219) * y + COEFF(0.9936, 224) * cr;
-		*r = *r >> 12;
-		lin_r = rec709_to_linear(*r);
-		lin_b = rec709_to_linear(*b);
-		lin_y = rec709_to_linear((y * 255) / 219);
-
-		lin_g = COEFF(1.0 / 0.6780, 255) * lin_y -
-			COEFF(0.2627 / 0.6780, 255) * lin_r -
-			COEFF(0.0593 / 0.6780, 255) * lin_b;
-		*g = linear_to_rec709(lin_g >> 12);
-		break;
-	case V4L2_YCBCR_ENC_SMPTE240M:
-		ycbcr2rgb(smpte240m, y, cb, cr, 16, r, g, b);
-		break;
-	case V4L2_YCBCR_ENC_709:
-	case V4L2_YCBCR_ENC_XV709:
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SRGB:
 	default:
-		ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, 16, r, g, b);
+		r = 4769 * y + 7343 * cr;
 		break;
 	}
+	return clamp(r >> 12, 0, 0xff0);
+}
+
+static u16 ycbcr_to_g(struct tpg_data *tpg, int y, int cb, int cr)
+{
+	int g;
+
+	y -= 16 << 4;
+	cb -= 128 << 4;
+	cr -= 128 << 4;
+	switch (tpg->colorspace) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		g = 4769 * y - 1605 * cb - 3330 * cr;
+		break;
+	case V4L2_COLORSPACE_SMPTE240M:
+		g = 4769 * y - 1055 * cb - 2341 * cr;
+		break;
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SRGB:
+	default:
+		g = 4769 * y - 873 * cb - 2183 * cr;
+		break;
+	}
+	return clamp(g >> 12, 0, 0xff0);
+}
+
+static u16 ycbcr_to_b(struct tpg_data *tpg, int y, int cb, int cr)
+{
+	int b;
+
+	y -= 16 << 4;
+	cb -= 128 << 4;
+	cr -= 128 << 4;
+	switch (tpg->colorspace) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		b = 4769 * y + 7343 * cb;
+		break;
+	case V4L2_COLORSPACE_SMPTE240M:
+		b = 4769 * y + 8552 * cb;
+		break;
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SRGB:
+	default:
+		b = 4769 * y + 8652 * cb;
+		break;
+	}
+	return clamp(b >> 12, 0, 0xff0);
 }
 
 /* precalculate color bar values to speed up rendering */
@@ -522,17 +456,18 @@
 		g <<= 4;
 		b <<= 4;
 	}
-	if (tpg->qual == TPG_QUAL_GRAY) {
-		/* Rec. 709 Luma function */
-		/* (0.2126, 0.7152, 0.0722) * (255 * 256) */
-		r = g = b = ((13879 * r + 46688 * g + 4713 * b) >> 16) + (16 << 4);
-	}
+	if (tpg->qual == TPG_QUAL_GRAY)
+		r = g = b = color_to_y(tpg, r, g, b);
 
 	/*
 	 * The assumption is that the RGB output is always full range,
 	 * so only if the rgb_range overrides the 'real' rgb range do
 	 * we need to convert the RGB values.
 	 *
+	 * Currently there is no way of signalling to userspace if you
+	 * are actually giving it limited range RGB (or full range
+	 * YUV for that matter).
+	 *
 	 * Remember that r, g and b are still in the 0 - 0xff0 range.
 	 */
 	if (tpg->real_rgb_range == V4L2_DV_RGB_RANGE_LIMITED &&
@@ -562,12 +497,12 @@
 	if (tpg->brightness != 128 || tpg->contrast != 128 ||
 	    tpg->saturation != 128 || tpg->hue) {
 		/* Implement these operations */
-		int y, cb, cr;
-		int tmp_cb, tmp_cr;
 
 		/* First convert to YCbCr */
-
-		color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
+		int y = color_to_y(tpg, r, g, b);	/* Luma */
+		int cb = color_to_cb(tpg, r, g, b);	/* Cb */
+		int cr = color_to_cr(tpg, r, g, b);	/* Cr */
+		int tmp_cb, tmp_cr;
 
 		y = (16 << 4) + ((y - (16 << 4)) * tpg->contrast) / 128;
 		y += (tpg->brightness << 4) - (128 << 4);
@@ -585,29 +520,21 @@
 			tpg->colors[k][2] = clamp(cr >> 4, 1, 254);
 			return;
 		}
-		ycbcr_to_color(tpg, y, cb, cr, &r, &g, &b);
+		r = ycbcr_to_r(tpg, y, cb, cr);
+		g = ycbcr_to_g(tpg, y, cb, cr);
+		b = ycbcr_to_b(tpg, y, cb, cr);
 	}
 
 	if (tpg->is_yuv) {
 		/* Convert to YCbCr */
-		int y, cb, cr;
+		u16 y = color_to_y(tpg, r, g, b);	/* Luma */
+		u16 cb = color_to_cb(tpg, r, g, b);	/* Cb */
+		u16 cr = color_to_cr(tpg, r, g, b);	/* Cr */
 
-		color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
-
-		if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
-			y = clamp(y, 16 << 4, 235 << 4);
-			cb = clamp(cb, 16 << 4, 240 << 4);
-			cr = clamp(cr, 16 << 4, 240 << 4);
-		}
 		tpg->colors[k][0] = clamp(y >> 4, 1, 254);
 		tpg->colors[k][1] = clamp(cb >> 4, 1, 254);
 		tpg->colors[k][2] = clamp(cr >> 4, 1, 254);
 	} else {
-		if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
-			r = (r * 219) / 255 + (16 << 4);
-			g = (g * 219) / 255 + (16 << 4);
-			b = (b * 219) / 255 + (16 << 4);
-		}
 		switch (tpg->fourcc) {
 		case V4L2_PIX_FMT_RGB565:
 		case V4L2_PIX_FMT_RGB565X:
@@ -1225,46 +1152,6 @@
 	if (tpg->recalc_colors) {
 		tpg->recalc_colors = false;
 		tpg->recalc_lines = true;
-		tpg->real_ycbcr_enc = tpg->ycbcr_enc;
-		tpg->real_quantization = tpg->quantization;
-		if (tpg->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
-			switch (tpg->colorspace) {
-			case V4L2_COLORSPACE_REC709:
-				tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_709;
-				break;
-			case V4L2_COLORSPACE_SRGB:
-				tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_SYCC;
-				break;
-			case V4L2_COLORSPACE_BT2020:
-				tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_BT2020;
-				break;
-			case V4L2_COLORSPACE_SMPTE240M:
-				tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_SMPTE240M;
-				break;
-			case V4L2_COLORSPACE_SMPTE170M:
-			case V4L2_COLORSPACE_470_SYSTEM_M:
-			case V4L2_COLORSPACE_470_SYSTEM_BG:
-			case V4L2_COLORSPACE_ADOBERGB:
-			default:
-				tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_601;
-				break;
-			}
-		}
-		if (tpg->quantization == V4L2_QUANTIZATION_DEFAULT) {
-			tpg->real_quantization = V4L2_QUANTIZATION_FULL_RANGE;
-			if (tpg->is_yuv) {
-				switch (tpg->real_ycbcr_enc) {
-				case V4L2_YCBCR_ENC_SYCC:
-				case V4L2_YCBCR_ENC_XV601:
-				case V4L2_YCBCR_ENC_XV709:
-					break;
-				default:
-					tpg->real_quantization =
-						V4L2_QUANTIZATION_LIM_RANGE;
-					break;
-				}
-			}
-		}
 		tpg_precalculate_colors(tpg);
 	}
 	if (tpg->recalc_square_border) {
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index 9dc463a..8ef3e52 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -119,18 +119,6 @@
 	u32				fourcc;
 	bool				is_yuv;
 	u32				colorspace;
-	u32				ycbcr_enc;
-	/*
-	 * Stores the actual Y'CbCr encoding, i.e. will never be
-	 * V4L2_YCBCR_ENC_DEFAULT.
-	 */
-	u32				real_ycbcr_enc;
-	u32				quantization;
-	/*
-	 * Stores the actual quantization, i.e. will never be
-	 * V4L2_QUANTIZATION_DEFAULT.
-	 */
-	u32				real_quantization;
 	enum tpg_video_aspect		vid_aspect;
 	enum tpg_pixel_aspect		pix_aspect;
 	unsigned			rgb_range;
@@ -298,32 +286,6 @@
 	return tpg->colorspace;
 }
 
-static inline void tpg_s_ycbcr_enc(struct tpg_data *tpg, u32 ycbcr_enc)
-{
-	if (tpg->ycbcr_enc == ycbcr_enc)
-		return;
-	tpg->ycbcr_enc = ycbcr_enc;
-	tpg->recalc_colors = true;
-}
-
-static inline u32 tpg_g_ycbcr_enc(const struct tpg_data *tpg)
-{
-	return tpg->ycbcr_enc;
-}
-
-static inline void tpg_s_quantization(struct tpg_data *tpg, u32 quantization)
-{
-	if (tpg->quantization == quantization)
-		return;
-	tpg->quantization = quantization;
-	tpg->recalc_colors = true;
-}
-
-static inline u32 tpg_g_quantization(const struct tpg_data *tpg)
-{
-	return tpg->quantization;
-}
-
 static inline unsigned tpg_g_planes(const struct tpg_data *tpg)
 {
 	return tpg->planes;
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
index ef81b01..2166d0b 100644
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
@@ -236,8 +236,8 @@
 	.buf_queue		= vbi_cap_buf_queue,
 	.start_streaming	= vbi_cap_start_streaming,
 	.stop_streaming		= vbi_cap_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
+	.wait_prepare		= vivid_unlock,
+	.wait_finish		= vivid_lock,
 };
 
 int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c
index 4e4c70e..9d00a07 100644
--- a/drivers/media/platform/vivid/vivid-vbi-out.c
+++ b/drivers/media/platform/vivid/vivid-vbi-out.c
@@ -131,8 +131,8 @@
 	.buf_queue		= vbi_out_buf_queue,
 	.start_streaming	= vbi_out_start_streaming,
 	.stop_streaming		= vbi_out_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
+	.wait_prepare		= vivid_unlock,
+	.wait_finish		= vivid_lock,
 };
 
 int vidioc_g_fmt_vbi_out(struct file *file, void *priv,
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 867a29a..331c544 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -288,8 +288,8 @@
 	.buf_queue		= vid_cap_buf_queue,
 	.start_streaming	= vid_cap_start_streaming,
 	.stop_streaming		= vid_cap_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
+	.wait_prepare		= vivid_unlock,
+	.wait_finish		= vivid_lock,
 };
 
 /*
@@ -443,12 +443,12 @@
 			break;
 		if (bt->standards & V4L2_DV_BT_STD_CEA861) {
 			if (bt->width == 720 && bt->height <= 576)
-				v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
+				v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SMPTE170M);
 			else
-				v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_709);
+				v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_REC709);
 			v4l2_ctrl_s_ctrl(dev->real_rgb_range_cap, 1);
 		} else {
-			v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
+			v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SRGB);
 			v4l2_ctrl_s_ctrl(dev->real_rgb_range_cap, 0);
 		}
 		tpg_s_rgb_range(&dev->tpg, v4l2_ctrl_g_ctrl(dev->rgb_range_cap));
@@ -498,20 +498,6 @@
 	return dev->colorspace_out;
 }
 
-static unsigned vivid_ycbcr_enc_cap(struct vivid_dev *dev)
-{
-	if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
-		return tpg_g_ycbcr_enc(&dev->tpg);
-	return dev->ycbcr_enc_out;
-}
-
-static unsigned vivid_quantization_cap(struct vivid_dev *dev)
-{
-	if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
-		return tpg_g_quantization(&dev->tpg);
-	return dev->quantization_out;
-}
-
 int vivid_g_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
 {
@@ -524,8 +510,6 @@
 	mp->field        = dev->field_cap;
 	mp->pixelformat  = dev->fmt_cap->fourcc;
 	mp->colorspace   = vivid_colorspace_cap(dev);
-	mp->ycbcr_enc    = vivid_ycbcr_enc_cap(dev);
-	mp->quantization = vivid_quantization_cap(dev);
 	mp->num_planes = dev->fmt_cap->planes;
 	for (p = 0; p < mp->num_planes; p++) {
 		mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(&dev->tpg, p);
@@ -611,8 +595,6 @@
 		memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
 	}
 	mp->colorspace = vivid_colorspace_cap(dev);
-	mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
-	mp->quantization = vivid_quantization_cap(dev);
 	memset(mp->reserved, 0, sizeof(mp->reserved));
 	return 0;
 }
@@ -1325,20 +1307,20 @@
 	if (dev->colorspace) {
 		switch (dev->input_type[i]) {
 		case WEBCAM:
-			v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
+			v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SRGB);
 			break;
 		case TV:
 		case SVID:
-			v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
+			v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SMPTE170M);
 			break;
 		case HDMI:
 			if (bt->standards & V4L2_DV_BT_STD_CEA861) {
 				if (dev->src_rect.width == 720 && dev->src_rect.height <= 576)
-					v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
+					v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SMPTE170M);
 				else
-					v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_709);
+					v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_REC709);
 			} else {
-				v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
+				v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SRGB);
 			}
 			break;
 		}
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 6bef1e6..16cd6d2 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -259,8 +259,6 @@
 	mp->pixelformat = pix->pixelformat;
 	mp->field = pix->field;
 	mp->colorspace = pix->colorspace;
-	mp->ycbcr_enc = pix->ycbcr_enc;
-	mp->quantization = pix->quantization;
 	mp->num_planes = 1;
 	mp->flags = pix->flags;
 	ppix->sizeimage = pix->sizeimage;
@@ -287,8 +285,6 @@
 	pix->pixelformat = mp->pixelformat;
 	pix->field = mp->field;
 	pix->colorspace = mp->colorspace;
-	pix->ycbcr_enc = mp->ycbcr_enc;
-	pix->quantization = mp->quantization;
 	pix->sizeimage = ppix->sizeimage;
 	pix->bytesperline = ppix->bytesperline;
 	pix->flags = mp->flags;
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 39ff79f..69c2dbd 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -209,8 +209,8 @@
 	.buf_queue		= vid_out_buf_queue,
 	.start_streaming	= vid_out_start_streaming,
 	.stop_streaming		= vid_out_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
+	.wait_prepare		= vivid_unlock,
+	.wait_finish		= vivid_lock,
 };
 
 /*
@@ -259,8 +259,6 @@
 		}
 		break;
 	}
-	dev->ycbcr_enc_out = V4L2_YCBCR_ENC_DEFAULT;
-	dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
 	dev->compose_out = dev->sink_rect;
 	dev->compose_bounds_out = dev->sink_rect;
 	dev->crop_out = dev->compose_out;
@@ -320,8 +318,6 @@
 	mp->field        = dev->field_out;
 	mp->pixelformat  = dev->fmt_out->fourcc;
 	mp->colorspace   = dev->colorspace_out;
-	mp->ycbcr_enc    = dev->ycbcr_enc_out;
-	mp->quantization = dev->quantization_out;
 	mp->num_planes = dev->fmt_out->planes;
 	for (p = 0; p < mp->num_planes; p++) {
 		mp->plane_fmt[p].bytesperline = dev->bytesperline_out[p];
@@ -398,23 +394,16 @@
 		pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height;
 		memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
 	}
-	mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
-	mp->quantization = V4L2_QUANTIZATION_DEFAULT;
-	if (vivid_is_svid_out(dev)) {
+	if (vivid_is_svid_out(dev))
 		mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	} else if (dev->dvi_d_out || !(bt->standards & V4L2_DV_BT_STD_CEA861)) {
+	else if (dev->dvi_d_out || !(bt->standards & V4L2_DV_BT_STD_CEA861))
 		mp->colorspace = V4L2_COLORSPACE_SRGB;
-		if (dev->dvi_d_out)
-			mp->quantization = V4L2_QUANTIZATION_LIM_RANGE;
-	} else if (bt->width == 720 && bt->height <= 576) {
+	else if (bt->width == 720 && bt->height <= 576)
 		mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	} else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M &&
-		   mp->colorspace != V4L2_COLORSPACE_REC709 &&
-		   mp->colorspace != V4L2_COLORSPACE_ADOBERGB &&
-		   mp->colorspace != V4L2_COLORSPACE_BT2020 &&
-		   mp->colorspace != V4L2_COLORSPACE_SRGB) {
+	else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M &&
+		 mp->colorspace != V4L2_COLORSPACE_REC709 &&
+		 mp->colorspace != V4L2_COLORSPACE_SRGB)
 		mp->colorspace = V4L2_COLORSPACE_REC709;
-	}
 	memset(mp->reserved, 0, sizeof(mp->reserved));
 	return 0;
 }
@@ -533,8 +522,6 @@
 
 set_colorspace:
 	dev->colorspace_out = mp->colorspace;
-	dev->ycbcr_enc_out = mp->ycbcr_enc;
-	dev->quantization_out = mp->quantization;
 	if (dev->loop_video) {
 		vivid_send_source_change(dev, SVID);
 		vivid_send_source_change(dev, HDMI);
@@ -625,7 +612,7 @@
 		sel->r = dev->fmt_out_rect;
 		break;
 	case V4L2_SEL_TGT_CROP_BOUNDS:
-		if (!dev->has_crop_out)
+		if (!dev->has_compose_out)
 			return -EINVAL;
 		sel->r = vivid_max_rect;
 		break;
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index b21f381..a0c1984 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -187,8 +187,8 @@
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
 	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
+		V4L2_MBUS_FMT_ARGB8888_1X32,
+		V4L2_MBUS_FMT_AYUV8_1X32,
 	};
 	struct v4l2_mbus_framefmt *format;
 
@@ -215,8 +215,8 @@
 	if (fse->index)
 		return -EINVAL;
 
-	if (fse->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-	    fse->code != MEDIA_BUS_FMT_AYUV8_1X32)
+	if (fse->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+	    fse->code != V4L2_MBUS_FMT_AYUV8_1X32)
 		return -EINVAL;
 
 	fse->min_width = BRU_MIN_SIZE;
@@ -261,9 +261,9 @@
 	switch (pad) {
 	case BRU_PAD_SINK(0):
 		/* Default to YUV if the requested format is not supported. */
-		if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-		    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
-			fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+		if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+		    fmt->code != V4L2_MBUS_FMT_AYUV8_1X32)
+			fmt->code = V4L2_MBUS_FMT_AYUV8_1X32;
 		break;
 
 	default:
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 5eb16e8..3e6601b 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -562,6 +562,7 @@
 	.probe		= vsp1_probe,
 	.remove		= vsp1_remove,
 	.driver		= {
+		.owner	= THIS_MODULE,
 		.name	= "vsp1",
 		.pm	= &vsp1_pm_ops,
 		.of_match_table = vsp1_of_match,
diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c
index 80bedc5..db2950a 100644
--- a/drivers/media/platform/vsp1/vsp1_hsit.c
+++ b/drivers/media/platform/vsp1/vsp1_hsit.c
@@ -70,9 +70,9 @@
 
 	if ((code->pad == HSIT_PAD_SINK && !hsit->inverse) |
 	    (code->pad == HSIT_PAD_SOURCE && hsit->inverse))
-		code->code = MEDIA_BUS_FMT_ARGB8888_1X32;
+		code->code = V4L2_MBUS_FMT_ARGB8888_1X32;
 	else
-		code->code = MEDIA_BUS_FMT_AHSV8888_1X32;
+		code->code = V4L2_MBUS_FMT_AHSV8888_1X32;
 
 	return 0;
 }
@@ -136,8 +136,8 @@
 		return 0;
 	}
 
-	format->code = hsit->inverse ? MEDIA_BUS_FMT_AHSV8888_1X32
-		     : MEDIA_BUS_FMT_ARGB8888_1X32;
+	format->code = hsit->inverse ? V4L2_MBUS_FMT_AHSV8888_1X32
+		     : V4L2_MBUS_FMT_ARGB8888_1X32;
 	format->width = clamp_t(unsigned int, fmt->format.width,
 				HSIT_MIN_SIZE, HSIT_MAX_SIZE);
 	format->height = clamp_t(unsigned int, fmt->format.height,
@@ -151,8 +151,8 @@
 	format = vsp1_entity_get_pad_format(&hsit->entity, fh, HSIT_PAD_SOURCE,
 					    fmt->which);
 	*format = fmt->format;
-	format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32
-		     : MEDIA_BUS_FMT_AHSV8888_1X32;
+	format->code = hsit->inverse ? V4L2_MBUS_FMT_ARGB8888_1X32
+		     : V4L2_MBUS_FMT_AHSV8888_1X32;
 
 	return 0;
 }
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index 17a6ca7..d4fb23e 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -78,8 +78,8 @@
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
 	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
+		V4L2_MBUS_FMT_ARGB8888_1X32,
+		V4L2_MBUS_FMT_AYUV8_1X32,
 	};
 
 	if (code->pad == LIF_PAD_SINK) {
@@ -147,9 +147,9 @@
 	struct v4l2_mbus_framefmt *format;
 
 	/* Default to YUV if the requested format is not supported. */
-	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
-		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+	if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+	    fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32)
+		fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32;
 
 	format = vsp1_entity_get_pad_format(&lif->entity, fh, fmt->pad,
 					    fmt->which);
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index 6f185c3..fea36eb 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -86,9 +86,9 @@
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
 	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AHSV8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
+		V4L2_MBUS_FMT_ARGB8888_1X32,
+		V4L2_MBUS_FMT_AHSV8888_1X32,
+		V4L2_MBUS_FMT_AYUV8_1X32,
 	};
 	struct v4l2_mbus_framefmt *format;
 
@@ -158,10 +158,10 @@
 	struct v4l2_mbus_framefmt *format;
 
 	/* Default to YUV if the requested format is not supported. */
-	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
-		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+	if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+	    fmt->format.code != V4L2_MBUS_FMT_AHSV8888_1X32 &&
+	    fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32)
+		fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32;
 
 	format = vsp1_entity_get_pad_format(&lut->entity, fh, fmt->pad,
 					    fmt->which);
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c
index 1f1ba26..ec3dab6 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.c
@@ -29,8 +29,8 @@
 			     struct v4l2_subdev_mbus_code_enum *code)
 {
 	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
+		V4L2_MBUS_FMT_ARGB8888_1X32,
+		V4L2_MBUS_FMT_AYUV8_1X32,
 	};
 
 	if (code->index >= ARRAY_SIZE(codes))
@@ -103,9 +103,9 @@
 	struct v4l2_rect *crop;
 
 	/* Default to YUV if the requested format is not supported. */
-	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
-		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+	if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+	    fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32)
+		fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32;
 
 	format = vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad,
 					    fmt->which);
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index 1129494..b7d3c8b 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -139,7 +139,7 @@
 	input = &sru->entity.formats[SRU_PAD_SINK];
 	output = &sru->entity.formats[SRU_PAD_SOURCE];
 
-	if (input->code == MEDIA_BUS_FMT_ARGB8888_1X32)
+	if (input->code == V4L2_MBUS_FMT_ARGB8888_1X32)
 		ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3
 		      | VI6_SRU_CTRL0_PARAM4;
 	else
@@ -170,8 +170,8 @@
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
 	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
+		V4L2_MBUS_FMT_ARGB8888_1X32,
+		V4L2_MBUS_FMT_AYUV8_1X32,
 	};
 	struct v4l2_mbus_framefmt *format;
 
@@ -248,9 +248,9 @@
 	switch (pad) {
 	case SRU_PAD_SINK:
 		/* Default to YUV if the requested format is not supported. */
-		if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-		    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
-			fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+		if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+		    fmt->code != V4L2_MBUS_FMT_AYUV8_1X32)
+			fmt->code = V4L2_MBUS_FMT_AYUV8_1X32;
 
 		fmt->width = clamp(fmt->width, SRU_MIN_SIZE, SRU_MAX_SIZE);
 		fmt->height = clamp(fmt->height, SRU_MIN_SIZE, SRU_MAX_SIZE);
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index a4afec1..de92ef4 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -173,8 +173,8 @@
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
 	static const unsigned int codes[] = {
-		MEDIA_BUS_FMT_ARGB8888_1X32,
-		MEDIA_BUS_FMT_AYUV8_1X32,
+		V4L2_MBUS_FMT_ARGB8888_1X32,
+		V4L2_MBUS_FMT_AYUV8_1X32,
 	};
 
 	if (code->pad == UDS_PAD_SINK) {
@@ -246,9 +246,9 @@
 	switch (pad) {
 	case UDS_PAD_SINK:
 		/* Default to YUV if the requested format is not supported. */
-		if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
-		    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
-			fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+		if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+		    fmt->code != V4L2_MBUS_FMT_AYUV8_1X32)
+			fmt->code = V4L2_MBUS_FMT_AYUV8_1X32;
 
 		fmt->width = clamp(fmt->width, UDS_MIN_SIZE, UDS_MAX_SIZE);
 		fmt->height = clamp(fmt->height, UDS_MIN_SIZE, UDS_MAX_SIZE);
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index d91f19a..915a20e 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -48,85 +48,85 @@
  */
 
 static const struct vsp1_format_info vsp1_video_formats[] = {
-	{ V4L2_PIX_FMT_RGB332, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 8, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_ARGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS,
 	  1, { 16, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_XRGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS,
 	  1, { 16, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_ARGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS,
 	  1, { 16, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_XRGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_XRGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS,
 	  1, { 16, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS,
 	  1, { 16, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_BGR24, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 24, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_RGB24, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 24, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_ABGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_ABGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
 	  1, { 32, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_XBGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
 	  1, { 32, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_ARGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 32, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_XRGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
+	{ V4L2_PIX_FMT_XRGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
 	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 32, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_UYVY, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 16, 0, 0 }, false, false, 2, 1, false },
-	{ V4L2_PIX_FMT_VYUY, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_VYUY, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 16, 0, 0 }, false, true, 2, 1, false },
-	{ V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_YUYV, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 16, 0, 0 }, true, false, 2, 1, false },
-	{ V4L2_PIX_FMT_YVYU, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_YVYU, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 16, 0, 0 }, true, true, 2, 1, false },
-	{ V4L2_PIX_FMT_NV12M, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  2, { 8, 16, 0 }, false, false, 2, 2, false },
-	{ V4L2_PIX_FMT_NV21M, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  2, { 8, 16, 0 }, false, true, 2, 2, false },
-	{ V4L2_PIX_FMT_NV16M, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  2, { 8, 16, 0 }, false, false, 2, 1, false },
-	{ V4L2_PIX_FMT_NV61M, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  2, { 8, 16, 0 }, false, true, 2, 1, false },
-	{ V4L2_PIX_FMT_YUV420M, MEDIA_BUS_FMT_AYUV8_1X32,
+	{ V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32,
 	  VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  3, { 8, 8, 8 }, false, false, 2, 2, false },
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c
index da160f4..5215a21 100644
--- a/drivers/media/radio/radio-si476x.c
+++ b/drivers/media/radio/radio-si476x.c
@@ -1575,6 +1575,7 @@
 static struct platform_driver si476x_radio_driver = {
 	.driver		= {
 		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
 	},
 	.probe		= si476x_radio_probe,
 	.remove		= si476x_radio_remove,
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index e6b55ed..b9285e6 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -174,6 +174,7 @@
 static struct platform_driver timbradio_platform_driver = {
 	.driver = {
 		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
 	},
 	.probe		= timbradio_probe,
 	.remove		= timbradio_remove,
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index b8f3644..9cf6731 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -1279,12 +1279,10 @@
 	strlcpy(capability->bus_info, radio->bus_type,
 		sizeof(capability->bus_info));
 
-	capability->device_caps = V4L2_CAP_HW_FREQ_SEEK |
+	capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
 		V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_AUDIO |
 		V4L2_CAP_RDS_CAPTURE | V4L2_CAP_MODULATOR |
 		V4L2_CAP_RDS_OUTPUT;
-	capability->capabilities = capability->device_caps |
-		V4L2_CAP_DEVICE_CAPS;
 
 	return 0;
 }
@@ -2150,6 +2148,7 @@
 	.remove		= wl1273_fm_radio_remove,
 	.driver		= {
 		.name	= "wl1273_fm_radio",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/media/radio/si4713/Kconfig b/drivers/media/radio/si4713/Kconfig
index 19f9fde..c8aca65 100644
--- a/drivers/media/radio/si4713/Kconfig
+++ b/drivers/media/radio/si4713/Kconfig
@@ -1,5 +1,4 @@
 config USB_SI4713
-	depends on !KERNEL_3_13
 	tristate "Silicon Labs Si4713 FM Radio Transmitter support with USB"
 	depends on m
 	depends on USB && I2C && RADIO_SI4713
@@ -16,7 +15,6 @@
 	  module will be called radio-usb-si4713.
 
 config PLATFORM_SI4713
-	depends on !KERNEL_3_13
 	tristate "Silicon Labs Si4713 FM Radio Transmitter support with I2C"
 	depends on m
 	depends on I2C && RADIO_SI4713
@@ -32,7 +30,6 @@
 	  module will be called radio-platform-si4713.
 
 config I2C_SI4713
-	depends on !KERNEL_3_13
 	tristate "Silicon Labs Si4713 FM Radio Transmitter support"
 	depends on m
 	depends on I2C && RADIO_SI4713
diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c
index 6c75973..a47502a 100644
--- a/drivers/media/radio/si4713/radio-platform-si4713.c
+++ b/drivers/media/radio/si4713/radio-platform-si4713.c
@@ -34,7 +34,7 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-event.h>
-#include "si4713.h"
+#include <media/radio-si4713.h>
 
 /* module parameters */
 static int radio_nr = -1;	/* radio device minor (-1 ==> auto assign) */
@@ -153,6 +153,7 @@
 {
 	struct radio_si4713_platform_data *pdata = pdev->dev.platform_data;
 	struct radio_si4713_device *rsdev;
+	struct i2c_adapter *adapter;
 	struct v4l2_subdev *sd;
 	int rval = 0;
 
@@ -176,13 +177,22 @@
 		goto exit;
 	}
 
-	sd = i2c_get_clientdata(pdata->subdev);
-	rval = v4l2_device_register_subdev(&rsdev->v4l2_dev, sd);
-	if (rval) {
-		dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
+	adapter = i2c_get_adapter(pdata->i2c_bus);
+	if (!adapter) {
+		dev_err(&pdev->dev, "Cannot get i2c adapter %d\n",
+			pdata->i2c_bus);
+		rval = -ENODEV;
 		goto unregister_v4l2_dev;
 	}
 
+	sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
+				       pdata->subdev_board_info, NULL);
+	if (!sd) {
+		dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
+		rval = -ENODEV;
+		goto put_adapter;
+	}
+
 	rsdev->radio_dev = radio_si4713_vdev_template;
 	rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
 	rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
@@ -192,12 +202,14 @@
 	if (video_register_device(&rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
 		dev_err(&pdev->dev, "Could not register video device.\n");
 		rval = -EIO;
-		goto unregister_v4l2_dev;
+		goto put_adapter;
 	}
 	dev_info(&pdev->dev, "New device successfully probed\n");
 
 	goto exit;
 
+put_adapter:
+	i2c_put_adapter(adapter);
 unregister_v4l2_dev:
 	v4l2_device_unregister(&rsdev->v4l2_dev);
 exit:
@@ -208,10 +220,14 @@
 static int radio_si4713_pdriver_remove(struct platform_device *pdev)
 {
 	struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+	struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
+					    struct v4l2_subdev, list);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct radio_si4713_device *rsdev;
 
 	rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
 	video_unregister_device(&rsdev->radio_dev);
+	i2c_put_adapter(client->adapter);
 	v4l2_device_unregister(&rsdev->v4l2_dev);
 
 	return 0;
@@ -220,6 +236,7 @@
 static struct platform_driver radio_si4713_pdriver = {
 	.driver		= {
 		.name	= "radio-si4713",
+		.owner	= THIS_MODULE,
 	},
 	.probe		= radio_si4713_pdriver_probe,
 	.remove         = radio_si4713_pdriver_remove,
diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
index c90004d..b576555 100644
--- a/drivers/media/radio/si4713/si4713.c
+++ b/drivers/media/radio/si4713/si4713.c
@@ -23,7 +23,6 @@
 
 #include <linux/completion.h>
 #include <linux/delay.h>
-#include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
@@ -367,25 +366,16 @@
 	if (sdev->power_state)
 		return 0;
 
-	if (sdev->vdd) {
-		err = regulator_enable(sdev->vdd);
+	if (sdev->supplies) {
+		err = regulator_bulk_enable(sdev->supplies, sdev->supply_data);
 		if (err) {
-			v4l2_err(&sdev->sd, "Failed to enable vdd: %d\n", err);
+			v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err);
 			return err;
 		}
 	}
-
-	if (sdev->vio) {
-		err = regulator_enable(sdev->vio);
-		if (err) {
-			v4l2_err(&sdev->sd, "Failed to enable vio: %d\n", err);
-			return err;
-		}
-	}
-
-	if (!IS_ERR(sdev->gpio_reset)) {
+	if (gpio_is_valid(sdev->gpio_reset)) {
 		udelay(50);
-		gpiod_set_value(sdev->gpio_reset, 1);
+		gpio_set_value(sdev->gpio_reset, 1);
 	}
 
 	if (client->irq)
@@ -407,20 +397,13 @@
 						SI4713_STC_INT | SI4713_CTS);
 		return err;
 	}
-	if (!IS_ERR(sdev->gpio_reset))
-		gpiod_set_value(sdev->gpio_reset, 0);
-
-
-	if (sdev->vdd) {
-		err = regulator_disable(sdev->vdd);
+	if (gpio_is_valid(sdev->gpio_reset))
+		gpio_set_value(sdev->gpio_reset, 0);
+	if (sdev->supplies) {
+		err = regulator_bulk_disable(sdev->supplies, sdev->supply_data);
 		if (err)
-			v4l2_err(&sdev->sd, "Failed to disable vdd: %d\n", err);
-	}
-
-	if (sdev->vio) {
-		err = regulator_disable(sdev->vio);
-		if (err)
-			v4l2_err(&sdev->sd, "Failed to disable vio: %d\n", err);
+			v4l2_err(&sdev->sd,
+				 "Failed to disable supplies: %d\n", err);
 	}
 
 	return err;
@@ -447,23 +430,14 @@
 		v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",
 				resp[0]);
 		v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");
-		if (!IS_ERR(sdev->gpio_reset))
-			gpiod_set_value(sdev->gpio_reset, 0);
-
-		if (sdev->vdd) {
-			err = regulator_disable(sdev->vdd);
-			if (err) {
+		if (gpio_is_valid(sdev->gpio_reset))
+			gpio_set_value(sdev->gpio_reset, 0);
+		if (sdev->supplies) {
+			err = regulator_bulk_disable(sdev->supplies,
+						     sdev->supply_data);
+			if (err)
 				v4l2_err(&sdev->sd,
-					"Failed to disable vdd: %d\n", err);
-			}
-		}
-
-		if (sdev->vio) {
-			err = regulator_disable(sdev->vio);
-			if (err) {
-				v4l2_err(&sdev->sd,
-					"Failed to disable vio: %d\n", err);
-			}
+					 "Failed to disable supplies: %d\n", err);
 		}
 		sdev->power_state = POWER_OFF;
 	}
@@ -1446,51 +1420,38 @@
 					const struct i2c_device_id *id)
 {
 	struct si4713_device *sdev;
-	struct v4l2_ctrl_handler *hdl;
 	struct si4713_platform_data *pdata = client->dev.platform_data;
-	struct device_node *np = client->dev.of_node;
-	struct radio_si4713_platform_data si4713_pdev_pdata;
-	struct platform_device *si4713_pdev;
-	int rval;
+	struct v4l2_ctrl_handler *hdl;
+	int rval, i;
 
-	sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL);
+	sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
 	if (!sdev) {
 		dev_err(&client->dev, "Failed to alloc video device.\n");
 		rval = -ENOMEM;
 		goto exit;
 	}
 
-	sdev->gpio_reset = devm_gpiod_get(&client->dev, "reset");
-	if (!IS_ERR(sdev->gpio_reset)) {
-		gpiod_direction_output(sdev->gpio_reset, 0);
-	} else if (PTR_ERR(sdev->gpio_reset) == -ENOENT) {
-		dev_dbg(&client->dev, "No reset GPIO assigned\n");
-	} else if (PTR_ERR(sdev->gpio_reset) == -ENOSYS) {
-		dev_dbg(&client->dev, "No reset GPIO support\n");
-	} else {
-		rval = PTR_ERR(sdev->gpio_reset);
-		dev_err(&client->dev, "Failed to request gpio: %d\n", rval);
-		goto exit;
+	sdev->gpio_reset = -1;
+	if (pdata && gpio_is_valid(pdata->gpio_reset)) {
+		rval = gpio_request(pdata->gpio_reset, "si4713 reset");
+		if (rval) {
+			dev_err(&client->dev,
+				"Failed to request gpio: %d\n", rval);
+			goto free_sdev;
+		}
+		sdev->gpio_reset = pdata->gpio_reset;
+		gpio_direction_output(sdev->gpio_reset, 0);
+		sdev->supplies = pdata->supplies;
 	}
 
-	sdev->vdd = devm_regulator_get_optional(&client->dev, "vdd");
-	if (IS_ERR(sdev->vdd)) {
-		rval = PTR_ERR(sdev->vdd);
-		if (rval == -EPROBE_DEFER)
-			goto exit;
+	for (i = 0; i < sdev->supplies; i++)
+		sdev->supply_data[i].supply = pdata->supply_names[i];
 
-		dev_dbg(&client->dev, "no vdd regulator found: %d\n", rval);
-		sdev->vdd = NULL;
-	}
-
-	sdev->vio = devm_regulator_get_optional(&client->dev, "vio");
-	if (IS_ERR(sdev->vio)) {
-		rval = PTR_ERR(sdev->vio);
-		if (rval == -EPROBE_DEFER)
-			goto exit;
-
-		dev_dbg(&client->dev, "no vio regulator found: %d\n", rval);
-		sdev->vio = NULL;
+	rval = regulator_bulk_get(&client->dev, sdev->supplies,
+				  sdev->supply_data);
+	if (rval) {
+		dev_err(&client->dev, "Cannot get regulators: %d\n", rval);
+		goto free_gpio;
 	}
 
 	v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
@@ -1593,12 +1554,12 @@
 	sdev->sd.ctrl_handler = hdl;
 
 	if (client->irq) {
-		rval = devm_request_irq(&client->dev, client->irq,
+		rval = request_irq(client->irq,
 			si4713_handler, IRQF_TRIGGER_FALLING,
 			client->name, sdev);
 		if (rval < 0) {
 			v4l2_err(&sdev->sd, "Could not request IRQ\n");
-			goto free_ctrls;
+			goto put_reg;
 		}
 		v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
 	} else {
@@ -1608,35 +1569,23 @@
 	rval = si4713_initialize(sdev);
 	if (rval < 0) {
 		v4l2_err(&sdev->sd, "Failed to probe device information.\n");
-		goto free_ctrls;
+		goto free_irq;
 	}
 
-	if (!np && (!pdata || !pdata->is_platform_device))
-		return 0;
-
-	si4713_pdev = platform_device_alloc("radio-si4713", -1);
-	if (!si4713_pdev)
-		goto put_main_pdev;
-
-	si4713_pdev_pdata.subdev = client;
-	rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata,
-					sizeof(si4713_pdev_pdata));
-	if (rval)
-		goto put_main_pdev;
-
-	rval = platform_device_add(si4713_pdev);
-	if (rval)
-		goto put_main_pdev;
-
-	sdev->pd = si4713_pdev;
-
 	return 0;
 
-put_main_pdev:
-	platform_device_put(si4713_pdev);
-	v4l2_device_unregister_subdev(&sdev->sd);
+free_irq:
+	if (client->irq)
+		free_irq(client->irq, sdev);
 free_ctrls:
 	v4l2_ctrl_handler_free(hdl);
+put_reg:
+	regulator_bulk_free(sdev->supplies, sdev->supply_data);
+free_gpio:
+	if (gpio_is_valid(sdev->gpio_reset))
+		gpio_free(sdev->gpio_reset);
+free_sdev:
+	kfree(sdev);
 exit:
 	return rval;
 }
@@ -1647,13 +1596,18 @@
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	struct si4713_device *sdev = to_si4713_device(sd);
 
-	platform_device_unregister(sdev->pd);
-
 	if (sdev->power_state)
 		si4713_set_power_state(sdev, POWER_DOWN);
 
+	if (client->irq > 0)
+		free_irq(client->irq, sdev);
+
 	v4l2_device_unregister_subdev(sd);
 	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	regulator_bulk_free(sdev->supplies, sdev->supply_data);
+	if (gpio_is_valid(sdev->gpio_reset))
+		gpio_free(sdev->gpio_reset);
+	kfree(sdev);
 
 	return 0;
 }
diff --git a/drivers/media/radio/si4713/si4713.h b/drivers/media/radio/si4713/si4713.h
index 8a376e1..ed700e3 100644
--- a/drivers/media/radio/si4713/si4713.h
+++ b/drivers/media/radio/si4713/si4713.h
@@ -15,9 +15,7 @@
 #ifndef SI4713_I2C_H
 #define SI4713_I2C_H
 
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-#include <linux/gpio/consumer.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-ctrls.h>
 #include <media/si4713.h>
@@ -192,6 +190,8 @@
 #define MIN_ACOMP_THRESHOLD		(-40)
 #define MAX_ACOMP_GAIN			20
 
+#define SI4713_NUM_SUPPLIES		2
+
 /*
  * si4713_device - private data
  */
@@ -236,10 +236,9 @@
 		struct v4l2_ctrl *tune_ant_cap;
 	};
 	struct completion work;
-	struct regulator *vdd;
-	struct regulator *vio;
-	struct gpio_desc *gpio_reset;
-	struct platform_device *pd;
+	unsigned supplies;
+	struct regulator_bulk_data supply_data[SI4713_NUM_SUPPLIES];
+	int gpio_reset;
 	u32 power_state;
 	u32 rds_enabled;
 	u32 frequency;
@@ -247,8 +246,4 @@
 	u32 stereo;
 	u32 tune_rnl;
 };
-
-struct radio_si4713_platform_data {
-	struct i2c_client *subdev;
-};
 #endif /* ifndef SI4713_I2C_H */
diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c
index 704397f..6f28f6e 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.c
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
@@ -1256,7 +1256,7 @@
 		fmerr("Unable to read firmware(%s) content\n", fw_name);
 		return ret;
 	}
-	fmdbg("Firmware(%s) length : %zu bytes\n", fw_name, fw_entry->size);
+	fmdbg("Firmware(%s) length : %d bytes\n", fw_name, fw_entry->size);
 
 	fw_data = (void *)fw_entry->data;
 	fw_len = fw_entry->size;
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index a5bd3f6..b55012c 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -198,12 +198,10 @@
 	strlcpy(capability->card, FM_DRV_CARD_SHORT_NAME,
 			sizeof(capability->card));
 	sprintf(capability->bus_info, "UART");
-	capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
+	capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
 		V4L2_CAP_RADIO | V4L2_CAP_MODULATOR |
 		V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
 		V4L2_CAP_RDS_CAPTURE;
-	capability->capabilities = capability->device_caps |
-		V4L2_CAP_DEVICE_CAPS;
 
 	return 0;
 }
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 99c880f..a4c907d 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -179,7 +179,7 @@
 	   module will be called ene_ir.
 
 config IR_HIX5HD2
-	depends on !KERNEL_3_7
+	depends on !BACKPORT_KERNEL_3_7
 	depends on CONFIG_MFD_SYSCON
 	tristate "Hisilicon hix5hd2 IR remote control"
 	depends on m
@@ -244,18 +244,6 @@
 	   To compile this driver as a module, choose M here: the
 	   module will be called fintek-cir.
 
-config IR_MESON
-	tristate "Amlogic Meson IR remote receiver"
-	depends on m
-	depends on RC_CORE
-	depends on ARCH_MESON || COMPILE_TEST
-	---help---
-	   Say Y if you want to use the IR remote receiver available
-	   on Amlogic Meson SoCs.
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called meson-ir.
-
 config IR_NUVOTON
 	tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
 	depends on m
@@ -275,8 +263,8 @@
 	depends on m
 	depends on USB_ARCH_HAS_HCD
 	depends on RC_CORE
-	select BPAUTO_NEW_LEDS
-	select BPAUTO_LEDS_CLASS
+	select BACKPORT_NEW_LEDS
+	select BACKPORT_LEDS_CLASS
 	depends on USB
 	---help---
 	   Say Y here if you want to use a RedRat3 Infrared Transceiver.
@@ -302,8 +290,8 @@
 	depends on m
 	depends on X86 && PNP
 	depends on RC_CORE
-	select BPAUTO_NEW_LEDS
-	select BPAUTO_LEDS_CLASS
+	select BACKPORT_NEW_LEDS
+	select BACKPORT_LEDS_CLASS
 	depends on BITREVERSE
 	---help---
 	   Say Y here if you want to use the IR remote functionality found
@@ -314,22 +302,6 @@
 	   To compile this driver as a module, choose M here: the module will
 	   be called winbond_cir.
 
-config IR_IGORPLUGUSB
-	tristate "IgorPlug-USB IR Receiver"
-	depends on m
-	depends on USB_ARCH_HAS_HCD
-	depends on RC_CORE
-	depends on USB
-	---help---
-	   Say Y here if you want to use the IgorPlug-USB IR Receiver by
-	   Igor Cesko. This device is included on the Fit-PC2.
-
-	   Note that this device can only record bursts of 36 IR pulses and
-	   spaces, which is not enough for the NEC, Sanyo and RC-6 protocol.
-
-	   To compile this driver as a module, choose M here: the module will
-	   be called igorplugusb.
-
 config IR_IGUANA
 	tristate "IguanaWorks USB IR Transceiver"
 	depends on m
@@ -353,8 +325,8 @@
 	depends on USB_ARCH_HAS_HCD
 	depends on RC_CORE
 	depends on USB
-	select BPAUTO_NEW_LEDS
-	select BPAUTO_LEDS_CLASS
+	select BACKPORT_NEW_LEDS
+	select BACKPORT_LEDS_CLASS
 	---help---
 	   Say Y here if you want to use the TechnoTrend USB IR Receiver. The
 	   driver can control the led.
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 0652848..9bba1fd 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -22,7 +22,6 @@
 obj-$(CPTCFG_IR_ITE_CIR) += ite-cir.o
 obj-$(CPTCFG_IR_MCEUSB) += mceusb.o
 obj-$(CPTCFG_IR_FINTEK) += fintek-cir.o
-obj-$(CPTCFG_IR_MESON) += meson-ir.o
 obj-$(CPTCFG_IR_NUVOTON) += nuvoton-cir.o
 obj-$(CPTCFG_IR_ENE) += ene_ir.o
 obj-$(CPTCFG_IR_REDRAT3) += redrat3.o
@@ -31,7 +30,6 @@
 obj-$(CPTCFG_IR_WINBOND_CIR) += winbond-cir.o
 obj-$(CPTCFG_RC_LOOPBACK) += rc-loopback.o
 obj-$(CPTCFG_IR_GPIO_CIR) += gpio-ir-recv.o
-obj-$(CPTCFG_IR_IGORPLUGUSB) += igorplugusb.o
 obj-$(CPTCFG_IR_IGUANA) += iguanair.o
 obj-$(CPTCFG_IR_TTUSBIR) += ttusbir.o
 obj-$(CPTCFG_RC_ST) += st_rc.o
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 229853d..5985308 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -240,6 +240,7 @@
 	.remove = gpio_ir_recv_remove,
 	.driver = {
 		.name   = GPIO_IR_DRIVER_NAME,
+		.owner  = THIS_MODULE,
 		.of_match_table = of_match_ptr(gpio_ir_recv_of_match),
 #ifdef CONFIG_PM
 		.pm	= &gpio_ir_recv_pm_ops,
diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c
deleted file mode 100644
index b36e515..0000000
--- a/drivers/media/rc/igorplugusb.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * IgorPlug-USB IR Receiver
- *
- * Copyright (C) 2014 Sean Young <sean@mess.org>
- *
- * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware.
- * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm
- *
- * Based on the lirc_igorplugusb.c driver:
- *	Copyright (C) 2004 Jan M. Hochstein
- *	<hochstein@algo.informatik.tu-darmstadt.de>
- *
- * 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/device.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-#include <media/rc-core.h>
-
-#define DRIVER_DESC		"IgorPlug-USB IR Receiver"
-#define DRIVER_NAME		"igorplugusb"
-
-#define HEADERLEN		3
-#define BUFLEN			36
-#define MAX_PACKET		(HEADERLEN + BUFLEN)
-
-#define SET_INFRABUFFER_EMPTY	1
-#define GET_INFRACODE		2
-
-
-struct igorplugusb {
-	struct rc_dev *rc;
-	struct device *dev;
-
-	struct urb *urb;
-	struct usb_ctrlrequest request;
-
-	struct timer_list timer;
-
-	uint8_t buf_in[MAX_PACKET];
-
-	char phys[64];
-};
-
-static void igorplugusb_cmd(struct igorplugusb *ir, int cmd);
-
-static void igorplugusb_irdata(struct igorplugusb *ir, unsigned len)
-{
-	DEFINE_IR_RAW_EVENT(rawir);
-	unsigned i, start, overflow;
-
-	dev_dbg(ir->dev, "irdata: %*ph (len=%u)", len, ir->buf_in, len);
-
-	/*
-	 * If more than 36 pulses and spaces follow each other, the igorplugusb
-	 * overwrites its buffer from the beginning. The overflow value is the
-	 * last offset which was not overwritten. Everything from this offset
-	 * onwards occurred before everything until this offset.
-	 */
-	overflow = ir->buf_in[2];
-	i = start = overflow + HEADERLEN;
-
-	if (start >= len) {
-		dev_err(ir->dev, "receive overflow invalid: %u", overflow);
-	} else {
-		if (overflow > 0)
-			dev_warn(ir->dev, "receive overflow, at least %u lost",
-								overflow);
-
-		do {
-			rawir.duration = ir->buf_in[i] * 85333;
-			rawir.pulse = i & 1;
-
-			ir_raw_event_store_with_filter(ir->rc, &rawir);
-
-			if (++i == len)
-				i = HEADERLEN;
-		} while (i != start);
-
-		/* add a trailing space */
-		rawir.duration = ir->rc->timeout;
-		rawir.pulse = false;
-		ir_raw_event_store_with_filter(ir->rc, &rawir);
-
-		ir_raw_event_handle(ir->rc);
-	}
-
-	igorplugusb_cmd(ir, SET_INFRABUFFER_EMPTY);
-}
-
-static void igorplugusb_callback(struct urb *urb)
-{
-	struct usb_ctrlrequest *req;
-	struct igorplugusb *ir = urb->context;
-
-	req = (struct usb_ctrlrequest *)urb->setup_packet;
-
-	switch (urb->status) {
-	case 0:
-		if (req->bRequest == GET_INFRACODE &&
-					urb->actual_length > HEADERLEN)
-			igorplugusb_irdata(ir, urb->actual_length);
-		else /* request IR */
-			mod_timer(&ir->timer, jiffies + msecs_to_jiffies(50));
-		break;
-	case -EPROTO:
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		usb_unlink_urb(urb);
-		return;
-	default:
-		dev_warn(ir->dev, "Error: urb status = %d\n", urb->status);
-		igorplugusb_cmd(ir, SET_INFRABUFFER_EMPTY);
-		break;
-	}
-}
-
-static void igorplugusb_cmd(struct igorplugusb *ir, int cmd)
-{
-	int ret;
-
-	ir->request.bRequest = cmd;
-	ir->urb->transfer_flags = 0;
-	ret = usb_submit_urb(ir->urb, GFP_ATOMIC);
-	if (ret)
-		dev_err(ir->dev, "submit urb failed: %d", ret);
-}
-
-static void igorplugusb_timer(unsigned long data)
-{
-	struct igorplugusb *ir = (struct igorplugusb *)data;
-
-	igorplugusb_cmd(ir, GET_INFRACODE);
-}
-
-static int igorplugusb_probe(struct usb_interface *intf,
-					const struct usb_device_id *id)
-{
-	struct usb_device *udev;
-	struct usb_host_interface *idesc;
-	struct usb_endpoint_descriptor *ep;
-	struct igorplugusb *ir;
-	struct rc_dev *rc;
-	int ret;
-
-	udev = interface_to_usbdev(intf);
-	idesc = intf->cur_altsetting;
-
-	if (idesc->desc.bNumEndpoints != 1) {
-		dev_err(&intf->dev, "incorrect number of endpoints");
-		return -ENODEV;
-	}
-
-	ep = &idesc->endpoint[0].desc;
-	if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_control(ep)) {
-		dev_err(&intf->dev, "endpoint incorrect");
-		return -ENODEV;
-	}
-
-	ir = devm_kzalloc(&intf->dev, sizeof(*ir), GFP_KERNEL);
-	if (!ir)
-		return -ENOMEM;
-
-	ir->dev = &intf->dev;
-
-	setup_timer(&ir->timer, igorplugusb_timer, (unsigned long)ir);
-
-	ir->request.bRequest = GET_INFRACODE;
-	ir->request.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN;
-	ir->request.wLength = cpu_to_le16(sizeof(ir->buf_in));
-
-	ir->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ir->urb)
-		return -ENOMEM;
-
-	usb_fill_control_urb(ir->urb, udev,
-		usb_rcvctrlpipe(udev, 0), (uint8_t *)&ir->request,
-		ir->buf_in, sizeof(ir->buf_in), igorplugusb_callback, ir);
-
-	usb_make_path(udev, ir->phys, sizeof(ir->phys));
-
-	rc = rc_allocate_device();
-	rc->input_name = DRIVER_DESC;
-	rc->input_phys = ir->phys;
-	usb_to_input_id(udev, &rc->input_id);
-	rc->dev.parent = &intf->dev;
-	rc->driver_type = RC_DRIVER_IR_RAW;
-	/*
-	 * This device can only store 36 pulses + spaces, which is not enough
-	 * for the NEC protocol and many others.
-	 */
-	rc->allowed_protocols = RC_BIT_ALL & ~(RC_BIT_NEC | RC_BIT_RC6_6A_20 |
-			RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE |
-			RC_BIT_SONY20 | RC_BIT_MCE_KBD | RC_BIT_SANYO);
-
-	rc->priv = ir;
-	rc->driver_name = DRIVER_NAME;
-	rc->map_name = RC_MAP_HAUPPAUGE;
-	rc->timeout = MS_TO_NS(100);
-	rc->rx_resolution = 85333;
-
-	ir->rc = rc;
-	ret = rc_register_device(rc);
-	if (ret) {
-		dev_err(&intf->dev, "failed to register rc device: %d", ret);
-		rc_free_device(rc);
-		usb_free_urb(ir->urb);
-		return ret;
-	}
-
-	usb_set_intfdata(intf, ir);
-
-	igorplugusb_cmd(ir, SET_INFRABUFFER_EMPTY);
-
-	return 0;
-}
-
-static void igorplugusb_disconnect(struct usb_interface *intf)
-{
-	struct igorplugusb *ir = usb_get_intfdata(intf);
-
-	rc_unregister_device(ir->rc);
-	del_timer_sync(&ir->timer);
-	usb_set_intfdata(intf, NULL);
-	usb_kill_urb(ir->urb);
-	usb_free_urb(ir->urb);
-}
-
-static struct usb_device_id igorplugusb_table[] = {
-	/* Igor Plug USB (Atmel's Manufact. ID) */
-	{ USB_DEVICE(0x03eb, 0x0002) },
-	/* Fit PC2 Infrared Adapter */
-	{ USB_DEVICE(0x03eb, 0x21fe) },
-	/* Terminating entry */
-	{ }
-};
-
-static struct usb_driver igorplugusb_driver = {
-	.name =	DRIVER_NAME,
-	.probe = igorplugusb_probe,
-	.disconnect = igorplugusb_disconnect,
-	.id_table = igorplugusb_table
-};
-
-module_usb_driver(igorplugusb_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Sean Young <sean@mess.org>");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, igorplugusb_table);
diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig
index 74ba6bb..2e5bf62 100644
--- a/drivers/media/rc/img-ir/Kconfig
+++ b/drivers/media/rc/img-ir/Kconfig
@@ -1,9 +1,8 @@
 config IR_IMG
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_5
 	tristate "ImgTec IR Decoder"
 	depends on m
 	depends on RC_CORE
-	depends on METAG || MIPS || COMPILE_TEST
 	select IR_IMG_HW if !IR_IMG_RAW
 	help
 	   Say Y or M here if you want to use the ImgTec infrared decoder
diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c
index 77c78de..a0cac2f 100644
--- a/drivers/media/rc/img-ir/img-ir-core.c
+++ b/drivers/media/rc/img-ir/img-ir-core.c
@@ -166,6 +166,7 @@
 static struct platform_driver img_ir_driver = {
 	.driver = {
 		.name = "img-ir",
+		.owner	= THIS_MODULE,
 		.of_match_table	= img_ir_match,
 		.pm = &img_ir_pmops,
 	},
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
index 44e3c51..2ccc3bd 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -530,22 +530,6 @@
 	u32 ir_status, irq_en;
 	spin_lock_irq(&priv->lock);
 
-	/*
-	 * First record that the protocol is being stopped so that the end timer
-	 * isn't restarted while we're trying to stop it.
-	 */
-	hw->stopping = true;
-
-	/*
-	 * Release the lock to stop the end timer, since the end timer handler
-	 * acquires the lock and we don't want to deadlock waiting for it.
-	 */
-	spin_unlock_irq(&priv->lock);
-	del_timer_sync(&hw->end_timer);
-	spin_lock_irq(&priv->lock);
-
-	hw->stopping = false;
-
 	/* switch off and disable interrupts */
 	img_ir_write(priv, IMG_IR_CONTROL, 0);
 	irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
@@ -557,13 +541,12 @@
 	if (ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2)) {
 		ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2);
 		img_ir_write(priv, IMG_IR_STATUS, ir_status);
+		img_ir_read(priv, IMG_IR_DATA_LW);
+		img_ir_read(priv, IMG_IR_DATA_UP);
 	}
 
-	/* always read data to clear buffer if IR wakes the device */
-	img_ir_read(priv, IMG_IR_DATA_LW);
-	img_ir_read(priv, IMG_IR_DATA_UP);
-
-	/* switch back to normal mode */
+	/* stop the end timer and switch back to normal mode */
+	del_timer_sync(&hw->end_timer);
 	hw->mode = IMG_IR_M_NORMAL;
 
 	/* clear the wakeup scancode filter */
@@ -834,8 +817,7 @@
 	}
 
 
-	/* we mustn't update the end timer while trying to stop it */
-	if (dec->repeat && !hw->stopping) {
+	if (dec->repeat) {
 		unsigned long interval;
 
 		img_ir_begin_repeat(priv);
diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
index 463bddf..9119bd1 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.h
+++ b/drivers/media/rc/img-ir/img-ir-hw.h
@@ -186,6 +186,9 @@
 	struct img_ir_timing_regvals	rtimings;
 };
 
+int img_ir_register_decoder(struct img_ir_decoder *dec);
+void img_ir_unregister_decoder(struct img_ir_decoder *dec);
+
 struct img_ir_priv;
 
 #ifdef CPTCFG_IR_IMG_HW
@@ -211,8 +214,6 @@
  * @flags:		IMG_IR_F_*.
  * @filters:		HW filters (derived from scancode filters).
  * @mode:		Current decode mode.
- * @stopping:		Indicates that decoder is being taken down and timers
- *			should not be restarted.
  * @suspend_irqen:	Saved IRQ enable mask over suspend.
  */
 struct img_ir_priv_hw {
@@ -228,7 +229,6 @@
 	struct img_ir_filter		filters[RC_FILTER_MAX];
 
 	enum img_ir_mode		mode;
-	bool				stopping;
 	u32				suspend_irqen;
 };
 
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 65f80b8..b8837dd 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -1678,8 +1678,7 @@
 		if (press_type == 0)
 			rc_keyup(ictx->rdev);
 		else {
-			if (ictx->rc_type == RC_BIT_RC6_MCE ||
-			    ictx->rc_type == RC_BIT_OTHER)
+			if (ictx->rc_type == RC_BIT_RC6_MCE)
 				rc_keydown(ictx->rdev,
 					   ictx->rc_type == RC_BIT_RC6_MCE ? RC_TYPE_RC6_MCE : RC_TYPE_OTHER,
 					   ictx->rc_scancode, ictx->rc_toggle);
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index 3a3192c..b6bcf2b 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -298,7 +298,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static int hix5hd2_ir_suspend(struct device *dev)
 {
 	struct hix5hd2_ir_priv *priv = dev_get_drvdata(dev);
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 98893a8..ed2c8a1 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -42,17 +42,11 @@
 		return -EINVAL;
 
 	/* Packet start */
-	if (ev.reset) {
-		/* Userspace expects a long space event before the start of
-		 * the signal to use as a sync.  This may be done with repeat
-		 * packets and normal samples.  But if a reset has been sent
-		 * then we assume that a long time has passed, so we send a
-		 * space with the maximum time value. */
-		sample = LIRC_SPACE(LIRC_VALUE_MASK);
-		IR_dprintk(2, "delivering reset sync space to lirc_dev\n");
+	if (ev.reset)
+		return 0;
 
 	/* Carrier reports */
-	} else if (ev.carrier_report) {
+	if (ev.carrier_report) {
 		sample = LIRC_FREQUENCY(ev.carrier);
 		IR_dprintk(2, "carrier report (freq: %d)\n", sample);
 
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 84fa6e9..2ef7639 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -53,7 +53,7 @@
 	u32 scancode;
 	enum rc_type protocol;
 
-	if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ)))
+	if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index d16bc67..f1f098e 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -259,8 +259,8 @@
 			case 32:
 				if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
 					protocol = RC_TYPE_RC6_MCE;
-					toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
 					scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
+					toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
 				} else {
 					protocol = RC_BIT_RC6_6A_32;
 					toggle = 0;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 1e0545a..249d2fb 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -518,7 +518,8 @@
 
 	WARN_ON(mutex_lock_killable(&lirc_dev_lock));
 
-	rc_close(ir->d.rdev);
+	if (ir->d.rdev)
+		rc_close(ir->d.rdev);
 
 	ir->open--;
 	if (ir->attached) {
diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
deleted file mode 100644
index fcc3b82..0000000
--- a/drivers/media/rc/meson-ir.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Driver for Amlogic Meson IR remote receiver
- *
- * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.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.
- *
- * 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/device.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-
-#include <media/rc-core.h>
-
-#define DRIVER_NAME		"meson-ir"
-
-#define IR_DEC_LDR_ACTIVE	0x00
-#define IR_DEC_LDR_IDLE		0x04
-#define IR_DEC_LDR_REPEAT	0x08
-#define IR_DEC_BIT_0		0x0c
-#define IR_DEC_REG0		0x10
-#define IR_DEC_FRAME		0x14
-#define IR_DEC_STATUS		0x18
-#define IR_DEC_REG1		0x1c
-
-#define REG0_RATE_MASK		(BIT(11) - 1)
-
-#define REG1_MODE_MASK		(BIT(7) | BIT(8))
-#define REG1_MODE_NEC		(0 << 7)
-#define REG1_MODE_GENERAL	(2 << 7)
-
-#define REG1_TIME_IV_SHIFT	16
-#define REG1_TIME_IV_MASK	((BIT(13) - 1) << REG1_TIME_IV_SHIFT)
-
-#define REG1_IRQSEL_MASK	(BIT(2) | BIT(3))
-#define REG1_IRQSEL_NEC_MODE	(0 << 2)
-#define REG1_IRQSEL_RISE_FALL	(1 << 2)
-#define REG1_IRQSEL_FALL	(2 << 2)
-#define REG1_IRQSEL_RISE	(3 << 2)
-
-#define REG1_RESET		BIT(0)
-#define REG1_ENABLE		BIT(15)
-
-#define STATUS_IR_DEC_IN	BIT(8)
-
-#define MESON_TRATE		10	/* us */
-
-struct meson_ir {
-	void __iomem	*reg;
-	struct rc_dev	*rc;
-	int		irq;
-	spinlock_t	lock;
-};
-
-static void meson_ir_set_mask(struct meson_ir *ir, unsigned int reg,
-			      u32 mask, u32 value)
-{
-	u32 data;
-
-	data = readl(ir->reg + reg);
-	data &= ~mask;
-	data |= (value & mask);
-	writel(data, ir->reg + reg);
-}
-
-static irqreturn_t meson_ir_irq(int irqno, void *dev_id)
-{
-	struct meson_ir *ir = dev_id;
-	u32 duration;
-	DEFINE_IR_RAW_EVENT(rawir);
-
-	spin_lock(&ir->lock);
-
-	duration = readl(ir->reg + IR_DEC_REG1);
-	duration = (duration & REG1_TIME_IV_MASK) >> REG1_TIME_IV_SHIFT;
-	rawir.duration = US_TO_NS(duration * MESON_TRATE);
-
-	rawir.pulse = !!(readl(ir->reg + IR_DEC_STATUS) & STATUS_IR_DEC_IN);
-
-	ir_raw_event_store_with_filter(ir->rc, &rawir);
-	ir_raw_event_handle(ir->rc);
-
-	spin_unlock(&ir->lock);
-
-	return IRQ_HANDLED;
-}
-
-static int meson_ir_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct device_node *node = dev->of_node;
-	struct resource *res;
-	const char *map_name;
-	struct meson_ir *ir;
-	int ret;
-
-	ir = devm_kzalloc(dev, sizeof(struct meson_ir), GFP_KERNEL);
-	if (!ir)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	ir->reg = devm_ioremap_resource(dev, res);
-	if (IS_ERR(ir->reg)) {
-		dev_err(dev, "failed to map registers\n");
-		return PTR_ERR(ir->reg);
-	}
-
-	ir->irq = platform_get_irq(pdev, 0);
-	if (ir->irq < 0) {
-		dev_err(dev, "no irq resource\n");
-		return ir->irq;
-	}
-
-	ir->rc = rc_allocate_device();
-	if (!ir->rc) {
-		dev_err(dev, "failed to allocate rc device\n");
-		return -ENOMEM;
-	}
-
-	ir->rc->priv = ir;
-	ir->rc->input_name = DRIVER_NAME;
-	ir->rc->input_phys = DRIVER_NAME "/input0";
-	ir->rc->input_id.bustype = BUS_HOST;
-	map_name = of_get_property(node, "linux,rc-map-name", NULL);
-	ir->rc->map_name = map_name ? map_name : RC_MAP_EMPTY;
-	ir->rc->dev.parent = dev;
-	ir->rc->driver_type = RC_DRIVER_IR_RAW;
-	ir->rc->allowed_protocols = RC_BIT_ALL;
-	ir->rc->rx_resolution = US_TO_NS(MESON_TRATE);
-	ir->rc->timeout = MS_TO_NS(200);
-	ir->rc->driver_name = DRIVER_NAME;
-
-	spin_lock_init(&ir->lock);
-	platform_set_drvdata(pdev, ir);
-
-	ret = rc_register_device(ir->rc);
-	if (ret) {
-		dev_err(dev, "failed to register rc device\n");
-		goto out_free;
-	}
-
-	ret = devm_request_irq(dev, ir->irq, meson_ir_irq, 0, "ir-meson", ir);
-	if (ret) {
-		dev_err(dev, "failed to request irq\n");
-		goto out_unreg;
-	}
-
-	/* Reset the decoder */
-	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, REG1_RESET);
-	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, 0);
-	/* Set general operation mode */
-	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK, REG1_MODE_GENERAL);
-	/* Set rate */
-	meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, MESON_TRATE - 1);
-	/* IRQ on rising and falling edges */
-	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_IRQSEL_MASK,
-			  REG1_IRQSEL_RISE_FALL);
-	/* Enable the decoder */
-	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, REG1_ENABLE);
-
-	dev_info(dev, "receiver initialized\n");
-
-	return 0;
-out_unreg:
-	rc_unregister_device(ir->rc);
-	ir->rc = NULL;
-out_free:
-	rc_free_device(ir->rc);
-
-	return ret;
-}
-
-static int meson_ir_remove(struct platform_device *pdev)
-{
-	struct meson_ir *ir = platform_get_drvdata(pdev);
-	unsigned long flags;
-
-	/* Disable the decoder */
-	spin_lock_irqsave(&ir->lock, flags);
-	meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0);
-	spin_unlock_irqrestore(&ir->lock, flags);
-
-	rc_unregister_device(ir->rc);
-
-	return 0;
-}
-
-static const struct of_device_id meson_ir_match[] = {
-	{ .compatible = "amlogic,meson6-ir" },
-	{ },
-};
-
-static struct platform_driver meson_ir_driver = {
-	.probe		= meson_ir_probe,
-	.remove		= meson_ir_remove,
-	.driver = {
-		.name		= DRIVER_NAME,
-		.of_match_table	= meson_ir_match,
-	},
-};
-
-module_platform_driver(meson_ir_driver);
-
-MODULE_DESCRIPTION("Amlogic Meson IR remote receiver driver");
-MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index b732ac6..e8fff2a 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -262,6 +262,7 @@
 		return -ENOMEM;
 
 	dev->raw->dev = dev;
+	dev->enabled_protocols = ~0;
 	dev->change_protocol = change_protocol;
 	rc = kfifo_alloc(&dev->raw->kfifo,
 			 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 46ee99c..b59eee2 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1302,7 +1302,8 @@
 	if (!dev)
 		return;
 
-	input_free_device(dev->input_dev);
+	if (dev->input_dev)
+		input_free_device(dev->input_dev);
 
 	put_device(&dev->dev);
 
@@ -1417,18 +1418,13 @@
 			ir_raw_init();
 			raw_init = true;
 		}
-		/* calls ir_register_device so unlock mutex here*/
-		mutex_unlock(&dev->lock);
 		rc = ir_raw_event_register(dev);
-		mutex_lock(&dev->lock);
 		if (rc < 0)
 			goto out_input;
 	}
 
 	if (dev->change_protocol) {
-		u64 rc_type = (1ll << rc_map->rc_type);
-		if (dev->driver_type == RC_DRIVER_IR_RAW)
-			rc_type |= RC_BIT_LIRC;
+		u64 rc_type = (1 << rc_map->rc_type);
 		rc = dev->change_protocol(dev, &rc_type);
 		if (rc < 0)
 			goto out_raw;
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index c4def66..795b394 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -966,7 +966,7 @@
 
 	rr3->ep_in = ep_in;
 	rr3->bulk_in_buf = usb_alloc_coherent(udev,
-		le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in);
+		le16_to_cpu(ep_in->wMaxPacketSize), GFP_ATOMIC, &rr3->dma_in);
 	if (!rr3->bulk_in_buf) {
 		dev_err(dev, "Read buffer allocation failure\n");
 		goto error;
@@ -975,8 +975,6 @@
 	pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
 	usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
 		le16_to_cpu(ep_in->wMaxPacketSize), redrat3_handle_async, rr3);
-	rr3->read_urb->transfer_dma = rr3->dma_in;
-	rr3->read_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	rr3->ep_out = ep_out;
 	rr3->udev = udev;
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
index 340f7f5..bcee8e1 100644
--- a/drivers/media/rc/sunxi-cir.c
+++ b/drivers/media/rc/sunxi-cir.c
@@ -306,6 +306,7 @@
 	.remove         = sunxi_ir_remove,
 	.driver = {
 		.name = SUNXI_IR_DEV,
+		.owner = THIS_MODULE,
 		.of_match_table = sunxi_ir_match,
 	},
 };
diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index 86602cc..02f497c 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -228,7 +228,7 @@
 	  Fitipower FC0013 silicon tuner driver.
 
 config MEDIA_TUNER_TDA18212
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "NXP TDA18212 silicon tuner"
 	depends on m
 	depends on MEDIA_SUPPORT && I2C
@@ -238,8 +238,8 @@
 	  NXP TDA18212 silicon tuner driver.
 
 config MEDIA_TUNER_E4000
-	depends on !KERNEL_3_4
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Elonics E4000 silicon tuner"
 	depends on m
 	depends on MEDIA_SUPPORT && I2C
@@ -257,7 +257,7 @@
 	  FCI FC2580 silicon tuner driver.
 
 config MEDIA_TUNER_M88TS2022
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Montage M88TS2022 silicon tuner"
 	depends on m
 	depends on MEDIA_SUPPORT && I2C
@@ -266,16 +266,6 @@
 	help
 	  Montage M88TS2022 silicon tuner driver.
 
-config MEDIA_TUNER_M88RS6000T
-	depends on !KERNEL_3_3
-	tristate "Montage M88RS6000 internal tuner"
-	depends on m
-	depends on MEDIA_SUPPORT && I2C
-	depends on REGMAP_I2C
-	default m if !MEDIA_SUBDRV_AUTOSELECT
-	help
-	  Montage M88RS6000 internal tuner.
-
 config MEDIA_TUNER_TUA9001
 	tristate "Infineon TUA 9001 silicon tuner"
 	depends on m
@@ -293,7 +283,7 @@
 	  Silicon Labs Si2157 silicon tuner driver.
 
 config MEDIA_TUNER_IT913X
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "ITE Tech IT913x silicon tuner"
 	depends on m
 	depends on MEDIA_SUPPORT && I2C
diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile
index bc7b685..c3e58a6 100644
--- a/drivers/media/tuners/Makefile
+++ b/drivers/media/tuners/Makefile
@@ -41,7 +41,6 @@
 obj-$(CPTCFG_MEDIA_TUNER_R820T) += r820t.o
 obj-$(CPTCFG_MEDIA_TUNER_MXL301RF) += mxl301rf.o
 obj-$(CPTCFG_MEDIA_TUNER_QM1D1C0042) += qm1d1c0042.o
-obj-$(CPTCFG_MEDIA_TUNER_M88RS6000T) += m88rs6000t.o
 
 ccflags-y += -I$(backport_srctree)/drivers/media/dvb-core
 ccflags-y += -I$(backport_srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/tuners/m88rs6000t.c b/drivers/media/tuners/m88rs6000t.c
deleted file mode 100644
index d4c13fe..0000000
--- a/drivers/media/tuners/m88rs6000t.c
+++ /dev/null
@@ -1,744 +0,0 @@
-/*
- * Driver for the internal tuner of Montage M88RS6000
- *
- * Copyright (C) 2014 Max nibble <nibble.max@gmail.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 "m88rs6000t.h"
-#include <linux/regmap.h>
-
-struct m88rs6000t_dev {
-	struct m88rs6000t_config cfg;
-	struct i2c_client *client;
-	struct regmap *regmap;
-	u32 frequency_khz;
-};
-
-struct m88rs6000t_reg_val {
-	u8 reg;
-	u8 val;
-};
-
-/* set demod main mclk and ts mclk */
-static int m88rs6000t_set_demod_mclk(struct dvb_frontend *fe)
-{
-	struct m88rs6000t_dev *dev = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u8 reg11, reg15, reg16, reg1D, reg1E, reg1F;
-	u8 N, f0 = 0, f1 = 0, f2 = 0, f3 = 0;
-	u16 pll_div_fb;
-	u32 div, ts_mclk;
-	unsigned int utmp;
-	int ret;
-
-	/* select demod main mclk */
-	ret = regmap_read(dev->regmap, 0x15, &utmp);
-	if (ret)
-		goto err;
-	reg15 = utmp;
-	if (c->symbol_rate > 45010000) {
-		reg11 = 0x0E;
-		reg15 |= 0x02;
-		reg16 = 115; /* mclk = 110.25MHz */
-	} else {
-		reg11 = 0x0A;
-		reg15 &= ~0x02;
-		reg16 = 96; /* mclk = 96MHz */
-	}
-
-	/* set ts mclk */
-	if (c->delivery_system == SYS_DVBS)
-		ts_mclk = 96000;
-	else
-		ts_mclk = 144000;
-
-	pll_div_fb = (reg15 & 0x01) << 8;
-	pll_div_fb += reg16;
-	pll_div_fb += 32;
-
-	div = 36000 * pll_div_fb;
-	div /= ts_mclk;
-
-	if (div <= 32) {
-		N = 2;
-		f0 = 0;
-		f1 = div / 2;
-		f2 = div - f1;
-		f3 = 0;
-	} else if (div <= 48) {
-		N = 3;
-		f0 = div / 3;
-		f1 = (div - f0) / 2;
-		f2 = div - f0 - f1;
-		f3 = 0;
-	} else if (div <= 64) {
-		N = 4;
-		f0 = div / 4;
-		f1 = (div - f0) / 3;
-		f2 = (div - f0 - f1) / 2;
-		f3 = div - f0 - f1 - f2;
-	} else {
-		N = 4;
-		f0 = 16;
-		f1 = 16;
-		f2 = 16;
-		f3 = 16;
-	}
-
-	if (f0 == 16)
-		f0 = 0;
-	if (f1 == 16)
-		f1 = 0;
-	if (f2 == 16)
-		f2 = 0;
-	if (f3 == 16)
-		f3 = 0;
-
-	ret = regmap_read(dev->regmap, 0x1D, &utmp);
-	if (ret)
-		goto err;
-	reg1D = utmp;
-	reg1D &= ~0x03;
-	reg1D |= N - 1;
-	reg1E = ((f3 << 4) + f2) & 0xFF;
-	reg1F = ((f1 << 4) + f0) & 0xFF;
-
-	/* program and recalibrate demod PLL */
-	ret = regmap_write(dev->regmap, 0x05, 0x40);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x11, 0x08);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x15, reg15);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x16, reg16);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x1D, reg1D);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x1E, reg1E);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x1F, reg1F);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x17, 0xc1);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x17, 0x81);
-	if (ret)
-		goto err;
-	usleep_range(5000, 50000);
-	ret = regmap_write(dev->regmap, 0x05, 0x00);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x11, reg11);
-	if (ret)
-		goto err;
-	usleep_range(5000, 50000);
-err:
-	if (ret)
-		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-	return ret;
-}
-
-static int m88rs6000t_set_pll_freq(struct m88rs6000t_dev *dev,
-			u32 tuner_freq_MHz)
-{
-	u32 fcry_KHz, ulNDiv1, ulNDiv2, ulNDiv;
-	u8 refDiv, ucLoDiv1, ucLomod1, ucLoDiv2, ucLomod2, ucLoDiv, ucLomod;
-	u8 reg27, reg29, reg42, reg42buf;
-	unsigned int utmp;
-	int ret;
-
-	fcry_KHz = 27000; /* in kHz */
-	refDiv = 27;
-
-	ret = regmap_write(dev->regmap, 0x36, (refDiv - 8));
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x31, 0x00);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x2c, 0x02);
-	if (ret)
-		goto err;
-
-	if (tuner_freq_MHz >= 1550) {
-		ucLoDiv1 = 2;
-		ucLomod1 = 0;
-		ucLoDiv2 = 2;
-		ucLomod2 = 0;
-	} else if (tuner_freq_MHz >= 1380) {
-		ucLoDiv1 = 3;
-		ucLomod1 = 16;
-		ucLoDiv2 = 2;
-		ucLomod2 = 0;
-	} else if (tuner_freq_MHz >= 1070) {
-		ucLoDiv1 = 3;
-		ucLomod1 = 16;
-		ucLoDiv2 = 3;
-		ucLomod2 = 16;
-	} else if (tuner_freq_MHz >= 1000) {
-		ucLoDiv1 = 3;
-		ucLomod1 = 16;
-		ucLoDiv2 = 4;
-		ucLomod2 = 64;
-	} else if (tuner_freq_MHz >= 775) {
-		ucLoDiv1 = 4;
-		ucLomod1 = 64;
-		ucLoDiv2 = 4;
-		ucLomod2 = 64;
-	} else if (tuner_freq_MHz >= 700) {
-		ucLoDiv1 = 6;
-		ucLomod1 = 48;
-		ucLoDiv2 = 4;
-		ucLomod2 = 64;
-	} else if (tuner_freq_MHz >= 520) {
-		ucLoDiv1 = 6;
-		ucLomod1 = 48;
-		ucLoDiv2 = 6;
-		ucLomod2 = 48;
-	} else {
-		ucLoDiv1 = 8;
-		ucLomod1 = 96;
-		ucLoDiv2 = 8;
-		ucLomod2 = 96;
-	}
-
-	ulNDiv1 = ((tuner_freq_MHz * ucLoDiv1 * 1000) * refDiv
-			/ fcry_KHz - 1024) / 2;
-	ulNDiv2 = ((tuner_freq_MHz * ucLoDiv2 * 1000) * refDiv
-			/ fcry_KHz - 1024) / 2;
-
-	reg27 = (((ulNDiv1 >> 8) & 0x0F) + ucLomod1) & 0x7F;
-	ret = regmap_write(dev->regmap, 0x27, reg27);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x28, (u8)(ulNDiv1 & 0xFF));
-	if (ret)
-		goto err;
-	reg29 = (((ulNDiv2 >> 8) & 0x0F) + ucLomod2) & 0x7f;
-	ret = regmap_write(dev->regmap, 0x29, reg29);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x2a, (u8)(ulNDiv2 & 0xFF));
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x2F, 0xf5);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x30, 0x05);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x08, 0x1f);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x08, 0x3f);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x09, 0x20);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x09, 0x00);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x3e, 0x11);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x08, 0x2f);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x08, 0x3f);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x09, 0x10);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x09, 0x00);
-	if (ret)
-		goto err;
-	usleep_range(2000, 50000);
-
-	ret = regmap_read(dev->regmap, 0x42, &utmp);
-	if (ret)
-		goto err;
-	reg42 = utmp;
-
-	ret = regmap_write(dev->regmap, 0x3e, 0x10);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x08, 0x2f);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x08, 0x3f);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x09, 0x10);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x09, 0x00);
-	if (ret)
-		goto err;
-	usleep_range(2000, 50000);
-
-	ret = regmap_read(dev->regmap, 0x42, &utmp);
-	if (ret)
-		goto err;
-	reg42buf = utmp;
-	if (reg42buf < reg42) {
-		ret = regmap_write(dev->regmap, 0x3e, 0x11);
-		if (ret)
-			goto err;
-	}
-	usleep_range(5000, 50000);
-
-	ret = regmap_read(dev->regmap, 0x2d, &utmp);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x2d, utmp);
-	if (ret)
-		goto err;
-	ret = regmap_read(dev->regmap, 0x2e, &utmp);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x2e, utmp);
-	if (ret)
-		goto err;
-
-	ret = regmap_read(dev->regmap, 0x27, &utmp);
-	if (ret)
-		goto err;
-	reg27 = utmp & 0x70;
-	ret = regmap_read(dev->regmap, 0x83, &utmp);
-	if (ret)
-		goto err;
-	if (reg27 == (utmp & 0x70)) {
-		ucLoDiv	= ucLoDiv1;
-		ulNDiv = ulNDiv1;
-		ucLomod = ucLomod1 / 16;
-	} else {
-		ucLoDiv	= ucLoDiv2;
-		ulNDiv = ulNDiv2;
-		ucLomod = ucLomod2 / 16;
-	}
-
-	if ((ucLoDiv == 3) || (ucLoDiv == 6)) {
-		refDiv = 18;
-		ret = regmap_write(dev->regmap, 0x36, (refDiv - 8));
-		if (ret)
-			goto err;
-		ulNDiv = ((tuner_freq_MHz * ucLoDiv * 1000) * refDiv
-				/ fcry_KHz - 1024) / 2;
-	}
-
-	reg27 = (0x80 + ((ucLomod << 4) & 0x70)
-			+ ((ulNDiv >> 8) & 0x0F)) & 0xFF;
-	ret = regmap_write(dev->regmap, 0x27, reg27);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x28, (u8)(ulNDiv & 0xFF));
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x29, 0x80);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x31, 0x03);
-	if (ret)
-		goto err;
-
-	if (ucLoDiv == 3)
-		utmp = 0xCE;
-	else
-		utmp = 0x8A;
-	ret = regmap_write(dev->regmap, 0x3b, utmp);
-	if (ret)
-		goto err;
-
-	dev->frequency_khz = fcry_KHz * (ulNDiv * 2 + 1024) / refDiv / ucLoDiv;
-
-	dev_dbg(&dev->client->dev,
-		"actual tune frequency=%d\n", dev->frequency_khz);
-err:
-	if (ret)
-		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-	return ret;
-}
-
-static int m88rs6000t_set_bb(struct m88rs6000t_dev *dev,
-		u32 symbol_rate_KSs, s32 lpf_offset_KHz)
-{
-	u32 f3dB;
-	u8  reg40;
-
-	f3dB = symbol_rate_KSs * 9 / 14 + 2000;
-	f3dB += lpf_offset_KHz;
-	f3dB = clamp_val(f3dB, 6000U, 43000U);
-	reg40 = f3dB / 1000;
-	return regmap_write(dev->regmap, 0x40, reg40);
-}
-
-static int m88rs6000t_set_params(struct dvb_frontend *fe)
-{
-	struct m88rs6000t_dev *dev = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-	s32 lpf_offset_KHz;
-	u32 realFreq, freq_MHz;
-
-	dev_dbg(&dev->client->dev,
-			"frequency=%d symbol_rate=%d\n",
-			c->frequency, c->symbol_rate);
-
-	if (c->symbol_rate < 5000000)
-		lpf_offset_KHz = 3000;
-	else
-		lpf_offset_KHz = 0;
-
-	realFreq = c->frequency + lpf_offset_KHz;
-	/* set tuner pll.*/
-	freq_MHz = (realFreq + 500) / 1000;
-	ret = m88rs6000t_set_pll_freq(dev, freq_MHz);
-	if (ret)
-		goto err;
-	ret = m88rs6000t_set_bb(dev, c->symbol_rate / 1000, lpf_offset_KHz);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x00, 0x01);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x00, 0x00);
-	if (ret)
-		goto err;
-	/* set demod mlck */
-	ret = m88rs6000t_set_demod_mclk(fe);
-err:
-	if (ret)
-		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-	return ret;
-}
-
-static int m88rs6000t_init(struct dvb_frontend *fe)
-{
-	struct m88rs6000t_dev *dev = fe->tuner_priv;
-	int ret;
-
-	dev_dbg(&dev->client->dev, "%s:\n", __func__);
-
-	ret = regmap_update_bits(dev->regmap, 0x11, 0x08, 0x08);
-	if (ret)
-		goto err;
-	usleep_range(5000, 50000);
-	ret = regmap_update_bits(dev->regmap, 0x10, 0x01, 0x01);
-	if (ret)
-		goto err;
-	usleep_range(10000, 50000);
-	ret = regmap_write(dev->regmap, 0x07, 0x7d);
-err:
-	if (ret)
-		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-	return ret;
-}
-
-static int m88rs6000t_sleep(struct dvb_frontend *fe)
-{
-	struct m88rs6000t_dev *dev = fe->tuner_priv;
-	int ret;
-
-	dev_dbg(&dev->client->dev, "%s:\n", __func__);
-
-	ret = regmap_write(dev->regmap, 0x07, 0x6d);
-	if (ret)
-		goto err;
-	usleep_range(5000, 10000);
-err:
-	if (ret)
-		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-	return ret;
-}
-
-static int m88rs6000t_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct m88rs6000t_dev *dev = fe->tuner_priv;
-
-	dev_dbg(&dev->client->dev, "\n");
-
-	*frequency = dev->frequency_khz;
-	return 0;
-}
-
-static int m88rs6000t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct m88rs6000t_dev *dev = fe->tuner_priv;
-
-	dev_dbg(&dev->client->dev, "\n");
-
-	*frequency = 0; /* Zero-IF */
-	return 0;
-}
-
-
-static int m88rs6000t_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct m88rs6000t_dev *dev = fe->tuner_priv;
-	unsigned int val, i;
-	int ret;
-	u16 gain;
-	u32 PGA2_cri_GS = 46, PGA2_crf_GS = 290, TIA_GS = 290;
-	u32 RF_GC = 1200, IF_GC = 1100, BB_GC = 300;
-	u32 PGA2_GC = 300, TIA_GC = 300, PGA2_cri = 0, PGA2_crf = 0;
-	u32 RFG = 0, IFG = 0, BBG = 0, PGA2G = 0, TIAG = 0;
-	u32 RFGS[13] = {0, 245, 266, 268, 270, 285,
-			298, 295, 283, 285, 285, 300, 300};
-	u32 IFGS[12] = {0, 300, 230, 270, 270, 285,
-			295, 285, 290, 295, 295, 310};
-	u32 BBGS[14] = {0, 286, 275, 290, 294, 300, 290,
-			290, 285, 283, 260, 295, 290, 260};
-
-	ret = regmap_read(dev->regmap, 0x5A, &val);
-	if (ret)
-		goto err;
-	RF_GC = val & 0x0f;
-
-	ret = regmap_read(dev->regmap, 0x5F, &val);
-	if (ret)
-		goto err;
-	IF_GC = val & 0x0f;
-
-	ret = regmap_read(dev->regmap, 0x3F, &val);
-	if (ret)
-		goto err;
-	TIA_GC = (val >> 4) & 0x07;
-
-	ret = regmap_read(dev->regmap, 0x77, &val);
-	if (ret)
-		goto err;
-	BB_GC = (val >> 4) & 0x0f;
-
-	ret = regmap_read(dev->regmap, 0x76, &val);
-	if (ret)
-		goto err;
-	PGA2_GC = val & 0x3f;
-	PGA2_cri = PGA2_GC >> 2;
-	PGA2_crf = PGA2_GC & 0x03;
-
-	for (i = 0; i <= RF_GC; i++)
-		RFG += RFGS[i];
-
-	if (RF_GC == 0)
-		RFG += 400;
-	if (RF_GC == 1)
-		RFG += 300;
-	if (RF_GC == 2)
-		RFG += 200;
-	if (RF_GC == 3)
-		RFG += 100;
-
-	for (i = 0; i <= IF_GC; i++)
-		IFG += IFGS[i];
-
-	TIAG = TIA_GC * TIA_GS;
-
-	for (i = 0; i <= BB_GC; i++)
-		BBG += BBGS[i];
-
-	PGA2G = PGA2_cri * PGA2_cri_GS + PGA2_crf * PGA2_crf_GS;
-
-	gain = RFG + IFG - TIAG + BBG + PGA2G;
-
-	/* scale value to 0x0000-0xffff */
-	gain = clamp_val(gain, 1000U, 10500U);
-	*strength = (10500 - gain) * 0xffff / (10500 - 1000);
-err:
-	if (ret)
-		dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-	return ret;
-}
-
-static const struct dvb_tuner_ops m88rs6000t_tuner_ops = {
-	.info = {
-		.name          = "Montage M88RS6000 Internal Tuner",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-	},
-
-	.init = m88rs6000t_init,
-	.sleep = m88rs6000t_sleep,
-	.set_params = m88rs6000t_set_params,
-	.get_frequency = m88rs6000t_get_frequency,
-	.get_if_frequency = m88rs6000t_get_if_frequency,
-	.get_rf_strength = m88rs6000t_get_rf_strength,
-};
-
-static int m88rs6000t_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
-{
-	struct m88rs6000t_config *cfg = client->dev.platform_data;
-	struct dvb_frontend *fe = cfg->fe;
-	struct m88rs6000t_dev *dev;
-	int ret, i;
-	unsigned int utmp;
-	static const struct regmap_config regmap_config = {
-		.reg_bits = 8,
-		.val_bits = 8,
-	};
-	static const struct m88rs6000t_reg_val reg_vals[] = {
-		{0x10, 0xfb},
-		{0x24, 0x38},
-		{0x11, 0x0a},
-		{0x12, 0x00},
-		{0x2b, 0x1c},
-		{0x44, 0x48},
-		{0x54, 0x24},
-		{0x55, 0x06},
-		{0x59, 0x00},
-		{0x5b, 0x4c},
-		{0x60, 0x8b},
-		{0x61, 0xf4},
-		{0x65, 0x07},
-		{0x6d, 0x6f},
-		{0x6e, 0x31},
-		{0x3c, 0xf3},
-		{0x37, 0x0f},
-		{0x48, 0x28},
-		{0x49, 0xd8},
-		{0x70, 0x66},
-		{0x71, 0xCF},
-		{0x72, 0x81},
-		{0x73, 0xA7},
-		{0x74, 0x4F},
-		{0x75, 0xFC},
-	};
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev) {
-		ret = -ENOMEM;
-		dev_err(&client->dev, "kzalloc() failed\n");
-		goto err;
-	}
-
-	memcpy(&dev->cfg, cfg, sizeof(struct m88rs6000t_config));
-	dev->client = client;
-	dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
-	if (IS_ERR(dev->regmap)) {
-		ret = PTR_ERR(dev->regmap);
-		goto err;
-	}
-
-	ret = regmap_update_bits(dev->regmap, 0x11, 0x08, 0x08);
-	if (ret)
-		goto err;
-	usleep_range(5000, 50000);
-	ret = regmap_update_bits(dev->regmap, 0x10, 0x01, 0x01);
-	if (ret)
-		goto err;
-	usleep_range(10000, 50000);
-	ret = regmap_write(dev->regmap, 0x07, 0x7d);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x04, 0x01);
-	if (ret)
-		goto err;
-
-	/* check tuner chip id */
-	ret = regmap_read(dev->regmap, 0x01, &utmp);
-	if (ret)
-		goto err;
-	dev_info(&dev->client->dev, "chip_id=%02x\n", utmp);
-	if (utmp != 0x64) {
-		ret = -ENODEV;
-		goto err;
-	}
-
-	/* tuner init. */
-	ret = regmap_write(dev->regmap, 0x05, 0x40);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x11, 0x08);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x15, 0x6c);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x17, 0xc1);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x17, 0x81);
-	if (ret)
-		goto err;
-	usleep_range(10000, 50000);
-	ret = regmap_write(dev->regmap, 0x05, 0x00);
-	if (ret)
-		goto err;
-	ret = regmap_write(dev->regmap, 0x11, 0x0a);
-	if (ret)
-		goto err;
-
-	for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
-		ret = regmap_write(dev->regmap,
-				reg_vals[i].reg, reg_vals[i].val);
-		if (ret)
-			goto err;
-	}
-
-	dev_info(&dev->client->dev, "Montage M88RS6000 internal tuner successfully identified\n");
-
-	fe->tuner_priv = dev;
-	memcpy(&fe->ops.tuner_ops, &m88rs6000t_tuner_ops,
-			sizeof(struct dvb_tuner_ops));
-	i2c_set_clientdata(client, dev);
-	return 0;
-err:
-	dev_dbg(&client->dev, "failed=%d\n", ret);
-	kfree(dev);
-	return ret;
-}
-
-static int m88rs6000t_remove(struct i2c_client *client)
-{
-	struct m88rs6000t_dev *dev = i2c_get_clientdata(client);
-	struct dvb_frontend *fe = dev->cfg.fe;
-
-	dev_dbg(&client->dev, "\n");
-
-	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
-	fe->tuner_priv = NULL;
-	kfree(dev);
-
-	return 0;
-}
-
-static const struct i2c_device_id m88rs6000t_id[] = {
-	{"m88rs6000t", 0},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, m88rs6000t_id);
-
-static struct i2c_driver m88rs6000t_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "m88rs6000t",
-	},
-	.probe		= m88rs6000t_probe,
-	.remove		= m88rs6000t_remove,
-	.id_table	= m88rs6000t_id,
-};
-
-module_i2c_driver(m88rs6000t_driver);
-
-MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
-MODULE_DESCRIPTION("Montage M88RS6000 internal tuner driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/m88rs6000t.h b/drivers/media/tuners/m88rs6000t.h
deleted file mode 100644
index 264c13e..0000000
--- a/drivers/media/tuners/m88rs6000t.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Driver for the internal tuner of Montage M88RS6000
- *
- * Copyright (C) 2014 Max nibble <nibble.max@gmail.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 _M88RS6000T_H_
-#define _M88RS6000T_H_
-
-#include "dvb_frontend.h"
-
-struct m88rs6000t_config {
-	/*
-	 * pointer to DVB frontend
-	 */
-	struct dvb_frontend *fe;
-};
-
-#endif
diff --git a/drivers/media/tuners/m88ts2022.c b/drivers/media/tuners/m88ts2022.c
index 066e543..caa5423 100644
--- a/drivers/media/tuners/m88ts2022.c
+++ b/drivers/media/tuners/m88ts2022.c
@@ -488,7 +488,6 @@
 	case 0x83:
 		break;
 	default:
-		ret = -ENODEV;
 		goto err;
 	}
 
@@ -506,7 +505,6 @@
 		u8tmp = 0x6c;
 		break;
 	default:
-		ret = -EINVAL;
 		goto err;
 	}
 
diff --git a/drivers/media/tuners/mxl5007t.c b/drivers/media/tuners/mxl5007t.c
index 1810ad6..69e453e 100644
--- a/drivers/media/tuners/mxl5007t.c
+++ b/drivers/media/tuners/mxl5007t.c
@@ -374,6 +374,7 @@
 	mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);
 	mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);
 
+	set_reg_bits(state->tab_init, 0x04, 0x01, cfg->loop_thru_enable);
 	set_reg_bits(state->tab_init, 0x03, 0x08, cfg->clk_out_enable << 3);
 	set_reg_bits(state->tab_init, 0x03, 0x07, cfg->clk_out_amp);
 
@@ -530,6 +531,10 @@
 	struct reg_pair_t *init_regs;
 	int ret;
 
+	ret = mxl5007t_soft_reset(state);
+	if (mxl_fail(ret))
+		goto fail;
+
 	/* calculate initialization reg array */
 	init_regs = mxl5007t_calc_init_regs(state, mode);
 
@@ -895,32 +900,7 @@
 		/* existing tuner instance */
 		break;
 	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	ret = mxl5007t_soft_reset(state);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	if (mxl_fail(ret))
-		goto fail;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	ret = mxl5007t_write_reg(state, 0x04,
-		state->config->loop_thru_enable);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	if (mxl_fail(ret))
-		goto fail;
-
 	fe->tuner_priv = state;
-
 	mutex_unlock(&mxl5007t_list_mutex);
 
 	memcpy(&fe->ops.tuner_ops, &mxl5007t_tuner_ops,
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index 8e040cf..a759742 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -959,18 +959,6 @@
 		lt_att = 0x00;		/* r31[7], lt att enable */
 		flt_ext_widest = 0x00;	/* r15[7]: flt_ext_wide off */
 		polyfil_cur = 0x60;	/* r25[6:5]:min */
-	} else if (delsys == SYS_DVBC_ANNEX_A) {
-		if_khz = 5070;
-		filt_cal_lo = 73500;
-		filt_gain = 0x10;	/* +3db, 6mhz on */
-		img_r = 0x00;		/* image negative */
-		filt_q = 0x10;		/* r10[4]:low q(1'b1) */
-		hp_cor = 0x0b;		/* 1.7m disable, +0cap, 1.0mhz */
-		ext_enable = 0x40;	/* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
-		loop_through = 0x00;	/* r5[7], lt on */
-		lt_att = 0x00;		/* r31[7], lt att enable */
-		flt_ext_widest = 0x00;	/* r15[7]: flt_ext_wide off */
-		polyfil_cur = 0x60;	/* r25[6:5]:min */
 	} else {
 		if (bw <= 6) {
 			if_khz = 3570;
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 2180de9..cf97142 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -1,5 +1,5 @@
 /*
- * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
+ * Silicon Labs Si2147/2157/2158 silicon tuner driver
  *
  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
  *
@@ -93,13 +93,8 @@
 		goto warm;
 
 	/* power up */
-	if (s->chiptype == SI2157_CHIPTYPE_SI2146) {
-		memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
-		cmd.wlen = 9;
-	} else {
-		memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
-		cmd.wlen = 15;
-	}
+	memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
+	cmd.wlen = 15;
 	cmd.rlen = 1;
 	ret = si2157_cmd_execute(s, &cmd);
 	if (ret)
@@ -117,20 +112,17 @@
 			cmd.args[4] << 0;
 
 	#define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
-	#define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0)
 	#define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
 	#define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
-	#define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
 
 	switch (chip_id) {
 	case SI2158_A20:
-	case SI2148_A20:
 		fw_file = SI2158_A20_FIRMWARE;
 		break;
 	case SI2157_A30:
 	case SI2147_A30:
-	case SI2146_A10:
 		goto skip_fw_download;
+		break;
 	default:
 		dev_err(&s->client->dev,
 				"unknown chip version Si21%d-%c%c%c\n",
@@ -157,7 +149,7 @@
 		dev_err(&s->client->dev, "firmware file '%s' is invalid\n",
 				fw_file);
 		ret = -EINVAL;
-		goto fw_release_exit;
+		goto err;
 	}
 
 	dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
@@ -173,7 +165,7 @@
 			dev_err(&s->client->dev,
 					"firmware download failed=%d\n",
 					ret);
-			goto fw_release_exit;
+			goto err;
 		}
 	}
 
@@ -195,9 +187,10 @@
 	s->active = true;
 	return 0;
 
-fw_release_exit:
-	release_firmware(fw);
 err:
+	if (fw)
+		release_firmware(fw);
+
 	dev_dbg(&s->client->dev, "failed=%d\n", ret);
 	return ret;
 }
@@ -257,9 +250,6 @@
 	case SYS_ATSC:
 			delivery_system = 0x00;
 			break;
-	case SYS_DVBC_ANNEX_B:
-			delivery_system = 0x10;
-			break;
 	case SYS_DVBT:
 	case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
 			delivery_system = 0x20;
@@ -282,10 +272,7 @@
 	if (ret)
 		goto err;
 
-	if (s->chiptype == SI2157_CHIPTYPE_SI2146)
-		memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
-	else
-		memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6);
+	memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6);
 	cmd.wlen = 6;
 	cmd.rlen = 4;
 	ret = si2157_cmd_execute(s, &cmd);
@@ -318,7 +305,7 @@
 
 static const struct dvb_tuner_ops si2157_ops = {
 	.info = {
-		.name           = "Silicon Labs Si2146/2147/2148/2157/2158",
+		.name           = "Silicon Labs Si2157/Si2158",
 		.frequency_min  = 110000000,
 		.frequency_max  = 862000000,
 	},
@@ -349,7 +336,6 @@
 	s->fe = cfg->fe;
 	s->inversion = cfg->inversion;
 	s->fw_loaded = false;
-	s->chiptype = (u8)id->driver_data;
 	mutex_init(&s->i2c_mutex);
 
 	/* check if the tuner is there */
@@ -366,10 +352,7 @@
 	i2c_set_clientdata(client, s);
 
 	dev_info(&s->client->dev,
-			"Silicon Labs %s successfully attached\n",
-			s->chiptype == SI2157_CHIPTYPE_SI2146 ?
-			"Si2146" : "Si2147/2148/2157/2158");
-
+			"Silicon Labs Si2157/Si2158 successfully attached\n");
 	return 0;
 err:
 	dev_dbg(&client->dev, "failed=%d\n", ret);
@@ -394,7 +377,6 @@
 
 static const struct i2c_device_id si2157_id[] = {
 	{"si2157", 0},
-	{"si2146", 1},
 	{}
 };
 MODULE_DEVICE_TABLE(i2c, si2157_id);
@@ -411,7 +393,7 @@
 
 module_i2c_driver(si2157_driver);
 
-MODULE_DESCRIPTION("Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver");
+MODULE_DESCRIPTION("Silicon Labs Si2157/Si2158 silicon tuner driver");
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
diff --git a/drivers/media/tuners/si2157.h b/drivers/media/tuners/si2157.h
index a564c4a..d3b19ca 100644
--- a/drivers/media/tuners/si2157.h
+++ b/drivers/media/tuners/si2157.h
@@ -1,5 +1,5 @@
 /*
- * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
+ * Silicon Labs Si2147/2157/2158 silicon tuner driver
  *
  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
  *
diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h
index d6e07cd..e71ffaf 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -1,5 +1,5 @@
 /*
- * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
+ * Silicon Labs Si2147/2157/2158 silicon tuner driver
  *
  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
  *
@@ -28,13 +28,9 @@
 	bool active;
 	bool fw_loaded;
 	bool inversion;
-	u8 chiptype;
 };
 
-#define SI2157_CHIPTYPE_SI2157 0
-#define SI2157_CHIPTYPE_SI2146 1
-
-/* firmware command struct */
+/* firmare command struct */
 #define SI2157_ARGLEN      30
 struct si2157_cmd {
 	u8 args[SI2157_ARGLEN];
diff --git a/drivers/media/tuners/tda18271-common.c b/drivers/media/tuners/tda18271-common.c
index a26bb33..86e5e31 100644
--- a/drivers/media/tuners/tda18271-common.c
+++ b/drivers/media/tuners/tda18271-common.c
@@ -178,7 +178,7 @@
 		    (i != R_EB17) &&
 		    (i != R_EB19) &&
 		    (i != R_EB20))
-			regs[i] = regdump[i];
+		regs[i] = regdump[i];
 	}
 
 	if (tda18271_debug & DBG_REG)
diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c
index 2a039de..e44c8ab 100644
--- a/drivers/media/tuners/xc5000.c
+++ b/drivers/media/tuners/xc5000.c
@@ -62,7 +62,6 @@
 	unsigned int mode;
 	u8  rf_mode;
 	u8  radio_input;
-	u16  output_amp;
 
 	int chip_id;
 	u16 pll_register_no;
@@ -745,9 +744,7 @@
 		return -EIO;
 	}
 
-	dprintk(1, "%s() setting OUTPUT_AMP to 0x%x\n",
-		__func__, priv->output_amp);
-	xc_write_reg(priv, XREG_OUTPUT_AMP, priv->output_amp);
+	xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a);
 
 	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
 
@@ -1336,8 +1333,9 @@
 
 	if (priv) {
 		cancel_delayed_work(&priv->timer_sleep);
-		release_firmware(priv->firmware);
 		hybrid_tuner_release_state(priv);
+		if (priv->firmware)
+			release_firmware(priv->firmware);
 	}
 
 	mutex_unlock(&xc5000_list_mutex);
@@ -1360,9 +1358,6 @@
 	if (p->radio_input)
 		priv->radio_input = p->radio_input;
 
-	if (p->output_amp)
-		priv->output_amp = p->output_amp;
-
 	return 0;
 }
 
@@ -1443,12 +1438,6 @@
 		   it can be overridden if this is a hybrid driver */
 		priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0;
 
-	/* don't override output_amp if it's already been set
-	   unless explicitly specified */
-	if ((priv->output_amp == 0) || (cfg->output_amp))
-		/* use default output_amp value if none specified */
-		priv->output_amp = (cfg->output_amp) ? cfg->output_amp : 0x8a;
-
 	/* Check if firmware has been loaded. It is possible that another
 	   instance of the driver has loaded the firmware.
 	 */
diff --git a/drivers/media/tuners/xc5000.h b/drivers/media/tuners/xc5000.h
index d3ffe4b..38ff591 100644
--- a/drivers/media/tuners/xc5000.h
+++ b/drivers/media/tuners/xc5000.h
@@ -36,7 +36,6 @@
 	u32  if_khz;
 	u8   radio_input;
 	u16  xtal_khz;
-	u16  output_amp;
 
 	int chip_id;
 };
diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig
index 7496f33..056181f 100644
--- a/drivers/media/usb/Kconfig
+++ b/drivers/media/usb/Kconfig
@@ -24,6 +24,7 @@
 	comment "Analog TV USB devices"
 source "drivers/media/usb/pvrusb2/Kconfig"
 source "drivers/media/usb/hdpvr/Kconfig"
+source "drivers/media/usb/tlg2300/Kconfig"
 source "drivers/media/usb/usbvision/Kconfig"
 source "drivers/media/usb/stk1160/Kconfig"
 source "drivers/media/usb/go7007/Kconfig"
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile
index 920c1ed..417760e 100644
--- a/drivers/media/usb/Makefile
+++ b/drivers/media/usb/Makefile
@@ -16,6 +16,7 @@
 obj-$(CPTCFG_VIDEO_AU0828) += au0828/
 obj-$(CPTCFG_VIDEO_HDPVR)	+= hdpvr/
 obj-$(CPTCFG_VIDEO_PVRUSB2) += pvrusb2/
+obj-$(CPTCFG_VIDEO_TLG2300) += tlg2300/
 obj-$(CPTCFG_VIDEO_USBVISION) += usbvision/
 obj-$(CPTCFG_VIDEO_STK1160) += stk1160/
 obj-$(CPTCFG_VIDEO_CX231XX) += cx231xx/
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c
index b52f470..6c164d9 100644
--- a/drivers/media/usb/au0828/au0828-cards.c
+++ b/drivers/media/usb/au0828/au0828-cards.c
@@ -36,11 +36,6 @@
 		au0828_clear(dev, REG_000, 0x10);
 }
 
-/*
- * WARNING: There's a quirks table at sound/usb/quirks-table.h
- * that should also be updated every time a new device with V4L2 support
- * is added here.
- */
 struct au0828_board au0828_boards[] = {
 	[AU0828_BOARD_UNKNOWN] = {
 		.name	= "Unknown board",
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 73b6093..c697199 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -153,14 +153,6 @@
 
 	dprintk(1, "%s()\n", __func__);
 
-	/* there is a small window after disconnect, before
-	   dev->usbdev is NULL, for poll (e.g: IR) try to access
-	   the device and fill the dmesg with error messages.
-	   Set the status so poll routines can check and avoid
-	   access after disconnect.
-	*/
-	dev->dev_state = DEV_DISCONNECTED;
-
 	au0828_rc_unregister(dev);
 	/* Digital TV */
 	au0828_dvb_unregister(dev);
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c
index c267d76..00ab156 100644
--- a/drivers/media/usb/au0828/au0828-dvb.c
+++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -88,14 +88,12 @@
 	.i2c_address      = 0x61,
 	.if_khz           = 6000,
 	.chip_id          = XC5000A,
-	.output_amp       = 0x8f,
 };
 
 static struct xc5000_config hauppauge_xc5000c_config = {
 	.i2c_address      = 0x61,
 	.if_khz           = 6000,
 	.chip_id          = XC5000C,
-	.output_amp       = 0x8f,
 };
 
 static struct mxl5007t_config mxl5007t_hvr950q_config = {
diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c
index b0f0679..63995f9 100644
--- a/drivers/media/usb/au0828/au0828-input.c
+++ b/drivers/media/usb/au0828/au0828-input.c
@@ -129,10 +129,6 @@
 	int prv_bit, bit, width;
 	bool first = true;
 
-	/* do nothing if device is disconnected */
-	if (ir->dev->dev_state == DEV_DISCONNECTED)
-		return 0;
-
 	/* Check IR int */
 	rc = au8522_rc_read(ir, 0xe1, -1, buf, 1);
 	if (rc < 0 || !(buf[0] & (1 << 4))) {
@@ -259,11 +255,8 @@
 
 	cancel_delayed_work_sync(&ir->work);
 
-	/* do nothing if device is disconnected */
-	if (ir->dev->dev_state != DEV_DISCONNECTED) {
-		/* Disable IR */
-		au8522_rc_clear(ir, 0xe0, 1 << 4);
-	}
+	/* Disable IR */
+	au8522_rc_clear(ir, 0xe0, 1 << 4);
 }
 
 static int au0828_probe_i2c_ir(struct au0828_dev *dev)
@@ -370,7 +363,8 @@
 	if (!ir)
 		return;
 
-	rc_unregister_device(ir->rc);
+	if (ir->rc)
+		rc_unregister_device(ir->rc);
 
 	/* done */
 	kfree(ir);
diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig
index 0d1ff87..47209ab 100644
--- a/drivers/media/usb/cx231xx/Kconfig
+++ b/drivers/media/usb/cx231xx/Kconfig
@@ -8,7 +8,6 @@
 	select VIDEOBUF_VMALLOC
 	select VIDEO_CX25840
 	select VIDEO_CX2341X
-	depends on I2C_MUX
 
 	---help---
 	  This is a video4linux driver for Conexant 231xx USB based TV cards.
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
index 64f345d..6afc620 100644
--- a/drivers/media/usb/cx231xx/cx231xx-417.c
+++ b/drivers/media/usb/cx231xx/cx231xx-417.c
@@ -24,8 +24,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -39,6 +37,9 @@
 #include <media/v4l2-event.h>
 #include <media/cx2341x.h>
 #include <media/tuner.h>
+#include <linux/usb.h>
+
+#include "cx231xx.h"
 
 #define CX231xx_FIRM_IMAGE_SIZE 376836
 #define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
@@ -89,10 +90,10 @@
 module_param(v4l_debug, int, 0644);
 MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
 
-#define dprintk(level, fmt, arg...)	\
-	do {				\
-		if (v4l_debug >= level) \
-			printk(KERN_DEBUG pr_fmt(fmt), ## arg); \
+#define dprintk(level, fmt, arg...)\
+	do { if (v4l_debug >= level) \
+		pr_info("%s: " fmt, \
+		(dev) ? dev->name : "cx231xx[?]", ## arg); \
 	} while (0)
 
 static struct cx231xx_tvnorm cx231xx_tvnorms[] = {
@@ -987,34 +988,29 @@
 		IVTV_REG_APU, 0);
 
 	if (retval != 0) {
-		dev_err(dev->dev,
-			"%s: Error with mc417_register_write\n", __func__);
+		pr_err("%s: Error with mc417_register_write\n", __func__);
 		return -1;
 	}
 
 	retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME,
-				  dev->dev);
+				  &dev->udev->dev);
 
 	if (retval != 0) {
-		dev_err(dev->dev,
-			"ERROR: Hotplug firmware request failed (%s).\n",
+		pr_err("ERROR: Hotplug firmware request failed (%s).\n",
 			CX231xx_FIRM_IMAGE_NAME);
-		dev_err(dev->dev,
-			"Please fix your hotplug setup, the board will not work without firmware loaded!\n");
+		pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
 		return -1;
 	}
 
 	if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {
-		dev_err(dev->dev,
-			"ERROR: Firmware size mismatch (have %zd, expected %d)\n",
+		pr_err("ERROR: Firmware size mismatch (have %zd, expected %d)\n",
 			firmware->size, CX231xx_FIRM_IMAGE_SIZE);
 		release_firmware(firmware);
 		return -1;
 	}
 
 	if (0 != memcmp(firmware->data, magic, 8)) {
-		dev_err(dev->dev,
-			"ERROR: Firmware magic mismatch, wrong file?\n");
+		pr_err("ERROR: Firmware magic mismatch, wrong file?\n");
 		release_firmware(firmware);
 		return -1;
 	}
@@ -1061,8 +1057,7 @@
 	retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
 		IVTV_CMD_HW_BLOCKS_RST);
 	if (retval < 0) {
-		dev_err(dev->dev,
-			"%s: Error with mc417_register_write\n",
+		pr_err("%s: Error with mc417_register_write\n",
 			__func__);
 		return retval;
 	}
@@ -1074,8 +1069,7 @@
 	retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
 
 	if (retval < 0) {
-		dev_err(dev->dev,
-			"%s: Error with mc417_register_write\n",
+		pr_err("%s: Error with mc417_register_write\n",
 			__func__);
 		return retval;
 	}
@@ -1120,31 +1114,28 @@
 	cx231xx_disable656(dev);
 	retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
 	if (retval < 0) {
-		dprintk(2, "%s: PING OK\n", __func__);
+		dprintk(2, "%s() PING OK\n", __func__);
 		retval = cx231xx_load_firmware(dev);
 		if (retval < 0) {
-			dev_err(dev->dev,
-				"%s: f/w load failed\n", __func__);
+			pr_err("%s() f/w load failed\n", __func__);
 			return retval;
 		}
 		retval = cx231xx_find_mailbox(dev);
 		if (retval < 0) {
-			dev_err(dev->dev, "%s: mailbox < 0, error\n",
+			pr_err("%s() mailbox < 0, error\n",
 				__func__);
 			return -1;
 		}
 		dev->cx23417_mailbox = retval;
 		retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
 		if (retval < 0) {
-			dev_err(dev->dev,
-				"ERROR: cx23417 firmware ping failed!\n");
+			pr_err("ERROR: cx23417 firmware ping failed!\n");
 			return -1;
 		}
 		retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
 			&version);
 		if (retval < 0) {
-			dev_err(dev->dev,
-				"ERROR: cx23417 firmware get encoder: version failed!\n");
+			pr_err("ERROR: cx23417 firmware get encoder: version failed!\n");
 			return -1;
 		}
 		dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
@@ -1425,9 +1416,8 @@
 		if (!dev->video_mode.bulk_ctl.num_bufs)
 			urb_init = 1;
 	}
-	dev_dbg(dev->dev,
-		"urb_init=%d dev->video_mode.max_pkt_size=%d\n",
-		urb_init, dev->video_mode.max_pkt_size);
+	/*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
+		urb_init, dev->video_mode.max_pkt_size);*/
 	dev->mode_tv = 1;
 
 	if (urb_init) {
@@ -1698,7 +1688,7 @@
 			    sizeof(struct cx231xx_buffer), fh, &dev->lock);
 /*
 	videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,
-			    dev->dev, &dev->ts1.slock,
+			    &dev->udev->dev, &dev->ts1.slock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_INTERLACED,
 			    sizeof(struct cx231xx_buffer),
@@ -1808,6 +1798,7 @@
 static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct cx231xx_fh *fh = file->private_data;
+	struct cx231xx *dev = fh->dev;
 
 	dprintk(2, "%s()\n", __func__);
 
@@ -1887,7 +1878,7 @@
 	/* fix videodecoder resolution */
 	fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
 	fmt.height = cxhdl->height;
-	fmt.code = MEDIA_BUS_FMT_FIXED;
+	fmt.code = V4L2_MBUS_FMT_FIXED;
 	v4l2_subdev_call(dev->sd_cx25840, video, s_mbus_fmt, &fmt);
 	return 0;
 }
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
index de4ae5e..9b92587 100644
--- a/drivers/media/usb/cx231xx/cx231xx-audio.c
+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c
@@ -20,8 +20,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
 #include <linux/kernel.h>
+#include <linux/usb.h>
 #include <linux/init.h>
 #include <linux/sound.h>
 #include <linux/spinlock.h>
@@ -37,18 +37,25 @@
 #include <sound/initval.h>
 #include <sound/control.h>
 #include <media/v4l2-common.h>
+#include "cx231xx.h"
 
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
+#define dprintk(fmt, arg...) do {					\
+		if (debug)						\
+			printk(KERN_INFO "cx231xx-audio %s: " fmt,	\
+				__func__, ##arg); 			\
+	} while (0)
+
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 
 static int cx231xx_isoc_audio_deinit(struct cx231xx *dev)
 {
 	int i;
 
-	dev_dbg(dev->dev, "Stopping isoc\n");
+	dprintk("Stopping isoc\n");
 
 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
 		if (dev->adev.urb[i]) {
@@ -72,7 +79,7 @@
 {
 	int i;
 
-	dev_dbg(dev->dev, "Stopping bulk\n");
+	dprintk("Stopping bulk\n");
 
 	for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
 		if (dev->adev.urb[i]) {
@@ -116,8 +123,7 @@
 	case -ESHUTDOWN:
 		return;
 	default:		/* error */
-		dev_dbg(dev->dev, "urb completition error %d.\n",
-			urb->status);
+		dprintk("urb completition error %d.\n", urb->status);
 		break;
 	}
 
@@ -176,9 +182,8 @@
 
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status < 0) {
-		dev_err(dev->dev,
-			"resubmit of audio urb failed (error=%i)\n",
-			status);
+		cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
+			       status);
 	}
 	return;
 }
@@ -206,8 +211,7 @@
 	case -ESHUTDOWN:
 		return;
 	default:		/* error */
-		dev_dbg(dev->dev, "urb completition error %d.\n",
-			urb->status);
+		dprintk("urb completition error %d.\n", urb->status);
 		break;
 	}
 
@@ -262,9 +266,8 @@
 
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status < 0) {
-		dev_err(dev->dev,
-			"resubmit of audio urb failed (error=%i)\n",
-			status);
+		cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
+			       status);
 	}
 	return;
 }
@@ -274,8 +277,7 @@
 	int i, errCode;
 	int sb_size;
 
-	dev_dbg(dev->dev,
-		"%s: Starting ISO AUDIO transfers\n", __func__);
+	cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__);
 
 	if (dev->state & DEV_DISCONNECTED)
 		return -ENODEV;
@@ -293,7 +295,7 @@
 		memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
 		urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC);
 		if (!urb) {
-			dev_err(dev->dev, "usb_alloc_urb failed!\n");
+			cx231xx_errdev("usb_alloc_urb failed!\n");
 			for (j = 0; j < i; j++) {
 				usb_free_urb(dev->adev.urb[j]);
 				kfree(dev->adev.transfer_buffer[j]);
@@ -336,8 +338,7 @@
 	int i, errCode;
 	int sb_size;
 
-	dev_dbg(dev->dev,
-		"%s: Starting BULK AUDIO transfers\n", __func__);
+	cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__);
 
 	if (dev->state & DEV_DISCONNECTED)
 		return -ENODEV;
@@ -355,7 +356,7 @@
 		memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
 		urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
 		if (!urb) {
-			dev_err(dev->dev, "usb_alloc_urb failed!\n");
+			cx231xx_errdev("usb_alloc_urb failed!\n");
 			for (j = 0; j < i; j++) {
 				usb_free_urb(dev->adev.urb[j]);
 				kfree(dev->adev.transfer_buffer[j]);
@@ -391,9 +392,8 @@
 					size_t size)
 {
 	struct snd_pcm_runtime *runtime = subs->runtime;
-	struct cx231xx *dev = snd_pcm_substream_chip(subs);
 
-	dev_dbg(dev->dev, "Allocating vbuffer\n");
+	dprintk("Allocating vbuffer\n");
 	if (runtime->dma_area) {
 		if (runtime->dma_bytes > size)
 			return 0;
@@ -436,12 +436,16 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int ret = 0;
 
-	dev_dbg(dev->dev,
-		"opening device and trying to acquire exclusive lock\n");
+	dprintk("opening device and trying to acquire exclusive lock\n");
+
+	if (!dev) {
+		cx231xx_errdev("BUG: cx231xx can't find device struct."
+			       " Can't proceed with open\n");
+		return -ENODEV;
+	}
 
 	if (dev->state & DEV_DISCONNECTED) {
-		dev_err(dev->dev,
-			"Can't open. the device was removed.\n");
+		cx231xx_errdev("Can't open. the device was removed.\n");
 		return -ENODEV;
 	}
 
@@ -454,8 +458,7 @@
 		ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
 	mutex_unlock(&dev->lock);
 	if (ret < 0) {
-		dev_err(dev->dev,
-			"failed to set alternate setting !\n");
+		cx231xx_errdev("failed to set alternate setting !\n");
 
 		return ret;
 	}
@@ -481,7 +484,7 @@
 	int ret;
 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
 
-	dev_dbg(dev->dev, "closing device\n");
+	dprintk("closing device\n");
 
 	/* inform hardware to stop streaming */
 	mutex_lock(&dev->lock);
@@ -491,8 +494,7 @@
 	/* 1 - 48000 samples per sec */
 	ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
 	if (ret < 0) {
-		dev_err(dev->dev,
-			"failed to set alternate setting !\n");
+		cx231xx_errdev("failed to set alternate setting !\n");
 
 		mutex_unlock(&dev->lock);
 		return ret;
@@ -502,10 +504,10 @@
 	mutex_unlock(&dev->lock);
 
 	if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
-		dev_dbg(dev->dev, "audio users: %d\n", dev->adev.users);
-		dev_dbg(dev->dev, "disabling audio stream!\n");
+		dprintk("audio users: %d\n", dev->adev.users);
+		dprintk("disabling audio stream!\n");
 		dev->adev.shutdown = 0;
-		dev_dbg(dev->dev, "released lock\n");
+		dprintk("released lock\n");
 		if (atomic_read(&dev->stream_started) > 0) {
 			atomic_set(&dev->stream_started, 0);
 			schedule_work(&dev->wq_trigger);
@@ -517,10 +519,9 @@
 static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream,
 					 struct snd_pcm_hw_params *hw_params)
 {
-	struct cx231xx *dev = snd_pcm_substream_chip(substream);
 	int ret;
 
-	dev_dbg(dev->dev, "Setting capture parameters\n");
+	dprintk("Setting capture parameters\n");
 
 	ret = snd_pcm_alloc_vmalloc_buffer(substream,
 					   params_buffer_bytes(hw_params));
@@ -542,7 +543,7 @@
 {
 	struct cx231xx *dev = snd_pcm_substream_chip(substream);
 
-	dev_dbg(dev->dev, "Stop capture, if needed\n");
+	dprintk("Stop capture, if needed\n");
 
 	if (atomic_read(&dev->stream_started) > 0) {
 		atomic_set(&dev->stream_started, 0);
@@ -567,7 +568,7 @@
 	struct cx231xx *dev = container_of(work, struct cx231xx, wq_trigger);
 
 	if (atomic_read(&dev->stream_started)) {
-		dev_dbg(dev->dev, "starting capture");
+		dprintk("starting capture");
 		if (is_fw_load(dev) == 0)
 			cx25840_call(dev, core, load_fw);
 		if (dev->USE_ISO)
@@ -575,7 +576,7 @@
 		else
 			cx231xx_init_audio_bulk(dev);
 	} else {
-		dev_dbg(dev->dev, "stopping capture");
+		dprintk("stopping capture");
 		cx231xx_isoc_audio_deinit(dev);
 	}
 }
@@ -661,10 +662,10 @@
 		return 0;
 	}
 
-	dev_dbg(dev->dev,
-		"probing for cx231xx non standard usbaudio\n");
+	cx231xx_info("cx231xx-audio.c: probing for cx231xx "
+		     "non standard usbaudio\n");
 
-	err = snd_card_new(dev->dev, index[devnr], "Cx231xx Audio",
+	err = snd_card_new(&dev->udev->dev, index[devnr], "Cx231xx Audio",
 			   THIS_MODULE, 0, &card);
 	if (err < 0)
 		return err;
@@ -706,13 +707,14 @@
 			bEndpointAddress;
 
 	adev->num_alt = uif->num_altsetting;
-	dev_info(dev->dev,
-		"audio EndPoint Addr 0x%x, Alternate settings: %i\n",
-		adev->end_point_addr, adev->num_alt);
+	cx231xx_info("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)
+	if (adev->alt_max_pkt_size == NULL) {
+		cx231xx_errdev("out of memory!\n");
 		return -ENOMEM;
+	}
 
 	for (i = 0; i < adev->num_alt; i++) {
 		u16 tmp =
@@ -720,9 +722,8 @@
 				wMaxPacketSize);
 		adev->alt_max_pkt_size[i] =
 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-		dev_dbg(dev->dev,
-			"audio alternate setting %i, max size= %i\n", i,
-			adev->alt_max_pkt_size[i]);
+		cx231xx_info("Alternate setting %i, max size= %i\n", i,
+			     adev->alt_max_pkt_size[i]);
 	}
 
 	return 0;
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c
index 39e8879..40a6987 100644
--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c
@@ -22,12 +22,12 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/bitmap.h>
+#include <linux/usb.h>
 #include <linux/i2c.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
@@ -36,6 +36,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 
+#include "cx231xx.h"
 #include "cx231xx-dif.h"
 
 #define TUNER_MODE_FM_RADIO 0
@@ -82,10 +83,10 @@
 	cx231xx_send_gpio_cmd(dev, _gpio_direction, (u8 *)&value, 4, 0, 0);
 
 	verve_read_byte(dev, 0x07, &val);
-	dev_dbg(dev->dev, "verve_read_byte address0x07=0x%x\n", val);
+	cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
 	verve_write_byte(dev, 0x07, 0xF4);
 	verve_read_byte(dev, 0x07, &val);
-	dev_dbg(dev->dev, "verve_read_byte address0x07=0x%x\n", val);
+	cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
 
 	cx231xx_capture_start(dev, 1, Vbi);
 
@@ -155,25 +156,22 @@
 	while (afe_power_status != 0x18) {
 		status = afe_write_byte(dev, SUP_BLK_PWRDN, 0x18);
 		if (status < 0) {
-			dev_dbg(dev->dev,
-				"%s: Init Super Block failed in send cmd\n",
-				__func__);
+			cx231xx_info(
+			": Init Super Block failed in send cmd\n");
 			break;
 		}
 
 		status = afe_read_byte(dev, SUP_BLK_PWRDN, &afe_power_status);
 		afe_power_status &= 0xff;
 		if (status < 0) {
-			dev_dbg(dev->dev,
-				"%s: Init Super Block failed in receive cmd\n",
-				__func__);
+			cx231xx_info(
+			": Init Super Block failed in receive cmd\n");
 			break;
 		}
 		i++;
 		if (i == 10) {
-			dev_dbg(dev->dev,
-				"%s: Init Super Block force break in loop !!!!\n",
-				__func__);
+			cx231xx_info(
+			": Init Super Block force break in loop !!!!\n");
 			status = -1;
 			break;
 		}
@@ -412,7 +410,7 @@
 			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
 						0x00);
 		} else {
-			dev_dbg(dev->dev, "Invalid AV mode input\n");
+			cx231xx_info("Invalid AV mode input\n");
 			status = -1;
 		}
 		break;
@@ -469,7 +467,7 @@
 			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
 							0x40);
 		} else {
-			dev_dbg(dev->dev, "Invalid AV mode input\n");
+			cx231xx_info("Invalid AV mode input\n");
 			status = -1;
 		}
 	}			/* switch  */
@@ -575,9 +573,9 @@
 			status = cx231xx_set_power_mode(dev,
 					POLARIS_AVMODE_ENXTERNAL_AV);
 			if (status < 0) {
-				dev_err(dev->dev,
-					"%s: Failed to set Power - errCode [%d]!\n",
-					__func__, status);
+				cx231xx_errdev("%s: set_power_mode : Failed to"
+						" set Power - errCode [%d]!\n",
+						__func__, status);
 				return status;
 			}
 		}
@@ -593,8 +591,8 @@
 			status = cx231xx_set_power_mode(dev,
 						POLARIS_AVMODE_ANALOGT_TV);
 			if (status < 0) {
-				dev_err(dev->dev,
-					"%s: Failed to set Power - errCode [%d]!\n",
+				cx231xx_errdev("%s: set_power_mode:Failed"
+					" to set Power - errCode [%d]!\n",
 					__func__, status);
 				return status;
 			}
@@ -610,8 +608,8 @@
 
 		break;
 	default:
-		dev_err(dev->dev, "%s: Unknown Input %d !\n",
-			__func__, INPUT(input)->type);
+		cx231xx_errdev("%s: set_power_mode : Unknown Input %d !\n",
+		     __func__, INPUT(input)->type);
 		break;
 	}
 
@@ -630,8 +628,8 @@
 	if (pin_type != dev->video_input) {
 		status = cx231xx_afe_adjust_ref_count(dev, pin_type);
 		if (status < 0) {
-			dev_err(dev->dev,
-				"%s: adjust_ref_count :Failed to set AFE input mux - errCode [%d]!\n",
+			cx231xx_errdev("%s: adjust_ref_count :Failed to set"
+				"AFE input mux - errCode [%d]!\n",
 				__func__, status);
 			return status;
 		}
@@ -640,9 +638,9 @@
 	/* call afe block to set video inputs */
 	status = cx231xx_afe_set_input_mux(dev, input);
 	if (status < 0) {
-		dev_err(dev->dev,
-			"%s: set_input_mux :Failed to set AFE input mux - errCode [%d]!\n",
-			__func__, status);
+		cx231xx_errdev("%s: set_input_mux :Failed to set"
+				" AFE input mux - errCode [%d]!\n",
+				__func__, status);
 		return status;
 	}
 
@@ -672,8 +670,8 @@
 		/* Tell DIF object to go to baseband mode  */
 		status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
 		if (status < 0) {
-			dev_err(dev->dev,
-				"%s: cx231xx_dif set to By pass mode- errCode [%d]!\n",
+			cx231xx_errdev("%s: cx231xx_dif set to By pass"
+						   " mode- errCode [%d]!\n",
 				__func__, status);
 			return status;
 		}
@@ -717,8 +715,8 @@
 		/* Tell DIF object to go to baseband mode */
 		status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
 		if (status < 0) {
-			dev_err(dev->dev,
-				"%s: cx231xx_dif set to By pass mode- errCode [%d]!\n",
+			cx231xx_errdev("%s: cx231xx_dif set to By pass"
+						   " mode- errCode [%d]!\n",
 				__func__, status);
 			return status;
 		}
@@ -792,9 +790,9 @@
 			status = cx231xx_dif_set_standard(dev,
 							  DIF_USE_BASEBAND);
 			if (status < 0) {
-				dev_err(dev->dev,
-					"%s: cx231xx_dif set to By pass mode- errCode [%d]!\n",
-				       __func__, status);
+				cx231xx_errdev("%s: cx231xx_dif set to By pass"
+						" mode- errCode [%d]!\n",
+						__func__, status);
 				return status;
 			}
 
@@ -828,9 +826,9 @@
 			/* Reinitialize the DIF */
 			status = cx231xx_dif_set_standard(dev, dev->norm);
 			if (status < 0) {
-				dev_err(dev->dev,
-					"%s: cx231xx_dif set to By pass mode- errCode [%d]!\n",
-					__func__, status);
+				cx231xx_errdev("%s: cx231xx_dif set to By pass"
+						" mode- errCode [%d]!\n",
+						__func__, status);
 				return status;
 			}
 
@@ -972,14 +970,14 @@
 {
 	int status = 0;
 
-	dev_dbg(dev->dev, "%s: 0x%x\n",
-		__func__, (unsigned int)dev->norm);
+	cx231xx_info("do_mode_ctrl_overrides : 0x%x\n",
+		     (unsigned int)dev->norm);
 
 	/* Change the DFE_CTRL3 bp_percent to fix flagging */
 	status = vid_blk_write_word(dev, DFE_CTRL3, 0xCD3F0280);
 
 	if (dev->norm & (V4L2_STD_NTSC | V4L2_STD_PAL_M)) {
-		dev_dbg(dev->dev, "%s: NTSC\n", __func__);
+		cx231xx_info("do_mode_ctrl_overrides NTSC\n");
 
 		/* Move the close caption lines out of active video,
 		   adjust the active video start point */
@@ -1006,7 +1004,7 @@
 							(FLD_HBLANK_CNT, 0x79));
 
 	} else if (dev->norm & V4L2_STD_SECAM) {
-		dev_dbg(dev->dev, "%s: SECAM\n", __func__);
+		cx231xx_info("do_mode_ctrl_overrides SECAM\n");
 		status =  cx231xx_read_modify_write_i2c_dword(dev,
 							VID_BLK_I2C_ADDRESS,
 							VERT_TIM_CTRL,
@@ -1033,7 +1031,7 @@
 							cx231xx_set_field
 							(FLD_HBLANK_CNT, 0x85));
 	} else {
-		dev_dbg(dev->dev, "%s: PAL\n", __func__);
+		cx231xx_info("do_mode_ctrl_overrides PAL\n");
 		status = cx231xx_read_modify_write_i2c_dword(dev,
 							VID_BLK_I2C_ADDRESS,
 							VERT_TIM_CTRL,
@@ -1208,8 +1206,7 @@
 			/* This is just a casual suggestion to people adding
 			   new boards in case they use a tuner type we don't
 			   currently know about */
-			dev_info(dev->dev,
-				 "Unknown tuner type configuring SIF");
+			printk(KERN_INFO "Unknown tuner type configuring SIF");
 			break;
 		}
 		break;
@@ -1273,13 +1270,8 @@
 	int status = 0;
 	bool current_is_port_3;
 
-	/*
-	 * Should this code check dev->port_3_switch_enabled first
-	 * to skip unnecessary reading of the register?
-	 * If yes, the flag dev->port_3_switch_enabled must be initialized
-	 * correctly.
-	 */
-
+	if (dev->board.dont_use_port_3)
+		is_port_3 = false;
 	status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
 				       PWR_CTL_EN, value, 4);
 	if (status < 0)
@@ -1296,13 +1288,12 @@
 	else
 		value[0] &= ~I2C_DEMOD_EN;
 
+	cx231xx_info("Changing the i2c master port to %d\n",
+		     is_port_3 ?  3 : 1);
+
 	status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
 					PWR_CTL_EN, value, 4);
 
-	/* remember status of the switch for usage in is_tuner */
-	if (status >= 0)
-		dev->port_3_switch_enabled = is_port_3;
-
 	return status;
 
 }
@@ -1334,131 +1325,113 @@
 
 	for (i = 0x100; i < 0x140; i++) {
 		vid_blk_read_word(dev, i, &value);
-		dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
+		cx231xx_info("reg0x%x=0x%x\n", i, value);
 		i = i+3;
 	}
 
 	for (i = 0x300; i < 0x400; i++) {
 		vid_blk_read_word(dev, i, &value);
-		dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
+		cx231xx_info("reg0x%x=0x%x\n", i, value);
 		i = i+3;
 	}
 
 	for (i = 0x400; i < 0x440; i++) {
 		vid_blk_read_word(dev, i,  &value);
-		dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
+		cx231xx_info("reg0x%x=0x%x\n", i, value);
 		i = i+3;
 	}
 
 	vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
-	dev_dbg(dev->dev, "AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
+	cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
 	vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
 	vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
-	dev_dbg(dev->dev, "AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
+	cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
 }
 
-#if 0
-static void cx231xx_dump_SC_reg(struct cx231xx *dev)
+void cx231xx_dump_SC_reg(struct cx231xx *dev)
 {
 	u8 value[4] = { 0, 0, 0, 0 };
-	dev_dbg(dev->dev, "%s!\n", __func__);
+	cx231xx_info("cx231xx_dump_SC_reg!\n");
 
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", BOARD_CFG_STAT, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", BOARD_CFG_STAT, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS_MODE_REG,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS_MODE_REG, value[0],
-		 value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS_MODE_REG, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_CFG_REG,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_CFG_REG, value[0],
-		 value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_CFG_REG, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_LENGTH_REG,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_LENGTH_REG, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_LENGTH_REG, value[0],
+				 value[1], value[2], value[3]);
 
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_CFG_REG,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_CFG_REG, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_CFG_REG, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_LENGTH_REG,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_LENGTH_REG, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_LENGTH_REG, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", EP_MODE_SET, value[0],
-		 value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", EP_MODE_SET, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN1,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN1, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN1, value[0],
+				 value[1], value[2], value[3]);
 
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN2,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN2, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN2, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN3,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN3, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN3, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK0,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK0, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK0, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK1,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK1, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK1, value[0],
+				 value[1], value[2], value[3]);
 
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK2,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK2, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK2, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_GAIN,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_GAIN, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_GAIN, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_CAR_REG,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_CAR_REG, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_CAR_REG, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG1,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG1, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG1, value[0],
+				 value[1], value[2], value[3]);
 
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG2,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG2, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG2, value[0],
+				 value[1], value[2], value[3]);
 	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
 				 value, 4);
-	dev_dbg(dev->dev,
-		"reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
-		value[1], value[2], value[3]);
+	cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
+				 value[1], value[2], value[3]);
+
+
 }
-#endif
 
 void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev)
 
@@ -1524,7 +1497,7 @@
 	u32 standard = 0;
 	u8 value[4] = { 0, 0, 0, 0 };
 
-	dev_dbg(dev->dev, "Enter cx231xx_set_Colibri_For_LowIF()\n");
+	cx231xx_info("Enter cx231xx_set_Colibri_For_LowIF()\n");
 	value[0] = (u8) 0x6F;
 	value[1] = (u8) 0x6F;
 	value[2] = (u8) 0x6F;
@@ -1544,7 +1517,7 @@
 	colibri_carrier_offset = cx231xx_Get_Colibri_CarrierOffset(mode,
 								   standard);
 
-	dev_dbg(dev->dev, "colibri_carrier_offset=%d, standard=0x%x\n",
+	cx231xx_info("colibri_carrier_offset=%d, standard=0x%x\n",
 		     colibri_carrier_offset, standard);
 
 	/* Set the band Pass filter for DIF*/
@@ -1578,8 +1551,8 @@
 	u64 pll_freq_u64 = 0;
 	u32 i = 0;
 
-	dev_dbg(dev->dev, "if_freq=%d;spectral_invert=0x%x;mode=0x%x\n",
-		if_freq, spectral_invert, mode);
+	cx231xx_info("if_freq=%d;spectral_invert=0x%x;mode=0x%x\n",
+			 if_freq, spectral_invert, mode);
 
 
 	if (mode == TUNER_MODE_FM_RADIO) {
@@ -1622,7 +1595,8 @@
 		if_freq = 16000000;
 	}
 
-	dev_dbg(dev->dev, "Enter IF=%zu\n", ARRAY_SIZE(Dif_set_array));
+	cx231xx_info("Enter IF=%zu\n",
+			ARRAY_SIZE(Dif_set_array));
 	for (i = 0; i < ARRAY_SIZE(Dif_set_array); i++) {
 		if (Dif_set_array[i].if_freq == if_freq) {
 			vid_blk_write_word(dev,
@@ -1734,7 +1708,7 @@
 	u32 dif_misc_ctrl_value = 0;
 	u32 func_mode = 0;
 
-	dev_dbg(dev->dev, "%s: setStandard to %x\n", __func__, standard);
+	cx231xx_info("%s: setStandard to %x\n", __func__, standard);
 
 	status = vid_blk_read_word(dev, DIF_MISC_CTRL, &dif_misc_ctrl_value);
 	if (standard != DIF_USE_BASEBAND)
@@ -2137,8 +2111,8 @@
 {
 	int status = 0;
 	u32 dwval;
-	dev_dbg(dev->dev, "%s: dev->tuner_type =0%d\n",
-		__func__, dev->tuner_type);
+	cx231xx_info("cx231xx_tuner_post_channel_change  dev->tuner_type =0%d\n",
+		     dev->tuner_type);
 	/* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for
 	 * SECAM L/B/D standards */
 	status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
@@ -2239,8 +2213,8 @@
 	if (dev->power_mode != mode)
 		dev->power_mode = mode;
 	else {
-		dev_dbg(dev->dev, "%s: mode = %d, No Change req.\n",
-			 __func__, mode);
+		cx231xx_info(" setPowerMode::mode = %d, No Change req.\n",
+			     mode);
 		return 0;
 	}
 
@@ -2290,6 +2264,7 @@
 	case POLARIS_AVMODE_ANALOGT_TV:
 
 		tmp |= PWR_DEMOD_EN;
+		tmp |= (I2C_DEMOD_EN);
 		value[0] = (u8) tmp;
 		value[1] = (u8) (tmp >> 8);
 		value[2] = (u8) (tmp >> 16);
@@ -2342,6 +2317,9 @@
 		}
 
 		if (dev->board.tuner_type != TUNER_ABSENT) {
+			/* Enable tuner */
+			cx231xx_enable_i2c_port_3(dev, true);
+
 			/* reset the Tuner */
 			if (dev->board.tuner_gpio)
 				cx231xx_gpio_set(dev, dev->board.tuner_gpio);
@@ -2385,7 +2363,7 @@
 		}
 
 		tmp &= (~PWR_AV_MODE);
-		tmp |= POLARIS_AVMODE_DIGITAL;
+		tmp |= POLARIS_AVMODE_DIGITAL | I2C_DEMOD_EN;
 		value[0] = (u8) tmp;
 		value[1] = (u8) (tmp >> 8);
 		value[2] = (u8) (tmp >> 16);
@@ -2406,6 +2384,15 @@
 		}
 
 		if (dev->board.tuner_type != TUNER_ABSENT) {
+			/*
+			 * Enable tuner
+			 *	Hauppauge Exeter seems to need to do something different!
+			 */
+			if (dev->model == CX231XX_BOARD_HAUPPAUGE_EXETER)
+				cx231xx_enable_i2c_port_3(dev, false);
+			else
+				cx231xx_enable_i2c_port_3(dev, true);
+
 			/* reset the Tuner */
 			if (dev->board.tuner_gpio)
 				cx231xx_gpio_set(dev, dev->board.tuner_gpio);
@@ -2479,7 +2466,7 @@
 	u32 tmp = 0;
 	int status = 0;
 
-	dev_dbg(dev->dev, "%s: ep_mask = %x\n", __func__, ep_mask);
+	cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask);
 	status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
 				       value, 4);
 	if (status < 0)
@@ -2504,7 +2491,7 @@
 	u32 tmp = 0;
 	int status = 0;
 
-	dev_dbg(dev->dev, "%s: ep_mask = %x\n", __func__, ep_mask);
+	cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask);
 	status =
 	    cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, value, 4);
 	if (status < 0)
@@ -2532,72 +2519,61 @@
 	if (dev->udev->speed == USB_SPEED_HIGH) {
 		switch (media_type) {
 		case Audio:
-			dev_dbg(dev->dev,
-				"%s: Audio enter HANC\n", __func__);
+			cx231xx_info("%s: Audio enter HANC\n", __func__);
 			status =
 			    cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
 			break;
 
 		case Vbi:
-			dev_dbg(dev->dev,
-				"%s: set vanc registers\n", __func__);
+			cx231xx_info("%s: set vanc registers\n", __func__);
 			status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
 			break;
 
 		case Sliced_cc:
-			dev_dbg(dev->dev,
-				"%s: set hanc registers\n", __func__);
+			cx231xx_info("%s: set hanc registers\n", __func__);
 			status =
 			    cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
 			break;
 
 		case Raw_Video:
-			dev_dbg(dev->dev,
-				"%s: set video registers\n", __func__);
+			cx231xx_info("%s: set video registers\n", __func__);
 			status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
 			break;
 
 		case TS1_serial_mode:
-			dev_dbg(dev->dev,
-				"%s: set ts1 registers", __func__);
+			cx231xx_info("%s: set ts1 registers", __func__);
 
-			if (dev->board.has_417) {
-				dev_dbg(dev->dev,
-					"%s: MPEG\n", __func__);
-				value &= 0xFFFFFFFC;
-				value |= 0x3;
+		if (dev->board.has_417) {
+			cx231xx_info(" MPEG\n");
+			value &= 0xFFFFFFFC;
+			value |= 0x3;
 
-				status = cx231xx_mode_register(dev,
-							 TS_MODE_REG, value);
+			status = cx231xx_mode_register(dev, TS_MODE_REG, value);
 
-				val[0] = 0x04;
-				val[1] = 0xA3;
-				val[2] = 0x3B;
-				val[3] = 0x00;
-				status = cx231xx_write_ctrl_reg(dev,
-							VRT_SET_REGISTER,
-							TS1_CFG_REG, val, 4);
+			val[0] = 0x04;
+			val[1] = 0xA3;
+			val[2] = 0x3B;
+			val[3] = 0x00;
+			status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+				 TS1_CFG_REG, val, 4);
 
-				val[0] = 0x00;
-				val[1] = 0x08;
-				val[2] = 0x00;
-				val[3] = 0x08;
-				status = cx231xx_write_ctrl_reg(dev,
-							VRT_SET_REGISTER,
-							TS1_LENGTH_REG, val, 4);
-			} else {
-				dev_dbg(dev->dev, "%s: BDA\n", __func__);
-				status = cx231xx_mode_register(dev,
-							 TS_MODE_REG, 0x101);
-				status = cx231xx_mode_register(dev,
-							TS1_CFG_REG, 0x010);
-			}
+			val[0] = 0x00;
+			val[1] = 0x08;
+			val[2] = 0x00;
+			val[3] = 0x08;
+			status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+				 TS1_LENGTH_REG, val, 4);
+
+		} else {
+			cx231xx_info(" BDA\n");
+			status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
+			status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x010);
+		}
 			break;
 
 		case TS1_parallel_mode:
-			dev_dbg(dev->dev,
-				"%s: set ts1 parallel mode registers\n",
-				__func__);
+			cx231xx_info("%s: set ts1 parallel mode registers\n",
+				     __func__);
 			status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
 			status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400);
 			break;
@@ -2950,9 +2926,8 @@
 			 (nCnt > 0));
 
 	if (nCnt == 0)
-		dev_dbg(dev->dev,
-			"No ACK after %d msec -GPIO I2C failed!",
-			nInit * 10);
+		cx231xx_info("No ACK after %d msec -GPIO I2C failed!",
+			     nInit * 10);
 
 	/*
 	 * readAck
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index ae05d59..791f00c 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -20,12 +20,12 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/usb.h>
 #include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/v4l2-common.h>
@@ -35,6 +35,7 @@
 #include "xc5000.h"
 #include "tda18271.h"
 
+#include "cx231xx.h"
 
 static int tuner = -1;
 module_param(tuner, int, 0444);
@@ -103,8 +104,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x02,
 		.norm = V4L2_STD_PAL,
@@ -143,8 +144,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x32,
 		.norm = V4L2_STD_NTSC,
@@ -183,8 +184,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x1c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x02,
 		.norm = V4L2_STD_PAL,
@@ -224,8 +225,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x1c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x02,
 		.norm = V4L2_STD_PAL,
@@ -261,6 +262,7 @@
 		.norm = V4L2_STD_PAL,
 		.no_alt_vanc = 1,
 		.external_av = 1,
+		.dont_use_port_3 = 1,
 		/* Actually, it has a 417, but it isn't working correctly.
 		 * So set to 0 for now until someone can manage to get this
 		 * to work reliably. */
@@ -295,8 +297,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x02,
 		.norm = V4L2_STD_PAL,
@@ -323,8 +325,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x32,
 		.norm = V4L2_STD_NTSC,
@@ -351,8 +353,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_1,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x0e,
 		.norm = V4L2_STD_NTSC,
@@ -388,6 +390,7 @@
 		.norm = V4L2_STD_NTSC,
 		.no_alt_vanc = 1,
 		.external_av = 1,
+		.dont_use_port_3 = 1,
 		.input = {{
 			.type = CX231XX_VMUX_COMPOSITE1,
 			.vmux = CX231XX_VIN_2_1,
@@ -415,9 +418,9 @@
 		.tuner_scl_gpio = -1,
 		.tuner_sda_gpio = -1,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_2,
-		.demod_i2c_master = I2C_1_MUX_3,
-		.ir_i2c_master = I2C_2,
+		.tuner_i2c_master = 2,
+		.demod_i2c_master = 1,
+		.ir_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x10,
 		.norm = V4L2_STD_PAL_M,
@@ -453,9 +456,9 @@
 		.tuner_scl_gpio = -1,
 		.tuner_sda_gpio = -1,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_2,
-		.demod_i2c_master = I2C_1_MUX_3,
-		.ir_i2c_master = I2C_2,
+		.tuner_i2c_master = 2,
+		.demod_i2c_master = 1,
+		.ir_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x10,
 		.norm = V4L2_STD_NTSC_M,
@@ -491,9 +494,9 @@
 		.tuner_scl_gpio = -1,
 		.tuner_sda_gpio = -1,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_2,
-		.demod_i2c_master = I2C_1_MUX_3,
-		.ir_i2c_master = I2C_2,
+		.tuner_i2c_master = 2,
+		.demod_i2c_master = 1,
+		.ir_i2c_master = 2,
 		.rc_map_name = RC_MAP_PIXELVIEW_002T,
 		.has_dvb = 1,
 		.demod_addr = 0x10,
@@ -529,6 +532,7 @@
 		.norm = V4L2_STD_NTSC,
 		.no_alt_vanc = 1,
 		.external_av = 1,
+		.dont_use_port_3 = 1,
 
 		.input = {{
 				.type = CX231XX_VMUX_COMPOSITE1,
@@ -583,7 +587,7 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
+		.tuner_i2c_master = 1,
 		.norm = V4L2_STD_PAL,
 
 		.input = {{
@@ -618,7 +622,7 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
+		.tuner_i2c_master = 1,
 		.norm = V4L2_STD_NTSC,
 
 		.input = {{
@@ -652,6 +656,7 @@
 		.norm = V4L2_STD_NTSC,
 		.no_alt_vanc = 1,
 		.external_av = 1,
+		.dont_use_port_3 = 1,
 		.input = {{
 			.type = CX231XX_VMUX_COMPOSITE1,
 			.vmux = CX231XX_VIN_2_1,
@@ -672,12 +677,13 @@
 		.decoder = CX231XX_AVDECODER,
 		.output_mode = OUT_MODE_VIP11,
 		.ctl_pin_status_mask = 0xFFFFFFC4,
-		.agc_analog_digital_select_gpio = 0x0c,
+		.agc_analog_digital_select_gpio = 0x0c, 
 			/* According with PV CxPlrCAP.inf file */
 		.gpio_pin_status_mask = 0x4001000,
 		.norm = V4L2_STD_NTSC,
 		.no_alt_vanc = 1,
 		.external_av = 1,
+		.dont_use_port_3 = 1,
 		/*.has_417 = 1, */
 		/* This board is believed to have a hardware encoding chip
 		 * supporting mpeg1/2/4, but as the 417 is apparently not
@@ -712,8 +718,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x0e,
 		.norm = V4L2_STD_PAL,
@@ -751,8 +757,8 @@
 		.ctl_pin_status_mask = 0xFFFFFFC4,
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
-		.tuner_i2c_master = I2C_1_MUX_3,
-		.demod_i2c_master = I2C_2,
+		.tuner_i2c_master = 1,
+		.demod_i2c_master = 2,
 		.has_dvb = 1,
 		.demod_addr = 0x0e,
 		.norm = V4L2_STD_PAL,
@@ -855,9 +861,9 @@
 
 	if (dev->tuner_type == TUNER_XC5000) {
 		if (command == XC5000_TUNER_RESET) {
-			dev_dbg(dev->dev,
-				"Tuner CB: RESET: cmd %d : tuner type %d\n",
-				command, dev->tuner_type);
+			cx231xx_info
+				("Tuner CB: RESET: cmd %d : tuner type %d \n",
+				 command, dev->tuner_type);
 			cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
 					       1);
 			msleep(10);
@@ -915,8 +921,8 @@
 
 	cx231xx_set_model(dev);
 
-	dev_info(dev->dev, "Identified as %s (card=%d)\n",
-		dev->board.name, dev->model);
+	cx231xx_info("Identified as %s (card=%d)\n",
+		     dev->board.name, dev->model);
 
 	/* set the direction for GPIO pins */
 	if (dev->board.tuner_gpio) {
@@ -974,22 +980,25 @@
 
 }
 
-static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
-		       u8 *eedata, int len)
+static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
 {
 	int ret = 0;
+	u8 addr = 0xa0 >> 1;
 	u8 start_offset = 0;
 	int len_todo = len;
 	u8 *eedata_cur = eedata;
 	int i;
-	struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
+	struct i2c_msg msg_write = { .addr = addr, .flags = 0,
 		.buf = &start_offset, .len = 1 };
-	struct i2c_msg msg_read = { .addr = client->addr, .flags = I2C_M_RD };
+	struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
+
+	/* mutex_lock(&dev->i2c_lock); */
+	cx231xx_enable_i2c_port_3(dev, false);
 
 	/* start reading at offset 0 */
-	ret = i2c_transfer(client->adapter, &msg_write, 1);
+	ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
 	if (ret < 0) {
-		dev_err(dev->dev, "Can't read eeprom\n");
+		cx231xx_err("Can't read eeprom\n");
 		return ret;
 	}
 
@@ -997,18 +1006,20 @@
 		msg_read.len = (len_todo > 64) ? 64 : len_todo;
 		msg_read.buf = eedata_cur;
 
-		ret = i2c_transfer(client->adapter, &msg_read, 1);
+		ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
 		if (ret < 0) {
-			dev_err(dev->dev, "Can't read eeprom\n");
+			cx231xx_err("Can't read eeprom\n");
 			return ret;
 		}
 		eedata_cur += msg_read.len;
 		len_todo -= msg_read.len;
 	}
 
+	cx231xx_enable_i2c_port_3(dev, true);
+	/* mutex_unlock(&dev->i2c_lock); */
+
 	for (i = 0; i + 15 < len; i += 16)
-		dev_dbg(dev->dev, "i2c eeprom %02x: %*ph\n",
-			i, 16, &eedata[i]);
+		cx231xx_info("i2c eeprom %02x: %*ph\n", i, 16, &eedata[i]);
 
 	return 0;
 }
@@ -1025,26 +1036,22 @@
 	/* request some modules */
 	if (dev->board.decoder == CX231XX_AVDECODER) {
 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-					cx231xx_get_i2c_adap(dev, I2C_0),
+					&dev->i2c_bus[0].i2c_adap,
 					"cx25840", 0x88 >> 1, NULL);
 		if (dev->sd_cx25840 == NULL)
-			dev_err(dev->dev,
-				"cx25840 subdev registration failure\n");
+			cx231xx_info("cx25840 subdev registration failure\n");
 		cx25840_call(dev, core, load_fw);
 
 	}
 
 	/* Initialize the tuner */
 	if (dev->board.tuner_type != TUNER_ABSENT) {
-		struct i2c_adapter *tuner_i2c = cx231xx_get_i2c_adap(dev,
-						dev->board.tuner_i2c_master);
 		dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-						    tuner_i2c,
+						    &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 						    "tuner",
 						    dev->tuner_addr, NULL);
 		if (dev->sd_tuner == NULL)
-			dev_err(dev->dev,
-				"tuner subdev registration failure\n");
+			cx231xx_info("tuner subdev registration failure\n");
 		else
 			cx231xx_config_tuner(dev);
 	}
@@ -1055,14 +1062,9 @@
 		{
 			struct tveeprom tvee;
 			static u8 eeprom[256];
-			struct i2c_client client;
 
-			memset(&client, 0, sizeof(client));
-			client.adapter = cx231xx_get_i2c_adap(dev, I2C_1_MUX_1);
-			client.addr = 0xa0 >> 1;
-
-			read_eeprom(dev, &client, eeprom, sizeof(eeprom));
-			tveeprom_hauppauge_analog(&client,
+			read_eeprom(dev, eeprom, sizeof(eeprom));
+			tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
 						&tvee, eeprom + 0xc0);
 			break;
 		}
@@ -1150,7 +1152,7 @@
 	/* Query cx231xx to find what pcb config it is related to */
 	retval = initialize_cx231xx(dev);
 	if (retval < 0) {
-		dev_err(dev->dev, "Failed to read PCB config\n");
+		cx231xx_errdev("Failed to read PCB config\n");
 		return retval;
 	}
 
@@ -1166,7 +1168,7 @@
 
 	retval = cx231xx_config(dev);
 	if (retval) {
-		dev_err(dev->dev, "error configuring device\n");
+		cx231xx_errdev("error configuring device\n");
 		return -ENOMEM;
 	}
 
@@ -1176,9 +1178,8 @@
 	/* register i2c bus */
 	retval = cx231xx_dev_init(dev);
 	if (retval) {
-		dev_err(dev->dev,
-			"%s: cx231xx_i2c_register - errCode [%d]!\n",
-			__func__, retval);
+		cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n",
+			       __func__, retval);
 		goto err_dev_init;
 	}
 
@@ -1199,8 +1200,8 @@
 
 	retval = cx231xx_config(dev);
 	if (retval) {
-		dev_err(dev->dev, "%s: cx231xx_config - errCode [%d]!\n",
-			__func__, retval);
+		cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n",
+			       __func__, retval);
 		goto err_dev_init;
 	}
 
@@ -1216,11 +1217,11 @@
 	cx231xx_add_into_devlist(dev);
 
 	if (dev->board.has_417) {
-		dev_info(dev->dev, "attach 417 %d\n", dev->model);
+		printk(KERN_INFO "attach 417 %d\n", dev->model);
 		if (cx231xx_417_register(dev) < 0) {
-			dev_err(dev->dev,
+			printk(KERN_ERR
 				"%s() Failed to register 417 on VID_B\n",
-				__func__);
+			       __func__);
 		}
 	}
 
@@ -1284,8 +1285,7 @@
 	/* compute alternate max packet sizes for video */
 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.video_index + 1;
 	if (idx >= dev->max_iad_interface_count) {
-		dev_err(dev->dev,
-			"Video PCB interface #%d doesn't exist\n", idx);
+		cx231xx_errdev("Video PCB interface #%d doesn't exist\n", idx);
 		return -ENODEV;
 	}
 
@@ -1294,29 +1294,28 @@
 	dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
 	dev->video_mode.num_alt = uif->num_altsetting;
 
-	dev_info(dev->dev,
-		 "video EndPoint Addr 0x%x, Alternate settings: %i\n",
-		 dev->video_mode.end_point_addr,
-		 dev->video_mode.num_alt);
+	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+		     dev->video_mode.end_point_addr,
+		     dev->video_mode.num_alt);
 
 	dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL);
-	if (dev->video_mode.alt_max_pkt_size == NULL)
+	if (dev->video_mode.alt_max_pkt_size == NULL) {
+		cx231xx_errdev("out of memory!\n");
 		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);
 		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,
-			dev->video_mode.alt_max_pkt_size[i]);
+		cx231xx_info("Alternate setting %i, max size= %i\n", i,
+			     dev->video_mode.alt_max_pkt_size[i]);
 	}
 
 	/* VBI Init */
 
 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index + 1;
 	if (idx >= dev->max_iad_interface_count) {
-		dev_err(dev->dev,
-			"VBI PCB interface #%d doesn't exist\n", idx);
+		cx231xx_errdev("VBI PCB interface #%d doesn't exist\n", idx);
 		return -ENODEV;
 	}
 	uif = udev->actconfig->interface[idx];
@@ -1326,15 +1325,16 @@
 			bEndpointAddress;
 
 	dev->vbi_mode.num_alt = uif->num_altsetting;
-	dev_info(dev->dev,
-		 "VBI EndPoint Addr 0x%x, Alternate settings: %i\n",
-		 dev->vbi_mode.end_point_addr,
-		 dev->vbi_mode.num_alt);
+	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+		     dev->vbi_mode.end_point_addr,
+		     dev->vbi_mode.num_alt);
 
 	/* compute alternate max packet sizes for vbi */
 	dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL);
-	if (dev->vbi_mode.alt_max_pkt_size == NULL)
+	if (dev->vbi_mode.alt_max_pkt_size == NULL) {
+		cx231xx_errdev("out of memory!\n");
 		return -ENOMEM;
+	}
 
 	for (i = 0; i < dev->vbi_mode.num_alt; i++) {
 		u16 tmp =
@@ -1342,9 +1342,8 @@
 				desc.wMaxPacketSize);
 		dev->vbi_mode.alt_max_pkt_size[i] =
 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-		dev_dbg(dev->dev,
-			"Alternate setting %i, max size= %i\n", i,
-			dev->vbi_mode.alt_max_pkt_size[i]);
+		cx231xx_info("Alternate setting %i, max size= %i\n", i,
+			     dev->vbi_mode.alt_max_pkt_size[i]);
 	}
 
 	/* Sliced CC VBI init */
@@ -1352,8 +1351,7 @@
 	/* compute alternate max packet sizes for sliced CC */
 	idx = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index + 1;
 	if (idx >= dev->max_iad_interface_count) {
-		dev_err(dev->dev,
-			"Sliced CC PCB interface #%d doesn't exist\n", idx);
+		cx231xx_errdev("Sliced CC PCB interface #%d doesn't exist\n", idx);
 		return -ENODEV;
 	}
 	uif = udev->actconfig->interface[idx];
@@ -1363,22 +1361,23 @@
 			bEndpointAddress;
 
 	dev->sliced_cc_mode.num_alt = uif->num_altsetting;
-	dev_info(dev->dev,
-		 "sliced CC EndPoint Addr 0x%x, Alternate settings: %i\n",
-		 dev->sliced_cc_mode.end_point_addr,
-		 dev->sliced_cc_mode.num_alt);
+	cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+		     dev->sliced_cc_mode.end_point_addr,
+		     dev->sliced_cc_mode.num_alt);
 	dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL);
-	if (dev->sliced_cc_mode.alt_max_pkt_size == NULL)
+
+	if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
+		cx231xx_errdev("out of memory!\n");
 		return -ENOMEM;
+	}
 
 	for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
 		u16 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);
-		dev_dbg(dev->dev,
-			"Alternate setting %i, max size= %i\n", i,
-			dev->sliced_cc_mode.alt_max_pkt_size[i]);
+		cx231xx_info("Alternate setting %i, max size= %i\n", i,
+			     dev->sliced_cc_mode.alt_max_pkt_size[i]);
 	}
 
 	return 0;
@@ -1392,7 +1391,6 @@
 			     const struct usb_device_id *id)
 {
 	struct usb_device *udev;
-	struct device *d = &interface->dev;
 	struct usb_interface *uif;
 	struct cx231xx *dev = NULL;
 	int retval = -ENODEV;
@@ -1403,7 +1401,6 @@
 	struct usb_interface_assoc_descriptor *assoc_desc;
 
 	ifnum = interface->altsetting[0].desc.bInterfaceNumber;
-	udev = usb_get_dev(interface_to_usbdev(interface));
 
 	/*
 	 * Interface number 0 - IR interface (handled by mceusb driver)
@@ -1417,16 +1414,18 @@
 		nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
 		if (nr >= CX231XX_MAXBOARDS) {
 			/* No free device slots */
-			dev_err(d,
-				"Supports only %i devices.\n",
-				CX231XX_MAXBOARDS);
+			cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n",
+					CX231XX_MAXBOARDS);
 			return -ENOMEM;
 		}
 	} while (test_and_set_bit(nr, &cx231xx_devused));
 
+	udev = usb_get_dev(interface_to_usbdev(interface));
+
 	/* allocate memory for our device state and initialize it */
 	dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
+		cx231xx_err(DRIVER_NAME ": out of memory!\n");
 		clear_bit(nr, &cx231xx_devused);
 		return -ENOMEM;
 	}
@@ -1435,7 +1434,6 @@
 	dev->devno = nr;
 	dev->model = id->driver_info;
 	dev->video_mode.alt = -1;
-	dev->dev = d;
 
 	dev->interface_count++;
 	/* reset gpio dir and value */
@@ -1474,14 +1472,14 @@
 		speed = "unknown";
 	}
 
-	dev_info(d,
-		 "New device %s %s @ %s Mbps (%04x:%04x) with %d interfaces\n",
-		 udev->manufacturer ? udev->manufacturer : "",
-		 udev->product ? udev->product : "",
-		 speed,
-		 le16_to_cpu(udev->descriptor.idVendor),
-		 le16_to_cpu(udev->descriptor.idProduct),
-		 dev->max_iad_interface_count);
+	cx231xx_info("New device %s %s @ %s Mbps "
+	     "(%04x:%04x) with %d interfaces\n",
+	     udev->manufacturer ? udev->manufacturer : "",
+	     udev->product ? udev->product : "",
+	     speed,
+	     le16_to_cpu(udev->descriptor.idVendor),
+	     le16_to_cpu(udev->descriptor.idProduct),
+	     dev->max_iad_interface_count);
 
 	/* increment interface count */
 	dev->interface_count++;
@@ -1491,12 +1489,13 @@
 
 	assoc_desc = udev->actconfig->intf_assoc[0];
 	if (assoc_desc->bFirstInterface != ifnum) {
-		dev_err(d, "Not found matching IAD interface\n");
+		cx231xx_err(DRIVER_NAME ": Not found "
+			    "matching IAD interface\n");
 		retval = -ENODEV;
 		goto err_if;
 	}
 
-	dev_dbg(d, "registering interface %d\n", ifnum);
+	cx231xx_info("registering interface %d\n", ifnum);
 
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(interface, dev);
@@ -1504,7 +1503,7 @@
 	/* Create v4l2 device */
 	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
 	if (retval) {
-		dev_err(d, "v4l2_device_register failed\n");
+		cx231xx_errdev("v4l2_device_register failed\n");
 		goto err_v4l2;
 	}
 
@@ -1521,8 +1520,7 @@
 		/* compute alternate max packet sizes for TS1 */
 		idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
 		if (idx >= dev->max_iad_interface_count) {
-			dev_err(d, "TS1 PCB interface #%d doesn't exist\n",
-				idx);
+			cx231xx_errdev("TS1 PCB interface #%d doesn't exist\n", idx);
 			retval = -ENODEV;
 			goto err_video_alt;
 		}
@@ -1533,13 +1531,13 @@
 				desc.bEndpointAddress;
 
 		dev->ts1_mode.num_alt = uif->num_altsetting;
-		dev_info(d,
-			 "TS EndPoint Addr 0x%x, Alternate settings: %i\n",
-			 dev->ts1_mode.end_point_addr,
-			 dev->ts1_mode.num_alt);
+		cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+			     dev->ts1_mode.end_point_addr,
+			     dev->ts1_mode.num_alt);
 
 		dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL);
 		if (dev->ts1_mode.alt_max_pkt_size == NULL) {
+			cx231xx_errdev("out of memory!\n");
 			retval = -ENOMEM;
 			goto err_video_alt;
 		}
@@ -1550,8 +1548,8 @@
 						wMaxPacketSize);
 			dev->ts1_mode.alt_max_pkt_size[i] =
 			    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-			dev_dbg(d, "Alternate setting %i, max size= %i\n",
-				i, dev->ts1_mode.alt_max_pkt_size[i]);
+			cx231xx_info("Alternate setting %i, max size= %i\n", i,
+				     dev->ts1_mode.alt_max_pkt_size[i]);
 		}
 	}
 
@@ -1615,9 +1613,10 @@
 	wake_up_interruptible_all(&dev->open);
 
 	if (dev->users) {
-		dev_warn(dev->dev,
-			 "device %s is open! Deregistration and memory deallocation are deferred on close.\n",
-			 video_device_node_name(dev->vdev));
+		cx231xx_warn
+		    ("device %s is open! Deregistration and memory "
+		     "deallocation are deferred on close.\n",
+		     video_device_node_name(dev->vdev));
 
 		/* Even having users, it is safe to remove the RC i2c driver */
 		cx231xx_ir_exit(dev);
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c
index 4a3f28c..180103e 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -20,15 +20,16 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/usb.h>
 #include <linux/vmalloc.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 
+#include "cx231xx.h"
 #include "cx231xx-reg.h"
 
 /* #define ENABLE_DEBUG_ISOC_FRAMES */
@@ -98,10 +99,10 @@
 
 	mutex_lock(&cx231xx_devlist_mutex);
 	list_add_tail(&ops->next, &cx231xx_extension_devlist);
-	list_for_each_entry(dev, &cx231xx_devlist, devlist) {
+	list_for_each_entry(dev, &cx231xx_devlist, devlist)
 		ops->init(dev);
-		dev_info(dev->dev, "%s initialized\n", ops->name);
-	}
+
+	printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name);
 	mutex_unlock(&cx231xx_devlist_mutex);
 	return 0;
 }
@@ -112,11 +113,11 @@
 	struct cx231xx *dev = NULL;
 
 	mutex_lock(&cx231xx_devlist_mutex);
-	list_for_each_entry(dev, &cx231xx_devlist, devlist) {
+	list_for_each_entry(dev, &cx231xx_devlist, devlist)
 		ops->fini(dev);
-		dev_info(dev->dev, "%s removed\n", ops->name);
-	}
 
+
+	printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name);
 	list_del(&ops->next);
 	mutex_unlock(&cx231xx_devlist_mutex);
 }
@@ -226,9 +227,10 @@
 
 	/* call common vendor command request */
 	status = cx231xx_send_vendor_cmd(dev, &ven_req);
-	if (status < 0 && !dev->i2c_scan_running) {
-		dev_err(dev->dev, "%s: failed with status -%d\n",
-			__func__, status);
+	if (status < 0) {
+		cx231xx_info
+		    ("UsbInterface::sendCommand, failed with status -%d\n",
+		     status);
 	}
 
 	return status;
@@ -522,9 +524,9 @@
 		    usb_set_interface(dev->udev, usb_interface_index,
 				      dev->video_mode.alt);
 		if (errCode < 0) {
-			dev_err(dev->dev,
-				"cannot change alt number to %d (error=%i)\n",
-				dev->video_mode.alt, errCode);
+			cx231xx_errdev
+			    ("cannot change alt number to %d (error=%i)\n",
+			     dev->video_mode.alt, errCode);
 			return errCode;
 		}
 	}
@@ -598,9 +600,9 @@
 	}
 
 	if (alt > 0 && max_pkt_size == 0) {
-		dev_err(dev->dev,
-			"can't change interface %d alt no. to %d: Max. Pkt size = 0\n",
-			usb_interface_index, alt);
+		cx231xx_errdev
+		("can't change interface %d alt no. to %d: Max. Pkt size = 0\n",
+		usb_interface_index, alt);
 		/*To workaround error number=-71 on EP0 for videograbber,
 		 need add following codes.*/
 		if (dev->board.no_alt_vanc)
@@ -614,9 +616,9 @@
 	if (usb_interface_index > 0) {
 		status = usb_set_interface(dev->udev, usb_interface_index, alt);
 		if (status < 0) {
-			dev_err(dev->dev,
-				"can't change interface %d alt no. to %d (err=%i)\n",
-				usb_interface_index, alt, status);
+			cx231xx_errdev
+			("can't change interface %d alt no. to %d (err=%i)\n",
+			usb_interface_index, alt, status);
 			return status;
 		}
 	}
@@ -765,17 +767,18 @@
 	u32 *buffer;
 
 	buffer = kzalloc(4096, GFP_KERNEL);
-	if (buffer == NULL)
+	if (buffer == NULL) {
+		cx231xx_info("out of mem\n");
 		return -ENOMEM;
+	}
 	memcpy(&buffer[0], firmware, 4096);
 
 	ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 5),
 			buffer, 4096, &actlen, 2000);
 
 	if (ret)
-		dev_err(dev->dev,
-			"bulk message failed: %d (%d/%d)", ret,
-			size, actlen);
+		cx231xx_info("bulk message failed: %d (%d/%d)", ret,
+				size, actlen);
 	else {
 		errCode = actlen != size ? -1 : 0;
 	}
@@ -984,8 +987,12 @@
 	cx231xx_uninit_isoc(dev);
 
 	dma_q->p_left_data = kzalloc(4096, GFP_KERNEL);
-	if (dma_q->p_left_data == NULL)
+	if (dma_q->p_left_data == NULL) {
+		cx231xx_info("out of mem\n");
 		return -ENOMEM;
+	}
+
+
 
 	dev->video_mode.isoc_ctl.isoc_copy = isoc_copy;
 	dev->video_mode.isoc_ctl.num_bufs = num_bufs;
@@ -1011,16 +1018,14 @@
 	dev->video_mode.isoc_ctl.urb =
 	    kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
 	if (!dev->video_mode.isoc_ctl.urb) {
-		dev_err(dev->dev,
-			"cannot alloc memory for usb buffers\n");
+		cx231xx_errdev("cannot alloc memory for usb buffers\n");
 		return -ENOMEM;
 	}
 
 	dev->video_mode.isoc_ctl.transfer_buffer =
 	    kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
 	if (!dev->video_mode.isoc_ctl.transfer_buffer) {
-		dev_err(dev->dev,
-			"cannot allocate memory for usbtransfer\n");
+		cx231xx_errdev("cannot allocate memory for usbtransfer\n");
 		kfree(dev->video_mode.isoc_ctl.urb);
 		return -ENOMEM;
 	}
@@ -1040,8 +1045,7 @@
 	for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
 		urb = usb_alloc_urb(max_packets, GFP_KERNEL);
 		if (!urb) {
-			dev_err(dev->dev,
-				"cannot alloc isoc_ctl.urb %i\n", i);
+			cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i);
 			cx231xx_uninit_isoc(dev);
 			return -ENOMEM;
 		}
@@ -1051,10 +1055,10 @@
 		    usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
 				       &urb->transfer_dma);
 		if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {
-			dev_err(dev->dev,
-				"unable to allocate %i bytes for transfer buffer %i%s\n",
-				sb_size, i,
-				in_interrupt() ? " while in int" : "");
+			cx231xx_err("unable to allocate %i bytes for transfer"
+				    " buffer %i%s\n",
+				    sb_size, i,
+				    in_interrupt() ? " while in int" : "");
 			cx231xx_uninit_isoc(dev);
 			return -ENOMEM;
 		}
@@ -1086,9 +1090,8 @@
 		rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i],
 				    GFP_ATOMIC);
 		if (rc) {
-			dev_err(dev->dev,
-				"submit of urb %i failed (error=%i)\n", i,
-				rc);
+			cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+				    rc);
 			cx231xx_uninit_isoc(dev);
 			return rc;
 		}
@@ -1148,16 +1151,14 @@
 	dev->video_mode.bulk_ctl.urb =
 	    kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
 	if (!dev->video_mode.bulk_ctl.urb) {
-		dev_err(dev->dev,
-			"cannot alloc memory for usb buffers\n");
+		cx231xx_errdev("cannot alloc memory for usb buffers\n");
 		return -ENOMEM;
 	}
 
 	dev->video_mode.bulk_ctl.transfer_buffer =
 	    kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
 	if (!dev->video_mode.bulk_ctl.transfer_buffer) {
-		dev_err(dev->dev,
-			"cannot allocate memory for usbtransfer\n");
+		cx231xx_errdev("cannot allocate memory for usbtransfer\n");
 		kfree(dev->video_mode.bulk_ctl.urb);
 		return -ENOMEM;
 	}
@@ -1177,8 +1178,7 @@
 	for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
 		urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!urb) {
-			dev_err(dev->dev,
-				"cannot alloc bulk_ctl.urb %i\n", i);
+			cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i);
 			cx231xx_uninit_bulk(dev);
 			return -ENOMEM;
 		}
@@ -1189,10 +1189,10 @@
 		    usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
 				     &urb->transfer_dma);
 		if (!dev->video_mode.bulk_ctl.transfer_buffer[i]) {
-			dev_err(dev->dev,
-				"unable to allocate %i bytes for transfer buffer %i%s\n",
-				sb_size, i,
-				in_interrupt() ? " while in int" : "");
+			cx231xx_err("unable to allocate %i bytes for transfer"
+				    " buffer %i%s\n",
+				    sb_size, i,
+				    in_interrupt() ? " while in int" : "");
 			cx231xx_uninit_bulk(dev);
 			return -ENOMEM;
 		}
@@ -1212,8 +1212,8 @@
 		rc = usb_submit_urb(dev->video_mode.bulk_ctl.urb[i],
 				    GFP_ATOMIC);
 		if (rc) {
-			dev_err(dev->dev,
-				"submit of urb %i failed (error=%i)\n", i, rc);
+			cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+				    rc);
 			cx231xx_uninit_bulk(dev);
 			return rc;
 		}
@@ -1300,15 +1300,6 @@
 	cx231xx_i2c_register(&dev->i2c_bus[1]);
 	cx231xx_i2c_register(&dev->i2c_bus[2]);
 
-	cx231xx_i2c_mux_register(dev, 0);
-	cx231xx_i2c_mux_register(dev, 1);
-
-	/* scan the real bus segments in the order of physical port numbers */
-	cx231xx_do_i2c_scan(dev, I2C_0);
-	cx231xx_do_i2c_scan(dev, I2C_1_MUX_1);
-	cx231xx_do_i2c_scan(dev, I2C_2);
-	cx231xx_do_i2c_scan(dev, I2C_1_MUX_3);
-
 	/* init hardware */
 	/* Note : with out calling set power mode function,
 	afe can not be set up correctly */
@@ -1316,18 +1307,18 @@
 		errCode = cx231xx_set_power_mode(dev,
 				 POLARIS_AVMODE_ENXTERNAL_AV);
 		if (errCode < 0) {
-			dev_err(dev->dev,
-				"%s: Failed to set Power - errCode [%d]!\n",
-				__func__, errCode);
+			cx231xx_errdev
+			("%s: Failed to set Power - errCode [%d]!\n",
+			__func__, errCode);
 			return errCode;
 		}
 	} else {
 		errCode = cx231xx_set_power_mode(dev,
 				 POLARIS_AVMODE_ANALOGT_TV);
 		if (errCode < 0) {
-			dev_err(dev->dev,
-				"%s: Failed to set Power - errCode [%d]!\n",
-				__func__, errCode);
+			cx231xx_errdev
+			("%s: Failed to set Power - errCode [%d]!\n",
+			__func__, errCode);
 			return errCode;
 		}
 	}
@@ -1340,43 +1331,42 @@
 	/* initialize Colibri block */
 	errCode = cx231xx_afe_init_super_block(dev, 0x23c);
 	if (errCode < 0) {
-		dev_err(dev->dev,
-			"%s: cx231xx_afe init super block - errCode [%d]!\n",
-			__func__, errCode);
+		cx231xx_errdev
+		    ("%s: cx231xx_afe init super block - errCode [%d]!\n",
+		     __func__, errCode);
 		return errCode;
 	}
 	errCode = cx231xx_afe_init_channels(dev);
 	if (errCode < 0) {
-		dev_err(dev->dev,
-			"%s: cx231xx_afe init channels - errCode [%d]!\n",
-			__func__, errCode);
+		cx231xx_errdev
+		    ("%s: cx231xx_afe init channels - errCode [%d]!\n",
+		     __func__, errCode);
 		return errCode;
 	}
 
 	/* Set DIF in By pass mode */
 	errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
 	if (errCode < 0) {
-		dev_err(dev->dev,
-			"%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
-			__func__, errCode);
+		cx231xx_errdev
+		    ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
+		     __func__, errCode);
 		return errCode;
 	}
 
 	/* I2S block related functions */
 	errCode = cx231xx_i2s_blk_initialize(dev);
 	if (errCode < 0) {
-		dev_err(dev->dev,
-			"%s: cx231xx_i2s block initialize - errCode [%d]!\n",
-			__func__, errCode);
+		cx231xx_errdev
+		    ("%s: cx231xx_i2s block initialize - errCode [%d]!\n",
+		     __func__, errCode);
 		return errCode;
 	}
 
 	/* init control pins */
 	errCode = cx231xx_init_ctrl_pin_status(dev);
 	if (errCode < 0) {
-		dev_err(dev->dev,
-			"%s: cx231xx_init ctrl pins - errCode [%d]!\n",
-			__func__, errCode);
+		cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n",
+			       __func__, errCode);
 		return errCode;
 	}
 
@@ -1401,9 +1391,9 @@
 		break;
 	}
 	if (errCode < 0) {
-		dev_err(dev->dev,
-			"%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
-			__func__, errCode);
+		cx231xx_errdev
+		    ("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
+		     __func__, errCode);
 		return errCode;
 	}
 
@@ -1414,7 +1404,9 @@
 	if (dev->board.has_dvb)
 		cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
 
-	errCode = 0;
+	/* set the I2C master port to 3 on channel 1 */
+	errCode = cx231xx_enable_i2c_port_3(dev, true);
+
 	return errCode;
 }
 EXPORT_SYMBOL_GPL(cx231xx_dev_init);
@@ -1422,8 +1414,6 @@
 void cx231xx_dev_uninit(struct cx231xx *dev)
 {
 	/* Un Initialize I2C bus */
-	cx231xx_i2c_mux_unregister(dev, 1);
-	cx231xx_i2c_mux_unregister(dev, 0);
 	cx231xx_i2c_unregister(&dev->i2c_bus[2]);
 	cx231xx_i2c_unregister(&dev->i2c_bus[1]);
 	cx231xx_i2c_unregister(&dev->i2c_bus[0]);
@@ -1478,8 +1468,9 @@
 	/* call common vendor command request */
 	status = cx231xx_send_vendor_cmd(dev, &ven_req);
 	if (status < 0) {
-		dev_err(dev->dev, "%s: failed with status -%d\n",
-			__func__, status);
+		cx231xx_info
+		    ("UsbInterface::sendCommand, failed with status -%d\n",
+		     status);
 	}
 
 	return status;
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c
index dd600b9..6c7b5e2 100644
--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c
@@ -19,10 +19,11 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/usb.h>
 
+#include "cx231xx.h"
 #include <media/v4l2-common.h>
 #include <media/videobuf-vmalloc.h>
 
@@ -45,6 +46,11 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+#define dprintk(level, fmt, arg...) do {			\
+if (debug >= level) 						\
+	printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg);	\
+} while (0)
+
 #define CX231XX_DVB_NUM_BUFS 5
 #define CX231XX_DVB_MAX_PACKETSIZE 564
 #define CX231XX_DVB_MAX_PACKETS 64
@@ -191,11 +197,9 @@
 		break;
 	}
 	if (packet < 0) {
-		dev_dbg(dev->dev,
-			"URB status %d [%s].\n", status, errmsg);
+		dprintk(1, "URB status %d [%s].\n", status, errmsg);
 	} else {
-		dev_dbg(dev->dev,
-			"URB packet %d, status %d [%s].\n",
+		dprintk(1, "URB packet %d, status %d [%s].\n",
 			packet, status, errmsg);
 	}
 }
@@ -261,8 +265,12 @@
 	struct cx231xx *dev = dvb->adapter.priv;
 
 	if (dev->USE_ISO) {
-		dev_dbg(dev->dev, "DVB transfer mode is ISO.\n");
+		cx231xx_info("DVB transfer mode is ISO.\n");
+		mutex_lock(&dev->i2c_lock);
+		cx231xx_enable_i2c_port_3(dev, false);
 		cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
+		cx231xx_enable_i2c_port_3(dev, true);
+		mutex_unlock(&dev->i2c_lock);
 		rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 		if (rc < 0)
 			return rc;
@@ -272,7 +280,7 @@
 					dev->ts1_mode.max_pkt_size,
 					dvb_isoc_copy);
 	} else {
-		dev_dbg(dev->dev, "DVB transfer mode is BULK.\n");
+		cx231xx_info("DVB transfer mode is BULK.\n");
 		cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
 		rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 		if (rc < 0)
@@ -370,24 +378,24 @@
 	struct xc5000_config cfg;
 
 	memset(&cfg, 0, sizeof(cfg));
-	cfg.i2c_adap = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);
+	cfg.i2c_adap = &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap;
 	cfg.i2c_addr = addr;
 
 	if (!dev->dvb->frontend) {
-		dev_err(dev->dev, "%s/2: dvb frontend not attached. "
+		printk(KERN_ERR "%s/2: dvb frontend not attached. "
 		       "Can't attach xc5000\n", dev->name);
 		return -EINVAL;
 	}
 
 	fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg);
 	if (!fe) {
-		dev_err(dev->dev, "%s/2: xc5000 attach failed\n", dev->name);
+		printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name);
 		dvb_frontend_detach(dev->dvb->frontend);
 		dev->dvb->frontend = NULL;
 		return -EINVAL;
 	}
 
-	dev_info(dev->dev, "%s/2: xc5000 attached\n", dev->name);
+	printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name);
 
 	return 0;
 }
@@ -426,17 +434,16 @@
 
 		if (dops->init != NULL && !dev->xc_fw_load_done) {
 
-			dev_dbg(dev->dev,
-				"Reloading firmware for XC5000\n");
+			cx231xx_info("Reloading firmware for XC5000\n");
 			status = dops->init(dev->dvb->frontend);
 			if (status == 0) {
 				dev->xc_fw_load_done = 1;
-				dev_dbg(dev->dev,
-					"XC5000 firmware download completed\n");
+				cx231xx_info
+				    ("XC5000 firmware download completed\n");
 			} else {
 				dev->xc_fw_load_done = 0;
-				dev_dbg(dev->dev,
-					"XC5000 firmware download failed !!!\n");
+				cx231xx_info
+				    ("XC5000 firmware download failed !!!\n");
 			}
 		}
 
@@ -459,7 +466,7 @@
 	result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
 				      adapter_nr);
 	if (result < 0) {
-		dev_warn(dev->dev,
+		printk(KERN_WARNING
 		       "%s: dvb_register_adapter failed (errno = %d)\n",
 		       dev->name, result);
 		goto fail_adapter;
@@ -473,7 +480,7 @@
 	/* register frontend */
 	result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
 	if (result < 0) {
-		dev_warn(dev->dev,
+		printk(KERN_WARNING
 		       "%s: dvb_register_frontend failed (errno = %d)\n",
 		       dev->name, result);
 		goto fail_frontend;
@@ -491,8 +498,7 @@
 
 	result = dvb_dmx_init(&dvb->demux);
 	if (result < 0) {
-		dev_warn(dev->dev,
-			 "%s: dvb_dmx_init failed (errno = %d)\n",
+		printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
 		       dev->name, result);
 		goto fail_dmx;
 	}
@@ -502,16 +508,15 @@
 	dvb->dmxdev.capabilities = 0;
 	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
 	if (result < 0) {
-		dev_warn(dev->dev,
-			 "%s: dvb_dmxdev_init failed (errno = %d)\n",
-			 dev->name, result);
+		printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
+		       dev->name, result);
 		goto fail_dmxdev;
 	}
 
 	dvb->fe_hw.source = DMX_FRONTEND_0;
 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 	if (result < 0) {
-		dev_warn(dev->dev,
+		printk(KERN_WARNING
 		       "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
 		       dev->name, result);
 		goto fail_fe_hw;
@@ -520,17 +525,17 @@
 	dvb->fe_mem.source = DMX_MEMORY_FE;
 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 	if (result < 0) {
-		dev_warn(dev->dev,
-			 "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
-			 dev->name, result);
+		printk(KERN_WARNING
+		       "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+		       dev->name, result);
 		goto fail_fe_mem;
 	}
 
 	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 	if (result < 0) {
-		dev_warn(dev->dev,
-			 "%s: connect_frontend failed (errno = %d)\n",
-			 dev->name, result);
+		printk(KERN_WARNING
+		       "%s: connect_frontend failed (errno = %d)\n", dev->name,
+		       result);
 		goto fail_fe_conn;
 	}
 
@@ -578,8 +583,6 @@
 {
 	int result = 0;
 	struct cx231xx_dvb *dvb;
-	struct i2c_adapter *tuner_i2c;
-	struct i2c_adapter *demod_i2c;
 
 	if (!dev->board.has_dvb) {
 		/* This device does not support the extension */
@@ -589,16 +592,13 @@
 	dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
 
 	if (dvb == NULL) {
-		dev_info(dev->dev,
-			 "cx231xx_dvb: memory allocation failed\n");
+		printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n");
 		return -ENOMEM;
 	}
 	dev->dvb = dvb;
 	dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
 	dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
 
-	tuner_i2c = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);
-	demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master);
 	mutex_lock(&dev->lock);
 	cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 	cx231xx_demod_reset(dev);
@@ -609,11 +609,11 @@
 
 		dev->dvb->frontend = dvb_attach(s5h1432_attach,
 					&dvico_s5h1432_config,
-					demod_i2c);
+					&dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 
 		if (dev->dvb->frontend == NULL) {
-			dev_err(dev->dev,
-				"Failed to attach s5h1432 front end\n");
+			printk(DRIVER_NAME
+			       ": Failed to attach s5h1432 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -622,7 +622,7 @@
 		dvb->frontend->callback = cx231xx_tuner_callback;
 
 		if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
-			       tuner_i2c,
+			       &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 			       &cnxt_rde250_tunerconfig)) {
 			result = -EINVAL;
 			goto out_free;
@@ -634,11 +634,11 @@
 
 		dev->dvb->frontend = dvb_attach(s5h1411_attach,
 					       &xc5000_s5h1411_config,
-					       demod_i2c);
+					       &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 
 		if (dev->dvb->frontend == NULL) {
-			dev_err(dev->dev,
-				"Failed to attach s5h1411 front end\n");
+			printk(DRIVER_NAME
+			       ": Failed to attach s5h1411 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -647,7 +647,7 @@
 		dvb->frontend->callback = cx231xx_tuner_callback;
 
 		if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
-			       tuner_i2c,
+			       &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 			       &cnxt_rdu250_tunerconfig)) {
 			result = -EINVAL;
 			goto out_free;
@@ -657,11 +657,11 @@
 
 		dev->dvb->frontend = dvb_attach(s5h1432_attach,
 					&dvico_s5h1432_config,
-					demod_i2c);
+					&dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 
 		if (dev->dvb->frontend == NULL) {
-			dev_err(dev->dev,
-				"Failed to attach s5h1432 front end\n");
+			printk(DRIVER_NAME
+			       ": Failed to attach s5h1432 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -670,7 +670,7 @@
 		dvb->frontend->callback = cx231xx_tuner_callback;
 
 		if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
-			       0x60, tuner_i2c,
+			       0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 			       &cnxt_rde253s_tunerconfig)) {
 			result = -EINVAL;
 			goto out_free;
@@ -681,11 +681,11 @@
 
 		dev->dvb->frontend = dvb_attach(s5h1411_attach,
 					       &tda18271_s5h1411_config,
-					       demod_i2c);
+					       &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 
 		if (dev->dvb->frontend == NULL) {
-			dev_err(dev->dev,
-				"Failed to attach s5h1411 front end\n");
+			printk(DRIVER_NAME
+			       ": Failed to attach s5h1411 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -694,7 +694,7 @@
 		dvb->frontend->callback = cx231xx_tuner_callback;
 
 		if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
-			       0x60, tuner_i2c,
+			       0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 			       &cnxt_rde253s_tunerconfig)) {
 			result = -EINVAL;
 			goto out_free;
@@ -702,17 +702,16 @@
 		break;
 	case CX231XX_BOARD_HAUPPAUGE_EXETER:
 
-		dev_info(dev->dev,
-			 "%s: looking for tuner / demod on i2c bus: %d\n",
-		       __func__, i2c_adapter_id(tuner_i2c));
+		printk(KERN_INFO "%s: looking for tuner / demod on i2c bus: %d\n",
+		       __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
 
 		dev->dvb->frontend = dvb_attach(lgdt3305_attach,
 						&hcw_lgdt3305_config,
-						tuner_i2c);
+						&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap);
 
 		if (dev->dvb->frontend == NULL) {
-			dev_err(dev->dev,
-				"Failed to attach LG3305 front end\n");
+			printk(DRIVER_NAME
+			       ": Failed to attach LG3305 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -721,7 +720,7 @@
 		dvb->frontend->callback = cx231xx_tuner_callback;
 
 		dvb_attach(tda18271_attach, dev->dvb->frontend,
-			   0x60, tuner_i2c,
+			   0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 			   &hcw_tda18271_config);
 		break;
 
@@ -729,12 +728,12 @@
 
 		dev->dvb->frontend = dvb_attach(si2165_attach,
 			&hauppauge_930C_HD_1113xx_si2165_config,
-			tuner_i2c
+			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap
 			);
 
 		if (dev->dvb->frontend == NULL) {
-			dev_err(dev->dev,
-				"Failed to attach SI2165 front end\n");
+			printk(DRIVER_NAME
+			       ": Failed to attach SI2165 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -746,7 +745,7 @@
 
 		dvb_attach(tda18271_attach, dev->dvb->frontend,
 			0x60,
-			tuner_i2c,
+			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 			&hcw_tda18271_config);
 
 		dev->cx231xx_reset_analog_tuner = NULL;
@@ -762,12 +761,12 @@
 
 		dev->dvb->frontend = dvb_attach(si2165_attach,
 			&pctv_quatro_stick_1114xx_si2165_config,
-			tuner_i2c
+			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap
 			);
 
 		if (dev->dvb->frontend == NULL) {
-			dev_err(dev->dev,
-				"Failed to attach SI2165 front end\n");
+			printk(DRIVER_NAME
+			       ": Failed to attach SI2165 front end\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -787,7 +786,7 @@
 		request_module("si2157");
 
 		client = i2c_new_device(
-			tuner_i2c,
+			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 			&info);
 		if (client == NULL || client->dev.driver == NULL) {
 			dvb_frontend_detach(dev->dvb->frontend);
@@ -811,17 +810,16 @@
 	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 	case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
 
-		dev_info(dev->dev,
-			 "%s: looking for demod on i2c bus: %d\n",
-			 __func__, i2c_adapter_id(tuner_i2c));
+		printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n",
+		       __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
 
 		dev->dvb->frontend = dvb_attach(mb86a20s_attach,
 						&pv_mb86a20s_config,
-						demod_i2c);
+						&dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 
 		if (dev->dvb->frontend == NULL) {
-			dev_err(dev->dev,
-				"Failed to attach mb86a20s demod\n");
+			printk(DRIVER_NAME
+			       ": Failed to attach mb86a20s demod\n");
 			result = -EINVAL;
 			goto out_free;
 		}
@@ -830,31 +828,30 @@
 		dvb->frontend->callback = cx231xx_tuner_callback;
 
 		dvb_attach(tda18271_attach, dev->dvb->frontend,
-			   0x60, tuner_i2c,
+			   0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 			   &pv_tda18271_config);
 		break;
 
 	default:
-		dev_err(dev->dev,
-			"%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
-			dev->name);
+		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
+		       " isn't supported yet\n", dev->name);
 		break;
 	}
 	if (NULL == dvb->frontend) {
-		dev_err(dev->dev,
+		printk(KERN_ERR
 		       "%s/2: frontend initialization failed\n", dev->name);
 		result = -EINVAL;
 		goto out_free;
 	}
 
 	/* register everything */
-	result = register_dvb(dvb, THIS_MODULE, dev, dev->dev);
+	result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
 
 	if (result < 0)
 		goto out_free;
 
 
-	dev_info(dev->dev, "Successfully loaded cx231xx-dvb\n");
+	printk(KERN_INFO "Successfully loaded cx231xx-dvb\n");
 
 ret:
 	cx231xx_set_mode(dev, CX231XX_SUSPEND);
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index a29c345..7c0f797 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -20,14 +20,14 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/usb.h>
 #include <linux/i2c.h>
-#include <linux/i2c-mux.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 
+#include "cx231xx.h"
 
 /* ----------------------------------------------------------- */
 
@@ -54,19 +54,10 @@
       } 						\
 } while (0)
 
-static inline int get_real_i2c_port(struct cx231xx *dev, int bus_nr)
-{
-	if (bus_nr == 1)
-		return dev->port_3_switch_enabled ? I2C_1_MUX_3 : I2C_1_MUX_1;
-	return bus_nr;
-}
-
 static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
 			const struct i2c_msg *msg, int tuner_type)
 {
-	int i2c_port = get_real_i2c_port(dev, bus->nr);
-
-	if (i2c_port != dev->board.tuner_i2c_master)
+	if (bus->nr != dev->board.tuner_i2c_master)
 		return false;
 
 	if (msg->addr != dev->board.tuner_addr)
@@ -349,15 +340,14 @@
 	struct cx231xx *dev = bus->dev;
 	struct cx231xx_i2c_xfer_data req_data;
 	int status = 0;
-	u8 buf[1];
 
 	/* prepare xfer_data struct */
 	req_data.dev_addr = msg->addr;
-	req_data.direction = I2C_M_RD;
+	req_data.direction = msg->flags;
 	req_data.saddr_len = 0;
 	req_data.saddr_dat = 0;
-	req_data.buf_size = 1;
-	req_data.p_buffer = buf;
+	req_data.buf_size = 0;
+	req_data.p_buffer = NULL;
 
 	/* usb send command */
 	status = dev->cx231xx_send_usb_command(bus, &req_data);
@@ -465,14 +455,17 @@
 	.algo = &cx231xx_algo,
 };
 
+static struct i2c_client cx231xx_client_template = {
+	.name = "cx231xx internal",
+};
+
 /* ----------------------------------------------------------- */
 
 /*
  * i2c_devs
  * incomplete list of known devices
  */
-static const char *i2c_devs[128] = {
-	[0x20 >> 1] = "demod",
+static char *i2c_devs[128] = {
 	[0x60 >> 1] = "colibri",
 	[0x88 >> 1] = "hammerhead",
 	[0x8e >> 1] = "CIR",
@@ -487,34 +480,22 @@
  * cx231xx_do_i2c_scan()
  * check i2c address range for devices
  */
-void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port)
+void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c)
 {
 	unsigned char buf;
 	int i, rc;
-	struct i2c_client client;
 
-	if (!i2c_scan)
-		return;
-
-	/* Don't generate I2C errors during scan */
-	dev->i2c_scan_running = true;
-
-	memset(&client, 0, sizeof(client));
-	client.adapter = cx231xx_get_i2c_adap(dev, i2c_port);
-
+	cx231xx_info(": Checking for I2C devices ..\n");
 	for (i = 0; i < 128; i++) {
-		client.addr = i;
-		rc = i2c_master_recv(&client, &buf, 0);
+		c->addr = i;
+		rc = i2c_master_recv(c, &buf, 0);
 		if (rc < 0)
 			continue;
-		dev_info(dev->dev,
-			 "i2c scan: found device @ port %d addr 0x%x  [%s]\n",
-			 i2c_port,
-			 i << 1,
-			 i2c_devs[i] ? i2c_devs[i] : "???");
+		cx231xx_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
+			     dev->name, i << 1,
+			     i2c_devs[i] ? i2c_devs[i] : "???");
 	}
-
-	dev->i2c_scan_running = false;
+	cx231xx_info(": Completed Checking for I2C devices.\n");
 }
 
 /*
@@ -528,17 +509,23 @@
 	BUG_ON(!dev->cx231xx_send_usb_command);
 
 	bus->i2c_adap = cx231xx_adap_template;
-	bus->i2c_adap.dev.parent = dev->dev;
+	bus->i2c_client = cx231xx_client_template;
+	bus->i2c_adap.dev.parent = &dev->udev->dev;
 
-	snprintf(bus->i2c_adap.name, sizeof(bus->i2c_adap.name), "%s-%d", bus->dev->name, bus->nr);
+	strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
 
 	bus->i2c_adap.algo_data = bus;
 	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
 	i2c_add_adapter(&bus->i2c_adap);
 
-	if (0 != bus->i2c_rc)
-		dev_warn(dev->dev,
-			 "i2c bus %d register FAILED\n", bus->nr);
+	bus->i2c_client.adapter = &bus->i2c_adap;
+
+	if (0 == bus->i2c_rc) {
+		if (i2c_scan)
+			cx231xx_do_i2c_scan(dev, &bus->i2c_client);
+	} else
+		cx231xx_warn("%s: i2c bus %d register FAILED\n",
+			     dev->name, bus->nr);
 
 	return bus->i2c_rc;
 }
@@ -552,62 +539,3 @@
 	i2c_del_adapter(&bus->i2c_adap);
 	return 0;
 }
-
-/*
- * cx231xx_i2c_mux_select()
- * switch i2c master number 1 between port1 and port3
- */
-static int cx231xx_i2c_mux_select(struct i2c_adapter *adap,
-			void *mux_priv, u32 chan_id)
-{
-	struct cx231xx *dev = mux_priv;
-
-	return cx231xx_enable_i2c_port_3(dev, chan_id);
-}
-
-int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
-{
-	struct i2c_adapter *i2c_parent = &dev->i2c_bus[1].i2c_adap;
-	/* what is the correct mux_dev? */
-	struct device *mux_dev = dev->dev;
-
-	dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent,
-				mux_dev,
-				dev /* mux_priv */,
-				0,
-				mux_no /* chan_id */,
-				0 /* class */,
-				&cx231xx_i2c_mux_select,
-				NULL);
-
-	if (!dev->i2c_mux_adap[mux_no])
-		dev_warn(dev->dev,
-			 "i2c mux %d register FAILED\n", mux_no);
-
-	return 0;
-}
-
-void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no)
-{
-	i2c_del_mux_adapter(dev->i2c_mux_adap[mux_no]);
-	dev->i2c_mux_adap[mux_no] = NULL;
-}
-
-struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port)
-{
-	switch (i2c_port) {
-	case I2C_0:
-		return &dev->i2c_bus[0].i2c_adap;
-	case I2C_1:
-		return &dev->i2c_bus[1].i2c_adap;
-	case I2C_2:
-		return &dev->i2c_bus[2].i2c_adap;
-	case I2C_1_MUX_1:
-		return dev->i2c_mux_adap[0];
-	case I2C_1_MUX_3:
-		return dev->i2c_mux_adap[1];
-	default:
-		return NULL;
-	}
-}
-EXPORT_SYMBOL_GPL(cx231xx_get_i2c_adap);
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c
index 15d8d1b..05f0434 100644
--- a/drivers/media/usb/cx231xx/cx231xx-input.c
+++ b/drivers/media/usb/cx231xx/cx231xx-input.c
@@ -19,6 +19,7 @@
  */
 
 #include "cx231xx.h"
+#include <linux/usb.h>
 #include <linux/slab.h>
 #include <linux/bitrev.h>
 
@@ -62,7 +63,7 @@
 	struct i2c_board_info info;
 	u8 ir_i2c_bus;
 
-	dev_dbg(dev->dev, "%s\n", __func__);
+	dev_dbg(&dev->udev->dev, "%s\n", __func__);
 
 	/* Only initialize if a rc keycode map is defined */
 	if (!cx231xx_boards[dev->model].rc_map_name)
@@ -97,10 +98,9 @@
 
 	/* Load and bind ir-kbd-i2c */
 	ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master;
-	dev_dbg(dev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
+	dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
 		ir_i2c_bus, info.addr);
-	dev->ir_i2c_client = i2c_new_device(
-		cx231xx_get_i2c_adap(dev, ir_i2c_bus), &info);
+	dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
 
 	return 0;
 }
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
index 5bc7414..3052c4c 100644
--- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
+++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
@@ -703,9 +703,9 @@
 			_current_scenario_idx = INDEX_BUSPOWER_DIF_ONLY;
 			break;
 		default:
-			dev_err(dev->dev,
-				"bad config in buspower!!!!\nconfig_info=%x\n",
-				config_info & BUSPOWER_MASK);
+			cx231xx_info("bad config in buspower!!!!\n");
+			cx231xx_info("config_info=%x\n",
+				     (config_info & BUSPOWER_MASK));
 			return 1;
 		}
 	} else {		/* self-power */
@@ -768,9 +768,9 @@
 			_current_scenario_idx = INDEX_SELFPOWER_COMPRESSOR;
 			break;
 		default:
-			dev_err(dev->dev,
-				"bad senario!!!!!\nconfig_info=%x\n",
-				config_info & SELFPOWER_MASK);
+			cx231xx_info("bad senario!!!!!\n");
+			cx231xx_info("config_info=%x\n",
+				     (config_info & SELFPOWER_MASK));
 			return -ENODEV;
 		}
 	}
@@ -781,29 +781,18 @@
 		   sizeof(struct pcb_config));
 
 	if (pcb_debug) {
-		dev_info(dev->dev,
-			 "SC(0x00) register = 0x%x\n", config_info);
-		dev_info(dev->dev,
-			 "scenario %d\n",
-			 (dev->current_pcb_config.index) + 1);
-		dev_info(dev->dev,
-			"type=%x\n",
-			 dev->current_pcb_config.type);
-		dev_info(dev->dev,
-			 "mode=%x\n",
-			 dev->current_pcb_config.mode);
-		dev_info(dev->dev,
-			 "speed=%x\n",
-			 dev->current_pcb_config.speed);
-		dev_info(dev->dev,
-			 "ts1_source=%x\n",
-			 dev->current_pcb_config.ts1_source);
-		dev_info(dev->dev,
-			 "ts2_source=%x\n",
-			 dev->current_pcb_config.ts2_source);
-		dev_info(dev->dev,
-			 "analog_source=%x\n",
-			 dev->current_pcb_config.analog_source);
+		cx231xx_info("SC(0x00) register = 0x%x\n", config_info);
+		cx231xx_info("scenario %d\n",
+			    (dev->current_pcb_config.index) + 1);
+		cx231xx_info("type=%x\n", dev->current_pcb_config.type);
+		cx231xx_info("mode=%x\n", dev->current_pcb_config.mode);
+		cx231xx_info("speed=%x\n", dev->current_pcb_config.speed);
+		cx231xx_info("ts1_source=%x\n",
+			     dev->current_pcb_config.ts1_source);
+		cx231xx_info("ts2_source=%x\n",
+			     dev->current_pcb_config.ts2_source);
+		cx231xx_info("analog_source=%x\n",
+			     dev->current_pcb_config.analog_source);
 	}
 
 	return 0;
diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c
index 80261ac..c027942 100644
--- a/drivers/media/usb/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c
@@ -19,12 +19,12 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/bitmap.h>
+#include <linux/usb.h>
 #include <linux/i2c.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
@@ -35,6 +35,7 @@
 #include <media/msp3400.h>
 #include <media/tuner.h>
 
+#include "cx231xx.h"
 #include "cx231xx-vbi.h"
 
 static inline void print_err_status(struct cx231xx *dev, int packet, int status)
@@ -68,12 +69,11 @@
 		break;
 	}
 	if (packet < 0) {
-		dev_err(dev->dev,
-			"URB status %d [%s].\n", status, errmsg);
+		cx231xx_err("URB status %d [%s].\n", status,
+			    errmsg);
 	} else {
-		dev_err(dev->dev,
-			"URB packet %d, status %d [%s].\n",
-			packet, status, errmsg);
+		cx231xx_err("URB packet %d, status %d [%s].\n",
+			    packet, status, errmsg);
 	}
 }
 
@@ -316,8 +316,8 @@
 	case -ESHUTDOWN:
 		return;
 	default:		/* error */
-		dev_err(dev->dev,
-			"urb completition error %d.\n",	urb->status);
+		cx231xx_err("urb completition error %d.\n",
+			    urb->status);
 		break;
 	}
 
@@ -331,8 +331,8 @@
 
 	urb->status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (urb->status) {
-		dev_err(dev->dev, "urb resubmit failed (error=%i)\n",
-			urb->status);
+		cx231xx_err("urb resubmit failed (error=%i)\n",
+			    urb->status);
 	}
 }
 
@@ -344,7 +344,7 @@
 	struct urb *urb;
 	int i;
 
-	dev_dbg(dev->dev, "called cx231xx_uninit_vbi_isoc\n");
+	cx231xx_info("called cx231xx_uninit_vbi_isoc\n");
 
 	dev->vbi_mode.bulk_ctl.nfields = -1;
 	for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
@@ -393,7 +393,7 @@
 	struct urb *urb;
 	int rc;
 
-	dev_dbg(dev->dev, "called cx231xx_vbi_isoc\n");
+	cx231xx_info("called cx231xx_vbi_isoc\n");
 
 	/* De-allocates all pending stuff */
 	cx231xx_uninit_vbi_isoc(dev);
@@ -419,16 +419,14 @@
 	dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
 					     GFP_KERNEL);
 	if (!dev->vbi_mode.bulk_ctl.urb) {
-		dev_err(dev->dev,
-			"cannot alloc memory for usb buffers\n");
+		cx231xx_errdev("cannot alloc memory for usb buffers\n");
 		return -ENOMEM;
 	}
 
 	dev->vbi_mode.bulk_ctl.transfer_buffer =
 	    kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
 	if (!dev->vbi_mode.bulk_ctl.transfer_buffer) {
-		dev_err(dev->dev,
-			"cannot allocate memory for usbtransfer\n");
+		cx231xx_errdev("cannot allocate memory for usbtransfer\n");
 		kfree(dev->vbi_mode.bulk_ctl.urb);
 		return -ENOMEM;
 	}
@@ -443,8 +441,7 @@
 
 		urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!urb) {
-			dev_err(dev->dev,
-				"cannot alloc bulk_ctl.urb %i\n", i);
+			cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i);
 			cx231xx_uninit_vbi_isoc(dev);
 			return -ENOMEM;
 		}
@@ -454,10 +451,9 @@
 		dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
 		    kzalloc(sb_size, GFP_KERNEL);
 		if (!dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
-			dev_err(dev->dev,
-				"unable to allocate %i bytes for transfer buffer %i%s\n",
-				sb_size, i,
-				in_interrupt() ? " while in int" : "");
+			cx231xx_err("unable to allocate %i bytes for transfer"
+				    " buffer %i%s\n", sb_size, i,
+				    in_interrupt() ? " while in int" : "");
 			cx231xx_uninit_vbi_isoc(dev);
 			return -ENOMEM;
 		}
@@ -474,8 +470,8 @@
 	for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
 		rc = usb_submit_urb(dev->vbi_mode.bulk_ctl.urb[i], GFP_ATOMIC);
 		if (rc) {
-			dev_err(dev->dev,
-				"submit of urb %i failed (error=%i)\n", i, rc);
+			cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+				    rc);
 			cx231xx_uninit_vbi_isoc(dev);
 			return rc;
 		}
@@ -526,7 +522,7 @@
 				     struct cx231xx_buffer *buf)
 {
 	/* Advice that buffer was filled */
-	/* dev_dbg(dev->dev, "[%p/%d] wakeup\n", buf, buf->vb.i); */
+	/* cx231xx_info("[%p/%d] wakeup\n", buf, buf->vb.i); */
 
 	buf->vb.state = VIDEOBUF_DONE;
 	buf->vb.field_count++;
@@ -618,7 +614,7 @@
 	char *outp;
 
 	if (list_empty(&dma_q->active)) {
-		dev_err(dev->dev, "No active queue to serve\n");
+		cx231xx_err("No active queue to serve\n");
 		dev->vbi_mode.bulk_ctl.buf = NULL;
 		*buf = NULL;
 		return;
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index d72d74e..425080b 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -22,12 +22,12 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "cx231xx.h"
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/bitmap.h>
+#include <linux/usb.h>
 #include <linux/i2c.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
@@ -41,9 +41,10 @@
 
 #include "dvb_frontend.h"
 
+#include "cx231xx.h"
 #include "cx231xx-vbi.h"
 
-#define CX231XX_VERSION "0.0.3"
+#define CX231XX_VERSION "0.0.2"
 
 #define DRIVER_AUTHOR   "Srinivasa Deevi <srinivasa.deevi@conexant.com>"
 #define DRIVER_DESC     "Conexant cx231xx based USB video device driver"
@@ -736,9 +737,8 @@
 		if (!dev->video_mode.bulk_ctl.num_bufs)
 			urb_init = 1;
 	}
-	dev_dbg(dev->dev,
-		"urb_init=%d dev->video_mode.max_pkt_size=%d\n",
-		urb_init, dev->video_mode.max_pkt_size);
+	/*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
+		urb_init, dev->video_mode.max_pkt_size);*/
 	if (urb_init) {
 		dev->mode_tv = 0;
 		if (dev->USE_ISO)
@@ -809,7 +809,7 @@
 
 	cx231xx_set_audio_input(dev, dev->ctl_ainput);
 
-	dev_dbg(dev->dev, "video_mux : %d\n", index);
+	cx231xx_info("video_mux : %d\n", index);
 
 	/* do mode control overrides if required */
 	cx231xx_do_mode_ctrl_overrides(dev);
@@ -861,7 +861,7 @@
 static int check_dev(struct cx231xx *dev)
 {
 	if (dev->state & DEV_DISCONNECTED) {
-		dev_err(dev->dev, "v4l2 ioctl: device not present\n");
+		cx231xx_errdev("v4l2 ioctl: device not present\n");
 		return -ENODEV;
 	}
 	return 0;
@@ -953,13 +953,12 @@
 		return -EINVAL;
 
 	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
-		dev_err(dev->dev, "%s: queue busy\n", __func__);
+		cx231xx_errdev("%s queue busy\n", __func__);
 		return -EBUSY;
 	}
 
 	if (dev->stream_on && !fh->stream_on) {
-		dev_err(dev->dev,
-			"%s: device in use by another fh\n", __func__);
+		cx231xx_errdev("%s device in use by another fh\n", __func__);
 		return -EBUSY;
 	}
 
@@ -968,7 +967,7 @@
 	dev->height = f->fmt.pix.height;
 	dev->format = fmt;
 
-	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
 	call_all(dev, video, s_mbus_fmt, &mbus_fmt);
 	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 
@@ -1013,7 +1012,7 @@
 	   resolution (since a standard change effects things like the number
 	   of lines in VACT, etc) */
 	memset(&mbus_fmt, 0, sizeof(mbus_fmt));
-	mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
+	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
 	mbus_fmt.width = dev->width;
 	mbus_fmt.height = dev->height;
 	call_all(dev, video, s_mbus_fmt, &mbus_fmt);
@@ -1177,9 +1176,9 @@
 	int rc;
 	u32 if_frequency = 5400000;
 
-	dev_dbg(dev->dev,
-		"Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
-		f->frequency, f->type);
+	cx231xx_info("Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
+		 f->frequency, f->type);
+	/*cx231xx_info("f->type:  1-radio 2-analogTV 3-digitalTV\n");*/
 
 	rc = check_dev(dev);
 	if (rc < 0)
@@ -1214,14 +1213,13 @@
 		else if (dev->norm & V4L2_STD_SECAM_LC)
 			if_frequency = 1250000;  /*1.25MHz	*/
 
-		dev_dbg(dev->dev,
-			"if_frequency is set to %d\n", if_frequency);
+		cx231xx_info("if_frequency is set to %d\n", if_frequency);
 		cx231xx_set_Colibri_For_LowIF(dev, if_frequency, 1, 1);
 
 		update_HH_register_after_set_DIF(dev);
 	}
 
-	dev_dbg(dev->dev, "Set New FREQUENCY to %d\n", f->frequency);
+	cx231xx_info("Set New FREQUENCY to %d\n", f->frequency);
 
 	return rc;
 }
@@ -1525,8 +1523,7 @@
 	struct cx231xx *dev = fh->dev;
 
 	if (dev->vbi_stream_on && !fh->stream_on) {
-		dev_err(dev->dev,
-			"%s device in use by another fh\n", __func__);
+		cx231xx_errdev("%s device in use by another fh\n", __func__);
 		return -EBUSY;
 	}
 	return vidioc_try_fmt_vbi_cap(file, priv, f);
@@ -1645,15 +1642,17 @@
 #if 0
 	errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
 	if (errCode < 0) {
-		dev_err(dev->dev,
-			"Device locked on digital mode. Can't open analog\n");
+		cx231xx_errdev
+		    ("Device locked on digital mode. Can't open analog\n");
 		return -EBUSY;
 	}
 #endif
 
 	fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
-	if (!fh)
+	if (!fh) {
+		cx231xx_errdev("cx231xx-video.c: Out of memory?!\n");
 		return -ENOMEM;
+	}
 	if (mutex_lock_interruptible(&dev->lock)) {
 		kfree(fh);
 		return -ERESTARTSYS;
@@ -1737,8 +1736,8 @@
 		dev->radio_dev = NULL;
 	}
 	if (dev->vbi_dev) {
-		dev_info(dev->dev, "V4L2 device %s deregistered\n",
-			video_device_node_name(dev->vbi_dev));
+		cx231xx_info("V4L2 device %s deregistered\n",
+			     video_device_node_name(dev->vbi_dev));
 		if (video_is_registered(dev->vbi_dev))
 			video_unregister_device(dev->vbi_dev);
 		else
@@ -1746,8 +1745,8 @@
 		dev->vbi_dev = NULL;
 	}
 	if (dev->vdev) {
-		dev_info(dev->dev, "V4L2 device %s deregistered\n",
-			video_device_node_name(dev->vdev));
+		cx231xx_info("V4L2 device %s deregistered\n",
+			     video_device_node_name(dev->vdev));
 
 		if (dev->board.has_417)
 			cx231xx_417_unregister(dev);
@@ -2081,7 +2080,8 @@
 {
 	int ret;
 
-	dev_info(dev->dev, "v4l2 driver version %s\n", CX231XX_VERSION);
+	cx231xx_info("%s: v4l2 driver version %s\n",
+		     dev->name, CX231XX_VERSION);
 
 	/* set default norm */
 	dev->norm = V4L2_STD_PAL;
@@ -2119,7 +2119,7 @@
 	/* allocate and fill video video_device struct */
 	dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video");
 	if (!dev->vdev) {
-		dev_err(dev->dev, "cannot allocate video_device.\n");
+		cx231xx_errdev("cannot allocate video_device.\n");
 		return -ENODEV;
 	}
 
@@ -2128,14 +2128,13 @@
 	ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
 				    video_nr[dev->devno]);
 	if (ret) {
-		dev_err(dev->dev,
-			"unable to register video device (error=%i).\n",
-			ret);
+		cx231xx_errdev("unable to register video device (error=%i).\n",
+			       ret);
 		return ret;
 	}
 
-	dev_info(dev->dev, "Registered video device %s [v4l2]\n",
-		video_device_node_name(dev->vdev));
+	cx231xx_info("%s/0: registered device %s [v4l2]\n",
+		     dev->name, video_device_node_name(dev->vdev));
 
 	/* Initialize VBI template */
 	cx231xx_vbi_template = cx231xx_video_template;
@@ -2145,7 +2144,7 @@
 	dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi");
 
 	if (!dev->vbi_dev) {
-		dev_err(dev->dev, "cannot allocate video_device.\n");
+		cx231xx_errdev("cannot allocate video_device.\n");
 		return -ENODEV;
 	}
 	dev->vbi_dev->ctrl_handler = &dev->ctrl_handler;
@@ -2153,32 +2152,34 @@
 	ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
 				    vbi_nr[dev->devno]);
 	if (ret < 0) {
-		dev_err(dev->dev, "unable to register vbi device\n");
+		cx231xx_errdev("unable to register vbi device\n");
 		return ret;
 	}
 
-	dev_info(dev->dev, "Registered VBI device %s\n",
-		video_device_node_name(dev->vbi_dev));
+	cx231xx_info("%s/0: registered device %s\n",
+		     dev->name, video_device_node_name(dev->vbi_dev));
 
 	if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
 		dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template,
 						   "radio");
 		if (!dev->radio_dev) {
-			dev_err(dev->dev,
-				"cannot allocate video_device.\n");
+			cx231xx_errdev("cannot allocate video_device.\n");
 			return -ENODEV;
 		}
 		dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
 		ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
 					    radio_nr[dev->devno]);
 		if (ret < 0) {
-			dev_err(dev->dev,
-				"can't register radio device\n");
+			cx231xx_errdev("can't register radio device\n");
 			return ret;
 		}
-		dev_info(dev->dev, "Registered radio device as %s\n",
-			video_device_node_name(dev->radio_dev));
+		cx231xx_info("Registered radio device as %s\n",
+			     video_device_node_name(dev->radio_dev));
 	}
 
+	cx231xx_info("V4L2 device registered as %s and %s\n",
+		     video_device_node_name(dev->vdev),
+		     video_device_node_name(dev->vbi_dev));
+
 	return 0;
 }
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h
index 2ebe7c4..d607c5c 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -28,7 +28,6 @@
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
-#include <linux/usb.h>
 
 #include <media/cx2341x.h>
 
@@ -323,11 +322,10 @@
 };
 
 enum CX231XX_I2C_MASTER_PORT {
-	I2C_0 = 0,       /* master 0 - internal connection */
-	I2C_1 = 1,       /* master 1 - used with mux */
-	I2C_2 = 2,       /* master 2 */
-	I2C_1_MUX_1 = 3, /* master 1 - port 1 (I2C_DEMOD_EN = 0) */
-	I2C_1_MUX_3 = 4  /* master 1 - port 3 (I2C_DEMOD_EN = 1) */
+	I2C_0 = 0,
+	I2C_1 = 1,
+	I2C_2 = 2,
+	I2C_3 = 3
 };
 
 struct cx231xx_board {
@@ -369,6 +367,7 @@
 	unsigned int valid:1;
 	unsigned int no_alt_vanc:1;
 	unsigned int external_av:1;
+	unsigned int dont_use_port_3:1;
 
 	unsigned char xclk, i2c_speed;
 
@@ -473,6 +472,7 @@
 
 	/* i2c i/o */
 	struct i2c_adapter i2c_adap;
+	struct i2c_client i2c_client;
 	u32 i2c_rc;
 
 	/* different settings for each bus */
@@ -597,7 +597,6 @@
 	char name[30];		/* name (including minor) of the device */
 	int model;		/* index in the device_data struct */
 	int devno;		/* marks the number of this device */
-	struct device *dev;	/* pointer to USB interface's dev */
 
 	struct cx231xx_board board;
 
@@ -610,8 +609,6 @@
 	unsigned int has_audio_class:1;
 	unsigned int has_alsa_audio:1;
 
-	unsigned int i2c_scan_running:1; /* true only during i2c_scan */
-
 	struct cx231xx_fmt *format;
 
 	struct v4l2_device v4l2_dev;
@@ -631,10 +628,7 @@
 
 	/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
 	struct cx231xx_i2c i2c_bus[3];
-	struct i2c_adapter *i2c_mux_adap[2];
-
 	unsigned int xc_fw_load_done:1;
-	unsigned int port_3_switch_enabled:1;
 	/* locks */
 	struct mutex gpio_i2c_lock;
 	struct mutex i2c_lock;
@@ -757,12 +751,9 @@
 int cx231xx_reset_analog_tuner(struct cx231xx *dev);
 
 /* Provided by cx231xx-i2c.c */
-void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port);
+void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c);
 int cx231xx_i2c_register(struct cx231xx_i2c *bus);
 int cx231xx_i2c_unregister(struct cx231xx_i2c *bus);
-int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no);
-void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no);
-struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port);
 
 /* Internal block control functions */
 int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
@@ -811,6 +802,7 @@
 void reset_s5h1432_demod(struct cx231xx *dev);
 void cx231xx_dump_HH_reg(struct cx231xx *dev);
 void update_HH_register_after_set_DIF(struct cx231xx *dev);
+void cx231xx_dump_SC_reg(struct cx231xx *dev);
 
 
 
@@ -984,6 +976,23 @@
 #define cx231xx_ir_exit(dev)	(0)
 #endif
 
+
+/* printk macros */
+
+#define cx231xx_err(fmt, arg...) do {\
+	printk(KERN_ERR fmt , ##arg); } while (0)
+
+#define cx231xx_errdev(fmt, arg...) do {\
+	printk(KERN_ERR "%s: "fmt,\
+			dev->name , ##arg); } while (0)
+
+#define cx231xx_info(fmt, arg...) do {\
+	printk(KERN_INFO "%s: "fmt,\
+			dev->name , ##arg); } while (0)
+#define cx231xx_warn(fmt, arg...) do {\
+	printk(KERN_WARNING "%s: "fmt,\
+			dev->name , ##arg); } while (0)
+
 static inline unsigned int norm_maxw(struct cx231xx *dev)
 {
 	if (dev->board.max_range_640_480)
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index cf2482f..3d39fb7 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -31,7 +31,7 @@
 	  Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
 
 config DVB_USB_AF9035
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Afatech AF9035 DVB-T USB2.0 support"
 	depends on m
 	depends on DVB_USB_V2
@@ -46,7 +46,7 @@
 	  Say Y here to support the Afatech AF9035 based DVB USB receiver.
 
 config DVB_USB_ANYSEE
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Anysee DVB-T/C USB2.0 support"
 	depends on m
 	depends on DVB_USB_V2
@@ -138,7 +138,7 @@
 	  Say Y here to support the MxL111SF USB2.0 DTV receiver.
 
 config DVB_USB_RTL28XXU
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Realtek RTL28xxU DVB USB support"
 	depends on m
 	depends on DVB_USB_V2 && I2C_MUX
@@ -157,14 +157,11 @@
 	  Say Y here to support the Realtek RTL28xxU DVB USB receiver.
 
 config DVB_USB_DVBSKY
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "DVBSky USB support"
 	depends on m
 	depends on DVB_USB_V2
 	select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
-	select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
-	select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
-	select DVB_SP2 if MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y here to support the USB receivers from DVBSky.
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 5541221..badc331 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -193,8 +193,8 @@
 	return af9035_wr_regs(d, reg, &val, 1);
 }
 
-static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
-		u8 addr, void *platform_data, struct i2c_adapter *adapter)
+static int af9035_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
+		void *platform_data, struct i2c_adapter *adapter)
 {
 	int ret, num;
 	struct state *state = d_to_priv(d);
@@ -221,7 +221,7 @@
 		goto err;
 	}
 
-	request_module("%s", board_info.type);
+	request_module(board_info.type);
 
 	/* register I2C device */
 	client = i2c_new_device(adapter, &board_info);
@@ -1171,7 +1171,6 @@
 
 	dev_dbg(&d->udev->dev, "adap->id=%d\n", adap->id);
 
-	memset(&si2168_config, 0, sizeof(si2168_config));
 	si2168_config.i2c_adapter = &adapter;
 	si2168_config.fe = &adap->fe[0];
 	si2168_config.ts_mode = SI2168_TS_SERIAL;
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index fd5d0e6..8c5ec72 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -630,8 +630,8 @@
 	return ret;
 }
 
-static int anysee_add_i2c_dev(struct dvb_usb_device *d, const char *type,
-		u8 addr, void *platform_data)
+static int anysee_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
+		void *platform_data)
 {
 	int ret, num;
 	struct anysee_state *state = d_to_priv(d);
@@ -659,7 +659,7 @@
 		goto err;
 	}
 
-	request_module("%s", board_info.type);
+	request_module(board_info.type);
 
 	/* register I2C device */
 	client = i2c_new_device(adapter, &board_info);
diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c
index bfc85ed..0b41401 100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -21,17 +21,10 @@
 #include "dvb_usb.h"
 #include "m88ds3103.h"
 #include "m88ts2022.h"
-#include "sp2.h"
-#include "si2168.h"
-#include "si2157.h"
 
 #define DVBSKY_MSG_DELAY	0/*2000*/
 #define DVBSKY_BUF_LEN	64
 
-static int dvb_usb_dvbsky_disable_rc;
-module_param_named(disable_rc, dvb_usb_dvbsky_disable_rc, int, 0644);
-MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver.");
-
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 struct dvbsky_state {
@@ -39,9 +32,7 @@
 	u8 ibuf[DVBSKY_BUF_LEN];
 	u8 obuf[DVBSKY_BUF_LEN];
 	u8 last_lock;
-	struct i2c_client *i2c_client_demod;
 	struct i2c_client *i2c_client_tuner;
-	struct i2c_client *i2c_client_ci;
 
 	/* fe hook functions*/
 	int (*fe_set_voltage)(struct dvb_frontend *fe,
@@ -105,7 +96,8 @@
 	obuf[2] = value;
 	ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1);
 	if (ret)
-		dev_err(&d->udev->dev, "failed=%d\n", ret);
+		dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+			KBUILD_MODNAME, __func__, ret);
 	return ret;
 }
 
@@ -122,7 +114,7 @@
 
 	if (num > 2) {
 		dev_err(&d->udev->dev,
-		"too many i2c messages[%d], max 2.", num);
+		"dvbsky_usb: too many i2c messages[%d] than 2.", num);
 		ret = -EOPNOTSUPP;
 		goto i2c_error;
 	}
@@ -130,7 +122,7 @@
 	if (num == 1) {
 		if (msg[0].len > 60) {
 			dev_err(&d->udev->dev,
-			"too many i2c bytes[%d], max 60.",
+			"dvbsky_usb: too many i2c bytes[%d] than 60.",
 			msg[0].len);
 			ret = -EOPNOTSUPP;
 			goto i2c_error;
@@ -144,7 +136,8 @@
 			ret = dvbsky_usb_generic_rw(d, obuf, 4,
 					ibuf, msg[0].len + 1);
 			if (ret)
-				dev_err(&d->udev->dev, "failed=%d\n", ret);
+				dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+					KBUILD_MODNAME, __func__, ret);
 			if (!ret)
 				memcpy(msg[0].buf, &ibuf[1], msg[0].len);
 		} else {
@@ -156,12 +149,13 @@
 			ret = dvbsky_usb_generic_rw(d, obuf,
 					msg[0].len + 3, ibuf, 1);
 			if (ret)
-				dev_err(&d->udev->dev, "failed=%d\n", ret);
+				dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+					KBUILD_MODNAME, __func__, ret);
 		}
 	} else {
 		if ((msg[0].len > 60) || (msg[1].len > 60)) {
 			dev_err(&d->udev->dev,
-			"too many i2c bytes[w-%d][r-%d], max 60.",
+			"dvbsky_usb: too many i2c bytes[w-%d][r-%d] than 60.",
 			msg[0].len, msg[1].len);
 			ret = -EOPNOTSUPP;
 			goto i2c_error;
@@ -175,7 +169,8 @@
 		ret = dvbsky_usb_generic_rw(d, obuf,
 			msg[0].len + 4, ibuf, msg[1].len + 1);
 		if (ret)
-			dev_err(&d->udev->dev, "failed=%d\n", ret);
+			dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+				KBUILD_MODNAME, __func__, ret);
 
 		if (!ret)
 			memcpy(msg[1].buf, &ibuf[1], msg[1].len);
@@ -206,7 +201,8 @@
 	obuf[0] = 0x10;
 	ret = dvbsky_usb_generic_rw(d, obuf, 1, ibuf, 2);
 	if (ret)
-		dev_err(&d->udev->dev, "failed=%d\n", ret);
+		dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+			KBUILD_MODNAME, __func__, ret);
 	if (ret == 0)
 		code = (ibuf[0] << 8) | ibuf[1];
 	if (code != 0xffff) {
@@ -222,11 +218,6 @@
 
 static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
-	if (dvb_usb_dvbsky_disable_rc) {
-		rc->map_name = NULL;
-		return 0;
-	}
-
 	rc->allowed_protos = RC_BIT_RC5;
 	rc->query          = dvbsky_rc_query;
 	rc->interval       = 300;
@@ -274,6 +265,8 @@
 	if (i2c_transfer(&d->i2c_adap, msg, 2) == 2)
 		memcpy(mac, ibuf, 6);
 
+	dev_info(&d->udev->dev, "dvbsky_usb MAC address=%pM\n", mac);
+
 	return 0;
 }
 
@@ -369,300 +362,6 @@
 	return ret;
 }
 
-static int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe,
-	fe_sec_voltage_t voltage)
-{
-	struct dvb_usb_device *d = fe_to_d(fe);
-	struct dvbsky_state *state = d_to_priv(d);
-	u8 value;
-
-	if (voltage == SEC_VOLTAGE_OFF)
-		value = 0;
-	else
-		value = 1;
-	dvbsky_gpio_ctrl(d, 0x00, value);
-
-	return state->fe_set_voltage(fe, voltage);
-}
-
-static int dvbsky_ci_ctrl(void *priv, u8 read, int addr,
-					u8 data, int *mem)
-{
-	struct dvb_usb_device *d = priv;
-	int ret = 0;
-	u8 command[4], respond[2], command_size, respond_size;
-
-	command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/
-	command[2] = (u8)(addr & 0xff); /*low part of address*/
-	if (read) {
-		command[0] = 0x71;
-		command_size = 3;
-		respond_size = 2;
-	} else {
-		command[0] = 0x70;
-		command[3] = data;
-		command_size = 4;
-		respond_size = 1;
-	}
-	ret = dvbsky_usb_generic_rw(d, command, command_size,
-			respond, respond_size);
-	if (ret)
-		goto err;
-	if (read)
-		*mem = respond[1];
-	return ret;
-err:
-	dev_err(&d->udev->dev, "ci control failed=%d\n", ret);
-	return ret;
-}
-
-static const struct m88ds3103_config dvbsky_s960c_m88ds3103_config = {
-	.i2c_addr = 0x68,
-	.clock = 27000000,
-	.i2c_wr_max = 33,
-	.clock_out = 0,
-	.ts_mode = M88DS3103_TS_CI,
-	.ts_clk = 10000,
-	.ts_clk_pol = 1,
-	.agc = 0x99,
-	.lnb_hv_pol = 0,
-	.lnb_en_pol = 1,
-};
-
-static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvbsky_state *state = adap_to_priv(adap);
-	struct dvb_usb_device *d = adap_to_d(adap);
-	int ret = 0;
-	/* demod I2C adapter */
-	struct i2c_adapter *i2c_adapter;
-	struct i2c_client *client_tuner, *client_ci;
-	struct i2c_board_info info;
-	struct sp2_config sp2_config;
-	struct m88ts2022_config m88ts2022_config = {
-			.clock = 27000000,
-		};
-	memset(&info, 0, sizeof(struct i2c_board_info));
-
-	/* attach demod */
-	adap->fe[0] = dvb_attach(m88ds3103_attach,
-			&dvbsky_s960c_m88ds3103_config,
-			&d->i2c_adap,
-			&i2c_adapter);
-	if (!adap->fe[0]) {
-		dev_err(&d->udev->dev, "dvbsky_s960ci_attach fail.\n");
-		ret = -ENODEV;
-		goto fail_attach;
-	}
-
-	/* attach tuner */
-	m88ts2022_config.fe = adap->fe[0];
-	strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
-	info.addr = 0x60;
-	info.platform_data = &m88ts2022_config;
-	request_module("m88ts2022");
-	client_tuner = i2c_new_device(i2c_adapter, &info);
-	if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
-		ret = -ENODEV;
-		goto fail_tuner_device;
-	}
-
-	if (!try_module_get(client_tuner->dev.driver->owner)) {
-		ret = -ENODEV;
-		goto fail_tuner_module;
-	}
-
-	/* attach ci controller */
-	memset(&sp2_config, 0, sizeof(sp2_config));
-	sp2_config.dvb_adap = &adap->dvb_adap;
-	sp2_config.priv = d;
-	sp2_config.ci_control = dvbsky_ci_ctrl;
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	strlcpy(info.type, "sp2", I2C_NAME_SIZE);
-	info.addr = 0x40;
-	info.platform_data = &sp2_config;
-	request_module("sp2");
-	client_ci = i2c_new_device(&d->i2c_adap, &info);
-	if (client_ci == NULL || client_ci->dev.driver == NULL) {
-		ret = -ENODEV;
-		goto fail_ci_device;
-	}
-
-	if (!try_module_get(client_ci->dev.driver->owner)) {
-		ret = -ENODEV;
-		goto fail_ci_module;
-	}
-
-	/* delegate signal strength measurement to tuner */
-	adap->fe[0]->ops.read_signal_strength =
-			adap->fe[0]->ops.tuner_ops.get_rf_strength;
-
-	/* hook fe: need to resync the slave fifo when signal locks. */
-	state->fe_read_status = adap->fe[0]->ops.read_status;
-	adap->fe[0]->ops.read_status = dvbsky_usb_read_status;
-
-	/* hook fe: LNB off/on is control by Cypress usb chip. */
-	state->fe_set_voltage = adap->fe[0]->ops.set_voltage;
-	adap->fe[0]->ops.set_voltage = dvbsky_usb_ci_set_voltage;
-
-	state->i2c_client_tuner = client_tuner;
-	state->i2c_client_ci = client_ci;
-	return ret;
-fail_ci_module:
-	i2c_unregister_device(client_ci);
-fail_ci_device:
-	module_put(client_tuner->dev.driver->owner);
-fail_tuner_module:
-	i2c_unregister_device(client_tuner);
-fail_tuner_device:
-	dvb_frontend_detach(adap->fe[0]);
-fail_attach:
-	return ret;
-}
-
-static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvbsky_state *state = adap_to_priv(adap);
-	struct dvb_usb_device *d = adap_to_d(adap);
-	int ret = 0;
-	struct i2c_adapter *i2c_adapter;
-	struct i2c_client *client_demod, *client_tuner, *client_ci;
-	struct i2c_board_info info;
-	struct si2168_config si2168_config;
-	struct si2157_config si2157_config;
-	struct sp2_config sp2_config;
-
-	/* attach demod */
-	memset(&si2168_config, 0, sizeof(si2168_config));
-	si2168_config.i2c_adapter = &i2c_adapter;
-	si2168_config.fe = &adap->fe[0];
-	si2168_config.ts_mode = SI2168_TS_PARALLEL;
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	strlcpy(info.type, "si2168", I2C_NAME_SIZE);
-	info.addr = 0x64;
-	info.platform_data = &si2168_config;
-
-	request_module(info.type);
-	client_demod = i2c_new_device(&d->i2c_adap, &info);
-	if (client_demod == NULL ||
-			client_demod->dev.driver == NULL)
-		goto fail_demod_device;
-	if (!try_module_get(client_demod->dev.driver->owner))
-		goto fail_demod_module;
-
-	/* attach tuner */
-	memset(&si2157_config, 0, sizeof(si2157_config));
-	si2157_config.fe = adap->fe[0];
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	strlcpy(info.type, "si2157", I2C_NAME_SIZE);
-	info.addr = 0x60;
-	info.platform_data = &si2157_config;
-
-	request_module(info.type);
-	client_tuner = i2c_new_device(i2c_adapter, &info);
-	if (client_tuner == NULL ||
-			client_tuner->dev.driver == NULL)
-		goto fail_tuner_device;
-	if (!try_module_get(client_tuner->dev.driver->owner))
-		goto fail_tuner_module;
-
-	/* attach ci controller */
-	memset(&sp2_config, 0, sizeof(sp2_config));
-	sp2_config.dvb_adap = &adap->dvb_adap;
-	sp2_config.priv = d;
-	sp2_config.ci_control = dvbsky_ci_ctrl;
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	strlcpy(info.type, "sp2", I2C_NAME_SIZE);
-	info.addr = 0x40;
-	info.platform_data = &sp2_config;
-
-	request_module(info.type);
-	client_ci = i2c_new_device(&d->i2c_adap, &info);
-
-	if (client_ci == NULL || client_ci->dev.driver == NULL)
-		goto fail_ci_device;
-
-	if (!try_module_get(client_ci->dev.driver->owner))
-		goto fail_ci_module;
-
-	state->i2c_client_demod = client_demod;
-	state->i2c_client_tuner = client_tuner;
-	state->i2c_client_ci = client_ci;
-	return ret;
-fail_ci_module:
-	i2c_unregister_device(client_ci);
-fail_ci_device:
-	module_put(client_tuner->dev.driver->owner);
-fail_tuner_module:
-	i2c_unregister_device(client_tuner);
-fail_tuner_device:
-	module_put(client_demod->dev.driver->owner);
-fail_demod_module:
-	i2c_unregister_device(client_demod);
-fail_demod_device:
-	ret = -ENODEV;
-	return ret;
-}
-
-static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvbsky_state *state = adap_to_priv(adap);
-	struct dvb_usb_device *d = adap_to_d(adap);
-	int ret = 0;
-	struct i2c_adapter *i2c_adapter;
-	struct i2c_client *client_demod, *client_tuner;
-	struct i2c_board_info info;
-	struct si2168_config si2168_config;
-	struct si2157_config si2157_config;
-
-	/* attach demod */
-	memset(&si2168_config, 0, sizeof(si2168_config));
-	si2168_config.i2c_adapter = &i2c_adapter;
-	si2168_config.fe = &adap->fe[0];
-	si2168_config.ts_mode = SI2168_TS_PARALLEL | 0x40;
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	strlcpy(info.type, "si2168", I2C_NAME_SIZE);
-	info.addr = 0x64;
-	info.platform_data = &si2168_config;
-
-	request_module(info.type);
-	client_demod = i2c_new_device(&d->i2c_adap, &info);
-	if (client_demod == NULL ||
-			client_demod->dev.driver == NULL)
-		goto fail_demod_device;
-	if (!try_module_get(client_demod->dev.driver->owner))
-		goto fail_demod_module;
-
-	/* attach tuner */
-	memset(&si2157_config, 0, sizeof(si2157_config));
-	si2157_config.fe = adap->fe[0];
-	memset(&info, 0, sizeof(struct i2c_board_info));
-	strlcpy(info.type, "si2157", I2C_NAME_SIZE);
-	info.addr = 0x60;
-	info.platform_data = &si2157_config;
-
-	request_module(info.type);
-	client_tuner = i2c_new_device(i2c_adapter, &info);
-	if (client_tuner == NULL ||
-			client_tuner->dev.driver == NULL)
-		goto fail_tuner_device;
-	if (!try_module_get(client_tuner->dev.driver->owner))
-		goto fail_tuner_module;
-
-	state->i2c_client_demod = client_demod;
-	state->i2c_client_tuner = client_tuner;
-	return ret;
-fail_tuner_module:
-	i2c_unregister_device(client_tuner);
-fail_tuner_device:
-	module_put(client_demod->dev.driver->owner);
-fail_demod_module:
-	i2c_unregister_device(client_demod);
-fail_demod_device:
-	ret = -ENODEV;
-	return ret;
-}
-
 static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
 {
 	dvbsky_gpio_ctrl(d, 0x04, 1);
@@ -705,18 +404,6 @@
 		module_put(client->dev.driver->owner);
 		i2c_unregister_device(client);
 	}
-	client = state->i2c_client_demod;
-	/* remove I2C demod */
-	if (client) {
-		module_put(client->dev.driver->owner);
-		i2c_unregister_device(client);
-	}
-	client = state->i2c_client_ci;
-	/* remove I2C ci */
-	if (client) {
-		module_put(client->dev.driver->owner);
-		i2c_unregister_device(client);
-	}
 }
 
 /* DVB USB Driver stuff */
@@ -747,104 +434,9 @@
 	}
 };
 
-static struct dvb_usb_device_properties dvbsky_s960c_props = {
-	.driver_name = KBUILD_MODNAME,
-	.owner = THIS_MODULE,
-	.adapter_nr = adapter_nr,
-	.size_of_priv = sizeof(struct dvbsky_state),
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-	.generic_bulk_ctrl_endpoint_response = 0x81,
-	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
-
-	.i2c_algo         = &dvbsky_i2c_algo,
-	.frontend_attach  = dvbsky_s960c_attach,
-	.init             = dvbsky_init,
-	.get_rc_config    = dvbsky_get_rc_config,
-	.streaming_ctrl   = dvbsky_streaming_ctrl,
-	.identify_state	  = dvbsky_identify_state,
-	.exit             = dvbsky_exit,
-	.read_mac_address = dvbsky_read_mac_addr,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
-		}
-	}
-};
-
-static struct dvb_usb_device_properties dvbsky_t680c_props = {
-	.driver_name = KBUILD_MODNAME,
-	.owner = THIS_MODULE,
-	.adapter_nr = adapter_nr,
-	.size_of_priv = sizeof(struct dvbsky_state),
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-	.generic_bulk_ctrl_endpoint_response = 0x81,
-	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
-
-	.i2c_algo         = &dvbsky_i2c_algo,
-	.frontend_attach  = dvbsky_t680c_attach,
-	.init             = dvbsky_init,
-	.get_rc_config    = dvbsky_get_rc_config,
-	.streaming_ctrl   = dvbsky_streaming_ctrl,
-	.identify_state	  = dvbsky_identify_state,
-	.exit             = dvbsky_exit,
-	.read_mac_address = dvbsky_read_mac_addr,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
-		}
-	}
-};
-
-static struct dvb_usb_device_properties dvbsky_t330_props = {
-	.driver_name = KBUILD_MODNAME,
-	.owner = THIS_MODULE,
-	.adapter_nr = adapter_nr,
-	.size_of_priv = sizeof(struct dvbsky_state),
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-	.generic_bulk_ctrl_endpoint_response = 0x81,
-	.generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
-
-	.i2c_algo         = &dvbsky_i2c_algo,
-	.frontend_attach  = dvbsky_t330_attach,
-	.init             = dvbsky_init,
-	.get_rc_config    = dvbsky_get_rc_config,
-	.streaming_ctrl   = dvbsky_streaming_ctrl,
-	.identify_state	  = dvbsky_identify_state,
-	.exit             = dvbsky_exit,
-	.read_mac_address = dvbsky_read_mac_addr,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-			.stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
-		}
-	}
-};
-
 static const struct usb_device_id dvbsky_id_table[] = {
 	{ DVB_USB_DEVICE(0x0572, 0x6831,
 		&dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) },
-	{ DVB_USB_DEVICE(0x0572, 0x960c,
-		&dvbsky_s960c_props, "DVBSky S960CI", RC_MAP_DVBSKY) },
-	{ DVB_USB_DEVICE(0x0572, 0x680c,
-		&dvbsky_t680c_props, "DVBSky T680CI", RC_MAP_DVBSKY) },
-	{ DVB_USB_DEVICE(0x0572, 0x0320,
-		&dvbsky_t330_props, "DVBSky T330", RC_MAP_DVBSKY) },
-	{ DVB_USB_DEVICE(USB_VID_TECHNOTREND,
-		USB_PID_TECHNOTREND_TVSTICK_CT2_4400,
-		&dvbsky_t330_props, "TechnoTrend TVStick CT2-4400",
-		RC_MAP_TT_1500) },
-	{ DVB_USB_DEVICE(USB_VID_TECHNOTREND,
-		USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI,
-		&dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI",
-		RC_MAP_TT_1500) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index 994de53..9f2c545 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -817,22 +817,20 @@
 	case 0x1122:
 		switch (st->dvb_usb_lme2510_firmware) {
 		default:
+			st->dvb_usb_lme2510_firmware = TUNER_S0194;
 		case TUNER_S0194:
 			fw_lme = fw_s0194;
 			ret = request_firmware(&fw, fw_lme, &udev->dev);
 			if (ret == 0) {
-				st->dvb_usb_lme2510_firmware = TUNER_S0194;
 				cold = 0;
 				break;
 			}
-			/* fall through */
+			st->dvb_usb_lme2510_firmware = TUNER_LG;
 		case TUNER_LG:
 			fw_lme = fw_lg;
 			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0) {
-				st->dvb_usb_lme2510_firmware = TUNER_LG;
+			if (ret == 0)
 				break;
-			}
 			st->dvb_usb_lme2510_firmware = TUNER_DEFAULT;
 			break;
 		}
@@ -840,30 +838,26 @@
 	case 0x1120:
 		switch (st->dvb_usb_lme2510_firmware) {
 		default:
+			st->dvb_usb_lme2510_firmware = TUNER_S7395;
 		case TUNER_S7395:
 			fw_lme = fw_c_s7395;
 			ret = request_firmware(&fw, fw_lme, &udev->dev);
 			if (ret == 0) {
-				st->dvb_usb_lme2510_firmware = TUNER_S7395;
 				cold = 0;
 				break;
 			}
-			/* fall through */
+			st->dvb_usb_lme2510_firmware = TUNER_LG;
 		case TUNER_LG:
 			fw_lme = fw_c_lg;
 			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0) {
-				st->dvb_usb_lme2510_firmware = TUNER_LG;
+			if (ret == 0)
 				break;
-			}
-			/* fall through */
+			st->dvb_usb_lme2510_firmware = TUNER_S0194;
 		case TUNER_S0194:
 			fw_lme = fw_c_s0194;
 			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0) {
-				st->dvb_usb_lme2510_firmware = TUNER_S0194;
+			if (ret == 0)
 				break;
-			}
 			st->dvb_usb_lme2510_firmware = TUNER_DEFAULT;
 			cold = 0;
 			break;
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 026a68e..4bdb7ce 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -24,9 +24,6 @@
 
 #include "rtl2830.h"
 #include "rtl2832.h"
-#include "rtl2832_sdr.h"
-#include "mn88472.h"
-#include "mn88473.h"
 
 #include "qt1010.h"
 #include "mt2060.h"
@@ -38,6 +35,25 @@
 #include "tua9001.h"
 #include "r820t.h"
 
+/*
+ * RTL2832_SDR module is in staging. That logic is added in order to avoid any
+ * hard dependency to drivers/staging/ directory as we want compile mainline
+ * driver even whole staging directory is missing.
+ */
+#include <media/v4l2-subdev.h>
+
+#if IS_ENABLED(CPTCFG_DVB_RTL2832_SDR)
+struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+	struct v4l2_subdev *sd);
+#else
+static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+	struct v4l2_subdev *sd)
+{
+	return NULL;
+}
+#endif
 
 #ifdef CPTCFG_MEDIA_ATTACH
 #define dvb_attach_sdr(FUNCTION, ARGS...) ({ \
@@ -404,8 +420,6 @@
 	struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
 	struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf};
 	struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf};
-	struct rtl28xxu_req req_mn88472 = {0xff38, CMD_I2C_RD, 1, buf};
-	struct rtl28xxu_req req_mn88473 = {0xff38, CMD_I2C_RD, 1, buf};
 
 	dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
@@ -435,7 +449,7 @@
 	if (ret == 0 && buf[0] == 0xa1) {
 		priv->tuner = TUNER_RTL2832_FC0012;
 		priv->tuner_name = "FC0012";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check FC0013 ID register; reg=00 val=a3 */
@@ -443,7 +457,7 @@
 	if (ret == 0 && buf[0] == 0xa3) {
 		priv->tuner = TUNER_RTL2832_FC0013;
 		priv->tuner_name = "FC0013";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check MT2266 ID register; reg=00 val=85 */
@@ -451,7 +465,7 @@
 	if (ret == 0 && buf[0] == 0x85) {
 		priv->tuner = TUNER_RTL2832_MT2266;
 		priv->tuner_name = "MT2266";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check FC2580 ID register; reg=01 val=56 */
@@ -459,7 +473,7 @@
 	if (ret == 0 && buf[0] == 0x56) {
 		priv->tuner = TUNER_RTL2832_FC2580;
 		priv->tuner_name = "FC2580";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check MT2063 ID register; reg=00 val=9e || 9c */
@@ -467,7 +481,7 @@
 	if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
 		priv->tuner = TUNER_RTL2832_MT2063;
 		priv->tuner_name = "MT2063";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check MAX3543 ID register; reg=00 val=38 */
@@ -475,7 +489,7 @@
 	if (ret == 0 && buf[0] == 0x38) {
 		priv->tuner = TUNER_RTL2832_MAX3543;
 		priv->tuner_name = "MAX3543";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check TUA9001 ID register; reg=7e val=2328 */
@@ -483,7 +497,7 @@
 	if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
 		priv->tuner = TUNER_RTL2832_TUA9001;
 		priv->tuner_name = "TUA9001";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check MXL5007R ID register; reg=d9 val=14 */
@@ -491,7 +505,7 @@
 	if (ret == 0 && buf[0] == 0x14) {
 		priv->tuner = TUNER_RTL2832_MXL5007T;
 		priv->tuner_name = "MXL5007T";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check E4000 ID register; reg=02 val=40 */
@@ -499,7 +513,7 @@
 	if (ret == 0 && buf[0] == 0x40) {
 		priv->tuner = TUNER_RTL2832_E4000;
 		priv->tuner_name = "E4000";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check TDA18272 ID register; reg=00 val=c760  */
@@ -507,7 +521,7 @@
 	if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
 		priv->tuner = TUNER_RTL2832_TDA18272;
 		priv->tuner_name = "TDA18272";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check R820T ID register; reg=00 val=69 */
@@ -515,7 +529,7 @@
 	if (ret == 0 && buf[0] == 0x69) {
 		priv->tuner = TUNER_RTL2832_R820T;
 		priv->tuner_name = "R820T";
-		goto tuner_found;
+		goto found;
 	}
 
 	/* check R828D ID register; reg=00 val=69 */
@@ -523,44 +537,13 @@
 	if (ret == 0 && buf[0] == 0x69) {
 		priv->tuner = TUNER_RTL2832_R828D;
 		priv->tuner_name = "R828D";
-		goto tuner_found;
+		goto found;
 	}
 
-tuner_found:
+
+found:
 	dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name);
 
-	/* probe slave demod */
-	if (priv->tuner == TUNER_RTL2832_R828D) {
-		/* power on MN88472 demod on GPIO0 */
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01);
-		if (ret)
-			goto err;
-
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
-		if (ret)
-			goto err;
-
-		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
-		if (ret)
-			goto err;
-
-		/* check MN88472 answers */
-		ret = rtl28xxu_ctrl_msg(d, &req_mn88472);
-		if (ret == 0 && buf[0] == 0x02) {
-			dev_dbg(&d->udev->dev, "%s: MN88472 found\n", __func__);
-			priv->slave_demod = SLAVE_DEMOD_MN88472;
-			goto demod_found;
-		}
-
-		ret = rtl28xxu_ctrl_msg(d, &req_mn88473);
-		if (ret == 0 && buf[0] == 0x03) {
-			dev_dbg(&d->udev->dev, "%s: MN88473 found\n", __func__);
-			priv->slave_demod = SLAVE_DEMOD_MN88473;
-			goto demod_found;
-		}
-	}
-
-demod_found:
 	/* close demod I2C gate */
 	ret = rtl28xxu_ctrl_msg(d, &req_gate_close);
 	if (ret < 0)
@@ -835,66 +818,7 @@
 	/* set fe callback */
 	adap->fe[0]->callback = rtl2832u_frontend_callback;
 
-	if (priv->slave_demod) {
-		struct i2c_board_info info = {};
-		struct i2c_client *client;
-
-		/*
-		 * We continue on reduced mode, without DVB-T2/C, using master
-		 * demod, when slave demod fails.
-		 */
-		ret = 0;
-
-		/* attach slave demodulator */
-		if (priv->slave_demod == SLAVE_DEMOD_MN88472) {
-			struct mn88472_config mn88472_config = {};
-
-			mn88472_config.fe = &adap->fe[1];
-			mn88472_config.i2c_wr_max = 22,
-			strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
-			info.addr = 0x18;
-			info.platform_data = &mn88472_config;
-			request_module(info.type);
-			client = i2c_new_device(priv->demod_i2c_adapter, &info);
-			if (client == NULL || client->dev.driver == NULL) {
-				priv->slave_demod = SLAVE_DEMOD_NONE;
-				goto err_slave_demod_failed;
-			}
-
-			if (!try_module_get(client->dev.driver->owner)) {
-				i2c_unregister_device(client);
-				priv->slave_demod = SLAVE_DEMOD_NONE;
-				goto err_slave_demod_failed;
-			}
-
-			priv->i2c_client_slave_demod = client;
-		} else {
-			struct mn88473_config mn88473_config = {};
-
-			mn88473_config.fe = &adap->fe[1];
-			mn88473_config.i2c_wr_max = 22,
-			strlcpy(info.type, "mn88473", I2C_NAME_SIZE);
-			info.addr = 0x18;
-			info.platform_data = &mn88473_config;
-			request_module(info.type);
-			client = i2c_new_device(priv->demod_i2c_adapter, &info);
-			if (client == NULL || client->dev.driver == NULL) {
-				priv->slave_demod = SLAVE_DEMOD_NONE;
-				goto err_slave_demod_failed;
-			}
-
-			if (!try_module_get(client->dev.driver->owner)) {
-				i2c_unregister_device(client);
-				priv->slave_demod = SLAVE_DEMOD_NONE;
-				goto err_slave_demod_failed;
-			}
-
-			priv->i2c_client_slave_demod = client;
-		}
-	}
-
 	return 0;
-err_slave_demod_failed:
 err:
 	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 	return ret;
@@ -1060,7 +984,7 @@
 				break;
 			}
 
-			priv->i2c_client_tuner = client;
+			priv->client = client;
 			sd = i2c_get_clientdata(client);
 			i2c_set_adapdata(i2c_adap_internal, d);
 
@@ -1100,30 +1024,32 @@
 				&rtl28xxu_rtl2832_r820t_config, NULL);
 		break;
 	case TUNER_RTL2832_R828D:
-		fe = dvb_attach(r820t_attach, adap->fe[0],
-				priv->demod_i2c_adapter,
+		/* power off mn88472 demod on GPIO0 */
+		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x00, 0x01);
+		if (ret)
+			goto err;
+
+		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
+		if (ret)
+			goto err;
+
+		ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
+		if (ret)
+			goto err;
+
+		fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap,
 				&rtl2832u_r828d_config);
+
+		/* Use tuner to get the signal strength */
 		adap->fe[0]->ops.read_signal_strength =
 				adap->fe[0]->ops.tuner_ops.get_rf_strength;
-
-		if (adap->fe[1]) {
-			fe = dvb_attach(r820t_attach, adap->fe[1],
-					priv->demod_i2c_adapter,
-					&rtl2832u_r828d_config);
-			adap->fe[1]->ops.read_signal_strength =
-					adap->fe[1]->ops.tuner_ops.get_rf_strength;
-		}
-
-		/* attach SDR */
-		dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
-				&rtl28xxu_rtl2832_r820t_config, NULL);
 		break;
 	default:
 		dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
 				priv->tuner);
 	}
 
-	if (fe == NULL && priv->i2c_client_tuner == NULL) {
+	if (fe == NULL && priv->client == NULL) {
 		ret = -ENODEV;
 		goto err;
 	}
@@ -1171,19 +1097,11 @@
 static void rtl28xxu_exit(struct dvb_usb_device *d)
 {
 	struct rtl28xxu_priv *priv = d->priv;
-	struct i2c_client *client;
+	struct i2c_client *client = priv->client;
 
 	dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
 	/* remove I2C tuner */
-	client = priv->i2c_client_tuner;
-	if (client) {
-		module_put(client->dev.driver->owner);
-		i2c_unregister_device(client);
-	}
-
-	/* remove I2C slave demod */
-	client = priv->i2c_client_slave_demod;
 	if (client) {
 		module_put(client->dev.driver->owner);
 		i2c_unregister_device(client);
@@ -1283,6 +1201,13 @@
 		if (ret)
 			goto err;
 
+		mdelay(5);
+
+		/* enable ADC */
+		ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x48, 0x48);
+		if (ret)
+			goto err;
+
 		/* streaming EP: clear stall & reset */
 		ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2);
 		if (ret)
@@ -1297,6 +1222,11 @@
 		if (ret)
 			goto err;
 
+		/* disable ADC */
+		ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x48);
+		if (ret)
+			goto err;
+
 		/* disable PLL */
 		ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80);
 		if (ret)
@@ -1314,38 +1244,6 @@
 	return ret;
 }
 
-static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff)
-{
-	struct dvb_usb_device *d = fe_to_d(fe);
-	struct dvb_usb_adapter *adap = fe_to_adap(fe);
-	int ret;
-	u8 val;
-
-	dev_dbg(&d->udev->dev, "%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
-
-	/* control internal demod ADC */
-	if (fe->id == 0 && onoff)
-		val = 0x48; /* enable ADC */
-	else
-		val = 0x00; /* disable ADC */
-
-	ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, val, 0x48);
-	if (ret)
-		goto err;
-
-	/* bypass slave demod TS through master demod */
-	if (fe->id == 1 && onoff) {
-		ret = rtl2832_enable_external_ts_if(adap->fe[0]);
-		if (ret)
-			goto err;
-	}
-
-	return 0;
-err:
-	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
 #if IS_ENABLED(CPTCFG_RC_CORE)
 static int rtl2831u_rc_query(struct dvb_usb_device *d)
 {
@@ -1569,7 +1467,6 @@
 	.size_of_priv = sizeof(struct rtl28xxu_priv),
 
 	.power_ctrl = rtl2832u_power_ctrl,
-	.frontend_ctrl = rtl2832u_frontend_ctrl,
 	.i2c_algo = &rtl28xxu_i2c_algo,
 	.read_config = rtl2832u_read_config,
 	.frontend_attach = rtl2832u_frontend_attach,
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 3e3ea9d..a26cab1 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -57,12 +57,7 @@
 	u8 page; /* integrated demod active register page */
 	struct i2c_adapter *demod_i2c_adapter;
 	bool rc_active;
-	struct i2c_client *i2c_client_tuner;
-	struct i2c_client *i2c_client_slave_demod;
-	#define SLAVE_DEMOD_NONE           0
-	#define SLAVE_DEMOD_MN88472        1
-	#define SLAVE_DEMOD_MN88473        2
-	unsigned int slave_demod:2;
+	struct i2c_client *client;
 };
 
 enum rtl28xxu_chip_id {
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
index 1378eca..25da066 100644
--- a/drivers/media/usb/dvb-usb/Kconfig
+++ b/drivers/media/usb/dvb-usb/Kconfig
@@ -137,6 +137,7 @@
 
 	  Medion MD95700 hybrid USB2.0 device.
 	  DViCO FusionHDTV (Bluebird) USB2.0 devices
+	  TechnoTrend TVStick CT2-4400 and CT2-4650 CI devices
 
 config DVB_USB_M920X
 	tristate "Uli m920x DVB-T USB2.0 support"
diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c
index c0ab8c3..3f4361e 100644
--- a/drivers/media/usb/dvb-usb/af9005.c
+++ b/drivers/media/usb/dvb-usb/af9005.c
@@ -1081,12 +1081,9 @@
 		err("usb_register failed. (%d)", result);
 		return result;
 	}
-#if IS_MODULE(CPTCFG_DVB_USB_AF9005) || defined(CPTCFG_DVB_USB_AF9005_REMOTE)
-	/* FIXME: convert to todays kernel IR infrastructure */
 	rc_decode = symbol_request(af9005_rc_decode);
 	rc_keys = symbol_request(rc_map_af9005_table);
 	rc_keys_size = symbol_request(rc_map_af9005_table_size);
-#endif
 	if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
 		err("af9005_rc_decode function not found, disabling remote");
 		af9005_properties.rc.legacy.rc_query = NULL;
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index 0f345b1..356abb3 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -44,6 +44,7 @@
 #include "atbm8830.h"
 #include "si2168.h"
 #include "si2157.h"
+#include "sp2.h"
 
 /* Max transfer size done by I2C transfer functions */
 #define MAX_XFER_SIZE  80
@@ -146,6 +147,22 @@
 	}
 }
 
+static int cxusb_tt_ct2_4400_gpio_tuner(struct dvb_usb_device *d, int onoff)
+{
+	u8 o[2], i;
+	int rc;
+
+	o[0] = 0x83;
+	o[1] = onoff;
+	rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+
+	if (rc) {
+		deb_info("gpio_write failed.\n");
+		return -EIO;
+	}
+	return 0;
+}
+
 /* I2C */
 static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 			  int num)
@@ -507,6 +524,30 @@
 	return 0;
 }
 
+static int cxusb_tt_ct2_4400_rc_query(struct dvb_usb_device *d)
+{
+	u8 i[2];
+	int ret;
+	u32 cmd, keycode;
+	u8 rc5_cmd, rc5_addr, rc5_toggle;
+
+	ret = cxusb_ctrl_msg(d, 0x10, NULL, 0, i, 2);
+	if (ret)
+		return ret;
+
+	cmd = (i[0] << 8) | i[1];
+
+	if (cmd != 0xffff) {
+		rc5_cmd = cmd & 0x3F; /* bits 1-6 for command */
+		rc5_addr = (cmd & 0x07C0) >> 6; /* bits 7-11 for address */
+		rc5_toggle = (cmd & 0x0800) >> 11; /* bit 12 for toggle */
+		keycode = (rc5_addr << 8) | rc5_cmd;
+		rc_keydown(d->rc_dev, RC_BIT_RC5, keycode, rc5_toggle);
+	}
+
+	return 0;
+}
+
 static struct rc_map_table rc_map_dvico_mce_table[] = {
 	{ 0xfe02, KEY_TV },
 	{ 0xfe0e, KEY_MP3 },
@@ -632,6 +673,70 @@
 	{ 0x0025, KEY_POWER },
 };
 
+static int cxusb_tt_ct2_4400_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+	u8 wbuf[2];
+	u8 rbuf[6];
+	int ret;
+	struct i2c_msg msg[] = {
+		{
+			.addr = 0x51,
+			.flags = 0,
+			.buf = wbuf,
+			.len = 2,
+		}, {
+			.addr = 0x51,
+			.flags = I2C_M_RD,
+			.buf = rbuf,
+			.len = 6,
+		}
+	};
+
+	wbuf[0] = 0x1e;
+	wbuf[1] = 0x00;
+	ret = cxusb_i2c_xfer(&d->i2c_adap, msg, 2);
+
+	if (ret == 2) {
+		memcpy(mac, rbuf, 6);
+		return 0;
+	} else {
+		if (ret < 0)
+			return ret;
+		return -EIO;
+	}
+}
+
+static int cxusb_tt_ct2_4650_ci_ctrl(void *priv, u8 read, int addr,
+					u8 data, int *mem)
+{
+	struct dvb_usb_device *d = priv;
+	u8 wbuf[3];
+	u8 rbuf[2];
+	int ret;
+
+	wbuf[0] = (addr >> 8) & 0xff;
+	wbuf[1] = addr & 0xff;
+
+	if (read) {
+		ret = cxusb_ctrl_msg(d, CMD_SP2_CI_READ, wbuf, 2, rbuf, 2);
+	} else {
+		wbuf[2] = data;
+		ret = cxusb_ctrl_msg(d, CMD_SP2_CI_WRITE, wbuf, 3, rbuf, 1);
+	}
+
+	if (ret)
+		goto err;
+
+	if (read)
+		*mem = rbuf[1];
+
+	return 0;
+err:
+	deb_info("%s: ci usb write returned %d\n", __func__, ret);
+	return ret;
+
+}
+
 static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
 {
 	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x28 };
@@ -1303,34 +1408,36 @@
 	return 0;
 }
 
-static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap)
+static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap)
 {
 	struct dvb_usb_device *d = adap->dev;
 	struct cxusb_state *st = d->priv;
 	struct i2c_adapter *adapter;
 	struct i2c_client *client_demod;
 	struct i2c_client *client_tuner;
+	struct i2c_client *client_ci;
 	struct i2c_board_info info;
 	struct si2168_config si2168_config;
 	struct si2157_config si2157_config;
+	struct sp2_config sp2_config;
+	u8 o[2], i;
 
-	/* Select required USB configuration */
-	if (usb_set_interface(d->udev, 0, 0) < 0)
-		err("set interface failed");
-
-	/* Unblock all USB pipes */
-	usb_clear_halt(d->udev,
-		usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
+	/* reset the tuner */
+	if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) {
+		err("clear tuner gpio failed");
+		return -EIO;
+	}
+	msleep(100);
+	if (cxusb_tt_ct2_4400_gpio_tuner(d, 1) < 0) {
+		err("set tuner gpio failed");
+		return -EIO;
+	}
+	msleep(100);
 
 	/* attach frontend */
 	si2168_config.i2c_adapter = &adapter;
 	si2168_config.fe = &adap->fe_adap[0].fe;
 	si2168_config.ts_mode = SI2168_TS_PARALLEL;
-	si2168_config.ts_clock_inv = 1;
 	memset(&info, 0, sizeof(struct i2c_board_info));
 	strlcpy(info.type, "si2168", I2C_NAME_SIZE);
 	info.addr = 0x64;
@@ -1370,6 +1477,48 @@
 
 	st->i2c_client_tuner = client_tuner;
 
+	/* initialize CI */
+	if (d->udev->descriptor.idProduct ==
+		USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI) {
+
+		memcpy(o, "\xc0\x01", 2);
+		cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+		msleep(100);
+
+		memcpy(o, "\xc0\x00", 2);
+		cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+		msleep(100);
+
+		memset(&sp2_config, 0, sizeof(sp2_config));
+		sp2_config.dvb_adap = &adap->dvb_adap;
+		sp2_config.priv = d;
+		sp2_config.ci_control = cxusb_tt_ct2_4650_ci_ctrl;
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, "sp2", I2C_NAME_SIZE);
+		info.addr = 0x40;
+		info.platform_data = &sp2_config;
+		request_module(info.type);
+		client_ci = i2c_new_device(&d->i2c_adap, &info);
+		if (client_ci == NULL || client_ci->dev.driver == NULL) {
+			module_put(client_tuner->dev.driver->owner);
+			i2c_unregister_device(client_tuner);
+			module_put(client_demod->dev.driver->owner);
+			i2c_unregister_device(client_demod);
+			return -ENODEV;
+		}
+		if (!try_module_get(client_ci->dev.driver->owner)) {
+			i2c_unregister_device(client_ci);
+			module_put(client_tuner->dev.driver->owner);
+			i2c_unregister_device(client_tuner);
+			module_put(client_demod->dev.driver->owner);
+			i2c_unregister_device(client_demod);
+			return -ENODEV;
+		}
+
+		st->i2c_client_ci = client_ci;
+
+	}
+
 	return 0;
 }
 
@@ -1454,7 +1603,7 @@
 static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
 static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
 static struct dvb_usb_device_properties cxusb_mygica_d689_properties;
-static struct dvb_usb_device_properties cxusb_mygica_t230_properties;
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties;
 
 static int cxusb_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
@@ -1485,7 +1634,7 @@
 				     THIS_MODULE, NULL, adapter_nr) ||
 	    0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
 				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties,
+	    0 == dvb_usb_device_init(intf, &cxusb_tt_ct2_4400_properties,
 				     THIS_MODULE, NULL, adapter_nr) ||
 	    0)
 		return 0;
@@ -1499,6 +1648,13 @@
 	struct cxusb_state *st = d->priv;
 	struct i2c_client *client;
 
+	/* remove I2C client for CI */
+	client = st->i2c_client_ci;
+	if (client) {
+		module_put(client->dev.driver->owner);
+		i2c_unregister_device(client);
+	}
+
 	/* remove I2C client for tuner */
 	client = st->i2c_client_tuner;
 	if (client) {
@@ -1537,7 +1693,8 @@
 	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
 	{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
 	{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) },
-	{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230) },
+	{ USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) },
+	{ USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI) },
 	{}		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -2184,7 +2341,7 @@
 	}
 };
 
-static struct dvb_usb_device_properties cxusb_mygica_t230_properties = {
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl         = CYPRESS_FX2,
@@ -2192,21 +2349,25 @@
 	.size_of_priv     = sizeof(struct cxusb_state),
 
 	.num_adapters = 1,
+	.read_mac_address = cxusb_tt_ct2_4400_read_mac_address,
+
 	.adapter = {
 		{
 		.num_frontends = 1,
 		.fe = {{
 			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_mygica_t230_frontend_attach,
+			/* both frontend and tuner attached in the
+			   same function */
+			.frontend_attach  = cxusb_tt_ct2_4400_attach,
 
 			/* parameter for the MPEG2-data transfer */
 			.stream = {
 				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
+				.count = 8,
+				.endpoint = 0x82,
 				.u = {
 					.bulk = {
-						.buffersize = 8192,
+						.buffersize = 4096,
 					}
 				}
 			},
@@ -2214,25 +2375,28 @@
 		},
 	},
 
-	.power_ctrl       = cxusb_d680_dmb_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
+	.i2c_algo = &cxusb_i2c_algo,
 	.generic_bulk_ctrl_endpoint = 0x01,
+	.generic_bulk_ctrl_endpoint_response = 0x81,
 
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_d680_dmb_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_d680_dmb_table),
-		.rc_query         = cxusb_d680_dmb_rc_query,
+	.rc.core = {
+		.rc_codes       = RC_MAP_TT_1500,
+		.allowed_protos = RC_BIT_RC5,
+		.rc_query       = cxusb_tt_ct2_4400_rc_query,
+		.rc_interval    = 150,
 	},
 
-	.num_device_descs = 1,
+	.num_device_descs = 2,
 	.devices = {
 		{
-			"Mygica T230 DVB-T/T2/C",
+			"TechnoTrend TVStick CT2-4400",
 			{ NULL },
-			{ &cxusb_table[22], NULL },
+			{ &cxusb_table[20], NULL },
+		},
+		{
+			"TechnoTrend TT-connect CT2-4650 CI",
+			{ NULL },
+			{ &cxusb_table[21], NULL },
 		},
 	}
 };
diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h
index 527ff79..29f3e2e 100644
--- a/drivers/media/usb/dvb-usb/cxusb.h
+++ b/drivers/media/usb/dvb-usb/cxusb.h
@@ -28,10 +28,14 @@
 #define CMD_ANALOG        0x50
 #define CMD_DIGITAL       0x51
 
+#define CMD_SP2_CI_WRITE  0x70
+#define CMD_SP2_CI_READ   0x71
+
 struct cxusb_state {
 	u8 gpio_write_state[3];
 	struct i2c_client *i2c_client_demod;
 	struct i2c_client *i2c_client_tuner;
+	struct i2c_client *i2c_client_ci;
 };
 
 #endif
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c
index 5801ae7..6b0b8b6 100644
--- a/drivers/media/usb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/usb/dvb-usb/technisat-usb2.c
@@ -449,8 +449,6 @@
 	return 0;
 }
 
-static struct stv090x_config technisat_usb2_stv090x_config;
-
 /* frontend attach */
 static int technisat_usb2_set_voltage(struct dvb_frontend *fe,
 		fe_sec_voltage_t voltage)
@@ -474,8 +472,7 @@
 	}
 
 	for (i = 0; i < 3; i++)
-		if (technisat_usb2_stv090x_config.set_gpio(fe, i+2, 0,
-							   gpio[i], 0) != 0)
+		if (stv090x_set_gpio(fe, i+2, 0, gpio[i], 0) != 0)
 			return -EREMOTEIO;
 	return 0;
 }
diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig
index 82fbf57..ddec55a 100644
--- a/drivers/media/usb/em28xx/Kconfig
+++ b/drivers/media/usb/em28xx/Kconfig
@@ -38,7 +38,7 @@
 	  module will be called em28xx-alsa
 
 config VIDEO_EM28XX_DVB
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "DVB/ATSC Support for em28xx based TV cards"
 	depends on m
 	depends on VIDEO_EM28XX && DVB_CORE
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
index 44ae1e0..957c7ae 100644
--- a/drivers/media/usb/em28xx/em28xx-audio.c
+++ b/drivers/media/usb/em28xx/em28xx-audio.c
@@ -56,7 +56,7 @@
 #define dprintk(fmt, arg...) do {					\
 	    if (debug)							\
 		printk(KERN_INFO "em28xx-audio %s: " fmt,		\
-				  __func__, ##arg);		\
+				  __func__, ##arg); 		\
 	} while (0)
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
@@ -232,6 +232,7 @@
 	.channels_max = 2,
 	.buffer_bytes_max = 62720 * 8,	/* just about the value in usbaudio.c */
 
+
 	/*
 	 * The period is 12.288 bytes. Allow a 10% of variation along its
 	 * value, in order to avoid overruns/underruns due to some clock
@@ -360,7 +361,7 @@
 	dprintk("Setting capture parameters\n");
 
 	ret = snd_pcm_alloc_vmalloc_buffer(substream,
-					   params_buffer_bytes(hw_params));
+				params_buffer_bytes(hw_params));
 	if (ret < 0)
 		return ret;
 #if 0
@@ -477,7 +478,7 @@
  * AC97 volume control support
  */
 static int em28xx_vol_info(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_info *info)
+				struct snd_ctl_elem_info *info)
 {
 	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
 
@@ -493,7 +494,7 @@
 }
 
 static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
-			  struct snd_ctl_elem_value *value)
+			       struct snd_ctl_elem_value *value)
 {
 	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
 	struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
@@ -533,7 +534,7 @@
 }
 
 static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
-			  struct snd_ctl_elem_value *value)
+			       struct snd_ctl_elem_value *value)
 {
 	struct em28xx *dev = snd_kcontrol_chip(kcontrol);
 	struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
@@ -654,7 +655,7 @@
 	struct snd_kcontrol *kctl;
 	struct snd_kcontrol_new tmp;
 
-	memset(&tmp, 0, sizeof(tmp));
+	memset (&tmp, 0, sizeof(tmp));
 	tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	tmp.private_value = id,
 	tmp.name  = ctl_name,
@@ -671,7 +672,7 @@
 	dprintk("Added control %s for ac97 volume control 0x%04x\n",
 		ctl_name, id);
 
-	memset(&tmp, 0, sizeof(tmp));
+	memset (&tmp, 0, sizeof(tmp));
 	tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	tmp.private_value = id,
 	tmp.name  = ctl_name,
@@ -730,7 +731,7 @@
 
 /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
 static int em28xx_audio_ep_packet_size(struct usb_device *udev,
-				       struct usb_endpoint_descriptor *e)
+					struct usb_endpoint_descriptor *e)
 {
 	int size = le16_to_cpu(e->wMaxPacketSize);
 
@@ -780,7 +781,7 @@
 	interval = 1 << (ep->bInterval - 1);
 
 	em28xx_info("Endpoint 0x%02x %s on intf %d alt %d interval = %d, size %d\n",
-		    EM28XX_EP_AUDIO, usb_speed_string(dev->udev->speed),
+		     EM28XX_EP_AUDIO, usb_speed_string(dev->udev->speed),
 		     dev->ifnum, alt,
 		     interval,
 		     ep_size);
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
index 7be661f..6d2ea9a 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -27,6 +27,7 @@
 
 #include "em28xx.h"
 
+
 /* Possible i2c addresses of Micron sensors */
 static unsigned short micron_sensor_addrs[] = {
 	0xb8 >> 1,   /* MT9V111, MT9V403 */
@@ -42,6 +43,7 @@
 	I2C_CLIENT_END
 };
 
+
 static struct soc_camera_link camlink = {
 	.bus_id = 0,
 	.flags = 0,
@@ -49,6 +51,7 @@
 	.unbalanced_power = true,
 };
 
+
 /* FIXME: Should be replaced by a proper mt9m111 driver */
 static int em28xx_initialize_mt9m111(struct em28xx *dev)
 {
@@ -67,6 +70,7 @@
 	return 0;
 }
 
+
 /* FIXME: Should be replaced by a proper mt9m001 driver */
 static int em28xx_initialize_mt9m001(struct em28xx *dev)
 {
@@ -94,6 +98,7 @@
 	return 0;
 }
 
+
 /*
  * Probes Micron sensors with 8 bit address and 16 bit register width
  */
@@ -425,7 +430,7 @@
 			break;
 		}
 
-		fmt.code = MEDIA_BUS_FMT_YUYV8_2X8;
+		fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
 		fmt.width = 640;
 		fmt.height = 480;
 		v4l2_subdev_call(subdev, video, s_mbus_fmt, &fmt);
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index d9704e6..71fa51e 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -64,6 +64,7 @@
 MODULE_PARM_DESC(usb_xfer_mode,
 		 "USB transfer mode for frame data (-1 = auto, 0 = prefer isoc, 1 = prefer bulk)");
 
+
 /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
 static DECLARE_BITMAP(em28xx_devused, EM28XX_MAXBOARDS);
 
@@ -189,8 +190,8 @@
 };
 
 static struct em28xx_reg_seq kworld_ub435q_v3_digital[] = {
-	{EM2874_R80_GPIO_P0_CTRL,	0xff,	0xff,	100},
-	{EM2874_R80_GPIO_P0_CTRL,	0xfe,	0xff,	100},
+	{EM2874_R80_GPIO_P0_CTRL,	0xff, 	0xff,	100},
+	{EM2874_R80_GPIO_P0_CTRL,	0xfe, 	0xff,	100},
 	{EM2874_R80_GPIO_P0_CTRL,	0xbe,	0xff,	100},
 	{EM2874_R80_GPIO_P0_CTRL,	0xfe,	0xff,	100},
 	{	-1,			-1,	-1,	-1},
@@ -300,6 +301,7 @@
 	{	-1,		-1,	-1,		-1},
 };
 
+
 /* Reset for the most [digital] boards */
 static struct em28xx_reg_seq leadership_digital[] = {
 	{EM2874_R80_GPIO_P0_CTRL,	0x70,	0xff,	10},
@@ -477,20 +479,6 @@
 	{-1,                             -1,   -1,     -1},
 };
 
-static struct em28xx_reg_seq terratec_t2_stick_hd[] = {
-	{EM2874_R80_GPIO_P0_CTRL,	0xff,	0xff,	0},
-	{0x0d,				0xff,	0xff,	600},
-	{EM2874_R80_GPIO_P0_CTRL,	0xfc,	0xff,	10},
-	{EM2874_R80_GPIO_P0_CTRL,	0xbc,	0xff,	100},
-	{EM2874_R80_GPIO_P0_CTRL,	0xfc,	0xff,	100},
-	{EM2874_R80_GPIO_P0_CTRL,	0x00,	0xff,	300},
-	{EM2874_R80_GPIO_P0_CTRL,	0xf8,	0xff,	100},
-	{EM2874_R80_GPIO_P0_CTRL,	0xfc,	0xff,	300},
-	{0x0d,				0x42,	0xff,	1000},
-	{EM2874_R5F_TS_ENABLE,		0x85,	0xff,	0},
-	{-1,                             -1,   -1,     -1},
-};
-
 /*
  *  Button definitions
  */
@@ -560,6 +548,7 @@
 	{-1, 0, 0, 0},
 };
 
+
 /*
  *  Board definitions
  */
@@ -1525,7 +1514,7 @@
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = SAA7115_COMPOSITE2,
 			.amux     = EM28XX_AMUX_VIDEO,
-			.aout     = EM28XX_AOUT_MONO |	/* I2S */
+			.aout     = EM28XX_AOUT_MONO | 	/* I2S */
 				    EM28XX_AOUT_MASTER,	/* Line out pin */
 		}, {
 			.type     = EM28XX_VMUX_COMPOSITE1,
@@ -1547,7 +1536,7 @@
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = SAA7115_COMPOSITE2,
 			.amux     = EM28XX_AMUX_VIDEO,
-			.aout     = EM28XX_AOUT_MONO |	/* I2S */
+			.aout     = EM28XX_AOUT_MONO | 	/* I2S */
 				    EM28XX_AOUT_MASTER,	/* Line out pin */
 		}, {
 			.type     = EM28XX_VMUX_COMPOSITE1,
@@ -2254,31 +2243,6 @@
 		.has_dvb       = 1,
 		.ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
 	},
-	[EM2861_BOARD_LEADTEK_VC100] = {
-		.name          = "Leadtek VC100",
-		.tuner_type    = TUNER_ABSENT,	/* Capture only device */
-		.decoder       = EM28XX_TVP5150,
-		.input         = { {
-			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = TVP5150_COMPOSITE1,
-			.amux     = EM28XX_AMUX_LINE_IN,
-		}, {
-			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = TVP5150_SVIDEO,
-			.amux     = EM28XX_AMUX_LINE_IN,
-		} },
-	},
-	/* eb1a:8179 Terratec Cinergy T2 Stick HD.
-	 * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2146 */
-	[EM28178_BOARD_TERRATEC_T2_STICK_HD] = {
-		.name          = "Terratec Cinergy T2 Stick HD",
-		.def_i2c_bus   = 1,
-		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
-		.tuner_type    = TUNER_ABSENT,
-		.tuner_gpio    = terratec_t2_stick_hd,
-		.has_dvb       = 1,
-		.ir_codes      = RC_MAP_TERRATEC_SLIM_2,
-	},
 };
 EXPORT_SYMBOL_GPL(em28xx_boards);
 
@@ -2460,10 +2424,6 @@
 			.driver_info = EM28178_BOARD_PCTV_461E },
 	{ USB_DEVICE(0x2013, 0x025f),
 			.driver_info = EM28178_BOARD_PCTV_292E },
-	{ USB_DEVICE(0x0413, 0x6f07),
-			.driver_info = EM2861_BOARD_LEADTEK_VC100 },
-	{ USB_DEVICE(0xeb1a, 0x8179),
-			.driver_info = EM28178_BOARD_TERRATEC_T2_STICK_HD },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2493,7 +2453,6 @@
 	{0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
 	{0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT},
 };
-
 /* NOTE: introduce a separate hash table for devices with 16 bit eeproms */
 
 int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
@@ -2736,7 +2695,7 @@
 		      " insmod option:\n");
 	for (i = 0; i < em28xx_bcount; i++) {
 		em28xx_errdev("    card=%d -> %s\n",
-			      i, em28xx_boards[i].name);
+				i, em28xx_boards[i].name);
 	}
 	return -1;
 }
@@ -3092,7 +3051,6 @@
 			if (le16_to_cpu(dev->udev->descriptor.idVendor)
 								    == 0xeb1a) {
 				__le16 idProd = dev->udev->descriptor.idProduct;
-
 				if (le16_to_cpu(idProd) == 0x2710)
 					chip_name = "em2710";
 				else if (le16_to_cpu(idProd) == 0x2820)
@@ -3181,7 +3139,7 @@
 		retval = em28xx_i2c_register(dev, 0, EM28XX_I2C_ALGO_EM28XX);
 	if (retval < 0) {
 		em28xx_errdev("%s: em28xx_i2c_register bus 0 - error [%d]!\n",
-			      __func__, retval);
+			__func__, retval);
 		return retval;
 	}
 
@@ -3189,13 +3147,13 @@
 	if (dev->def_i2c_bus) {
 		if (dev->is_em25xx)
 			retval = em28xx_i2c_register(dev, 1,
-						     EM28XX_I2C_ALGO_EM25XX_BUS_B);
+						  EM28XX_I2C_ALGO_EM25XX_BUS_B);
 		else
 			retval = em28xx_i2c_register(dev, 1,
-						     EM28XX_I2C_ALGO_EM28XX);
+							EM28XX_I2C_ALGO_EM28XX);
 		if (retval < 0) {
 			em28xx_errdev("%s: em28xx_i2c_register bus 1 - error [%d]!\n",
-				      __func__, retval);
+				__func__, retval);
 
 			em28xx_i2c_unregister(dev, 0);
 
@@ -3235,7 +3193,7 @@
 		if (nr >= EM28XX_MAXBOARDS) {
 			/* No free device slots */
 			printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
-			       EM28XX_MAXBOARDS);
+					EM28XX_MAXBOARDS);
 			retval = -ENOMEM;
 			goto err_no_slot;
 		}
@@ -3419,7 +3377,6 @@
 	/* Checks if audio is provided by a USB Audio Class interface */
 	for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
 		struct usb_interface *uif = udev->config->interface[i];
-
 		if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
 			if (has_vendor_audio)
 				em28xx_err("em28xx: device seems to have vendor AND usb audio class interfaces !\n"
@@ -3530,7 +3487,7 @@
 }
 
 static int em28xx_usb_suspend(struct usb_interface *interface,
-			      pm_message_t message)
+				pm_message_t message)
 {
 	struct em28xx *dev;
 
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index 86461a7..b5e52fe 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -75,7 +75,7 @@
  * reads data from the usb device specifying bRequest
  */
 int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
-			    char *buf, int len)
+				   char *buf, int len)
 {
 	int ret;
 	int pipe = usb_rcvctrlpipe(dev->udev, 0);
@@ -151,7 +151,7 @@
  * sends data to the usb device, specifying bRequest
  */
 int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
-			  int len)
+				 int len)
 {
 	int ret;
 	int pipe = usb_sndctrlpipe(dev->udev, 0);
@@ -213,7 +213,7 @@
  * the actual value
  */
 int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
-			  u8 bitmask)
+				 u8 bitmask)
 {
 	int oldval;
 	u8 newval;
@@ -222,7 +222,7 @@
 	if (oldval < 0)
 		return oldval;
 
-	newval = (((u8)oldval) & ~bitmask) | (val & bitmask);
+	newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
 
 	return em28xx_write_regs(dev, reg, &newval, 1);
 }
@@ -314,7 +314,7 @@
 	if (ret < 0)
 		return ret;
 
-	ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *)&value, 2);
+	ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *) &value, 2);
 	if (ret < 0)
 		return ret;
 
@@ -361,7 +361,7 @@
 
 		if (ret < 0)
 			em28xx_warn("couldn't setup AC97 register %d\n",
-				    inputs[i].reg);
+				     inputs[i].reg);
 	}
 	return 0;
 }
@@ -445,7 +445,7 @@
 			ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000);
 			if (ret < 0)
 				em28xx_warn("couldn't setup AC97 register %d\n",
-					    outputs[i].reg);
+				     outputs[i].reg);
 		}
 	}
 
@@ -483,7 +483,7 @@
 							vol);
 			if (ret < 0)
 				em28xx_warn("couldn't setup AC97 register %d\n",
-					    outputs[i].reg);
+				     outputs[i].reg);
 		}
 
 		if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
@@ -504,7 +504,7 @@
 int em28xx_audio_setup(struct em28xx *dev)
 {
 	int vid1, vid2, feat, cfg;
-	u32 vid = 0;
+	u32 vid;
 	u8 i2s_samplerates;
 
 	if (dev->chip_id == CHIP_ID_EM2870 ||
@@ -531,7 +531,7 @@
 	} else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) != EM28XX_CHIPCFG_AC97) {
 		dev->int_audio_type = EM28XX_INT_AUDIO_I2S;
 		if (dev->chip_id < CHIP_ID_EM2860 &&
-		    (cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
+	            (cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
 		    EM2820_CHIPCFG_I2S_1_SAMPRATE)
 			i2s_samplerates = 1;
 		else if (dev->chip_id >= CHIP_ID_EM2860 &&
@@ -541,7 +541,7 @@
 		else
 			i2s_samplerates = 3;
 		em28xx_info("I2S Audio (%d sample rate(s))\n",
-			    i2s_samplerates);
+					       i2s_samplerates);
 		/* Skip the code that does AC97 vendor detection */
 		dev->audio_mode.ac97 = EM28XX_NO_AC97;
 		goto init_audio;
@@ -614,9 +614,8 @@
 {
 	if (dev->board.leds) {
 		u8 k = 0;
-
 		while (dev->board.leds[k].role >= 0 &&
-		       dev->board.leds[k].role < EM28XX_NUM_LED_ROLES) {
+			       dev->board.leds[k].role < EM28XX_NUM_LED_ROLES) {
 			if (dev->board.leds[k].role == role)
 				return &dev->board.leds[k];
 			k++;
@@ -659,12 +658,10 @@
 
 			if (dev->mode == EM28XX_ANALOG_MODE)
 				rc = em28xx_write_reg(dev,
-						      EM28XX_R12_VINENABLE,
-						      0x67);
+						    EM28XX_R12_VINENABLE, 0x67);
 			else
 				rc = em28xx_write_reg(dev,
-						      EM28XX_R12_VINENABLE,
-						      0x37);
+						    EM28XX_R12_VINENABLE, 0x37);
 			if (rc < 0)
 				return rc;
 
@@ -818,9 +815,9 @@
 
 			if (usb_bufs->transfer_buffer[i]) {
 				usb_free_coherent(dev->udev,
-						  urb->transfer_buffer_length,
-						  usb_bufs->transfer_buffer[i],
-						  urb->transfer_dma);
+					urb->transfer_buffer_length,
+					usb_bufs->transfer_buffer[i],
+					urb->transfer_dma);
 			}
 			usb_free_urb(urb);
 			usb_bufs->urb[i] = NULL;
@@ -892,7 +889,7 @@
 		if ((xfer_bulk && !dev->analog_ep_bulk) ||
 		    (!xfer_bulk && !dev->analog_ep_isoc)) {
 			em28xx_errdev("no endpoint for analog mode and transfer type %d\n",
-				      xfer_bulk > 0);
+				       xfer_bulk > 0);
 			return -EINVAL;
 		}
 		usb_bufs = &dev->usb_ctl.analog_bufs;
@@ -991,9 +988,9 @@
  * Allocate URBs and start IRQ
  */
 int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode,
-			 int xfer_bulk, int num_bufs, int max_pkt_size,
+		    int xfer_bulk, int num_bufs, int max_pkt_size,
 		    int packet_multiplier,
-		    int (*urb_data_copy)(struct em28xx *dev, struct urb *urb))
+		    int (*urb_data_copy) (struct em28xx *dev, struct urb *urb))
 {
 	struct em28xx_dmaqueue *dma_q = &dev->vidq;
 	struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 9877b69..9682c52 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -63,6 +63,7 @@
 MODULE_DESCRIPTION(DRIVER_DESC " - digital TV interface");
 MODULE_VERSION(EM28XX_VERSION);
 
+
 static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
@@ -70,7 +71,7 @@
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 #define dprintk(level, fmt, arg...) do {			\
-if (debug >= level)						\
+if (debug >= level) 						\
 	printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg);	\
 } while (0)
 
@@ -98,8 +99,9 @@
 	struct i2c_client	*i2c_client_tuner;
 };
 
+
 static inline void print_err_status(struct em28xx *dev,
-				    int packet, int status)
+				     int packet, int status)
 {
 	char *errmsg = "Unknown";
 
@@ -167,7 +169,7 @@
 			if (!urb->actual_length)
 				continue;
 			dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
-					 urb->actual_length);
+					urb->actual_length);
 		} else {
 			if (urb->iso_frame_desc[i].status < 0) {
 				print_err_status(dev, i,
@@ -278,6 +280,7 @@
 }
 
 
+
 /* ------------------------------------------------------------------ */
 static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
 {
@@ -737,7 +740,7 @@
 	return ret;
 #else
 	dev_warn(&dev->udev->dev, "%s: LNA control is disabled (lna=%u)\n",
-		 KBUILD_MODNAME, c->lna);
+			KBUILD_MODNAME, c->lna);
 	return 0;
 #endif
 }
@@ -827,7 +830,6 @@
 	.no_tuner = 1,
 	.parallel_ts = 1,
 };
-
 static struct qt1010_config em28xx_qt1010_config = {
 	.i2c_address = 0x62
 };
@@ -859,6 +861,7 @@
 	.agc = 0x99,
 };
 
+
 static struct tda18271_std_map drx_j_std_map = {
 	.atsc_6   = { .if_freq = 5000, .agc_mode = 3, .std = 0, .if_lvl = 1,
 		      .rfagc_top = 0x37, },
@@ -945,7 +948,7 @@
 		result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]);
 		if (result < 0) {
 			printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n",
-			       dev->name, result);
+				dev->name, result);
 			goto fail_frontend1;
 		}
 	}
@@ -1044,7 +1047,7 @@
 
 static int em28xx_dvb_init(struct em28xx *dev)
 {
-	int result = 0;
+	int result = 0, mfe_shared = 0;
 	struct em28xx_dvb *dvb;
 
 	if (dev->is_audio_only) {
@@ -1179,8 +1182,7 @@
 					   &dev->i2c_adap[dev->def_i2c_bus]);
 		if (dvb->fe[0] != NULL) {
 			if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
-					&dev->i2c_adap[dev->def_i2c_bus],
-					0x61, TUNER_THOMSON_DTT761X)) {
+				&dev->i2c_adap[dev->def_i2c_bus], 0x61, TUNER_THOMSON_DTT761X)) {
 				result = -EINVAL;
 				goto out_free;
 			}
@@ -1202,8 +1204,7 @@
 			&dev->i2c_adap[dev->def_i2c_bus], 0x48);
 		if (dvb->fe[0]) {
 			if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
-					&dev->i2c_adap[dev->def_i2c_bus],
-					0x60, TUNER_PHILIPS_CU1216L)) {
+				&dev->i2c_adap[dev->def_i2c_bus], 0x60, TUNER_PHILIPS_CU1216L)) {
 				result = -EINVAL;
 				goto out_free;
 			}
@@ -1218,7 +1219,7 @@
 			goto out_free;
 		}
 		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-				&dev->i2c_adap[dev->def_i2c_bus],
+			&dev->i2c_adap[dev->def_i2c_bus],
 			&kworld_a340_config)) {
 				dvb_frontend_detach(dvb->fe[0]);
 				result = -EINVAL;
@@ -1249,10 +1250,10 @@
 #ifdef CONFIG_GPIOLIB
 			/* enable LNA for DVB-T, DVB-T2 and DVB-C */
 			result = gpio_request_one(dvb->lna_gpio,
-						  GPIOF_OUT_INIT_LOW, NULL);
+					GPIOF_OUT_INIT_LOW, NULL);
 			if (result)
 				em28xx_errdev("gpio request failed %d\n",
-					      result);
+						result);
 			else
 				gpio_free(dvb->lna_gpio);
 
@@ -1265,7 +1266,6 @@
 	case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
 	{
 		struct xc5000_config cfg;
-
 		hauppauge_hvr930c_init(dev);
 
 		dvb->fe[0] = dvb_attach(drxk_attach,
@@ -1339,7 +1339,7 @@
 		/* attach SEC */
 		if (dvb->fe[0])
 			dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus],
-				   &em28xx_a8293_config);
+				&em28xx_a8293_config);
 		break;
 	case EM2874_BOARD_DELOCK_61959:
 	case EM2874_BOARD_MAXMEDIA_UB425_TC:
@@ -1553,7 +1553,6 @@
 			struct si2157_config si2157_config;
 
 			/* attach demod */
-			memset(&si2168_config, 0, sizeof(si2168_config));
 			si2168_config.i2c_adapter = &adapter;
 			si2168_config.fe = &dvb->fe[0];
 			si2168_config.ts_mode = SI2168_TS_PARALLEL;
@@ -1604,65 +1603,6 @@
 			dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna;
 		}
 		break;
-	case EM28178_BOARD_TERRATEC_T2_STICK_HD:
-		{
-			struct i2c_adapter *adapter;
-			struct i2c_client *client;
-			struct i2c_board_info info;
-			struct si2168_config si2168_config;
-			struct si2157_config si2157_config;
-
-			/* attach demod */
-			memset(&si2168_config, 0, sizeof(si2168_config));
-			si2168_config.i2c_adapter = &adapter;
-			si2168_config.fe = &dvb->fe[0];
-			si2168_config.ts_mode = SI2168_TS_PARALLEL;
-			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2168", I2C_NAME_SIZE);
-			info.addr = 0x64;
-			info.platform_data = &si2168_config;
-			request_module(info.type);
-			client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
-			if (client == NULL || client->dev.driver == NULL) {
-				result = -ENODEV;
-				goto out_free;
-			}
-
-			if (!try_module_get(client->dev.driver->owner)) {
-				i2c_unregister_device(client);
-				result = -ENODEV;
-				goto out_free;
-			}
-
-			dvb->i2c_client_demod = client;
-
-			/* attach tuner */
-			memset(&si2157_config, 0, sizeof(si2157_config));
-			si2157_config.fe = dvb->fe[0];
-			memset(&info, 0, sizeof(struct i2c_board_info));
-			strlcpy(info.type, "si2146", I2C_NAME_SIZE);
-			info.addr = 0x60;
-			info.platform_data = &si2157_config;
-			request_module("si2157");
-			client = i2c_new_device(adapter, &info);
-			if (client == NULL || client->dev.driver == NULL) {
-				module_put(dvb->i2c_client_demod->dev.driver->owner);
-				i2c_unregister_device(dvb->i2c_client_demod);
-				result = -ENODEV;
-				goto out_free;
-			}
-
-			if (!try_module_get(client->dev.driver->owner)) {
-				i2c_unregister_device(client);
-				module_put(dvb->i2c_client_demod->dev.driver->owner);
-				i2c_unregister_device(dvb->i2c_client_demod);
-				result = -ENODEV;
-				goto out_free;
-			}
-
-			dvb->i2c_client_tuner = client;
-		}
-		break;
 	default:
 		em28xx_errdev("/2: The frontend of your DVB/ATSC card"
 				" isn't supported yet\n");
@@ -1684,6 +1624,9 @@
 	if (result < 0)
 		goto out_free;
 
+	/* MFE lock */
+	dvb->adapter.mfe_shared = mfe_shared;
+
 	em28xx_info("DVB extension successfully initialized\n");
 
 	kref_get(&dev->ref);
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index a19b5c8..1048c1a 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -593,7 +593,6 @@
 	unsigned long l = 0;
 	int len = 0;
 	unsigned char c;
-
 	do {
 		if (len == length) {
 			c = (char)len;
@@ -878,7 +877,6 @@
  * incomplete list of known devices
  */
 static char *i2c_devs[128] = {
-       [0x1c >> 1] = "lgdt330x",
 	[0x3e >> 1] = "remote IR sensor",
 	[0x4a >> 1] = "saa7113h",
 	[0x52 >> 1] = "drxk",
@@ -951,7 +949,7 @@
 	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
 	if (retval < 0) {
 		em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
-			      __func__, retval);
+			__func__, retval);
 		return retval;
 	}
 
@@ -963,7 +961,7 @@
 		retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
 		if ((retval < 0) && (retval != -ENODEV)) {
 			em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
-				      __func__, retval);
+				__func__, retval);
 
 			return retval;
 		}
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index d8dc03a..581f6da 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -459,7 +459,7 @@
 		return em2874_ir_change_protocol(rc_dev, rc_type);
 	default:
 		printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
-		       dev->chip_id);
+			dev->chip_id);
 		return -EINVAL;
 	}
 }
@@ -505,7 +505,7 @@
 		/* Check states of the buttons and act */
 		j = 0;
 		while (dev->board.buttons[j].role >= 0 &&
-		       dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) {
+			 dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) {
 			struct em28xx_button *button = &dev->board.buttons[j];
 			/* Check if button uses the current address */
 			if (button->reg_r != dev->button_polling_addresses[i]) {
@@ -607,7 +607,7 @@
 
 	dev->button_polling_interval = EM28XX_BUTTONS_DEBOUNCED_QUERY_INTERVAL;
 	while (dev->board.buttons[i].role >= 0 &&
-	       dev->board.buttons[i].role < EM28XX_NUM_BUTTON_ROLES) {
+			 dev->board.buttons[i].role < EM28XX_NUM_BUTTON_ROLES) {
 		struct em28xx_button *button = &dev->board.buttons[i];
 		/* Check if polling address is already on the list */
 		addr_new = true;
@@ -653,11 +653,11 @@
 	/* Start polling */
 	if (dev->num_button_polling_addresses) {
 		memset(dev->button_polling_last_values, 0,
-		       EM28XX_NUM_BUTTON_ADDRESSES_MAX);
+					       EM28XX_NUM_BUTTON_ADDRESSES_MAX);
 		INIT_DELAYED_WORK(&dev->buttons_query_work,
-				  em28xx_query_buttons);
+							  em28xx_query_buttons);
 		schedule_delayed_work(&dev->buttons_query_work,
-				      msecs_to_jiffies(dev->button_polling_interval));
+			       msecs_to_jiffies(dev->button_polling_interval));
 	}
 }
 
@@ -712,10 +712,8 @@
 	em28xx_info("Registering input extension\n");
 
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-	if (!ir)
-		return -ENOMEM;
 	rc = rc_allocate_device();
-	if (!rc)
+	if (!ir || !rc)
 		goto error;
 
 	/* record handles to ourself */
@@ -841,7 +839,8 @@
 	if (!ir)
 		goto ref_put;
 
-	rc_unregister_device(ir->rc);
+	if (ir->rc)
+		rc_unregister_device(ir->rc);
 
 	kfree(ir->i2c_client);
 
@@ -886,7 +885,7 @@
 		schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 	if (dev->num_button_polling_addresses)
 		schedule_delayed_work(&dev->buttons_query_work,
-				      msecs_to_jiffies(dev->button_polling_interval));
+			       msecs_to_jiffies(dev->button_polling_interval));
 	return 0;
 }
 
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
index 13cbb7f..311fb34 100644
--- a/drivers/media/usb/em28xx/em28xx-reg.h
+++ b/drivers/media/usb/em28xx/em28xx-reg.h
@@ -49,6 +49,7 @@
 #define EM28XX_CHIPCFG2_TS_PACKETSIZE_564	0x02
 #define EM28XX_CHIPCFG2_TS_PACKETSIZE_752	0x03
 
+
 /* GPIO/GPO registers */
 #define EM2880_R04_GPO		0x04    /* em2880-em2883 only */
 #define EM2820_R08_GPIO_CTRL	0x08	/* em2820-em2873/83 only */
@@ -67,6 +68,7 @@
 #define EM28XX_I2C_FREQ_400_KHZ		0x01
 #define EM28XX_I2C_FREQ_100_KHZ		0x00
 
+
 #define EM28XX_R0A_CHIPID	0x0a
 #define EM28XX_R0C_USBSUSP	0x0c
 #define   EM28XX_R0C_USBSUSP_SNAPSHOT	0x20 /* 1=button pressed, needs reset */
@@ -155,6 +157,7 @@
 #define EM28XX_OUTFMT_YUV422_Y1UY0V	0x15
 #define EM28XX_OUTFMT_YUV411		0x18
 
+
 #define EM28XX_R28_XMIN	0x28
 #define EM28XX_R29_XMAX	0x29
 #define EM28XX_R2A_YMIN	0x2a
diff --git a/drivers/media/usb/em28xx/em28xx-v4l.h b/drivers/media/usb/em28xx/em28xx-v4l.h
index 8dfcb56..432862c 100644
--- a/drivers/media/usb/em28xx/em28xx-v4l.h
+++ b/drivers/media/usb/em28xx/em28xx-v4l.h
@@ -14,6 +14,7 @@
    GNU General Public License for more details.
  */
 
+
 int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count);
 void em28xx_stop_vbi_streaming(struct vb2_queue *vq);
 extern struct vb2_ops em28xx_vbi_qops;
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
index 744e7ed..34ee1e0 100644
--- a/drivers/media/usb/em28xx/em28xx-vbi.c
+++ b/drivers/media/usb/em28xx/em28xx-vbi.c
@@ -92,6 +92,7 @@
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
+
 struct vb2_ops em28xx_vbi_qops = {
 	.queue_setup    = vbi_queue_setup,
 	.buf_prepare    = vbi_buffer_prepare,
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index bf1be43..f35083c 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -81,6 +81,7 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(EM28XX_VERSION);
 
+
 #define EM25XX_FRMDATAHDR_BYTE1			0x02
 #define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE	0x20
 #define EM25XX_FRMDATAHDR_BYTE2_FRAME_END	0x02
@@ -89,6 +90,7 @@
 					 EM25XX_FRMDATAHDR_BYTE2_FRAME_END |   \
 					 EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
 
+
 static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
 static unsigned int vbi_nr[]   = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
 static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
@@ -192,10 +194,9 @@
 static void em28xx_wake_i2c(struct em28xx *dev)
 {
 	struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
-
 	v4l2_device_call_all(v4l2_dev, 0, core,  reset, 0);
 	v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
-			     INPUT(dev->ctl_input)->vmux, 0, 0);
+			INPUT(dev->ctl_input)->vmux, 0, 0);
 	v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0);
 }
 
@@ -274,7 +275,7 @@
 }
 
 static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
-				    u16 width, u16 height)
+				   u16 width, u16 height)
 {
 	u8 cwidth = width >> 2;
 	u8 cheight = height >> 2;
@@ -282,7 +283,7 @@
 	/* NOTE: size limit: 2047x1023 = 2MPix */
 
 	em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
-			hstart, vstart,
+		       hstart, vstart,
 		       ((overflow & 2) << 9 | cwidth << 2),
 		       ((overflow & 1) << 10 | cheight << 2));
 
@@ -405,13 +406,13 @@
 		dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
 	} else { /* isoc */
 		em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
-				min_pkt_size, dev->alt);
+			       min_pkt_size, dev->alt);
 		dev->max_pkt_size =
 				  dev->alt_max_pkt_size_isoc[dev->alt];
 		dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
 	}
 	em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
-			dev->alt, dev->max_pkt_size);
+		       dev->alt, dev->max_pkt_size);
 	errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
 	if (errCode < 0) {
 		em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
@@ -481,7 +482,7 @@
 
 	if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
 		em28xx_isocdbg("Overflow of %zu bytes past buffer end (1)\n",
-			       ((char *)startwrite + lencopy) -
+			      ((char *)startwrite + lencopy) -
 			      ((char *)buf->vb_buf + buf->length));
 		remain = (char *)buf->vb_buf + buf->length -
 			 (char *)startwrite;
@@ -547,7 +548,7 @@
 }
 
 static inline void print_err_status(struct em28xx *dev,
-				    int packet, int status)
+				     int packet, int status)
 {
 	char *errmsg = "Unknown";
 
@@ -830,6 +831,7 @@
 	return 1;
 }
 
+
 static int get_ressource(enum v4l2_buf_type f_type)
 {
 	switch (f_type) {
@@ -1001,7 +1003,6 @@
 	}
 	while (!list_empty(&vidq->active)) {
 		struct em28xx_buffer *buf;
-
 		buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
 		list_del(&buf->list);
 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
@@ -1032,7 +1033,6 @@
 	}
 	while (!list_empty(&vbiq->active)) {
 		struct em28xx_buffer *buf;
-
 		buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
 		list_del(&buf->list);
 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
@@ -1109,7 +1109,6 @@
 static void video_mux(struct em28xx *dev, int index)
 {
 	struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
-
 	dev->ctl_input = index;
 	dev->ctl_ainput = INPUT(index)->amux;
 	dev->ctl_aoutput = INPUT(index)->aout;
@@ -1118,22 +1117,21 @@
 		dev->ctl_aoutput = EM28XX_AOUT_MASTER;
 
 	v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
-			     INPUT(index)->vmux, 0, 0);
+			INPUT(index)->vmux, 0, 0);
 
 	if (dev->board.has_msp34xx) {
 		if (dev->i2s_speed) {
 			v4l2_device_call_all(v4l2_dev, 0, audio,
-					     s_i2s_clock_freq, dev->i2s_speed);
+				s_i2s_clock_freq, dev->i2s_speed);
 		}
 		/* Note: this is msp3400 specific */
 		v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
-				     dev->ctl_ainput,
-				     MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
+			 dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
 	}
 
 	if (dev->board.adecoder != EM28XX_NOADECODER) {
 		v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
-				     dev->ctl_ainput, dev->ctl_aoutput, 0);
+			dev->ctl_ainput, dev->ctl_aoutput, 0);
 	}
 
 	em28xx_audio_analog_set(dev);
@@ -1205,7 +1203,7 @@
 };
 
 static void size_to_scale(struct em28xx *dev,
-			  unsigned int width, unsigned int height,
+			unsigned int width, unsigned int height,
 			unsigned int *hscale, unsigned int *vscale)
 {
 	unsigned int          maxw = norm_maxw(dev);
@@ -1236,7 +1234,7 @@
    ------------------------------------------------------------------*/
 
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
+					struct v4l2_format *f)
 {
 	struct em28xx         *dev = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
@@ -1269,7 +1267,7 @@
 }
 
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-				  struct v4l2_format *f)
+			struct v4l2_format *f)
 {
 	struct em28xx         *dev   = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2  = dev->v4l2;
@@ -1340,7 +1338,7 @@
 
 	/* set new image size */
 	size_to_scale(dev, v4l2->width, v4l2->height,
-		      &v4l2->hscale, &v4l2->vscale);
+			   &v4l2->hscale, &v4l2->vscale);
 
 	em28xx_resolution_set(dev);
 
@@ -1348,7 +1346,7 @@
 }
 
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
+			struct v4l2_format *f)
 {
 	struct em28xx *dev = video_drvdata(file);
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
@@ -1403,7 +1401,7 @@
 	v4l2->width = f.fmt.pix.width;
 	v4l2->height = f.fmt.pix.height;
 	size_to_scale(dev, v4l2->width, v4l2->height,
-		      &v4l2->hscale, &v4l2->vscale);
+			   &v4l2->hscale, &v4l2->vscale);
 
 	em28xx_resolution_set(dev);
 	v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
@@ -1424,7 +1422,7 @@
 						video, g_parm, p);
 	else
 		v4l2_video_std_frame_period(v4l2->norm,
-					    &p->parm.capture.timeperframe);
+						 &p->parm.capture.timeperframe);
 
 	return rc;
 }
@@ -1452,7 +1450,7 @@
 };
 
 static int vidioc_enum_input(struct file *file, void *priv,
-			     struct v4l2_input *i)
+				struct v4l2_input *i)
 {
 	struct em28xx *dev = video_drvdata(file);
 	unsigned int       n;
@@ -1469,7 +1467,7 @@
 	strcpy(i->name, iname[INPUT(n)->type]);
 
 	if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
-	    (EM28XX_VMUX_CABLE == INPUT(n)->type))
+		(EM28XX_VMUX_CABLE == INPUT(n)->type))
 		i->type = V4L2_INPUT_TYPE_TUNER;
 
 	i->std = dev->v4l2->vdev->tvnorms;
@@ -1560,7 +1558,7 @@
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
-			  struct v4l2_tuner *t)
+				struct v4l2_tuner *t)
 {
 	struct em28xx *dev = video_drvdata(file);
 
@@ -1574,7 +1572,7 @@
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
-			  const struct v4l2_tuner *t)
+				const struct v4l2_tuner *t)
 {
 	struct em28xx *dev = video_drvdata(file);
 
@@ -1586,7 +1584,7 @@
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
-			      struct v4l2_frequency *f)
+				struct v4l2_frequency *f)
 {
 	struct em28xx         *dev = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
@@ -1599,7 +1597,7 @@
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
-			      const struct v4l2_frequency *f)
+				const struct v4l2_frequency *f)
 {
 	struct v4l2_frequency  new_freq = *f;
 	struct em28xx             *dev  = video_drvdata(file);
@@ -1617,7 +1615,7 @@
 
 #ifdef CPTCFG_VIDEO_ADV_DEBUG
 static int vidioc_g_chip_info(struct file *file, void *priv,
-			      struct v4l2_dbg_chip_info *chip)
+	       struct v4l2_dbg_chip_info *chip)
 {
 	struct em28xx *dev = video_drvdata(file);
 
@@ -1672,7 +1670,6 @@
 		reg->val = ret;
 	} else {
 		__le16 val = 0;
-
 		ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
 						   reg->reg, (char *)&val, 2);
 		if (ret < 0)
@@ -1703,8 +1700,9 @@
 }
 #endif
 
+
 static int vidioc_querycap(struct file *file, void  *priv,
-			   struct v4l2_capability *cap)
+					struct v4l2_capability *cap)
 {
 	struct video_device   *vdev = video_devdata(file);
 	struct em28xx         *dev  = video_drvdata(file);
@@ -1738,7 +1736,7 @@
 }
 
 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-				   struct v4l2_fmtdesc *f)
+					struct v4l2_fmtdesc *f)
 {
 	if (unlikely(f->index >= ARRAY_SIZE(format)))
 		return -EINVAL;
@@ -2179,10 +2177,9 @@
 
 /******************************** usb interface ******************************/
 
-static struct video_device
-*em28xx_vdev_init(struct em28xx *dev,
-		  const struct video_device *template,
-		  const char *type_name)
+static struct video_device *em28xx_vdev_init(struct em28xx *dev,
+					const struct video_device *template,
+					const char *type_name)
 {
 	struct video_device *vfd;
 
@@ -2347,24 +2344,21 @@
 
 		if (dev->board.radio.type)
 			v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
-					    &dev->i2c_adap[dev->def_i2c_bus],
-					    "tuner", dev->board.radio_addr,
-					    NULL);
+					  &dev->i2c_adap[dev->def_i2c_bus],
+					  "tuner", dev->board.radio_addr, NULL);
 
 		if (has_demod)
 			v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
-					    &dev->i2c_adap[dev->def_i2c_bus],
-					    "tuner", 0,
-					    v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+				&dev->i2c_adap[dev->def_i2c_bus], "tuner",
+				0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
 		if (tuner_addr == 0) {
 			enum v4l2_i2c_tuner_type type =
 				has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
 			struct v4l2_subdev *sd;
 
 			sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
-						 &dev->i2c_adap[dev->def_i2c_bus],
-						 "tuner", 0,
-						 v4l2_i2c_tuner_addrs(type));
+				&dev->i2c_adap[dev->def_i2c_bus], "tuner",
+				0, v4l2_i2c_tuner_addrs(type));
 
 			if (sd)
 				tuner_addr = v4l2_i2c_subdev_addr(sd);
@@ -2384,20 +2378,20 @@
 	ret = em28xx_audio_setup(dev);
 	if (ret < 0) {
 		em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
-			      __func__, ret);
+			__func__, ret);
 		goto unregister_dev;
 	}
 	if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
 		v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
-				  V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
 		v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
-				  V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
+			V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
 	} else {
 		/* install the em28xx notify callback */
 		v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
-				 em28xx_ctrl_notify, dev);
+				em28xx_ctrl_notify, dev);
 		v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
-				 em28xx_ctrl_notify, dev);
+				em28xx_ctrl_notify, dev);
 	}
 
 	/* wake i2c devices */
@@ -2524,7 +2518,7 @@
 
 	/* register v4l2 video video_device */
 	ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER,
-				    video_nr[dev->devno]);
+				       video_nr[dev->devno]);
 	if (ret) {
 		em28xx_errdev("unable to register video device (error=%i).\n",
 			      ret);
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 9c70753..a21a746 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -141,8 +141,6 @@
 #define EM28178_BOARD_PCTV_461E                   92
 #define EM2874_BOARD_KWORLD_UB435Q_V3		  93
 #define EM28178_BOARD_PCTV_292E                   94
-#define EM2861_BOARD_LEADTEK_VC100                95
-#define EM28178_BOARD_TERRATEC_T2_STICK_HD        96
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -217,6 +215,7 @@
 	EM28XX_DIGITAL_MODE,
 };
 
+
 struct em28xx;
 
 struct em28xx_usb_bufs {
@@ -244,11 +243,11 @@
 	struct em28xx_usb_bufs		digital_bufs;
 
 		/* Stores already requested buffers */
-	struct em28xx_buffer	*vid_buf;
-	struct em28xx_buffer	*vbi_buf;
+	struct em28xx_buffer    	*vid_buf;
+	struct em28xx_buffer    	*vbi_buf;
 
 		/* copy data from URB */
-	int (*urb_data_copy)(struct em28xx *dev, struct urb *urb);
+	int (*urb_data_copy) (struct em28xx *dev, struct urb *urb);
 
 };
 
@@ -696,14 +695,14 @@
 	char urb_buf[URB_MAX_CTRL_SIZE];	/* urb control msg buffer */
 
 	/* helper funcs that call usb_control_msg */
-	int (*em28xx_write_regs)(struct em28xx *dev, u16 reg,
-				 char *buf, int len);
-	int (*em28xx_read_reg)(struct em28xx *dev, u16 reg);
-	int (*em28xx_read_reg_req_len)(struct em28xx *dev, u8 req, u16 reg,
-				       char *buf, int len);
-	int (*em28xx_write_regs_req)(struct em28xx *dev, u8 req, u16 reg,
-				     char *buf, int len);
-	int (*em28xx_read_reg_req)(struct em28xx *dev, u8 req, u16 reg);
+	int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
+					char *buf, int len);
+	int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
+	int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
+					char *buf, int len);
+	int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
+				      char *buf, int len);
+	int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
 
 	enum em28xx_mode mode;
 
@@ -746,7 +745,7 @@
 int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
 int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val);
 int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
-			  u8 bitmask);
+				 u8 bitmask);
 int em28xx_toggle_reg_bits(struct em28xx *dev, u16 reg, u8 bitmask);
 
 int em28xx_read_ac97(struct em28xx *dev, u8 reg);
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index d6bf982..ec799b4 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -252,7 +252,7 @@
 	if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
 		struct v4l2_mbus_framefmt mbus_fmt;
 
-		mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
+		mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
 		mbus_fmt.width = fmt ? fmt->fmt.pix.width : width;
 		mbus_fmt.height = height;
 		go->encoder_h_halve = 0;
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig
index 918af60..b016ea7 100644
--- a/drivers/media/usb/gspca/Kconfig
+++ b/drivers/media/usb/gspca/Kconfig
@@ -168,7 +168,7 @@
 	  module will be called gspca_ov519.
 
 config USB_GSPCA_OV534
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_5
 	tristate "OV534 OV772x USB Camera Driver"
 	depends on m
 	depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index f7df15a..527e891 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -933,7 +933,7 @@
 	dev->bandwidth->val = bandwidth;
 	dev->bandwidth->cur.val = bandwidth;
 
-	dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth);
+	dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth_lut[i].freq);
 
 	u16tmp = 0;
 	u16tmp |= ((bandwidth >> 0) & 0xff) << 0;
diff --git a/drivers/media/usb/msi2500/Kconfig b/drivers/media/usb/msi2500/Kconfig
index 73096d6..bcbee22 100644
--- a/drivers/media/usb/msi2500/Kconfig
+++ b/drivers/media/usb/msi2500/Kconfig
@@ -1,5 +1,5 @@
 config USB_MSI2500
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Mirics MSi2500"
 	depends on m
 	depends on VIDEO_V4L2 && SPI
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-context.c b/drivers/media/usb/pvrusb2/pvrusb2-context.c
index c8761c7..7c19ff7 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-context.c
@@ -80,7 +80,7 @@
 static void pvr2_context_destroy(struct pvr2_context *mp)
 {
 	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
-	pvr2_hdw_destroy(mp->hdw);
+	if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
 	pvr2_context_set_notify(mp, 0);
 	mutex_lock(&pvr2_context_mutex);
 	if (mp->exist_next) {
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index 2fd9b5e..9623b62 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -2966,7 +2966,7 @@
 		memset(&fmt, 0, sizeof(fmt));
 		fmt.width = hdw->res_hor_val;
 		fmt.height = hdw->res_ver_val;
-		fmt.code = MEDIA_BUS_FMT_FIXED;
+		fmt.code = V4L2_MBUS_FMT_FIXED;
 		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
 			   fmt.width, fmt.height);
 		v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt);
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index de55e96..ccc0009 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -558,30 +558,27 @@
 
 }
 
-static void s2255_got_frame(struct s2255_vc *vc, int jpgsize)
+static int s2255_got_frame(struct s2255_vc *vc, int jpgsize)
 {
 	struct s2255_buffer *buf;
 	struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
 	unsigned long flags = 0;
-
+	int rc = 0;
 	spin_lock_irqsave(&vc->qlock, flags);
 	if (list_empty(&vc->buf_list)) {
 		dprintk(dev, 1, "No active queue to serve\n");
-		spin_unlock_irqrestore(&vc->qlock, flags);
-		return;
+		rc = -1;
+		goto unlock;
 	}
 	buf = list_entry(vc->buf_list.next,
 			 struct s2255_buffer, list);
 	list_del(&buf->list);
 	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	buf->vb.v4l2_buf.field = vc->field;
-	buf->vb.v4l2_buf.sequence = vc->frame_count;
-	spin_unlock_irqrestore(&vc->qlock, flags);
-
 	s2255_fillbuff(vc, buf, jpgsize);
-	/* tell v4l buffer was filled */
-	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
 	dprintk(dev, 2, "%s: [buf] [%p]\n", __func__, buf);
+unlock:
+	spin_unlock_irqrestore(&vc->qlock, flags);
+	return rc;
 }
 
 static const struct s2255_fmt *format_by_fourcc(int fourcc)
@@ -635,7 +632,7 @@
 			break;
 		case V4L2_PIX_FMT_JPEG:
 		case V4L2_PIX_FMT_MJPEG:
-			vb2_set_plane_payload(&buf->vb, 0, jpgsize);
+			buf->vb.v4l2_buf.length = jpgsize;
 			memcpy(vbuf, tmpbuf, jpgsize);
 			break;
 		case V4L2_PIX_FMT_YUV422P:
@@ -652,6 +649,11 @@
 	}
 	dprintk(dev, 2, "s2255fill at : Buffer 0x%08lx size= %d\n",
 		(unsigned long)vbuf, pos);
+	/* tell v4l buffer was filled */
+	buf->vb.v4l2_buf.field = vc->field;
+	buf->vb.v4l2_buf.sequence = vc->frame_count;
+	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
 }
 
 
@@ -1974,7 +1976,8 @@
 {
 	unsigned long i;
 	for (i = 0; i < SYS_FRAMES; i++) {
-		vfree(vc->buffer.frame[i].lpvbits);
+		if (vc->buffer.frame[i].lpvbits)
+			vfree(vc->buffer.frame[i].lpvbits);
 		vc->buffer.frame[i].lpvbits = NULL;
 	}
 	return 0;
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 963eae2..547f749 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -475,7 +475,7 @@
 	struct stk1160 *dev = video_drvdata(file);
 
 	/* Match host */
-	return stk1160_write_reg(dev, reg->reg, reg->val);
+	return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val));
 }
 #endif
 
diff --git a/drivers/media/usb/tlg2300/Kconfig b/drivers/media/usb/tlg2300/Kconfig
new file mode 100644
index 0000000..1d60d9b
--- /dev/null
+++ b/drivers/media/usb/tlg2300/Kconfig
@@ -0,0 +1,17 @@
+config VIDEO_TLG2300
+	tristate "Telegent TLG2300 USB video capture support"
+	depends on m
+	depends on VIDEO_DEV && I2C && SND && DVB_CORE
+	select VIDEO_TUNER
+	select VIDEO_TVEEPROM
+	depends on RC_CORE
+	select VIDEOBUF_VMALLOC
+	depends on SND_PCM
+	select VIDEOBUF_DVB
+
+	---help---
+	  This is a video4linux driver for Telegent tlg2300 based TV cards.
+	  The driver supports V4L2, DVB-T and radio.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called poseidon
diff --git a/drivers/media/usb/tlg2300/Makefile b/drivers/media/usb/tlg2300/Makefile
new file mode 100644
index 0000000..643eb25
--- /dev/null
+++ b/drivers/media/usb/tlg2300/Makefile
@@ -0,0 +1,9 @@
+poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o
+
+obj-$(CPTCFG_VIDEO_TLG2300) += poseidon.o
+
+ccflags-y += -I$(backport_srctree)/drivers/media/i2c
+ccflags-y += -I$(backport_srctree)/drivers/media/tuners
+ccflags-y += -I$(backport_srctree)/drivers/media/dvb-core
+ccflags-y += -I$(backport_srctree)/drivers/media/dvb-frontends
+
diff --git a/drivers/media/usb/tlg2300/pd-alsa.c b/drivers/media/usb/tlg2300/pd-alsa.c
new file mode 100644
index 0000000..dd8fe10
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-alsa.c
@@ -0,0 +1,337 @@
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/init.h>
+#include <linux/sound.h>
+#include <linux/spinlock.h>
+#include <linux/soundcard.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/gfp.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <media/v4l2-common.h>
+#include "pd-common.h"
+#include "vendorcmds.h"
+
+static void complete_handler_audio(struct urb *urb);
+#define AUDIO_EP	(0x83)
+#define AUDIO_BUF_SIZE	(512)
+#define PERIOD_SIZE	(1024 * 8)
+#define PERIOD_MIN	(4)
+#define PERIOD_MAX 	PERIOD_MIN
+
+static struct snd_pcm_hardware snd_pd_hw_capture = {
+	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP           |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_MMAP_VALID,
+
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rates = SNDRV_PCM_RATE_48000,
+
+	.rate_min = 48000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = PERIOD_SIZE * PERIOD_MIN,
+	.period_bytes_min = PERIOD_SIZE,
+	.period_bytes_max = PERIOD_SIZE,
+	.periods_min = PERIOD_MIN,
+	.periods_max = PERIOD_MAX,
+	/*
+	.buffer_bytes_max = 62720 * 8,
+	.period_bytes_min = 64,
+	.period_bytes_max = 12544,
+	.periods_min = 2,
+	.periods_max = 98
+	*/
+};
+
+static int snd_pd_capture_open(struct snd_pcm_substream *substream)
+{
+	struct poseidon *p = snd_pcm_substream_chip(substream);
+	struct poseidon_audio *pa = &p->audio;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	if (!p)
+		return -ENODEV;
+	pa->users++;
+	pa->card_close 		= 0;
+	pa->capture_pcm_substream	= substream;
+	runtime->private_data		= p;
+
+	runtime->hw = snd_pd_hw_capture;
+	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	usb_autopm_get_interface(p->interface);
+	kref_get(&p->kref);
+	return 0;
+}
+
+static int snd_pd_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct poseidon *p = snd_pcm_substream_chip(substream);
+	struct poseidon_audio *pa = &p->audio;
+
+	pa->users--;
+	pa->card_close 		= 1;
+	usb_autopm_put_interface(p->interface);
+	kref_put(&p->kref, poseidon_delete);
+	return 0;
+}
+
+static int snd_pd_hw_capture_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned int size;
+
+	size = params_buffer_bytes(hw_params);
+	if (runtime->dma_area) {
+		if (runtime->dma_bytes > size)
+			return 0;
+		vfree(runtime->dma_area);
+	}
+	runtime->dma_area = vmalloc(size);
+	if (!runtime->dma_area)
+		return -ENOMEM;
+	else
+		runtime->dma_bytes = size;
+	return 0;
+}
+
+static int audio_buf_free(struct poseidon *p)
+{
+	struct poseidon_audio *pa = &p->audio;
+	int i;
+
+	for (i = 0; i < AUDIO_BUFS; i++)
+		if (pa->urb_array[i])
+			usb_kill_urb(pa->urb_array[i]);
+	free_all_urb_generic(pa->urb_array, AUDIO_BUFS);
+	logpm();
+	return 0;
+}
+
+static int snd_pd_hw_capture_free(struct snd_pcm_substream *substream)
+{
+	struct poseidon *p = snd_pcm_substream_chip(substream);
+
+	logpm();
+	audio_buf_free(p);
+	return 0;
+}
+
+static int snd_pd_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+#define AUDIO_TRAILER_SIZE	(16)
+static inline void handle_audio_data(struct urb *urb, int *period_elapsed)
+{
+	struct poseidon_audio *pa = urb->context;
+	struct snd_pcm_runtime *runtime = pa->capture_pcm_substream->runtime;
+
+	int stride	= runtime->frame_bits >> 3;
+	int len		= urb->actual_length / stride;
+	unsigned char *cp	= urb->transfer_buffer;
+	unsigned int oldptr	= pa->rcv_position;
+
+	if (urb->actual_length == AUDIO_BUF_SIZE - 4)
+		len -= (AUDIO_TRAILER_SIZE / stride);
+
+	/* do the copy */
+	if (oldptr + len >= runtime->buffer_size) {
+		unsigned int cnt = runtime->buffer_size - oldptr;
+
+		memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride);
+		memcpy(runtime->dma_area, (cp + cnt * stride),
+					(len * stride - cnt * stride));
+	} else
+		memcpy(runtime->dma_area + oldptr * stride, cp, len * stride);
+
+	/* update the statas */
+	snd_pcm_stream_lock(pa->capture_pcm_substream);
+	pa->rcv_position	+= len;
+	if (pa->rcv_position >= runtime->buffer_size)
+		pa->rcv_position -= runtime->buffer_size;
+
+	pa->copied_position += (len);
+	if (pa->copied_position >= runtime->period_size) {
+		pa->copied_position -= runtime->period_size;
+		*period_elapsed = 1;
+	}
+	snd_pcm_stream_unlock(pa->capture_pcm_substream);
+}
+
+static void complete_handler_audio(struct urb *urb)
+{
+	struct poseidon_audio *pa = urb->context;
+	struct snd_pcm_substream *substream = pa->capture_pcm_substream;
+	int    period_elapsed = 0;
+	int    ret;
+
+	if (1 == pa->card_close || pa->capture_stream != STREAM_ON)
+		return;
+
+	if (urb->status != 0) {
+		/*if (urb->status == -ESHUTDOWN)*/
+			return;
+	}
+
+	if (substream) {
+		if (urb->actual_length) {
+			handle_audio_data(urb, &period_elapsed);
+			if (period_elapsed)
+				snd_pcm_period_elapsed(substream);
+		}
+	}
+
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret < 0)
+		log("audio urb failed (errcod = %i)", ret);
+	return;
+}
+
+static int fire_audio_urb(struct poseidon *p)
+{
+	int i, ret = 0;
+	struct poseidon_audio *pa = &p->audio;
+
+	alloc_bulk_urbs_generic(pa->urb_array, AUDIO_BUFS,
+			p->udev, AUDIO_EP,
+			AUDIO_BUF_SIZE, GFP_ATOMIC,
+			complete_handler_audio, pa);
+
+	for (i = 0; i < AUDIO_BUFS; i++) {
+		ret = usb_submit_urb(pa->urb_array[i], GFP_KERNEL);
+		if (ret)
+			log("urb err : %d", ret);
+	}
+	log();
+	return ret;
+}
+
+static int snd_pd_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct poseidon *p = snd_pcm_substream_chip(substream);
+	struct poseidon_audio *pa = &p->audio;
+
+	if (debug_mode)
+		log("cmd %d, audio stat : %d\n", cmd, pa->capture_stream);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_START:
+		if (pa->capture_stream == STREAM_ON)
+			return 0;
+
+		pa->rcv_position = pa->copied_position = 0;
+		pa->capture_stream = STREAM_ON;
+
+		if (in_hibernation(p))
+			return 0;
+		fire_audio_urb(p);
+		return 0;
+
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		pa->capture_stream = STREAM_SUSPEND;
+		return 0;
+	case SNDRV_PCM_TRIGGER_STOP:
+		pa->capture_stream = STREAM_OFF;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static snd_pcm_uframes_t
+snd_pd_capture_pointer(struct snd_pcm_substream *substream)
+{
+	struct poseidon *p = snd_pcm_substream_chip(substream);
+	struct poseidon_audio *pa = &p->audio;
+	return pa->rcv_position;
+}
+
+static struct page *snd_pcm_pd_get_page(struct snd_pcm_substream *subs,
+					     unsigned long offset)
+{
+	void *pageptr = subs->runtime->dma_area + offset;
+	return vmalloc_to_page(pageptr);
+}
+
+static struct snd_pcm_ops pcm_capture_ops = {
+	.open      = snd_pd_capture_open,
+	.close     = snd_pd_pcm_close,
+	.ioctl     = snd_pcm_lib_ioctl,
+	.hw_params = snd_pd_hw_capture_params,
+	.hw_free   = snd_pd_hw_capture_free,
+	.prepare   = snd_pd_prepare,
+	.trigger   = snd_pd_capture_trigger,
+	.pointer   = snd_pd_capture_pointer,
+	.page      = snd_pcm_pd_get_page,
+};
+
+#ifdef CONFIG_PM
+int pm_alsa_suspend(struct poseidon *p)
+{
+	logpm(p);
+	audio_buf_free(p);
+	return 0;
+}
+
+int pm_alsa_resume(struct poseidon *p)
+{
+	logpm(p);
+	fire_audio_urb(p);
+	return 0;
+}
+#endif
+
+int poseidon_audio_init(struct poseidon *p)
+{
+	struct poseidon_audio *pa = &p->audio;
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	int ret;
+
+	ret = snd_card_new(&p->interface->dev, -1, "Telegent",
+			   THIS_MODULE, 0, &card);
+	if (ret != 0)
+		return ret;
+
+	ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm);
+	if (ret < 0) {
+		snd_card_free(card);
+		return ret;
+	}
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
+	pcm->info_flags   = 0;
+	pcm->private_data = p;
+	strcpy(pcm->name, "poseidon audio capture");
+
+	strcpy(card->driver, "ALSA driver");
+	strcpy(card->shortname, "poseidon Audio");
+	strcpy(card->longname, "poseidon ALSA Audio");
+
+	if (snd_card_register(card)) {
+		snd_card_free(card);
+		return -ENOMEM;
+	}
+	pa->card = card;
+	return 0;
+}
+
+int poseidon_audio_free(struct poseidon *p)
+{
+	struct poseidon_audio *pa = &p->audio;
+
+	if (pa->card)
+		snd_card_free(pa->card);
+	return 0;
+}
diff --git a/drivers/media/usb/tlg2300/pd-common.h b/drivers/media/usb/tlg2300/pd-common.h
new file mode 100644
index 0000000..9e23ad3
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-common.h
@@ -0,0 +1,271 @@
+#ifndef PD_COMMON_H
+#define PD_COMMON_H
+
+#include <linux/fs.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/videodev2.h>
+#include <linux/semaphore.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#include "dvb_frontend.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dmxdev.h"
+
+#define SBUF_NUM	8
+#define MAX_BUFFER_NUM	6
+#define PK_PER_URB	32
+#define ISO_PKT_SIZE	3072
+
+#define POSEIDON_STATE_NONE		(0x0000)
+#define POSEIDON_STATE_ANALOG		(0x0001)
+#define POSEIDON_STATE_FM		(0x0002)
+#define POSEIDON_STATE_DVBT		(0x0004)
+#define POSEIDON_STATE_DISCONNECT	(0x0080)
+
+#define PM_SUSPEND_DELAY	3
+
+#define V4L_PAL_VBI_LINES	18
+#define V4L_NTSC_VBI_LINES	12
+#define V4L_PAL_VBI_FRAMESIZE	(V4L_PAL_VBI_LINES * 1440 * 2)
+#define V4L_NTSC_VBI_FRAMESIZE	(V4L_NTSC_VBI_LINES * 1440 * 2)
+
+#define TUNER_FREQ_MIN		(45000000U)
+#define TUNER_FREQ_MAX		(862000000U)
+
+struct vbi_data {
+	struct video_device	v_dev;
+	struct video_data	*video;
+	struct front_face	*front;
+
+	unsigned int		copied;
+	unsigned int		vbi_size; /* the whole size of two fields */
+	int 			users;
+};
+
+/*
+ * This is the running context of the video, it is useful for
+ * resume()
+ */
+struct running_context {
+	u32		freq;		/* VIDIOC_S_FREQUENCY */
+	int		audio_idx;	/* VIDIOC_S_TUNER    */
+	v4l2_std_id	tvnormid;	/* VIDIOC_S_STD     */
+	int		sig_index;	/* VIDIOC_S_INPUT  */
+	struct v4l2_pix_format pix;	/* VIDIOC_S_FMT   */
+};
+
+struct video_data {
+	/* v4l2 video device */
+	struct video_device	v_dev;
+	struct v4l2_ctrl_handler ctrl_handler;
+
+	/* the working context */
+	struct running_context	context;
+
+	/* for data copy */
+	int		field_count;
+
+	char		*dst;
+	int		lines_copied;
+	int		prev_left;
+
+	int		lines_per_field;
+	int		lines_size;
+
+	/* for communication */
+	u8			endpoint_addr;
+	struct urb 		*urb_array[SBUF_NUM];
+	struct vbi_data		*vbi;
+	struct poseidon 	*pd;
+	struct front_face	*front;
+
+	int			is_streaming;
+	int			users;
+
+	/* for bubble handler */
+	struct work_struct	bubble_work;
+};
+
+enum pcm_stream_state {
+	STREAM_OFF,
+	STREAM_ON,
+	STREAM_SUSPEND,
+};
+
+#define AUDIO_BUFS (3)
+#define CAPTURE_STREAM_EN 1
+struct poseidon_audio {
+	struct urb		*urb_array[AUDIO_BUFS];
+	unsigned int 		copied_position;
+	struct snd_pcm_substream   *capture_pcm_substream;
+
+	unsigned int 		rcv_position;
+	struct	snd_card	*card;
+	int 			card_close;
+
+	int 			users;
+	int			pm_state;
+	enum pcm_stream_state 	capture_stream;
+};
+
+struct radio_data {
+	__u32		fm_freq;
+	unsigned int	is_radio_streaming;
+	int		pre_emphasis;
+	struct video_device fm_dev;
+	struct v4l2_ctrl_handler ctrl_handler;
+};
+
+#define DVB_SBUF_NUM		4
+#define DVB_URB_BUF_SIZE	0x2000
+struct pd_dvb_adapter {
+	struct dvb_adapter	dvb_adap;
+	struct dvb_frontend	dvb_fe;
+	struct dmxdev		dmxdev;
+	struct dvb_demux	demux;
+
+	atomic_t		users;
+	atomic_t		active_feed;
+
+	/* data transfer */
+	s32			is_streaming;
+	struct urb		*urb_array[DVB_SBUF_NUM];
+	struct poseidon		*pd_device;
+	u8			ep_addr;
+	u8			reserved[3];
+
+	/* data for power resume*/
+	struct dtv_frontend_properties fe_param;
+
+	/* for channel scanning */
+	int		prev_freq;
+	int		bandwidth;
+	unsigned long	last_jiffies;
+};
+
+struct front_face {
+	/* use this field to distinguish VIDEO and VBI */
+	enum v4l2_buf_type	type;
+
+	/* for host */
+	struct videobuf_queue	q;
+
+	/* the bridge for host and device */
+	struct videobuf_buffer	*curr_frame;
+
+	/* for device */
+	spinlock_t		queue_lock;
+	struct list_head	active;
+	struct poseidon		*pd;
+};
+
+struct poseidon {
+	struct list_head	device_list;
+
+	struct mutex		lock;
+	struct kref		kref;
+
+	/* for V4L2 */
+	struct v4l2_device	v4l2_dev;
+
+	/* hardware info */
+	struct usb_device	*udev;
+	struct usb_interface	*interface;
+	int 			cur_transfer_mode;
+
+	struct video_data	video_data;	/* video */
+	struct vbi_data		vbi_data;	/* vbi	 */
+	struct poseidon_audio	audio;		/* audio (alsa) */
+	struct radio_data	radio_data;	/* FM	 */
+	struct pd_dvb_adapter	dvb_data;	/* DVB	 */
+
+	u32			state;
+	struct file		*file_for_stream; /* the active stream*/
+
+#ifdef CONFIG_PM
+	int (*pm_suspend)(struct poseidon *);
+	int (*pm_resume)(struct poseidon *);
+	pm_message_t		msg;
+
+	struct work_struct	pm_work;
+	u8			portnum;
+#endif
+};
+
+struct poseidon_format {
+	char 	*name;
+	int	fourcc;		 /* video4linux 2	  */
+	int	depth;		 /* bit/pixel		  */
+	int	flags;
+};
+
+struct poseidon_tvnorm {
+	v4l2_std_id	v4l2_id;
+	char		name[12];
+	u32		tlg_tvnorm;
+};
+
+/* video */
+int pd_video_init(struct poseidon *);
+void pd_video_exit(struct poseidon *);
+int stop_all_video_stream(struct poseidon *);
+
+/* alsa audio */
+int poseidon_audio_init(struct poseidon *);
+int poseidon_audio_free(struct poseidon *);
+#ifdef CONFIG_PM
+int pm_alsa_suspend(struct poseidon *);
+int pm_alsa_resume(struct poseidon *);
+#endif
+
+/* dvb */
+int pd_dvb_usb_device_init(struct poseidon *);
+void pd_dvb_usb_device_exit(struct poseidon *);
+void pd_dvb_usb_device_cleanup(struct poseidon *);
+int pd_dvb_get_adapter_num(struct pd_dvb_adapter *);
+void dvb_stop_streaming(struct pd_dvb_adapter *);
+
+/* FM */
+int poseidon_fm_init(struct poseidon *);
+int poseidon_fm_exit(struct poseidon *);
+
+/* vendor command ops */
+int send_set_req(struct poseidon*, u8, s32, s32*);
+int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32);
+s32 set_tuner_mode(struct poseidon*, unsigned char);
+
+/* bulk urb alloc/free */
+int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
+			struct usb_device *udev, u8 ep_addr,
+			int buf_size, gfp_t gfp_flags,
+			usb_complete_t complete_fn, void *context);
+void free_all_urb_generic(struct urb **urb_array, int num);
+
+/* misc */
+void poseidon_delete(struct kref *kref);
+extern int debug_mode;
+void set_debug_mode(struct video_device *vfd, int debug_mode);
+
+#ifdef CONFIG_PM
+#define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE)
+#else
+#define in_hibernation(pd) (0)
+#endif
+#define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt))
+
+#define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \
+				__func__, __LINE__,  ## __VA_ARGS__)
+
+/* for power management */
+#define logpm(pd) do {\
+			if (debug_mode & 0x10)\
+				log();\
+		} while (0)
+
+#endif
diff --git a/drivers/media/usb/tlg2300/pd-dvb.c b/drivers/media/usb/tlg2300/pd-dvb.c
new file mode 100644
index 0000000..ca4994a
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-dvb.c
@@ -0,0 +1,597 @@
+#include "pd-common.h"
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/time.h>
+#include <linux/dvb/dmx.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+
+#include "vendorcmds.h"
+#include <linux/sched.h>
+#include <linux/atomic.h>
+
+static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
+
+static int dvb_bandwidth[][2] = {
+	{ TLG_BW_8, 8000000 },
+	{ TLG_BW_7, 7000000 },
+	{ TLG_BW_6, 6000000 }
+};
+static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth);
+
+static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb);
+static int poseidon_check_mode_dvbt(struct poseidon *pd)
+{
+	s32 ret = 0, cmd_status = 0;
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ/4);
+
+	ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE);
+	if (ret != 0)
+		return ret;
+
+	ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T);
+	if (ret)
+		return ret;
+
+	/* signal source */
+	ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status);
+	if (ret|cmd_status)
+		return ret;
+
+	return 0;
+}
+
+/* acquire :
+ * 	1 == open
+ * 	0 == release
+ */
+static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+	struct poseidon *pd = fe->demodulator_priv;
+	struct pd_dvb_adapter *pd_dvb;
+	int ret = 0;
+
+	if (!pd)
+		return -ENODEV;
+
+	pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe);
+	if (acquire) {
+		mutex_lock(&pd->lock);
+		if (pd->state & POSEIDON_STATE_DISCONNECT) {
+			ret = -ENODEV;
+			goto open_out;
+		}
+
+		if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) {
+			ret = -EBUSY;
+			goto open_out;
+		}
+
+		usb_autopm_get_interface(pd->interface);
+		if (0 == pd->state) {
+			ret = poseidon_check_mode_dvbt(pd);
+			if (ret < 0) {
+				usb_autopm_put_interface(pd->interface);
+				goto open_out;
+			}
+			pd->state |= POSEIDON_STATE_DVBT;
+			pd_dvb->bandwidth = 0;
+			pd_dvb->prev_freq = 0;
+		}
+		atomic_inc(&pd_dvb->users);
+		kref_get(&pd->kref);
+open_out:
+		mutex_unlock(&pd->lock);
+	} else {
+		dvb_stop_streaming(pd_dvb);
+
+		if (atomic_dec_and_test(&pd_dvb->users)) {
+			mutex_lock(&pd->lock);
+			pd->state &= ~POSEIDON_STATE_DVBT;
+			mutex_unlock(&pd->lock);
+		}
+		kref_put(&pd->kref, poseidon_delete);
+		usb_autopm_put_interface(pd->interface);
+	}
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static void poseidon_fe_release(struct dvb_frontend *fe)
+{
+	struct poseidon *pd = fe->demodulator_priv;
+
+	pd->pm_suspend = NULL;
+	pd->pm_resume  = NULL;
+}
+#else
+#define poseidon_fe_release NULL
+#endif
+
+static s32 poseidon_fe_sleep(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+/*
+ * return true if we can satisfy the conditions, else return false.
+ */
+static bool check_scan_ok(__u32 freq, int bandwidth,
+			struct pd_dvb_adapter *adapter)
+{
+	if (bandwidth < 0)
+		return false;
+
+	if (adapter->prev_freq == freq
+		&& adapter->bandwidth == bandwidth) {
+		long nl = jiffies - adapter->last_jiffies;
+		unsigned int msec ;
+
+		msec = jiffies_to_msecs(abs(nl));
+		return msec > 15000 ? true : false;
+	}
+	return true;
+}
+
+/*
+ * Check if the firmware delays too long for an invalid frequency.
+ */
+static int fw_delay_overflow(struct pd_dvb_adapter *adapter)
+{
+	long nl = jiffies - adapter->last_jiffies;
+	unsigned int msec ;
+
+	msec = jiffies_to_msecs(abs(nl));
+	return msec > 800 ? true : false;
+}
+
+static int poseidon_set_fe(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	s32 ret = 0, cmd_status = 0;
+	s32 i, bandwidth = -1;
+	struct poseidon *pd = fe->demodulator_priv;
+	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+	if (in_hibernation(pd))
+		return -EBUSY;
+
+	mutex_lock(&pd->lock);
+	for (i = 0; i < dvb_bandwidth_length; i++)
+		if (fep->bandwidth_hz == dvb_bandwidth[i][1])
+			bandwidth = dvb_bandwidth[i][0];
+
+	if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) {
+		ret = send_set_req(pd, TUNE_FREQ_SELECT,
+					fep->frequency / 1000, &cmd_status);
+		if (ret | cmd_status) {
+			log("error line");
+			goto front_out;
+		}
+
+		ret = send_set_req(pd, DVBT_BANDW_SEL,
+						bandwidth, &cmd_status);
+		if (ret | cmd_status) {
+			log("error line");
+			goto front_out;
+		}
+
+		ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+		if (ret | cmd_status) {
+			log("error line");
+			goto front_out;
+		}
+
+		/* save the context for future */
+		memcpy(&pd_dvb->fe_param, fep, sizeof(*fep));
+		pd_dvb->bandwidth = bandwidth;
+		pd_dvb->prev_freq = fep->frequency;
+		pd_dvb->last_jiffies = jiffies;
+	}
+front_out:
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int pm_dvb_suspend(struct poseidon *pd)
+{
+	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+	dvb_stop_streaming(pd_dvb);
+	dvb_urb_cleanup(pd_dvb);
+	msleep(500);
+	return 0;
+}
+
+static int pm_dvb_resume(struct poseidon *pd)
+{
+	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+	poseidon_check_mode_dvbt(pd);
+	msleep(300);
+	poseidon_set_fe(&pd_dvb->dvb_fe);
+
+	dvb_start_streaming(pd_dvb);
+	return 0;
+}
+#endif
+
+static s32 poseidon_fe_init(struct dvb_frontend *fe)
+{
+	struct poseidon *pd = fe->demodulator_priv;
+	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+#ifdef CONFIG_PM
+	pd->pm_suspend = pm_dvb_suspend;
+	pd->pm_resume  = pm_dvb_resume;
+#endif
+	memset(&pd_dvb->fe_param, 0,
+			sizeof(struct dtv_frontend_properties));
+	return 0;
+}
+
+static int poseidon_get_fe(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	struct poseidon *pd = fe->demodulator_priv;
+	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+	memcpy(fep, &pd_dvb->fe_param, sizeof(*fep));
+	return 0;
+}
+
+static int poseidon_fe_get_tune_settings(struct dvb_frontend *fe,
+				struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static int poseidon_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+	struct poseidon *pd = fe->demodulator_priv;
+	s32 ret = -1, cmd_status;
+	struct tuner_dtv_sig_stat_s status = {};
+
+	if (in_hibernation(pd))
+		return -EBUSY;
+	mutex_lock(&pd->lock);
+
+	ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T,
+				&status, &cmd_status, sizeof(status));
+	if (ret | cmd_status) {
+		log("get tuner status error");
+		goto out;
+	}
+
+	if (debug_mode)
+		log("P : %d, L %d, LB :%d", status.sig_present,
+			status.sig_locked, status.sig_lock_busy);
+
+	if (status.sig_lock_busy) {
+		goto out;
+	} else if (status.sig_present || status.sig_locked) {
+		*stat |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER
+				| FE_HAS_SYNC | FE_HAS_VITERBI;
+	} else {
+		if (fw_delay_overflow(&pd->dvb_data))
+			*stat |= FE_TIMEDOUT;
+	}
+out:
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+static int poseidon_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct poseidon *pd = fe->demodulator_priv;
+	struct tuner_ber_rate_s tlg_ber = {};
+	s32 ret = -1, cmd_status;
+
+	mutex_lock(&pd->lock);
+	ret = send_get_req(pd, TUNER_BER_RATE, 0,
+				&tlg_ber, &cmd_status, sizeof(tlg_ber));
+	if (ret | cmd_status)
+		goto out;
+	*ber = tlg_ber.ber_rate;
+out:
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+static s32 poseidon_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct poseidon *pd = fe->demodulator_priv;
+	struct tuner_dtv_sig_stat_s status = {};
+	s32 ret = 0, cmd_status;
+
+	mutex_lock(&pd->lock);
+	ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T,
+				&status, &cmd_status, sizeof(status));
+	if (ret | cmd_status)
+		goto out;
+	if ((status.sig_present || status.sig_locked) && !status.sig_strength)
+		*strength = 0xFFFF;
+	else
+		*strength = status.sig_strength;
+out:
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+static int poseidon_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	return 0;
+}
+
+static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+	*unc = 0;
+	return 0;
+}
+
+static struct dvb_frontend_ops poseidon_frontend_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name		= "Poseidon DVB-T",
+		.frequency_min	= 174000000,
+		.frequency_max  = 862000000,
+		.frequency_stepsize	  = 62500,/* FIXME */
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = poseidon_fe_release,
+
+	.init = poseidon_fe_init,
+	.sleep = poseidon_fe_sleep,
+
+	.set_frontend = poseidon_set_fe,
+	.get_frontend = poseidon_get_fe,
+	.get_tune_settings = poseidon_fe_get_tune_settings,
+
+	.read_status	= poseidon_read_status,
+	.read_ber	= poseidon_read_ber,
+	.read_signal_strength = poseidon_read_signal_strength,
+	.read_snr	= poseidon_read_snr,
+	.read_ucblocks	= poseidon_read_unc_blocks,
+
+	.ts_bus_ctrl = poseidon_ts_bus_ctrl,
+};
+
+static void dvb_urb_irq(struct urb *urb)
+{
+	struct pd_dvb_adapter *pd_dvb = urb->context;
+	int len = urb->transfer_buffer_length;
+	struct dvb_demux *demux = &pd_dvb->demux;
+	s32 ret;
+
+	if (!pd_dvb->is_streaming || urb->status) {
+		if (urb->status == -EPROTO)
+			goto resend;
+		return;
+	}
+
+	if (urb->actual_length == len)
+		dvb_dmx_swfilter(demux, urb->transfer_buffer, len);
+	else if (urb->actual_length == len - 4) {
+		int offset;
+		u8 *buf = urb->transfer_buffer;
+
+		/*
+		 * The packet size is 512,
+		 * last packet contains 456 bytes tsp data
+		 */
+		for (offset = 456; offset < len; offset += 512) {
+			if (!strncmp(buf + offset, "DVHS", 4)) {
+				dvb_dmx_swfilter(demux, buf, offset);
+				if (len > offset + 52 + 4) {
+					/*16 bytes trailer + 36 bytes padding */
+					buf += offset + 52;
+					len -= offset + 52 + 4;
+					dvb_dmx_swfilter(demux, buf, len);
+				}
+				break;
+			}
+		}
+	}
+
+resend:
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret)
+		log(" usb_submit_urb failed: error %d", ret);
+}
+
+static int dvb_urb_init(struct pd_dvb_adapter *pd_dvb)
+{
+	if (pd_dvb->urb_array[0])
+		return 0;
+
+	alloc_bulk_urbs_generic(pd_dvb->urb_array, DVB_SBUF_NUM,
+			pd_dvb->pd_device->udev, pd_dvb->ep_addr,
+			DVB_URB_BUF_SIZE, GFP_KERNEL,
+			dvb_urb_irq, pd_dvb);
+	return 0;
+}
+
+static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb)
+{
+	free_all_urb_generic(pd_dvb->urb_array, DVB_SBUF_NUM);
+}
+
+static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb)
+{
+	struct poseidon *pd = pd_dvb->pd_device;
+	int ret = 0;
+
+	if (pd->state & POSEIDON_STATE_DISCONNECT)
+		return -ENODEV;
+
+	mutex_lock(&pd->lock);
+	if (!pd_dvb->is_streaming) {
+		s32 i, cmd_status = 0;
+		/*
+		 * Once upon a time, there was a difficult bug lying here.
+		 * ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+		 */
+
+		ret = send_set_req(pd, PLAY_SERVICE, 1, &cmd_status);
+		if (ret | cmd_status)
+			goto out;
+
+		ret = dvb_urb_init(pd_dvb);
+		if (ret < 0)
+			goto out;
+
+		pd_dvb->is_streaming = 1;
+		for (i = 0; i < DVB_SBUF_NUM; i++) {
+			ret = usb_submit_urb(pd_dvb->urb_array[i],
+						       GFP_KERNEL);
+			if (ret) {
+				log(" submit urb error %d", ret);
+				goto out;
+			}
+		}
+	}
+out:
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+void dvb_stop_streaming(struct pd_dvb_adapter *pd_dvb)
+{
+	struct poseidon *pd = pd_dvb->pd_device;
+
+	mutex_lock(&pd->lock);
+	if (pd_dvb->is_streaming) {
+		s32 i, ret, cmd_status = 0;
+
+		pd_dvb->is_streaming = 0;
+
+		for (i = 0; i < DVB_SBUF_NUM; i++)
+			if (pd_dvb->urb_array[i])
+				usb_kill_urb(pd_dvb->urb_array[i]);
+
+		ret = send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
+					&cmd_status);
+		if (ret | cmd_status)
+			log("error");
+	}
+	mutex_unlock(&pd->lock);
+}
+
+static int pd_start_feed(struct dvb_demux_feed *feed)
+{
+	struct pd_dvb_adapter *pd_dvb = feed->demux->priv;
+	int ret = 0;
+
+	if (!pd_dvb)
+		return -1;
+	if (atomic_inc_return(&pd_dvb->active_feed) == 1)
+		ret = dvb_start_streaming(pd_dvb);
+	return ret;
+}
+
+static int pd_stop_feed(struct dvb_demux_feed *feed)
+{
+	struct pd_dvb_adapter *pd_dvb = feed->demux->priv;
+
+	if (!pd_dvb)
+		return -1;
+	if (atomic_dec_and_test(&pd_dvb->active_feed))
+		dvb_stop_streaming(pd_dvb);
+	return 0;
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+int pd_dvb_usb_device_init(struct poseidon *pd)
+{
+	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+	struct dvb_demux *dvbdemux;
+	int ret = 0;
+
+	pd_dvb->ep_addr = 0x82;
+	atomic_set(&pd_dvb->users, 0);
+	atomic_set(&pd_dvb->active_feed, 0);
+	pd_dvb->pd_device = pd;
+
+	ret = dvb_register_adapter(&pd_dvb->dvb_adap,
+				"Poseidon dvbt adapter",
+				THIS_MODULE,
+				NULL /* for hibernation correctly*/,
+				adapter_nr);
+	if (ret < 0)
+		goto error1;
+
+	/* register frontend */
+	pd_dvb->dvb_fe.demodulator_priv = pd;
+	memcpy(&pd_dvb->dvb_fe.ops, &poseidon_frontend_ops,
+			sizeof(struct dvb_frontend_ops));
+	ret = dvb_register_frontend(&pd_dvb->dvb_adap, &pd_dvb->dvb_fe);
+	if (ret < 0)
+		goto error2;
+
+	/* register demux device */
+	dvbdemux = &pd_dvb->demux;
+	dvbdemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+	dvbdemux->priv = pd_dvb;
+	dvbdemux->feednum = dvbdemux->filternum = 64;
+	dvbdemux->start_feed = pd_start_feed;
+	dvbdemux->stop_feed = pd_stop_feed;
+	dvbdemux->write_to_decoder = NULL;
+
+	ret = dvb_dmx_init(dvbdemux);
+	if (ret < 0)
+		goto error3;
+
+	pd_dvb->dmxdev.filternum = pd_dvb->demux.filternum;
+	pd_dvb->dmxdev.demux = &pd_dvb->demux.dmx;
+	pd_dvb->dmxdev.capabilities = 0;
+
+	ret = dvb_dmxdev_init(&pd_dvb->dmxdev, &pd_dvb->dvb_adap);
+	if (ret < 0)
+		goto error3;
+	return 0;
+
+error3:
+	dvb_unregister_frontend(&pd_dvb->dvb_fe);
+error2:
+	dvb_unregister_adapter(&pd_dvb->dvb_adap);
+error1:
+	return ret;
+}
+
+void pd_dvb_usb_device_exit(struct poseidon *pd)
+{
+	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+	while (atomic_read(&pd_dvb->users) != 0
+		|| atomic_read(&pd_dvb->active_feed) != 0) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
+	}
+	dvb_dmxdev_release(&pd_dvb->dmxdev);
+	dvb_unregister_frontend(&pd_dvb->dvb_fe);
+	dvb_unregister_adapter(&pd_dvb->dvb_adap);
+	pd_dvb_usb_device_cleanup(pd);
+}
+
+void pd_dvb_usb_device_cleanup(struct poseidon *pd)
+{
+	struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+	dvb_urb_cleanup(pd_dvb);
+}
+
+int pd_dvb_get_adapter_num(struct pd_dvb_adapter *pd_dvb)
+{
+	return pd_dvb->dvb_adap.num;
+}
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c
new file mode 100644
index 0000000..b31f479
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-main.c
@@ -0,0 +1,553 @@
+/*
+ * device driver for Telegent tlg2300 based TV cards
+ *
+ * Author :
+ * 	Kang Yong	<kangyong@telegent.com>
+ * 	Zhang Xiaobing	<xbzhang@telegent.com>
+ * 	Huang Shijie	<zyziii@telegent.com> or <shijie8@gmail.com>
+ *
+ *	(c) 2009 Telegent Systems
+ *	(c) 2010 Telegent Systems
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/suspend.h>
+#include <linux/usb/quirks.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/firmware.h>
+
+#include "vendorcmds.h"
+#include "pd-common.h"
+
+#define VENDOR_ID	0x1B24
+#define PRODUCT_ID	0x4001
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+int debug_mode;
+module_param(debug_mode, int, 0644);
+MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose");
+
+#define TLG2300_FIRMWARE "tlg2300_firmware.bin"
+static const char *firmware_name = TLG2300_FIRMWARE;
+static LIST_HEAD(pd_device_list);
+
+/*
+ * send set request to USB firmware.
+ */
+s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status)
+{
+	s32 ret;
+	s8  data[32] = {};
+	u16 lower_16, upper_16;
+
+	if (pd->state & POSEIDON_STATE_DISCONNECT)
+		return -ENODEV;
+
+	mdelay(30);
+
+	if (param == 0) {
+		upper_16 = lower_16 = 0;
+	} else {
+		/* send 32 bit param as  two 16 bit param,little endian */
+		lower_16 = (unsigned short)(param & 0xffff);
+		upper_16 = (unsigned short)((param >> 16) & 0xffff);
+	}
+	ret = usb_control_msg(pd->udev,
+			 usb_rcvctrlpipe(pd->udev, 0),
+			 REQ_SET_CMD | cmdid,
+			 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			 lower_16,
+			 upper_16,
+			 &data,
+			 sizeof(*cmd_status),
+			 USB_CTRL_GET_TIMEOUT);
+
+	if (!ret) {
+		return -ENXIO;
+	} else {
+		/*  1st 4 bytes into cmd_status   */
+		memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status));
+	}
+	return 0;
+}
+
+/*
+ * send get request to Poseidon firmware.
+ */
+s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param,
+			void *buf, s32 *cmd_status, s32 datalen)
+{
+	s32 ret;
+	s8 data[128] = {};
+	u16 lower_16, upper_16;
+
+	if (pd->state & POSEIDON_STATE_DISCONNECT)
+		return -ENODEV;
+
+	mdelay(30);
+	if (param == 0) {
+		upper_16 = lower_16 = 0;
+	} else {
+		/*send 32 bit param as two 16 bit param, little endian */
+		lower_16 = (unsigned short)(param & 0xffff);
+		upper_16 = (unsigned short)((param >> 16) & 0xffff);
+	}
+	ret = usb_control_msg(pd->udev,
+			 usb_rcvctrlpipe(pd->udev, 0),
+			 REQ_GET_CMD | cmdid,
+			 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			 lower_16,
+			 upper_16,
+			 &data,
+			 (datalen + sizeof(*cmd_status)),
+			 USB_CTRL_GET_TIMEOUT);
+
+	if (ret < 0) {
+		return -ENXIO;
+	} else {
+		/* 1st 4 bytes into cmd_status, remaining data into cmd_data */
+		memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status));
+		memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen);
+	}
+	return 0;
+}
+
+static int pm_notifier_block(struct notifier_block *nb,
+				unsigned long event, void *dummy)
+{
+	struct poseidon *pd = NULL;
+	struct list_head *node, *next;
+
+	switch (event) {
+	case PM_POST_HIBERNATION:
+		list_for_each_safe(node, next, &pd_device_list) {
+			struct usb_device *udev;
+			struct usb_interface *iface;
+			int rc = 0;
+
+			pd = container_of(node, struct poseidon, device_list);
+			udev = pd->udev;
+			iface = pd->interface;
+
+			/* It will cause the system to reload the firmware */
+			rc = usb_lock_device_for_reset(udev, iface);
+			if (rc >= 0) {
+				usb_reset_device(udev);
+				usb_unlock_device(udev);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	log("event :%ld\n", event);
+	return 0;
+}
+
+static struct notifier_block pm_notifer = {
+	.notifier_call = pm_notifier_block,
+};
+
+int set_tuner_mode(struct poseidon *pd, unsigned char mode)
+{
+	s32 ret, cmd_status;
+
+	if (pd->state & POSEIDON_STATE_DISCONNECT)
+		return -ENODEV;
+
+	ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status);
+	if (ret || cmd_status)
+		return -ENXIO;
+	return 0;
+}
+
+void poseidon_delete(struct kref *kref)
+{
+	struct poseidon *pd = container_of(kref, struct poseidon, kref);
+
+	if (!pd)
+		return;
+	list_del_init(&pd->device_list);
+
+	pd_dvb_usb_device_cleanup(pd);
+	/* clean_audio_data(&pd->audio_data);*/
+
+	if (pd->udev) {
+		usb_put_dev(pd->udev);
+		pd->udev = NULL;
+	}
+	if (pd->interface) {
+		usb_put_intf(pd->interface);
+		pd->interface = NULL;
+	}
+	kfree(pd);
+	log();
+}
+
+static int firmware_download(struct usb_device *udev)
+{
+	int ret = 0, actual_length;
+	const struct firmware *fw = NULL;
+	void *fwbuf = NULL;
+	size_t fwlength = 0, offset;
+	size_t max_packet_size;
+
+	ret = request_firmware(&fw, firmware_name, &udev->dev);
+	if (ret) {
+		log("download err : %d", ret);
+		return ret;
+	}
+
+	fwlength = fw->size;
+
+	fwbuf = kmemdup(fw->data, fwlength, GFP_KERNEL);
+	if (!fwbuf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	max_packet_size = le16_to_cpu(udev->ep_out[0x1]->desc.wMaxPacketSize);
+	log("\t\t download size : %d", (int)max_packet_size);
+
+	for (offset = 0; offset < fwlength; offset += max_packet_size) {
+		actual_length = 0;
+		ret = usb_bulk_msg(udev,
+				usb_sndbulkpipe(udev, 0x01), /* ep 1 */
+				fwbuf + offset,
+				min(max_packet_size, fwlength - offset),
+				&actual_length,
+				HZ * 10);
+		if (ret)
+			break;
+	}
+	kfree(fwbuf);
+out:
+	release_firmware(fw);
+	return ret;
+}
+
+static inline struct poseidon *get_pd(struct usb_interface *intf)
+{
+	return usb_get_intfdata(intf);
+}
+
+#ifdef CONFIG_PM
+/* one-to-one map : poseidon{} <----> usb_device{}'s port */
+static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
+{
+	pd->portnum = udev->portnum;
+}
+
+static inline int get_autopm_ref(struct poseidon *pd)
+{
+	return  pd->video_data.users + pd->vbi_data.users + pd->audio.users
+		+ atomic_read(&pd->dvb_data.users) +
+		!list_empty(&pd->radio_data.fm_dev.fh_list);
+}
+
+/* fixup something for poseidon */
+static inline struct poseidon *fixup(struct poseidon *pd)
+{
+	int count;
+
+	/* old udev and interface have gone, so put back reference . */
+	count = get_autopm_ref(pd);
+	log("count : %d, ref count : %d", count, get_pm_count(pd));
+	while (count--)
+		usb_autopm_put_interface(pd->interface);
+	/*usb_autopm_set_interface(pd->interface); */
+
+	usb_put_dev(pd->udev);
+	usb_put_intf(pd->interface);
+	log("event : %d\n", pd->msg.event);
+	return pd;
+}
+
+static struct poseidon *find_old_poseidon(struct usb_device *udev)
+{
+	struct poseidon *pd;
+
+	list_for_each_entry(pd, &pd_device_list, device_list) {
+		if (pd->portnum == udev->portnum && in_hibernation(pd))
+			return fixup(pd);
+	}
+	return NULL;
+}
+
+/* Is the card working now ? */
+static inline int is_working(struct poseidon *pd)
+{
+	return get_pm_count(pd) > 0;
+}
+
+static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg)
+{
+	struct poseidon *pd = get_pd(intf);
+
+	if (!pd)
+		return 0;
+	if (!is_working(pd)) {
+		if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) {
+			pd->msg.event = PM_EVENT_AUTO_SUSPEND;
+			pd->pm_resume = NULL; /*  a good guard */
+			printk(KERN_DEBUG "TLG2300 auto suspend\n");
+		}
+		return 0;
+	}
+	pd->msg = msg; /* save it here */
+	logpm(pd);
+	return pd->pm_suspend ? pd->pm_suspend(pd) : 0;
+}
+
+static int poseidon_resume(struct usb_interface *intf)
+{
+	struct poseidon *pd = get_pd(intf);
+
+	if (!pd)
+		return 0;
+	printk(KERN_DEBUG "TLG2300 resume\n");
+
+	if (!is_working(pd)) {
+		if (PM_EVENT_AUTO_SUSPEND == pd->msg.event)
+			pd->msg = PMSG_ON;
+		return 0;
+	}
+	if (in_hibernation(pd)) {
+		logpm(pd);
+		return 0;
+	}
+	logpm(pd);
+	return pd->pm_resume ? pd->pm_resume(pd) : 0;
+}
+
+static void hibernation_resume(struct work_struct *w)
+{
+	struct poseidon *pd = container_of(w, struct poseidon, pm_work);
+	int count;
+
+	pd->msg.event = 0; /* clear it here */
+	pd->state &= ~POSEIDON_STATE_DISCONNECT;
+
+	/* set the new interface's reference */
+	count = get_autopm_ref(pd);
+	while (count--)
+		usb_autopm_get_interface(pd->interface);
+
+	/* resume the context */
+	logpm(pd);
+	if (pd->pm_resume)
+		pd->pm_resume(pd);
+}
+#else /* CONFIG_PM is not enabled: */
+static inline struct poseidon *find_old_poseidon(struct usb_device *udev)
+{
+	return NULL;
+}
+
+static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
+{
+}
+#endif
+
+static int check_firmware(struct usb_device *udev)
+{
+	void *buf;
+	int ret;
+	struct cmd_firmware_vers_s *cmd_firm;
+
+	buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	ret = usb_control_msg(udev,
+			 usb_rcvctrlpipe(udev, 0),
+			 REQ_GET_CMD | GET_FW_ID,
+			 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			 0,
+			 0,
+			 buf,
+			 sizeof(*cmd_firm) + sizeof(u32),
+			 USB_CTRL_GET_TIMEOUT);
+	kfree(buf);
+
+	if (ret < 0)
+		return firmware_download(udev);
+	return 0;
+}
+
+static int poseidon_probe(struct usb_interface *interface,
+				const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct poseidon *pd = NULL;
+	int ret = 0;
+	int new_one = 0;
+
+	/* download firmware */
+	ret = check_firmware(udev);
+	if (ret)
+		return ret;
+
+	/* Do I recovery from the hibernate ? */
+	pd = find_old_poseidon(udev);
+	if (!pd) {
+		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+		if (!pd)
+			return -ENOMEM;
+		kref_init(&pd->kref);
+		set_map_flags(pd, udev);
+		new_one = 1;
+	}
+
+	pd->udev	= usb_get_dev(udev);
+	pd->interface	= usb_get_intf(interface);
+	usb_set_intfdata(interface, pd);
+
+	if (new_one) {
+		logpm(pd);
+		mutex_init(&pd->lock);
+
+		/* register v4l2 device */
+		ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev);
+		if (ret)
+			goto err_v4l2;
+
+		/* register devices in directory /dev */
+		ret = pd_video_init(pd);
+		if (ret)
+			goto err_video;
+		ret = poseidon_audio_init(pd);
+		if (ret)
+			goto err_audio;
+		ret = poseidon_fm_init(pd);
+		if (ret)
+			goto err_fm;
+		ret = pd_dvb_usb_device_init(pd);
+		if (ret)
+			goto err_dvb;
+
+		INIT_LIST_HEAD(&pd->device_list);
+		list_add_tail(&pd->device_list, &pd_device_list);
+	}
+
+	device_init_wakeup(&udev->dev, 1);
+#ifdef CONFIG_PM
+	pm_runtime_set_autosuspend_delay(&pd->udev->dev,
+			1000 * PM_SUSPEND_DELAY);
+	usb_enable_autosuspend(pd->udev);
+
+	if (in_hibernation(pd)) {
+		INIT_WORK(&pd->pm_work, hibernation_resume);
+		schedule_work(&pd->pm_work);
+	}
+#endif
+	return 0;
+err_dvb:
+	poseidon_fm_exit(pd);
+err_fm:
+	poseidon_audio_free(pd);
+err_audio:
+	pd_video_exit(pd);
+err_video:
+	v4l2_device_unregister(&pd->v4l2_dev);
+err_v4l2:
+	usb_put_intf(pd->interface);
+	usb_put_dev(pd->udev);
+	kfree(pd);
+	return ret;
+}
+
+static void poseidon_disconnect(struct usb_interface *interface)
+{
+	struct poseidon *pd = get_pd(interface);
+
+	if (!pd)
+		return;
+	logpm(pd);
+	if (in_hibernation(pd))
+		return;
+
+	mutex_lock(&pd->lock);
+	pd->state |= POSEIDON_STATE_DISCONNECT;
+	mutex_unlock(&pd->lock);
+
+	/* stop urb transferring */
+	stop_all_video_stream(pd);
+	dvb_stop_streaming(&pd->dvb_data);
+
+	/*unregister v4l2 device */
+	v4l2_device_unregister(&pd->v4l2_dev);
+
+	pd_dvb_usb_device_exit(pd);
+	poseidon_fm_exit(pd);
+
+	poseidon_audio_free(pd);
+	pd_video_exit(pd);
+
+	usb_set_intfdata(interface, NULL);
+	kref_put(&pd->kref, poseidon_delete);
+}
+
+static struct usb_driver poseidon_driver = {
+	.name		= "poseidon",
+	.probe		= poseidon_probe,
+	.disconnect	= poseidon_disconnect,
+	.id_table	= id_table,
+#ifdef CONFIG_PM
+	.suspend	= poseidon_suspend,
+	.resume		= poseidon_resume,
+#endif
+	.supports_autosuspend = 1,
+};
+
+static int __init poseidon_init(void)
+{
+	int ret;
+
+	ret = usb_register(&poseidon_driver);
+	if (ret)
+		return ret;
+	register_pm_notifier(&pm_notifer);
+	return ret;
+}
+
+static void __exit poseidon_exit(void)
+{
+	log();
+	unregister_pm_notifier(&pm_notifer);
+	usb_deregister(&poseidon_driver);
+}
+
+module_init(poseidon_init);
+module_exit(poseidon_exit);
+
+MODULE_AUTHOR("Telegent Systems");
+MODULE_DESCRIPTION("For tlg2300-based USB device");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.2");
+MODULE_FIRMWARE(TLG2300_FIRMWARE);
diff --git a/drivers/media/usb/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c
new file mode 100644
index 0000000..b391194
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-radio.c
@@ -0,0 +1,339 @@
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bitmap.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <media/v4l2-dev.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <linux/sched.h>
+
+#include "pd-common.h"
+#include "vendorcmds.h"
+
+static int set_frequency(struct poseidon *p, __u32 frequency);
+static int poseidon_fm_close(struct file *filp);
+static int poseidon_fm_open(struct file *filp);
+
+#define TUNER_FREQ_MIN_FM 76000000U
+#define TUNER_FREQ_MAX_FM 108000000U
+
+#define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1)
+static int preemphasis[MAX_PREEMPHASIS] = {
+	TLG_TUNE_ASTD_NONE,   /* V4L2_PREEMPHASIS_DISABLED */
+	TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS    */
+	TLG_TUNE_ASTD_FM_US,  /* V4L2_PREEMPHASIS_75_uS    */
+};
+
+static int poseidon_check_mode_radio(struct poseidon *p)
+{
+	int ret;
+	u32 status;
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ/2);
+	ret = usb_set_interface(p->udev, 0, BULK_ALTERNATE_IFACE);
+	if (ret < 0)
+		goto out;
+
+	ret = set_tuner_mode(p, TLG_MODE_FM_RADIO);
+	if (ret != 0)
+		goto out;
+
+	ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status);
+	ret = send_set_req(p, TUNER_AUD_ANA_STD,
+				p->radio_data.pre_emphasis, &status);
+	ret |= send_set_req(p, TUNER_AUD_MODE,
+				TLG_TUNE_TVAUDIO_MODE_STEREO, &status);
+	ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL,
+				ATV_AUDIO_RATE_48K, &status);
+	ret |= send_set_req(p, TUNE_FREQ_SELECT, TUNER_FREQ_MIN_FM, &status);
+out:
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int pm_fm_suspend(struct poseidon *p)
+{
+	logpm(p);
+	pm_alsa_suspend(p);
+	usb_set_interface(p->udev, 0, 0);
+	msleep(300);
+	return 0;
+}
+
+static int pm_fm_resume(struct poseidon *p)
+{
+	logpm(p);
+	poseidon_check_mode_radio(p);
+	set_frequency(p, p->radio_data.fm_freq);
+	pm_alsa_resume(p);
+	return 0;
+}
+#endif
+
+static int poseidon_fm_open(struct file *filp)
+{
+	struct poseidon *p = video_drvdata(filp);
+	int ret = 0;
+
+	mutex_lock(&p->lock);
+	if (p->state & POSEIDON_STATE_DISCONNECT) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (p->state && !(p->state & POSEIDON_STATE_FM)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	ret = v4l2_fh_open(filp);
+	if (ret)
+		goto out;
+
+	usb_autopm_get_interface(p->interface);
+	if (0 == p->state) {
+		struct video_device *vfd = &p->radio_data.fm_dev;
+
+		/* default pre-emphasis */
+		if (p->radio_data.pre_emphasis == 0)
+			p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR;
+		set_debug_mode(vfd, debug_mode);
+
+		ret = poseidon_check_mode_radio(p);
+		if (ret < 0) {
+			usb_autopm_put_interface(p->interface);
+			goto out;
+		}
+		p->state |= POSEIDON_STATE_FM;
+	}
+	kref_get(&p->kref);
+out:
+	mutex_unlock(&p->lock);
+	return ret;
+}
+
+static int poseidon_fm_close(struct file *filp)
+{
+	struct poseidon *p = video_drvdata(filp);
+	struct radio_data *fm = &p->radio_data;
+	uint32_t status;
+
+	mutex_lock(&p->lock);
+	if (v4l2_fh_is_singular_file(filp))
+		p->state &= ~POSEIDON_STATE_FM;
+
+	if (fm->is_radio_streaming && filp == p->file_for_stream) {
+		fm->is_radio_streaming = 0;
+		send_set_req(p, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, &status);
+	}
+	usb_autopm_put_interface(p->interface);
+	mutex_unlock(&p->lock);
+
+	kref_put(&p->kref, poseidon_delete);
+	return v4l2_fh_release(filp);
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+			struct v4l2_capability *v)
+{
+	struct poseidon *p = video_drvdata(file);
+
+	strlcpy(v->driver, "tele-radio", sizeof(v->driver));
+	strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
+	usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info));
+	v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+	/* Report all capabilities of the USB device */
+	v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS |
+			V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
+			V4L2_CAP_AUDIO | V4L2_CAP_STREAMING |
+			V4L2_CAP_READWRITE;
+	return 0;
+}
+
+static const struct v4l2_file_operations poseidon_fm_fops = {
+	.owner         = THIS_MODULE,
+	.open          = poseidon_fm_open,
+	.release       = poseidon_fm_close,
+	.poll		= v4l2_ctrl_poll,
+	.unlocked_ioctl = video_ioctl2,
+};
+
+static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
+				 struct v4l2_tuner *vt)
+{
+	struct poseidon *p = video_drvdata(file);
+	struct tuner_fm_sig_stat_s fm_stat = {};
+	int ret, status, count = 5;
+
+	if (vt->index != 0)
+		return -EINVAL;
+
+	vt->type	= V4L2_TUNER_RADIO;
+	vt->capability	= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
+	vt->rangelow	= TUNER_FREQ_MIN_FM * 2 / 125;
+	vt->rangehigh	= TUNER_FREQ_MAX_FM * 2 / 125;
+	vt->rxsubchans	= V4L2_TUNER_SUB_STEREO;
+	vt->audmode	= V4L2_TUNER_MODE_STEREO;
+	vt->signal	= 0;
+	vt->afc 	= 0;
+	strlcpy(vt->name, "Radio", sizeof(vt->name));
+
+	mutex_lock(&p->lock);
+	ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
+			      &fm_stat, &status, sizeof(fm_stat));
+
+	while (fm_stat.sig_lock_busy && count-- && !ret) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
+
+		ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
+				  &fm_stat, &status, sizeof(fm_stat));
+	}
+	mutex_unlock(&p->lock);
+
+	if (ret || status) {
+		vt->signal = 0;
+	} else if ((fm_stat.sig_present || fm_stat.sig_locked)
+			&& fm_stat.sig_strength == 0) {
+		vt->signal = 0xffff;
+	} else
+		vt->signal = (fm_stat.sig_strength * 255 / 10) << 8;
+
+	return 0;
+}
+
+static int fm_get_freq(struct file *file, void *priv,
+		       struct v4l2_frequency *argp)
+{
+	struct poseidon *p = video_drvdata(file);
+
+	if (argp->tuner)
+		return -EINVAL;
+	argp->frequency = p->radio_data.fm_freq;
+	return 0;
+}
+
+static int set_frequency(struct poseidon *p, __u32 frequency)
+{
+	__u32 freq ;
+	int ret, status;
+
+	mutex_lock(&p->lock);
+
+	ret = send_set_req(p, TUNER_AUD_ANA_STD,
+				p->radio_data.pre_emphasis, &status);
+
+	freq = (frequency * 125) / 2; /* Hz */
+	freq = clamp(freq, TUNER_FREQ_MIN_FM, TUNER_FREQ_MAX_FM);
+
+	ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status);
+	if (ret < 0)
+		goto error ;
+	ret = send_set_req(p, TAKE_REQUEST, 0, &status);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ/4);
+	if (!p->radio_data.is_radio_streaming) {
+		ret = send_set_req(p, TAKE_REQUEST, 0, &status);
+		ret = send_set_req(p, PLAY_SERVICE,
+				TLG_TUNE_PLAY_SVC_START, &status);
+		p->radio_data.is_radio_streaming = 1;
+	}
+	p->radio_data.fm_freq = freq * 2 / 125;
+error:
+	mutex_unlock(&p->lock);
+	return ret;
+}
+
+static int fm_set_freq(struct file *file, void *priv,
+		       const struct v4l2_frequency *argp)
+{
+	struct poseidon *p = video_drvdata(file);
+
+	if (argp->tuner)
+		return -EINVAL;
+	p->file_for_stream = file;
+#ifdef CONFIG_PM
+	p->pm_suspend = pm_fm_suspend;
+	p->pm_resume  = pm_fm_resume;
+#endif
+	return set_frequency(p, argp->frequency);
+}
+
+static int tlg_fm_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct poseidon *p = container_of(ctrl->handler, struct poseidon,
+						radio_data.ctrl_handler);
+	int pre_emphasis;
+	u32 status;
+
+	switch (ctrl->id) {
+	case V4L2_CID_TUNE_PREEMPHASIS:
+		pre_emphasis = preemphasis[ctrl->val];
+		send_set_req(p, TUNER_AUD_ANA_STD, pre_emphasis, &status);
+		p->radio_data.pre_emphasis = pre_emphasis;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
+{
+	return vt->index > 0 ? -EINVAL : 0;
+}
+
+static const struct v4l2_ctrl_ops tlg_fm_ctrl_ops = {
+	.s_ctrl = tlg_fm_s_ctrl,
+};
+
+static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
+	.vidioc_querycap    = vidioc_querycap,
+	.vidioc_s_tuner     = vidioc_s_tuner,
+	.vidioc_g_tuner     = tlg_fm_vidioc_g_tuner,
+	.vidioc_g_frequency = fm_get_freq,
+	.vidioc_s_frequency = fm_set_freq,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static struct video_device poseidon_fm_template = {
+	.name       = "Telegent-Radio",
+	.fops       = &poseidon_fm_fops,
+	.minor      = -1,
+	.release    = video_device_release_empty,
+	.ioctl_ops  = &poseidon_fm_ioctl_ops,
+};
+
+int poseidon_fm_init(struct poseidon *p)
+{
+	struct video_device *vfd = &p->radio_data.fm_dev;
+	struct v4l2_ctrl_handler *hdl = &p->radio_data.ctrl_handler;
+
+	*vfd = poseidon_fm_template;
+
+	set_frequency(p, TUNER_FREQ_MIN_FM);
+	v4l2_ctrl_handler_init(hdl, 1);
+	v4l2_ctrl_new_std_menu(hdl, &tlg_fm_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS,
+			V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
+	if (hdl->error) {
+		v4l2_ctrl_handler_free(hdl);
+		return hdl->error;
+	}
+	vfd->v4l2_dev = &p->v4l2_dev;
+	vfd->ctrl_handler = hdl;
+	video_set_drvdata(vfd, p);
+	return video_register_device(vfd, VFL_TYPE_RADIO, -1);
+}
+
+int poseidon_fm_exit(struct poseidon *p)
+{
+	video_unregister_device(&p->radio_data.fm_dev);
+	v4l2_ctrl_handler_free(&p->radio_data.ctrl_handler);
+	return 0;
+}
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
new file mode 100644
index 0000000..8cd7f02
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-video.c
@@ -0,0 +1,1570 @@
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/videodev2.h>
+#include <linux/usb.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ctrls.h>
+
+#include "pd-common.h"
+#include "vendorcmds.h"
+
+#ifdef CONFIG_PM
+static int pm_video_suspend(struct poseidon *pd);
+static int pm_video_resume(struct poseidon *pd);
+#endif
+static void iso_bubble_handler(struct work_struct *w);
+
+static int usb_transfer_mode;
+module_param(usb_transfer_mode, int, 0644);
+MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous");
+
+static const struct poseidon_format poseidon_formats[] = {
+	{ "YUV 422", V4L2_PIX_FMT_YUYV, 16, 0},
+	{ "RGB565", V4L2_PIX_FMT_RGB565, 16, 0},
+};
+
+static const struct poseidon_tvnorm poseidon_tvnorms[] = {
+	{ V4L2_STD_PAL_D, "PAL-D",  TLG_TUNE_VSTD_PAL_D },
+	{ V4L2_STD_PAL_B, "PAL-B",  TLG_TUNE_VSTD_PAL_B },
+	{ V4L2_STD_PAL_G, "PAL-G",  TLG_TUNE_VSTD_PAL_G },
+	{ V4L2_STD_PAL_H, "PAL-H",  TLG_TUNE_VSTD_PAL_H },
+	{ V4L2_STD_PAL_I, "PAL-I",  TLG_TUNE_VSTD_PAL_I },
+	{ V4L2_STD_PAL_M, "PAL-M",  TLG_TUNE_VSTD_PAL_M },
+	{ V4L2_STD_PAL_N, "PAL-N",  TLG_TUNE_VSTD_PAL_N_COMBO },
+	{ V4L2_STD_PAL_Nc, "PAL-Nc", TLG_TUNE_VSTD_PAL_N_COMBO },
+	{ V4L2_STD_NTSC_M, "NTSC-M", TLG_TUNE_VSTD_NTSC_M },
+	{ V4L2_STD_NTSC_M_JP, "NTSC-JP", TLG_TUNE_VSTD_NTSC_M_J },
+	{ V4L2_STD_SECAM_B, "SECAM-B", TLG_TUNE_VSTD_SECAM_B },
+	{ V4L2_STD_SECAM_D, "SECAM-D", TLG_TUNE_VSTD_SECAM_D },
+	{ V4L2_STD_SECAM_G, "SECAM-G", TLG_TUNE_VSTD_SECAM_G },
+	{ V4L2_STD_SECAM_H, "SECAM-H", TLG_TUNE_VSTD_SECAM_H },
+	{ V4L2_STD_SECAM_K, "SECAM-K", TLG_TUNE_VSTD_SECAM_K },
+	{ V4L2_STD_SECAM_K1, "SECAM-K1", TLG_TUNE_VSTD_SECAM_K1 },
+	{ V4L2_STD_SECAM_L, "SECAM-L", TLG_TUNE_VSTD_SECAM_L },
+	{ V4L2_STD_SECAM_LC, "SECAM-LC", TLG_TUNE_VSTD_SECAM_L1 },
+};
+static const unsigned int POSEIDON_TVNORMS = ARRAY_SIZE(poseidon_tvnorms);
+
+struct pd_audio_mode {
+	u32 tlg_audio_mode;
+	u32 v4l2_audio_sub;
+	u32 v4l2_audio_mode;
+};
+
+static const struct pd_audio_mode pd_audio_modes[] = {
+	{ TLG_TUNE_TVAUDIO_MODE_MONO, V4L2_TUNER_SUB_MONO,
+		V4L2_TUNER_MODE_MONO },
+	{ TLG_TUNE_TVAUDIO_MODE_STEREO, V4L2_TUNER_SUB_STEREO,
+		V4L2_TUNER_MODE_STEREO },
+	{ TLG_TUNE_TVAUDIO_MODE_LANG_A, V4L2_TUNER_SUB_LANG1,
+		V4L2_TUNER_MODE_LANG1 },
+	{ TLG_TUNE_TVAUDIO_MODE_LANG_B, V4L2_TUNER_SUB_LANG2,
+		V4L2_TUNER_MODE_LANG2 },
+	{ TLG_TUNE_TVAUDIO_MODE_LANG_C, V4L2_TUNER_SUB_LANG1,
+		V4L2_TUNER_MODE_LANG1_LANG2 }
+};
+static const unsigned int POSEIDON_AUDIOMODS = ARRAY_SIZE(pd_audio_modes);
+
+struct pd_input {
+	char *name;
+	uint32_t tlg_src;
+};
+
+static const struct pd_input pd_inputs[] = {
+	{ "TV Antenna", TLG_SIG_SRC_ANTENNA },
+	{ "TV Cable", TLG_SIG_SRC_CABLE },
+	{ "TV SVideo", TLG_SIG_SRC_SVIDEO },
+	{ "TV Composite", TLG_SIG_SRC_COMPOSITE }
+};
+static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs);
+
+struct video_std_to_audio_std {
+	v4l2_std_id	video_std;
+	int 		audio_std;
+};
+
+static const struct video_std_to_audio_std video_to_audio_map[] = {
+	/* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64,
+			65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */
+	{ (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D |
+		V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM },
+
+	/* country : { 1, 52, 54, 55, 886 } */
+	{V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC},
+
+	/* country : { 81 } */
+	{ V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ },
+
+	/* other country : TLG_TUNE_ASTD_A2 */
+};
+static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map);
+
+static int get_audio_std(v4l2_std_id v4l2_std)
+{
+	int i = 0;
+
+	for (; i < map_size; i++) {
+		if (v4l2_std & video_to_audio_map[i].video_std)
+			return video_to_audio_map[i].audio_std;
+	}
+	return TLG_TUNE_ASTD_A2;
+}
+
+static int vidioc_querycap(struct file *file, void *fh,
+			struct v4l2_capability *cap)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct poseidon *p = video_get_drvdata(vdev);
+
+	strcpy(cap->driver, "tele-video");
+	strcpy(cap->card, "Telegent Poseidon");
+	usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info));
+	cap->device_caps = V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
+			V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+	if (vdev->vfl_type == VFL_TYPE_VBI)
+		cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
+	else
+		cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
+		V4L2_CAP_RADIO | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE;
+	return 0;
+}
+
+/*====================================================================*/
+static void init_copy(struct video_data *video, bool index)
+{
+	struct front_face *front = video->front;
+
+	video->field_count	= index;
+	video->lines_copied	= 0;
+	video->prev_left	= 0 ;
+	video->dst 		= (char *)videobuf_to_vmalloc(front->curr_frame)
+					+ index * video->lines_size;
+	video->vbi->copied 	= 0; /* set it here */
+}
+
+static bool get_frame(struct front_face *front, int *need_init)
+{
+	struct videobuf_buffer *vb = front->curr_frame;
+
+	if (vb)
+		return true;
+
+	spin_lock(&front->queue_lock);
+	if (!list_empty(&front->active)) {
+		vb = list_entry(front->active.next,
+			       struct videobuf_buffer, queue);
+		if (need_init)
+			*need_init = 1;
+		front->curr_frame = vb;
+		list_del_init(&vb->queue);
+	}
+	spin_unlock(&front->queue_lock);
+
+	return !!vb;
+}
+
+/* check if the video's buffer is ready */
+static bool get_video_frame(struct front_face *front, struct video_data *video)
+{
+	int need_init = 0;
+	bool ret = true;
+
+	ret = get_frame(front, &need_init);
+	if (ret && need_init)
+		init_copy(video, 0);
+	return ret;
+}
+
+static void submit_frame(struct front_face *front)
+{
+	struct videobuf_buffer *vb = front->curr_frame;
+
+	if (vb == NULL)
+		return;
+
+	front->curr_frame	= NULL;
+	vb->state		= VIDEOBUF_DONE;
+	vb->field_count++;
+	v4l2_get_timestamp(&vb->ts);
+
+	wake_up(&vb->done);
+}
+
+/*
+ * A frame is composed of two fields. If we receive all the two fields,
+ * call the  submit_frame() to submit the whole frame to applications.
+ */
+static void end_field(struct video_data *video)
+{
+	if (1 == video->field_count)
+		submit_frame(video->front);
+	else
+		init_copy(video, 1);
+}
+
+static void copy_video_data(struct video_data *video, char *src,
+				unsigned int count)
+{
+#define copy_data(len)  \
+	do { \
+		if (++video->lines_copied > video->lines_per_field) \
+			goto overflow; \
+		memcpy(video->dst, src, len);\
+		video->dst += len + video->lines_size; \
+		src += len; \
+		count -= len; \
+	 } while (0)
+
+	while (count && count >= video->lines_size) {
+		if (video->prev_left) {
+			copy_data(video->prev_left);
+			video->prev_left = 0;
+			continue;
+		}
+		copy_data(video->lines_size);
+	}
+	if (count && count < video->lines_size) {
+		memcpy(video->dst, src, count);
+
+		video->prev_left = video->lines_size - count;
+		video->dst += count;
+	}
+	return;
+
+overflow:
+	end_field(video);
+}
+
+static void check_trailer(struct video_data *video, char *src, int count)
+{
+	struct vbi_data *vbi = video->vbi;
+	int offset; /* trailer's offset */
+	char *buf;
+
+	offset = (video->context.pix.sizeimage / 2 + vbi->vbi_size / 2)
+		- (vbi->copied + video->lines_size * video->lines_copied);
+	if (video->prev_left)
+		offset -= (video->lines_size - video->prev_left);
+
+	if (offset > count || offset <= 0)
+		goto short_package;
+
+	buf = src + offset;
+
+	/* trailer : (VFHS) + U32 + U32 + field_num */
+	if (!strncmp(buf, "VFHS", 4)) {
+		int field_num = *((u32 *)(buf + 12));
+
+		if ((field_num & 1) ^ video->field_count) {
+			init_copy(video, video->field_count);
+			return;
+		}
+		copy_video_data(video, src, offset);
+	}
+short_package:
+	end_field(video);
+}
+
+/* ==========  Check this more carefully! =========== */
+static inline void copy_vbi_data(struct vbi_data *vbi,
+				char *src, unsigned int count)
+{
+	struct front_face *front = vbi->front;
+
+	if (front && get_frame(front, NULL)) {
+		char *buf = videobuf_to_vmalloc(front->curr_frame);
+
+		if (vbi->video->field_count)
+			buf += (vbi->vbi_size / 2);
+		memcpy(buf + vbi->copied, src, count);
+	}
+	vbi->copied += count;
+}
+
+/*
+ * Copy the normal data (VBI or VIDEO) without the trailer.
+ * VBI is not interlaced, while VIDEO is interlaced.
+ */
+static inline void copy_vbi_video_data(struct video_data *video,
+				char *src, unsigned int count)
+{
+	struct vbi_data *vbi = video->vbi;
+	unsigned int vbi_delta = (vbi->vbi_size / 2) - vbi->copied;
+
+	if (vbi_delta >= count) {
+		copy_vbi_data(vbi, src, count);
+	} else {
+		if (vbi_delta) {
+			copy_vbi_data(vbi, src, vbi_delta);
+
+			/* we receive the two fields of the VBI*/
+			if (vbi->front && video->field_count)
+				submit_frame(vbi->front);
+		}
+		copy_video_data(video, src + vbi_delta, count - vbi_delta);
+	}
+}
+
+static void urb_complete_bulk(struct urb *urb)
+{
+	struct front_face *front = urb->context;
+	struct video_data *video = &front->pd->video_data;
+	char *src = (char *)urb->transfer_buffer;
+	int count = urb->actual_length;
+	int ret = 0;
+
+	if (!video->is_streaming || urb->status) {
+		if (urb->status == -EPROTO)
+			goto resend_it;
+		return;
+	}
+	if (!get_video_frame(front, video))
+		goto resend_it;
+
+	if (count == urb->transfer_buffer_length)
+		copy_vbi_video_data(video, src, count);
+	else
+		check_trailer(video, src, count);
+
+resend_it:
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret)
+		log(" submit failed: error %d", ret);
+}
+
+/************************* for ISO *********************/
+#define GET_SUCCESS		(0)
+#define GET_TRAILER		(1)
+#define GET_TOO_MUCH_BUBBLE	(2)
+#define GET_NONE		(3)
+static int get_chunk(int start, struct urb *urb,
+			int *head, int *tail, int *bubble_err)
+{
+	struct usb_iso_packet_descriptor *pkt = NULL;
+	int ret = GET_SUCCESS;
+
+	for (*head = *tail = -1; start < urb->number_of_packets; start++) {
+		pkt = &urb->iso_frame_desc[start];
+
+		/* handle the bubble of the Hub */
+		if (-EOVERFLOW == pkt->status) {
+			if (++*bubble_err > urb->number_of_packets / 3)
+				return GET_TOO_MUCH_BUBBLE;
+			continue;
+		}
+
+		/* This is the gap */
+		if (pkt->status || pkt->actual_length <= 0
+				|| pkt->actual_length > ISO_PKT_SIZE) {
+			if (*head != -1)
+				break;
+			continue;
+		}
+
+		/* a good isochronous packet */
+		if (pkt->actual_length == ISO_PKT_SIZE) {
+			if (*head == -1)
+				*head = start;
+			*tail = start;
+			continue;
+		}
+
+		/* trailer is here */
+		if (pkt->actual_length < ISO_PKT_SIZE) {
+			if (*head == -1) {
+				*head = start;
+				*tail = start;
+				return GET_TRAILER;
+			}
+			break;
+		}
+	}
+
+	if (*head == -1 && *tail == -1)
+		ret = GET_NONE;
+	return ret;
+}
+
+/*
+ * |__|------|___|-----|_______|
+ *       ^          ^
+ *       |          |
+ *      gap        gap
+ */
+static void urb_complete_iso(struct urb *urb)
+{
+	struct front_face *front = urb->context;
+	struct video_data *video = &front->pd->video_data;
+	int bubble_err = 0, head = 0, tail = 0;
+	char *src = (char *)urb->transfer_buffer;
+	int ret = 0;
+
+	if (!video->is_streaming)
+		return;
+
+	do {
+		if (!get_video_frame(front, video))
+			goto out;
+
+		switch (get_chunk(head, urb, &head, &tail, &bubble_err)) {
+		case GET_SUCCESS:
+			copy_vbi_video_data(video, src + (head * ISO_PKT_SIZE),
+					(tail - head + 1) * ISO_PKT_SIZE);
+			break;
+		case GET_TRAILER:
+			check_trailer(video, src + (head * ISO_PKT_SIZE),
+					ISO_PKT_SIZE);
+			break;
+		case GET_NONE:
+			goto out;
+		case GET_TOO_MUCH_BUBBLE:
+			log("\t We got too much bubble");
+			schedule_work(&video->bubble_work);
+			return;
+		}
+	} while (head = tail + 1, head < urb->number_of_packets);
+
+out:
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret)
+		log("usb_submit_urb err : %d", ret);
+}
+/*============================= [  end  ] =====================*/
+
+static int prepare_iso_urb(struct video_data *video)
+{
+	struct usb_device *udev = video->pd->udev;
+	int i;
+
+	if (video->urb_array[0])
+		return 0;
+
+	for (i = 0; i < SBUF_NUM; i++) {
+		struct urb *urb;
+		void *mem;
+		int j;
+
+		urb = usb_alloc_urb(PK_PER_URB, GFP_KERNEL);
+		if (urb == NULL)
+			goto out;
+
+		video->urb_array[i] = urb;
+		mem = usb_alloc_coherent(udev,
+					 ISO_PKT_SIZE * PK_PER_URB,
+					 GFP_KERNEL,
+					 &urb->transfer_dma);
+
+		urb->complete	= urb_complete_iso;	/* handler */
+		urb->dev	= udev;
+		urb->context	= video->front;
+		urb->pipe	= usb_rcvisocpipe(udev,
+						video->endpoint_addr);
+		urb->interval	= 1;
+		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+		urb->number_of_packets	= PK_PER_URB;
+		urb->transfer_buffer	= mem;
+		urb->transfer_buffer_length = PK_PER_URB * ISO_PKT_SIZE;
+
+		for (j = 0; j < PK_PER_URB; j++) {
+			urb->iso_frame_desc[j].offset = ISO_PKT_SIZE * j;
+			urb->iso_frame_desc[j].length = ISO_PKT_SIZE;
+		}
+	}
+	return 0;
+out:
+	for (; i > 0; i--)
+		;
+	return -ENOMEM;
+}
+
+/* return the succeeded number of the allocation */
+int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
+			struct usb_device *udev, u8 ep_addr,
+			int buf_size, gfp_t gfp_flags,
+			usb_complete_t complete_fn, void *context)
+{
+	int i = 0;
+
+	for (; i < num; i++) {
+		void *mem;
+		struct urb *urb = usb_alloc_urb(0, gfp_flags);
+		if (urb == NULL)
+			return i;
+
+		mem = usb_alloc_coherent(udev, buf_size, gfp_flags,
+					 &urb->transfer_dma);
+		if (mem == NULL) {
+			usb_free_urb(urb);
+			return i;
+		}
+
+		usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr),
+				mem, buf_size, complete_fn, context);
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		urb_array[i] = urb;
+	}
+	return i;
+}
+
+void free_all_urb_generic(struct urb **urb_array, int num)
+{
+	int i;
+	struct urb *urb;
+
+	for (i = 0; i < num; i++) {
+		urb = urb_array[i];
+		if (urb) {
+			usb_free_coherent(urb->dev,
+					urb->transfer_buffer_length,
+					urb->transfer_buffer,
+					urb->transfer_dma);
+			usb_free_urb(urb);
+			urb_array[i] = NULL;
+		}
+	}
+}
+
+static int prepare_bulk_urb(struct video_data *video)
+{
+	if (video->urb_array[0])
+		return 0;
+
+	alloc_bulk_urbs_generic(video->urb_array, SBUF_NUM,
+			video->pd->udev, video->endpoint_addr,
+			0x2000, GFP_KERNEL,
+			urb_complete_bulk, video->front);
+	return 0;
+}
+
+/* free the URBs */
+static void free_all_urb(struct video_data *video)
+{
+	free_all_urb_generic(video->urb_array, SBUF_NUM);
+}
+
+static void pd_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	videobuf_vmalloc_free(vb);
+	vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static void pd_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct front_face *front = q->priv_data;
+	vb->state = VIDEOBUF_QUEUED;
+	list_add_tail(&vb->queue, &front->active);
+}
+
+static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+			   enum v4l2_field field)
+{
+	struct front_face *front = q->priv_data;
+	int rc;
+
+	switch (front->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		if (VIDEOBUF_NEEDS_INIT == vb->state) {
+			struct v4l2_pix_format *pix;
+
+			pix = &front->pd->video_data.context.pix;
+			vb->size	= pix->sizeimage; /* real frame size */
+			vb->width	= pix->width;
+			vb->height	= pix->height;
+			rc = videobuf_iolock(q, vb, NULL);
+			if (rc < 0)
+				return rc;
+		}
+		break;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		if (VIDEOBUF_NEEDS_INIT == vb->state) {
+			vb->size	= front->pd->vbi_data.vbi_size;
+			rc = videobuf_iolock(q, vb, NULL);
+			if (rc < 0)
+				return rc;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	vb->field = field;
+	vb->state = VIDEOBUF_PREPARED;
+	return 0;
+}
+
+static int fire_all_urb(struct video_data *video)
+{
+	int i, ret;
+
+	video->is_streaming = 1;
+
+	for (i = 0; i < SBUF_NUM; i++) {
+		ret = usb_submit_urb(video->urb_array[i], GFP_KERNEL);
+		if (ret)
+			log("(%d) failed: error %d", i, ret);
+	}
+	return ret;
+}
+
+static int start_video_stream(struct poseidon *pd)
+{
+	struct video_data *video = &pd->video_data;
+	s32 cmd_status;
+
+	send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+	send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_START, &cmd_status);
+
+	if (pd->cur_transfer_mode) {
+		prepare_iso_urb(video);
+		INIT_WORK(&video->bubble_work, iso_bubble_handler);
+	} else {
+		/* The bulk mode does not need a bubble handler */
+		prepare_bulk_urb(video);
+	}
+	fire_all_urb(video);
+	return 0;
+}
+
+static int pd_buf_setup(struct videobuf_queue *q, unsigned int *count,
+		       unsigned int *size)
+{
+	struct front_face *front = q->priv_data;
+	struct poseidon *pd	= front->pd;
+
+	switch (front->type) {
+	default:
+		return -EINVAL;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+		struct video_data *video = &pd->video_data;
+		struct v4l2_pix_format *pix = &video->context.pix;
+
+		*size = PAGE_ALIGN(pix->sizeimage);/* page aligned frame size */
+		if (*count < 4)
+			*count = 4;
+		if (1) {
+			/* same in different altersetting */
+			video->endpoint_addr	= 0x82;
+			video->vbi		= &pd->vbi_data;
+			video->vbi->video	= video;
+			video->pd		= pd;
+			video->lines_per_field	= pix->height / 2;
+			video->lines_size	= pix->width * 2;
+			video->front 		= front;
+		}
+		return start_video_stream(pd);
+	}
+
+	case V4L2_BUF_TYPE_VBI_CAPTURE: {
+		struct vbi_data *vbi = &pd->vbi_data;
+
+		*size = PAGE_ALIGN(vbi->vbi_size);
+		log("size : %d", *size);
+		if (*count == 0)
+			*count = 4;
+	}
+		break;
+	}
+	return 0;
+}
+
+static struct videobuf_queue_ops pd_video_qops = {
+	.buf_setup      = pd_buf_setup,
+	.buf_prepare    = pd_buf_prepare,
+	.buf_queue      = pd_buf_queue,
+	.buf_release    = pd_buf_release,
+};
+
+static int vidioc_enum_fmt(struct file *file, void *fh,
+				struct v4l2_fmtdesc *f)
+{
+	if (ARRAY_SIZE(poseidon_formats) <= f->index)
+		return -EINVAL;
+	f->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	f->flags	= 0;
+	f->pixelformat	= poseidon_formats[f->index].fourcc;
+	strcpy(f->description, poseidon_formats[f->index].name);
+	return 0;
+}
+
+static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct front_face *front = fh;
+	struct poseidon *pd = front->pd;
+
+	f->fmt.pix = pd->video_data.context.pix;
+	return 0;
+}
+
+/*
+ * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while
+ * Mplayer calls them in the reverse order.
+ */
+static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix)
+{
+	struct video_data *video	= &pd->video_data;
+	struct running_context *context = &video->context;
+	struct v4l2_pix_format *pix_def	= &context->pix;
+	s32 ret = 0, cmd_status = 0, vid_resol;
+
+	/* set the pixel format to firmware */
+	if (pix->pixelformat == V4L2_PIX_FMT_RGB565) {
+		vid_resol = TLG_TUNER_VID_FORMAT_RGB_565;
+	} else {
+		pix->pixelformat = V4L2_PIX_FMT_YUYV;
+		vid_resol = TLG_TUNER_VID_FORMAT_YUV;
+	}
+	ret = send_set_req(pd, VIDEO_STREAM_FMT_SEL,
+				vid_resol, &cmd_status);
+
+	/* set the resolution to firmware */
+	vid_resol = TLG_TUNE_VID_RES_720;
+	switch (pix->width) {
+	case 704:
+		vid_resol = TLG_TUNE_VID_RES_704;
+		break;
+	default:
+		pix->width = 720;
+	case 720:
+		break;
+	}
+	ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
+				vid_resol, &cmd_status);
+	if (ret || cmd_status)
+		return -EBUSY;
+
+	pix_def->pixelformat = pix->pixelformat; /* save it */
+	pix->height = (context->tvnormid & V4L2_STD_525_60) ?  480 : 576;
+
+	/* Compare with the default setting */
+	if ((pix_def->width != pix->width)
+		|| (pix_def->height != pix->height)) {
+		pix_def->width		= pix->width;
+		pix_def->height		= pix->height;
+		pix_def->bytesperline	= pix->width * 2;
+		pix_def->sizeimage 	= pix->width * pix->height * 2;
+	}
+	*pix = *pix_def;
+
+	return 0;
+}
+
+static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct front_face *front	= fh;
+	struct poseidon *pd		= front->pd;
+
+	/* stop VBI here */
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
+		return -EINVAL;
+
+	mutex_lock(&pd->lock);
+	if (pd->file_for_stream == NULL)
+		pd->file_for_stream = file;
+	else if (file != pd->file_for_stream) {
+		mutex_unlock(&pd->lock);
+		return -EINVAL;
+	}
+
+	pd_vidioc_s_fmt(pd, &f->fmt.pix);
+	mutex_unlock(&pd->lock);
+	return 0;
+}
+
+static int vidioc_g_fmt_vbi(struct file *file, void *fh,
+			       struct v4l2_format *v4l2_f)
+{
+	struct front_face *front	= fh;
+	struct poseidon *pd		= front->pd;
+	struct v4l2_vbi_format *vbi_fmt	= &v4l2_f->fmt.vbi;
+
+	vbi_fmt->samples_per_line	= 720 * 2;
+	vbi_fmt->sampling_rate		= 6750000 * 4;
+	vbi_fmt->sample_format		= V4L2_PIX_FMT_GREY;
+	vbi_fmt->offset			= 64 * 4;  /*FIXME: why offset */
+	if (pd->video_data.context.tvnormid & V4L2_STD_525_60) {
+		vbi_fmt->start[0] = 10;
+		vbi_fmt->start[1] = 264;
+		vbi_fmt->count[0] = V4L_NTSC_VBI_LINES;
+		vbi_fmt->count[1] = V4L_NTSC_VBI_LINES;
+	} else {
+		vbi_fmt->start[0] = 6;
+		vbi_fmt->start[1] = 314;
+		vbi_fmt->count[0] = V4L_PAL_VBI_LINES;
+		vbi_fmt->count[1] = V4L_PAL_VBI_LINES;
+	}
+	vbi_fmt->flags = V4L2_VBI_UNSYNC;
+	return 0;
+}
+
+static int set_std(struct poseidon *pd, v4l2_std_id norm)
+{
+	struct video_data *video = &pd->video_data;
+	struct vbi_data *vbi	= &pd->vbi_data;
+	struct running_context *context;
+	struct v4l2_pix_format *pix;
+	s32 i, ret = 0, cmd_status, param;
+	int height;
+
+	for (i = 0; i < POSEIDON_TVNORMS; i++) {
+		if (norm & poseidon_tvnorms[i].v4l2_id) {
+			param = poseidon_tvnorms[i].tlg_tvnorm;
+			log("name : %s", poseidon_tvnorms[i].name);
+			goto found;
+		}
+	}
+	return -EINVAL;
+found:
+	mutex_lock(&pd->lock);
+	ret = send_set_req(pd, VIDEO_STD_SEL, param, &cmd_status);
+	if (ret || cmd_status)
+		goto out;
+
+	/* Set vbi size and check the height of the frame */
+	context = &video->context;
+	context->tvnormid = poseidon_tvnorms[i].v4l2_id;
+	if (context->tvnormid & V4L2_STD_525_60) {
+		vbi->vbi_size = V4L_NTSC_VBI_FRAMESIZE;
+		height = 480;
+	} else {
+		vbi->vbi_size = V4L_PAL_VBI_FRAMESIZE;
+		height = 576;
+	}
+
+	pix = &context->pix;
+	if (pix->height != height) {
+		pix->height	= height;
+		pix->sizeimage 	= pix->width * pix->height * 2;
+	}
+
+out:
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id norm)
+{
+	struct front_face *front = fh;
+
+	return set_std(front->pd, norm);
+}
+
+static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+	struct front_face *front = fh;
+
+	*norm = front->pd->video_data.context.tvnormid;
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
+{
+	if (in->index >= POSEIDON_INPUTS)
+		return -EINVAL;
+	strcpy(in->name, pd_inputs[in->index].name);
+	in->type  = V4L2_INPUT_TYPE_TUNER;
+
+	/*
+	 * the audio input index mixed with this video input,
+	 * Poseidon only have one audio/video, set to "0"
+	 */
+	in->audioset	= 1;
+	in->tuner	= 0;
+	in->std		= V4L2_STD_ALL;
+	in->status	= 0;
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	struct front_face *front = fh;
+	struct poseidon *pd = front->pd;
+	struct running_context *context = &pd->video_data.context;
+
+	*i = context->sig_index;
+	return 0;
+}
+
+/* We can support several inputs */
+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
+{
+	struct front_face *front = fh;
+	struct poseidon *pd = front->pd;
+	s32 ret, cmd_status;
+
+	if (i >= POSEIDON_INPUTS)
+		return -EINVAL;
+	ret = send_set_req(pd, SGNL_SRC_SEL,
+			pd_inputs[i].tlg_src, &cmd_status);
+	if (ret)
+		return ret;
+
+	pd->video_data.context.sig_index = i;
+	return 0;
+}
+
+static int tlg_s_ctrl(struct v4l2_ctrl *c)
+{
+	struct poseidon *pd = container_of(c->handler, struct poseidon,
+						video_data.ctrl_handler);
+	struct tuner_custom_parameter_s param = {0};
+	s32 ret = 0, cmd_status, params;
+
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		param.param_id = CUST_PARM_ID_BRIGHTNESS_CTRL;
+		break;
+	case V4L2_CID_CONTRAST:
+		param.param_id = CUST_PARM_ID_CONTRAST_CTRL;
+		break;
+	case V4L2_CID_HUE:
+		param.param_id = CUST_PARM_ID_HUE_CTRL;
+		break;
+	case V4L2_CID_SATURATION:
+		param.param_id = CUST_PARM_ID_SATURATION_CTRL;
+		break;
+	}
+	param.param_value = c->val;
+	params = *(s32 *)&param; /* temp code */
+
+	mutex_lock(&pd->lock);
+	ret = send_set_req(pd, TUNER_CUSTOM_PARAMETER, params, &cmd_status);
+	ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+	mutex_unlock(&pd->lock);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ/4);
+	return ret;
+}
+
+/* Audio ioctls */
+static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	if (0 != a->index)
+		return -EINVAL;
+	a->capability = V4L2_AUDCAP_STEREO;
+	strcpy(a->name, "USB audio in");
+	/*Poseidon have no AVL function.*/
+	a->mode = 0;
+	return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	a->index = 0;
+	a->capability = V4L2_AUDCAP_STEREO;
+	strcpy(a->name, "USB audio in");
+	a->mode = 0;
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
+{
+	return (0 == a->index) ? 0 : -EINVAL;
+}
+
+/* Tuner ioctls */
+static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner)
+{
+	struct front_face *front	= fh;
+	struct poseidon *pd		= front->pd;
+	struct tuner_atv_sig_stat_s atv_stat;
+	s32 count = 5, ret, cmd_status;
+	int index;
+
+	if (0 != tuner->index)
+		return -EINVAL;
+
+	mutex_lock(&pd->lock);
+	ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV,
+				&atv_stat, &cmd_status, sizeof(atv_stat));
+
+	while (atv_stat.sig_lock_busy && count-- && !ret) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
+
+		ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV,
+				&atv_stat, &cmd_status, sizeof(atv_stat));
+	}
+	mutex_unlock(&pd->lock);
+
+	if (debug_mode)
+		log("P:%d,S:%d", atv_stat.sig_present, atv_stat.sig_strength);
+
+	if (ret || cmd_status)
+		tuner->signal = 0;
+	else if (atv_stat.sig_present && !atv_stat.sig_strength)
+		tuner->signal = 0xFFFF;
+	else
+		tuner->signal = (atv_stat.sig_strength * 255 / 10) << 8;
+
+	strcpy(tuner->name, "Telegent Systems");
+	tuner->type = V4L2_TUNER_ANALOG_TV;
+	tuner->rangelow = TUNER_FREQ_MIN / 62500;
+	tuner->rangehigh = TUNER_FREQ_MAX / 62500;
+	tuner->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
+				V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+	index = pd->video_data.context.audio_idx;
+	tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub;
+	tuner->audmode = pd_audio_modes[index].v4l2_audio_mode;
+	tuner->afc = 0;
+	return 0;
+}
+
+static int pd_vidioc_s_tuner(struct poseidon *pd, int index)
+{
+	s32 ret = 0, cmd_status, param, audiomode;
+
+	mutex_lock(&pd->lock);
+	param = pd_audio_modes[index].tlg_audio_mode;
+	ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status);
+	audiomode = get_audio_std(pd->video_data.context.tvnormid);
+	ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode,
+				&cmd_status);
+	if (!ret)
+		pd->video_data.context.audio_idx = index;
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *a)
+{
+	struct front_face *front	= fh;
+	struct poseidon *pd		= front->pd;
+	int index;
+
+	if (0 != a->index)
+		return -EINVAL;
+	for (index = 0; index < POSEIDON_AUDIOMODS; index++)
+		if (a->audmode == pd_audio_modes[index].v4l2_audio_mode)
+			return pd_vidioc_s_tuner(pd, index);
+	return -EINVAL;
+}
+
+static int vidioc_g_frequency(struct file *file, void *fh,
+			struct v4l2_frequency *freq)
+{
+	struct front_face *front = fh;
+	struct poseidon *pd = front->pd;
+	struct running_context *context = &pd->video_data.context;
+
+	if (0 != freq->tuner)
+		return -EINVAL;
+	freq->frequency = context->freq;
+	freq->type = V4L2_TUNER_ANALOG_TV;
+	return 0;
+}
+
+static int set_frequency(struct poseidon *pd, u32 *frequency)
+{
+	s32 ret = 0, param, cmd_status;
+	struct running_context *context = &pd->video_data.context;
+
+	*frequency = clamp(*frequency,
+			TUNER_FREQ_MIN / 62500, TUNER_FREQ_MAX / 62500);
+	param = (*frequency) * 62500 / 1000;
+
+	mutex_lock(&pd->lock);
+	ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status);
+	ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+
+	msleep(250); /* wait for a while until the hardware is ready. */
+	context->freq = *frequency;
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+static int vidioc_s_frequency(struct file *file, void *fh,
+				const struct v4l2_frequency *freq)
+{
+	struct front_face *front = fh;
+	struct poseidon *pd = front->pd;
+	u32 frequency = freq->frequency;
+
+	if (freq->tuner)
+		return -EINVAL;
+#ifdef CONFIG_PM
+	pd->pm_suspend = pm_video_suspend;
+	pd->pm_resume = pm_video_resume;
+#endif
+	return set_frequency(pd, &frequency);
+}
+
+static int vidioc_reqbufs(struct file *file, void *fh,
+				struct v4l2_requestbuffers *b)
+{
+	struct front_face *front = file->private_data;
+	return videobuf_reqbufs(&front->q, b);
+}
+
+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct front_face *front = file->private_data;
+	return videobuf_querybuf(&front->q, b);
+}
+
+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct front_face *front = file->private_data;
+	return videobuf_qbuf(&front->q, b);
+}
+
+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct front_face *front = file->private_data;
+	return videobuf_dqbuf(&front->q, b, file->f_flags & O_NONBLOCK);
+}
+
+/* Just stop the URBs, do not free the URBs */
+static int usb_transfer_stop(struct video_data *video)
+{
+	if (video->is_streaming) {
+		int i;
+		s32 cmd_status;
+		struct poseidon *pd = video->pd;
+
+		video->is_streaming = 0;
+		for (i = 0; i < SBUF_NUM; ++i) {
+			if (video->urb_array[i])
+				usb_kill_urb(video->urb_array[i]);
+		}
+
+		send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
+			       &cmd_status);
+	}
+	return 0;
+}
+
+int stop_all_video_stream(struct poseidon *pd)
+{
+	struct video_data *video = &pd->video_data;
+	struct vbi_data *vbi	= &pd->vbi_data;
+
+	mutex_lock(&pd->lock);
+	if (video->is_streaming) {
+		struct front_face *front = video->front;
+
+		/* stop the URBs */
+		usb_transfer_stop(video);
+		free_all_urb(video);
+
+		/* stop the host side of VIDEO */
+		videobuf_stop(&front->q);
+		videobuf_mmap_free(&front->q);
+
+		/* stop the host side of VBI */
+		front = vbi->front;
+		if (front) {
+			videobuf_stop(&front->q);
+			videobuf_mmap_free(&front->q);
+		}
+	}
+	mutex_unlock(&pd->lock);
+	return 0;
+}
+
+/*
+ * The bubbles can seriously damage the video's quality,
+ * though it occurs in very rare situation.
+ */
+static void iso_bubble_handler(struct work_struct *w)
+{
+	struct video_data *video;
+	struct poseidon *pd;
+
+	video = container_of(w, struct video_data, bubble_work);
+	pd = video->pd;
+
+	mutex_lock(&pd->lock);
+	usb_transfer_stop(video);
+	msleep(500);
+	start_video_stream(pd);
+	mutex_unlock(&pd->lock);
+}
+
+
+static int vidioc_streamon(struct file *file, void *fh,
+				enum v4l2_buf_type type)
+{
+	struct front_face *front = fh;
+
+	if (unlikely(type != front->type))
+		return -EINVAL;
+	return videobuf_streamon(&front->q);
+}
+
+static int vidioc_streamoff(struct file *file, void *fh,
+				enum v4l2_buf_type type)
+{
+	struct front_face *front = file->private_data;
+
+	if (unlikely(type != front->type))
+		return -EINVAL;
+	return videobuf_streamoff(&front->q);
+}
+
+/* Set the firmware's default values : need altersetting */
+static int pd_video_checkmode(struct poseidon *pd)
+{
+	s32 ret = 0, cmd_status, audiomode;
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ/2);
+
+	/* choose the altersetting */
+	ret = usb_set_interface(pd->udev, 0,
+					(pd->cur_transfer_mode ?
+					 ISO_3K_BULK_ALTERNATE_IFACE :
+					 BULK_ALTERNATE_IFACE));
+	if (ret < 0)
+		goto error;
+
+	/* set default parameters for PAL-D , with the VBI enabled*/
+	ret = set_tuner_mode(pd, TLG_MODE_ANALOG_TV);
+	ret |= send_set_req(pd, SGNL_SRC_SEL,
+				TLG_SIG_SRC_ANTENNA, &cmd_status);
+	ret |= send_set_req(pd, VIDEO_STD_SEL,
+				TLG_TUNE_VSTD_PAL_D, &cmd_status);
+	ret |= send_set_req(pd, VIDEO_STREAM_FMT_SEL,
+				TLG_TUNER_VID_FORMAT_YUV, &cmd_status);
+	ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
+				TLG_TUNE_VID_RES_720, &cmd_status);
+	ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status);
+	ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */
+
+	/* set the audio */
+	audiomode = get_audio_std(pd->video_data.context.tvnormid);
+	ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status);
+	ret |= send_set_req(pd, TUNER_AUD_MODE,
+				TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status);
+	ret |= send_set_req(pd, AUDIO_SAMPLE_RATE_SEL,
+				ATV_AUDIO_RATE_48K, &cmd_status);
+error:
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int pm_video_suspend(struct poseidon *pd)
+{
+	/* stop audio */
+	pm_alsa_suspend(pd);
+
+	/* stop and free all the URBs */
+	usb_transfer_stop(&pd->video_data);
+	free_all_urb(&pd->video_data);
+
+	/* reset the interface */
+	usb_set_interface(pd->udev, 0, 0);
+	msleep(300);
+	return 0;
+}
+
+static int restore_v4l2_context(struct poseidon *pd,
+				struct running_context *context)
+{
+	struct front_face *front = pd->video_data.front;
+
+	pd_video_checkmode(pd);
+
+	set_std(pd, context->tvnormid);
+	vidioc_s_input(NULL, front, context->sig_index);
+	pd_vidioc_s_tuner(pd, context->audio_idx);
+	pd_vidioc_s_fmt(pd, &context->pix);
+	set_frequency(pd, &context->freq);
+	return 0;
+}
+
+static int pm_video_resume(struct poseidon *pd)
+{
+	struct video_data *video = &pd->video_data;
+
+	/* resume the video */
+	/* [1] restore the origin V4L2 parameters */
+	restore_v4l2_context(pd, &video->context);
+
+	/* [2] initiate video copy variables */
+	if (video->front->curr_frame)
+		init_copy(video, 0);
+
+	/* [3] fire urbs	*/
+	start_video_stream(pd);
+
+	/* resume the audio */
+	pm_alsa_resume(pd);
+	return 0;
+}
+#endif
+
+void set_debug_mode(struct video_device *vfd, int debug_mode)
+{
+	vfd->debug = 0;
+	if (debug_mode & 0x1)
+		vfd->debug = V4L2_DEBUG_IOCTL;
+	if (debug_mode & 0x2)
+		vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
+}
+
+static void init_video_context(struct running_context *context)
+{
+	context->sig_index	= 0;
+	context->audio_idx	= 1; /* stereo */
+	context->tvnormid  	= V4L2_STD_PAL_D;
+	context->pix = (struct v4l2_pix_format) {
+				.width		= 720,
+				.height		= 576,
+				.pixelformat	= V4L2_PIX_FMT_YUYV,
+				.field		= V4L2_FIELD_INTERLACED,
+				.bytesperline	= 720 * 2,
+				.sizeimage	= 720 * 576 * 2,
+				.colorspace	= V4L2_COLORSPACE_SMPTE170M,
+			};
+}
+
+static int pd_video_open(struct file *file)
+{
+	struct video_device *vfd = video_devdata(file);
+	struct poseidon *pd = video_get_drvdata(vfd);
+	struct front_face *front = NULL;
+	int ret = -ENOMEM;
+
+	mutex_lock(&pd->lock);
+	usb_autopm_get_interface(pd->interface);
+
+	if (pd->state && !(pd->state & POSEIDON_STATE_ANALOG)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
+	if (!front)
+		goto out;
+	if (vfd->vfl_type == VFL_TYPE_GRABBER) {
+		pd->cur_transfer_mode	= usb_transfer_mode;/* bulk or iso */
+		init_video_context(&pd->video_data.context);
+
+		ret = pd_video_checkmode(pd);
+		if (ret < 0) {
+			kfree(front);
+			ret = -1;
+			goto out;
+		}
+
+		front->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		pd->video_data.users++;
+		set_debug_mode(vfd, debug_mode);
+
+		videobuf_queue_vmalloc_init(&front->q, &pd_video_qops,
+				NULL, &front->queue_lock,
+				V4L2_BUF_TYPE_VIDEO_CAPTURE,
+				V4L2_FIELD_INTERLACED,/* video is interlacd */
+				sizeof(struct videobuf_buffer),/*it's enough*/
+				front, NULL);
+	} else {
+		front->type	= V4L2_BUF_TYPE_VBI_CAPTURE;
+		pd->vbi_data.front = front;
+		pd->vbi_data.users++;
+
+		videobuf_queue_vmalloc_init(&front->q, &pd_video_qops,
+				NULL, &front->queue_lock,
+				V4L2_BUF_TYPE_VBI_CAPTURE,
+				V4L2_FIELD_NONE, /* vbi is NONE mode */
+				sizeof(struct videobuf_buffer),
+				front, NULL);
+	}
+
+	pd->state |= POSEIDON_STATE_ANALOG;
+	front->pd = pd;
+	front->curr_frame = NULL;
+	INIT_LIST_HEAD(&front->active);
+	spin_lock_init(&front->queue_lock);
+
+	file->private_data = front;
+	kref_get(&pd->kref);
+
+	mutex_unlock(&pd->lock);
+	return 0;
+out:
+	usb_autopm_put_interface(pd->interface);
+	mutex_unlock(&pd->lock);
+	return ret;
+}
+
+static int pd_video_release(struct file *file)
+{
+	struct front_face *front = file->private_data;
+	struct poseidon *pd = front->pd;
+	s32 cmd_status = 0;
+
+	mutex_lock(&pd->lock);
+
+	if (front->type	== V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		/* stop the device, and free the URBs */
+		usb_transfer_stop(&pd->video_data);
+		free_all_urb(&pd->video_data);
+
+		/* stop the firmware */
+		send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
+			       &cmd_status);
+
+		pd->file_for_stream = NULL;
+		pd->video_data.users--;
+	} else if (front->type	== V4L2_BUF_TYPE_VBI_CAPTURE) {
+		pd->vbi_data.front = NULL;
+		pd->vbi_data.users--;
+	}
+	if (!pd->vbi_data.users && !pd->video_data.users)
+		pd->state &= ~POSEIDON_STATE_ANALOG;
+	videobuf_stop(&front->q);
+	videobuf_mmap_free(&front->q);
+
+	usb_autopm_put_interface(pd->interface);
+	mutex_unlock(&pd->lock);
+
+	kfree(front);
+	file->private_data = NULL;
+	kref_put(&pd->kref, poseidon_delete);
+	return 0;
+}
+
+static int pd_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct front_face *front = file->private_data;
+	return  videobuf_mmap_mapper(&front->q, vma);
+}
+
+static unsigned int pd_video_poll(struct file *file, poll_table *table)
+{
+	struct front_face *front = file->private_data;
+	return videobuf_poll_stream(file, &front->q, table);
+}
+
+static ssize_t pd_video_read(struct file *file, char __user *buffer,
+			size_t count, loff_t *ppos)
+{
+	struct front_face *front = file->private_data;
+	return videobuf_read_stream(&front->q, buffer, count, ppos,
+				0, file->f_flags & O_NONBLOCK);
+}
+
+/* This struct works for both VIDEO and VBI */
+static const struct v4l2_file_operations pd_video_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pd_video_open,
+	.release	= pd_video_release,
+	.read		= pd_video_read,
+	.poll		= pd_video_poll,
+	.mmap		= pd_video_mmap,
+	.ioctl		= video_ioctl2, /* maybe changed in future */
+};
+
+static const struct v4l2_ioctl_ops pd_video_ioctl_ops = {
+	.vidioc_querycap	= vidioc_querycap,
+
+	/* Video format */
+	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt,
+	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt,
+	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt,
+	.vidioc_g_fmt_vbi_cap	= vidioc_g_fmt_vbi, /* VBI */
+
+	/* Input */
+	.vidioc_g_input		= vidioc_g_input,
+	.vidioc_s_input		= vidioc_s_input,
+	.vidioc_enum_input	= vidioc_enum_input,
+
+	/* Audio ioctls */
+	.vidioc_enumaudio	= vidioc_enumaudio,
+	.vidioc_g_audio		= vidioc_g_audio,
+	.vidioc_s_audio		= vidioc_s_audio,
+
+	/* Tuner ioctls */
+	.vidioc_g_tuner		= vidioc_g_tuner,
+	.vidioc_s_tuner		= vidioc_s_tuner,
+	.vidioc_g_std		= vidioc_g_std,
+	.vidioc_s_std		= vidioc_s_std,
+	.vidioc_g_frequency	= vidioc_g_frequency,
+	.vidioc_s_frequency	= vidioc_s_frequency,
+
+	/* Buffer handlers */
+	.vidioc_reqbufs		= vidioc_reqbufs,
+	.vidioc_querybuf	= vidioc_querybuf,
+	.vidioc_qbuf		= vidioc_qbuf,
+	.vidioc_dqbuf		= vidioc_dqbuf,
+
+	/* Stream on/off */
+	.vidioc_streamon	= vidioc_streamon,
+	.vidioc_streamoff	= vidioc_streamoff,
+};
+
+static struct video_device pd_video_template = {
+	.name = "Telegent-Video",
+	.fops = &pd_video_fops,
+	.minor = -1,
+	.release = video_device_release_empty,
+	.tvnorms = V4L2_STD_ALL,
+	.ioctl_ops = &pd_video_ioctl_ops,
+};
+
+static const struct v4l2_ctrl_ops tlg_ctrl_ops = {
+	.s_ctrl = tlg_s_ctrl,
+};
+
+void pd_video_exit(struct poseidon *pd)
+{
+	struct video_data *video = &pd->video_data;
+	struct vbi_data *vbi = &pd->vbi_data;
+
+	video_unregister_device(&video->v_dev);
+	video_unregister_device(&vbi->v_dev);
+	v4l2_ctrl_handler_free(&video->ctrl_handler);
+	log();
+}
+
+int pd_video_init(struct poseidon *pd)
+{
+	struct video_data *video = &pd->video_data;
+	struct vbi_data *vbi	= &pd->vbi_data;
+	struct v4l2_ctrl_handler *hdl = &video->ctrl_handler;
+	u32 freq = TUNER_FREQ_MIN / 62500;
+	int ret = -ENOMEM;
+
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_BRIGHTNESS,
+			0, 10000, 1, 100);
+	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_CONTRAST,
+			0, 10000, 1, 100);
+	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_HUE,
+			0, 10000, 1, 100);
+	v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_SATURATION,
+			0, 10000, 1, 100);
+	if (hdl->error) {
+		v4l2_ctrl_handler_free(hdl);
+		return hdl->error;
+	}
+	set_frequency(pd, &freq);
+	video->v_dev = pd_video_template;
+	video->v_dev.v4l2_dev = &pd->v4l2_dev;
+	video->v_dev.ctrl_handler = hdl;
+	video_set_drvdata(&video->v_dev, pd);
+
+	ret = video_register_device(&video->v_dev, VFL_TYPE_GRABBER, -1);
+	if (ret != 0)
+		goto out;
+
+	/* VBI uses the same template as video */
+	vbi->v_dev = pd_video_template;
+	vbi->v_dev.v4l2_dev = &pd->v4l2_dev;
+	vbi->v_dev.ctrl_handler = hdl;
+	video_set_drvdata(&vbi->v_dev, pd);
+	ret = video_register_device(&vbi->v_dev, VFL_TYPE_VBI, -1);
+	if (ret != 0)
+		goto out;
+	log("register VIDEO/VBI devices");
+	return 0;
+out:
+	log("VIDEO/VBI devices register failed, : %d", ret);
+	pd_video_exit(pd);
+	return ret;
+}
diff --git a/drivers/media/usb/tlg2300/vendorcmds.h b/drivers/media/usb/tlg2300/vendorcmds.h
new file mode 100644
index 0000000..ba6f4ae
--- /dev/null
+++ b/drivers/media/usb/tlg2300/vendorcmds.h
@@ -0,0 +1,243 @@
+#ifndef VENDOR_CMD_H_
+#define VENDOR_CMD_H_
+
+#define BULK_ALTERNATE_IFACE		(2)
+#define ISO_3K_BULK_ALTERNATE_IFACE     (1)
+#define REQ_SET_CMD			(0X00)
+#define REQ_GET_CMD			(0X80)
+
+enum tlg__analog_audio_standard {
+	TLG_TUNE_ASTD_NONE	= 0x00000000,
+	TLG_TUNE_ASTD_A2	= 0x00000001,
+	TLG_TUNE_ASTD_NICAM	= 0x00000002,
+	TLG_TUNE_ASTD_EIAJ	= 0x00000004,
+	TLG_TUNE_ASTD_BTSC	= 0x00000008,
+	TLG_TUNE_ASTD_FM_US	= 0x00000010,
+	TLG_TUNE_ASTD_FM_EUR	= 0x00000020,
+	TLG_TUNE_ASTD_ALL	= 0x0000003f
+};
+
+/*
+ * identifiers for Custom Parameter messages.
+ * @typedef cmd_custom_param_id_t
+ */
+enum cmd_custom_param_id {
+	CUST_PARM_ID_NONE		= 0x00,
+	CUST_PARM_ID_BRIGHTNESS_CTRL	= 0x01,
+	CUST_PARM_ID_CONTRAST_CTRL	= 0x02,
+	CUST_PARM_ID_HUE_CTRL		= 0x03,
+	CUST_PARM_ID_SATURATION_CTRL	  = 0x04,
+	CUST_PARM_ID_AUDIO_SNR_THRESHOLD  = 0x10,
+	CUST_PARM_ID_AUDIO_AGC_THRESHOLD  = 0x11,
+	CUST_PARM_ID_MAX
+};
+
+struct  tuner_custom_parameter_s {
+	uint16_t	param_id;	 /*  Parameter identifier  */
+	uint16_t	param_value;	 /*  Parameter value	   */
+};
+
+struct  tuner_ber_rate_s {
+	uint32_t	ber_rate;  /*  BER sample rate in seconds   */
+};
+
+struct tuner_atv_sig_stat_s {
+	uint32_t	sig_present;
+	uint32_t	sig_locked;
+	uint32_t	sig_lock_busy;
+	uint32_t	sig_strength;	   /*  milliDb	  */
+	uint32_t	tv_audio_chan;	  /*  mono/stereo/sap*/
+	uint32_t 	mvision_stat;	   /*  macrovision status */
+};
+
+struct tuner_dtv_sig_stat_s {
+	uint32_t sig_present;   /*  Boolean*/
+	uint32_t sig_locked;	/*  Boolean */
+	uint32_t sig_lock_busy; /*  Boolean	(Can this time-out?) */
+	uint32_t sig_strength;  /*  milliDb*/
+};
+
+struct tuner_fm_sig_stat_s {
+	uint32_t sig_present;	/* Boolean*/
+	uint32_t sig_locked;	 /* Boolean */
+	uint32_t sig_lock_busy;  /* Boolean */
+	uint32_t sig_stereo_mono;/* TBD*/
+	uint32_t sig_strength;   /* milliDb*/
+};
+
+enum _tag_tlg_tune_srv_cmd {
+	TLG_TUNE_PLAY_SVC_START = 1,
+	TLG_TUNE_PLAY_SVC_STOP
+};
+
+enum  _tag_tune_atv_audio_mode_caps {
+	TLG_TUNE_TVAUDIO_MODE_MONO	= 0x00000001,
+	TLG_TUNE_TVAUDIO_MODE_STEREO	= 0x00000002,
+	TLG_TUNE_TVAUDIO_MODE_LANG_A	= 0x00000010,/* Primary language*/
+	TLG_TUNE_TVAUDIO_MODE_LANG_B	= 0x00000020,/* 2nd avail language*/
+	TLG_TUNE_TVAUDIO_MODE_LANG_C	= 0x00000040
+};
+
+
+enum   _tag_tuner_atv_audio_rates {
+	ATV_AUDIO_RATE_NONE	= 0x00,/* Audio not supported*/
+	ATV_AUDIO_RATE_32K	= 0x01,/* Audio rate = 32 KHz*/
+	ATV_AUDIO_RATE_48K	= 0x02, /* Audio rate = 48 KHz*/
+	ATV_AUDIO_RATE_31_25K	= 0x04 /* Audio rate = 31.25KHz */
+};
+
+enum  _tag_tune_atv_vid_res_caps {
+	TLG_TUNE_VID_RES_NONE	= 0x00000000,
+	TLG_TUNE_VID_RES_720	= 0x00000001,
+	TLG_TUNE_VID_RES_704	= 0x00000002,
+	TLG_TUNE_VID_RES_360	= 0x00000004
+};
+
+enum _tag_tuner_analog_video_format {
+	TLG_TUNER_VID_FORMAT_YUV	= 0x00000001,
+	TLG_TUNER_VID_FORMAT_YCRCB	= 0x00000002,
+	TLG_TUNER_VID_FORMAT_RGB_565	= 0x00000004,
+};
+
+enum  tlg_ext_audio_support {
+	TLG_EXT_AUDIO_NONE 	= 0x00,/*  No external audio input supported */
+	TLG_EXT_AUDIO_LR	= 0x01/*  LR external audio inputs supported*/
+};
+
+enum {
+	TLG_MODE_NONE			= 0x00, /* No Mode specified*/
+	TLG_MODE_ANALOG_TV		= 0x01, /* Analog Television mode*/
+	TLG_MODE_ANALOG_TV_UNCOMP	= 0x01, /* Analog Television mode*/
+	TLG_MODE_ANALOG_TV_COMP  	= 0x02, /* Analog TV mode (compressed)*/
+	TLG_MODE_FM_RADIO		= 0x04, /* FM Radio mode*/
+	TLG_MODE_DVB_T			= 0x08, /* Digital TV (DVB-T)*/
+};
+
+enum  tlg_signal_sources_t {
+	TLG_SIG_SRC_NONE	= 0x00,/* Signal source not specified */
+	TLG_SIG_SRC_ANTENNA	= 0x01,/* Signal src is: Antenna */
+	TLG_SIG_SRC_CABLE	= 0x02,/* Signal src is: Coax Cable*/
+	TLG_SIG_SRC_SVIDEO	= 0x04,/* Signal src is: S_VIDEO   */
+	TLG_SIG_SRC_COMPOSITE   = 0x08 /* Signal src is: Composite Video */
+};
+
+enum tuner_analog_video_standard {
+	TLG_TUNE_VSTD_NONE	= 0x00000000,
+	TLG_TUNE_VSTD_NTSC_M	= 0x00000001,
+	TLG_TUNE_VSTD_NTSC_M_J	= 0x00000002,/* Japan   */
+	TLG_TUNE_VSTD_PAL_B	= 0x00000010,
+	TLG_TUNE_VSTD_PAL_D	= 0x00000020,
+	TLG_TUNE_VSTD_PAL_G	= 0x00000040,
+	TLG_TUNE_VSTD_PAL_H	= 0x00000080,
+	TLG_TUNE_VSTD_PAL_I	= 0x00000100,
+	TLG_TUNE_VSTD_PAL_M	= 0x00000200,
+	TLG_TUNE_VSTD_PAL_N	= 0x00000400,
+	TLG_TUNE_VSTD_SECAM_B	= 0x00001000,
+	TLG_TUNE_VSTD_SECAM_D	= 0x00002000,
+	TLG_TUNE_VSTD_SECAM_G	= 0x00004000,
+	TLG_TUNE_VSTD_SECAM_H	= 0x00008000,
+	TLG_TUNE_VSTD_SECAM_K	= 0x00010000,
+	TLG_TUNE_VSTD_SECAM_K1	= 0x00020000,
+	TLG_TUNE_VSTD_SECAM_L	= 0x00040000,
+	TLG_TUNE_VSTD_SECAM_L1	= 0x00080000,
+	TLG_TUNE_VSTD_PAL_N_COMBO = 0x00100000
+};
+
+enum tlg_mode_caps {
+	TLG_MODE_CAPS_NONE		= 0x00,  /*  No Mode specified	*/
+	TLG_MODE_CAPS_ANALOG_TV_UNCOMP  = 0x01,  /*  Analog TV mode     */
+	TLG_MODE_CAPS_ANALOG_TV_COMP	= 0x02,  /*  Analog TV (compressed)*/
+	TLG_MODE_CAPS_FM_RADIO		= 0x04,  /*  FM Radio mode	*/
+	TLG_MODE_CAPS_DVB_T		= 0x08,  /*  Digital TV (DVB-T)	*/
+};
+
+enum poseidon_vendor_cmds {
+	LAST_CMD_STAT		= 0x00,
+	GET_CHIP_ID		= 0x01,
+	GET_FW_ID		= 0x02,
+	PRODUCT_CAPS		= 0x03,
+
+	TUNE_MODE_CAP_ATV	= 0x10,
+	TUNE_MODE_CAP_ATVCOMP	= 0X10,
+	TUNE_MODE_CAP_DVBT	= 0x10,
+	TUNE_MODE_CAP_FM	= 0x10,
+	TUNE_MODE_SELECT	= 0x11,
+	TUNE_FREQ_SELECT	= 0x12,
+	SGNL_SRC_SEL		= 0x13,
+
+	VIDEO_STD_SEL		= 0x14,
+	VIDEO_STREAM_FMT_SEL	= 0x15,
+	VIDEO_ROSOLU_AVAIL	= 0x16,
+	VIDEO_ROSOLU_SEL	= 0x17,
+	VIDEO_CONT_PROTECT	= 0x20,
+
+	VCR_TIMING_MODSEL	= 0x21,
+	EXT_AUDIO_CAP		= 0x22,
+	EXT_AUDIO_SEL		= 0x23,
+	TEST_PATTERN_SEL	= 0x24,
+	VBI_DATA_SEL		= 0x25,
+	AUDIO_SAMPLE_RATE_CAP   = 0x28,
+	AUDIO_SAMPLE_RATE_SEL   = 0x29,
+	TUNER_AUD_MODE		= 0x2a,
+	TUNER_AUD_MODE_AVAIL	= 0x2b,
+	TUNER_AUD_ANA_STD	= 0x2c,
+	TUNER_CUSTOM_PARAMETER	= 0x2f,
+
+	DVBT_TUNE_MODE_SEL	= 0x30,
+	DVBT_BANDW_CAP		= 0x31,
+	DVBT_BANDW_SEL		= 0x32,
+	DVBT_GUARD_INTERV_CAP   = 0x33,
+	DVBT_GUARD_INTERV_SEL   = 0x34,
+	DVBT_MODULATION_CAP	= 0x35,
+	DVBT_MODULATION_SEL	= 0x36,
+	DVBT_INNER_FEC_RATE_CAP = 0x37,
+	DVBT_INNER_FEC_RATE_SEL = 0x38,
+	DVBT_TRANS_MODE_CAP	= 0x39,
+	DVBT_TRANS_MODE_SEL	= 0x3a,
+	DVBT_SEARCH_RANG	= 0x3c,
+
+	TUNER_SETUP_ANALOG	= 0x40,
+	TUNER_SETUP_DIGITAL	= 0x41,
+	TUNER_SETUP_FM_RADIO	= 0x42,
+	TAKE_REQUEST		= 0x43, /* Take effect of the command */
+	PLAY_SERVICE		= 0x44, /* Play start or Play stop */
+	TUNER_STATUS		= 0x45,
+	TUNE_PROP_DVBT		= 0x46,
+	ERR_RATE_STATS		= 0x47,
+	TUNER_BER_RATE		= 0x48,
+
+	SCAN_CAPS		= 0x50,
+	SCAN_SETUP		= 0x51,
+	SCAN_SERVICE		= 0x52,
+	SCAN_STATS		= 0x53,
+
+	PID_SET			= 0x58,
+	PID_UNSET		= 0x59,
+	PID_LIST		= 0x5a,
+
+	IRD_CAP			= 0x60,
+	IRD_MODE_SEL		= 0x61,
+	IRD_SETUP		= 0x62,
+
+	PTM_MODE_CAP		= 0x70,
+	PTM_MODE_SEL		= 0x71,
+	PTM_SERVICE		= 0x72,
+	TUNER_REG_SCRIPT	= 0x73,
+	CMD_CHIP_RST		= 0x74,
+};
+
+enum tlg_bw {
+	TLG_BW_5 = 5,
+	TLG_BW_6 = 6,
+	TLG_BW_7 = 7,
+	TLG_BW_8 = 8,
+	TLG_BW_12 = 12,
+	TLG_BW_15 = 15
+};
+
+struct cmd_firmware_vers_s {
+	uint8_t	 fw_rev_major;
+	uint8_t	 fw_rev_minor;
+	uint16_t fw_patch;
+};
+#endif /* VENDOR_CMD_H_ */
diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
index 282f11c..35ee9c3 100644
--- a/drivers/media/usb/usbvision/usbvision-video.c
+++ b/drivers/media/usb/usbvision/usbvision-video.c
@@ -446,7 +446,6 @@
 	if (usbvision->remove_pending) {
 		printk(KERN_INFO "%s: Final disconnect\n", __func__);
 		usbvision_release(usbvision);
-		return 0;
 	}
 	mutex_unlock(&usbvision->v4l2_lock);
 
@@ -509,12 +508,11 @@
 		usbvision_device_data[usbvision->dev_model].model_string,
 		sizeof(vc->card));
 	usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
-	vc->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+	vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
 		V4L2_CAP_AUDIO |
 		V4L2_CAP_READWRITE |
 		V4L2_CAP_STREAMING |
 		(usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
-	vc->capabilities = vc->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
 
@@ -1223,7 +1221,6 @@
 	if (usbvision->remove_pending) {
 		printk(KERN_INFO "%s: Final disconnect\n", __func__);
 		usbvision_release(usbvision);
-		return err_code;
 	}
 
 	mutex_unlock(&usbvision->v4l2_lock);
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 40d6c83..b578d68 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -331,7 +331,6 @@
 	struct uvc_format_desc *fmtdesc;
 	struct uvc_frame *frame;
 	const unsigned char *start = buffer;
-	unsigned int width_multiplier = 1;
 	unsigned int interval;
 	unsigned int i, n;
 	__u8 ftype;
@@ -367,20 +366,6 @@
 		}
 
 		format->bpp = buffer[21];
-
-		/* Some devices report a format that doesn't match what they
-		 * really send.
-		 */
-		if (dev->quirks & UVC_QUIRK_FORCE_Y8) {
-			if (format->fcc == V4L2_PIX_FMT_YUYV) {
-				strlcpy(format->name, "Greyscale 8-bit (Y8  )",
-					sizeof(format->name));
-				format->fcc = V4L2_PIX_FMT_GREY;
-				format->bpp = 8;
-				width_multiplier = 2;
-			}
-		}
-
 		if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
 			ftype = UVC_VS_FRAME_UNCOMPRESSED;
 		} else {
@@ -489,8 +474,7 @@
 
 		frame->bFrameIndex = buffer[3];
 		frame->bmCapabilities = buffer[4];
-		frame->wWidth = get_unaligned_le16(&buffer[5])
-			      * width_multiplier;
+		frame->wWidth = get_unaligned_le16(&buffer[5]);
 		frame->wHeight = get_unaligned_le16(&buffer[7]);
 		frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
 		frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
@@ -1639,12 +1623,12 @@
 {
 	struct list_head *p, *n;
 
-	uvc_status_cleanup(dev);
-	uvc_ctrl_cleanup_device(dev);
-
 	usb_put_intf(dev->intf);
 	usb_put_dev(dev->udev);
 
+	uvc_status_cleanup(dev);
+	uvc_ctrl_cleanup_device(dev);
+
 	if (dev->vdev.dev)
 		v4l2_device_unregister(&dev->vdev);
 #ifdef CPTCFG_MEDIA_CONTROLLER
@@ -1734,11 +1718,6 @@
 	struct video_device *vdev;
 	int ret;
 
-	/* Initialize the video buffers queue. */
-	ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
-	if (ret)
-		return ret;
-
 	/* Initialize the streaming interface with default streaming
 	 * parameters.
 	 */
@@ -1765,7 +1744,6 @@
 	 */
 	vdev->v4l2_dev = &dev->vdev;
 	vdev->fops = &uvc_fops;
-	vdev->ioctl_ops = &uvc_ioctl_ops;
 	vdev->release = uvc_release;
 	vdev->prio = &stream->chain->prio;
 	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -2013,13 +1991,14 @@
 {
 	struct uvc_device *dev = usb_get_intfdata(intf);
 	struct uvc_streaming *stream;
-	int ret = 0;
 
 	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
 		intf->cur_altsetting->desc.bInterfaceNumber);
 
 	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
 	    UVC_SC_VIDEOCONTROL) {
+		int ret = 0;
+
 		if (reset) {
 			ret = uvc_ctrl_restore_values(dev);
 			if (ret < 0)
@@ -2035,13 +2014,8 @@
 	}
 
 	list_for_each_entry(stream, &dev->streams, list) {
-		if (stream->intf == intf) {
-			ret = uvc_video_resume(stream, reset);
-			if (ret < 0)
-				uvc_queue_streamoff(&stream->queue,
-						    stream->queue.queue.type);
-			return ret;
-		}
+		if (stream->intf == intf)
+			return uvc_video_resume(stream, reset);
 	}
 
 	uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
@@ -2530,15 +2504,6 @@
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
 				| UVC_QUIRK_IGNORE_SELECTOR_UNIT },
-	/* Oculus VR Positional Tracker DK2 */
-	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
-				| USB_DEVICE_ID_MATCH_INT_INFO,
-	  .idVendor		= 0x2833,
-	  .idProduct		= 0x0201,
-	  .bInterfaceClass	= USB_CLASS_VIDEO,
-	  .bInterfaceSubClass	= 1,
-	  .bInterfaceProtocol	= 0,
-	  .driver_info		= UVC_QUIRK_FORCE_Y8 },
 	/* Generic USB Video Class */
 	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
 	{}
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index cc96072..6e92d20 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -36,34 +36,6 @@
  * the driver.
  */
 
-static inline struct uvc_streaming *
-uvc_queue_to_stream(struct uvc_video_queue *queue)
-{
-	return container_of(queue, struct uvc_streaming, queue);
-}
-
-/*
- * Return all queued buffers to videobuf2 in the requested state.
- *
- * This function must be called with the queue spinlock held.
- */
-static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
-			       enum uvc_buffer_state state)
-{
-	enum vb2_buffer_state vb2_state = state == UVC_BUF_STATE_ERROR
-					? VB2_BUF_STATE_ERROR
-					: VB2_BUF_STATE_QUEUED;
-
-	while (!list_empty(&queue->irqqueue)) {
-		struct uvc_buffer *buf = list_first_entry(&queue->irqqueue,
-							  struct uvc_buffer,
-							  queue);
-		list_del(&buf->queue);
-		buf->state = state;
-		vb2_buffer_done(&buf->buf, vb2_state);
-	}
-}
-
 /* -----------------------------------------------------------------------------
  * videobuf2 queue operations
  */
@@ -73,7 +45,8 @@
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
+	struct uvc_streaming *stream =
+			container_of(queue, struct uvc_streaming, queue);
 
 	/* Make sure the image size is large enough. */
 	if (fmt && fmt->fmt.pix.sizeimage < stream->ctrl.dwMaxVideoFrameSize)
@@ -136,7 +109,8 @@
 static void uvc_buffer_finish(struct vb2_buffer *vb)
 {
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
+	struct uvc_streaming *stream =
+			container_of(queue, struct uvc_streaming, queue);
 	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 
 	if (vb->state == VB2_BUF_STATE_DONE)
@@ -157,39 +131,6 @@
 	mutex_lock(&queue->mutex);
 }
 
-static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
-	unsigned long flags;
-	int ret;
-
-	queue->buf_used = 0;
-
-	ret = uvc_video_enable(stream, 1);
-	if (ret == 0)
-		return 0;
-
-	spin_lock_irqsave(&queue->irqlock, flags);
-	uvc_queue_return_buffers(queue, UVC_BUF_STATE_QUEUED);
-	spin_unlock_irqrestore(&queue->irqlock, flags);
-
-	return ret;
-}
-
-static void uvc_stop_streaming(struct vb2_queue *vq)
-{
-	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
-	unsigned long flags;
-
-	uvc_video_enable(stream, 0);
-
-	spin_lock_irqsave(&queue->irqlock, flags);
-	uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR);
-	spin_unlock_irqrestore(&queue->irqlock, flags);
-}
-
 static struct vb2_ops uvc_queue_qops = {
 	.queue_setup = uvc_queue_setup,
 	.buf_prepare = uvc_buffer_prepare,
@@ -197,8 +138,6 @@
 	.buf_finish = uvc_buffer_finish,
 	.wait_prepare = uvc_wait_prepare,
 	.wait_finish = uvc_wait_finish,
-	.start_streaming = uvc_start_streaming,
-	.stop_streaming = uvc_stop_streaming,
 };
 
 int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
@@ -226,19 +165,12 @@
 	return 0;
 }
 
-void uvc_queue_release(struct uvc_video_queue *queue)
-{
-	mutex_lock(&queue->mutex);
-	vb2_queue_release(&queue->queue);
-	mutex_unlock(&queue->mutex);
-}
-
 /* -----------------------------------------------------------------------------
  * V4L2 queue operations
  */
 
-int uvc_request_buffers(struct uvc_video_queue *queue,
-			struct v4l2_requestbuffers *rb)
+int uvc_alloc_buffers(struct uvc_video_queue *queue,
+		      struct v4l2_requestbuffers *rb)
 {
 	int ret;
 
@@ -249,6 +181,13 @@
 	return ret ? ret : rb->count;
 }
 
+void uvc_free_buffers(struct uvc_video_queue *queue)
+{
+	mutex_lock(&queue->mutex);
+	vb2_queue_release(&queue->queue);
+	mutex_unlock(&queue->mutex);
+}
+
 int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
 {
 	int ret;
@@ -295,28 +234,6 @@
 	return ret;
 }
 
-int uvc_queue_streamon(struct uvc_video_queue *queue, enum v4l2_buf_type type)
-{
-	int ret;
-
-	mutex_lock(&queue->mutex);
-	ret = vb2_streamon(&queue->queue, type);
-	mutex_unlock(&queue->mutex);
-
-	return ret;
-}
-
-int uvc_queue_streamoff(struct uvc_video_queue *queue, enum v4l2_buf_type type)
-{
-	int ret;
-
-	mutex_lock(&queue->mutex);
-	ret = vb2_streamoff(&queue->queue, type);
-	mutex_unlock(&queue->mutex);
-
-	return ret;
-}
-
 int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
 {
 	int ret;
@@ -372,6 +289,49 @@
 }
 
 /*
+ * Enable or disable the video buffers queue.
+ *
+ * The queue must be enabled before starting video acquisition and must be
+ * disabled after stopping it. This ensures that the video buffers queue
+ * state can be properly initialized before buffers are accessed from the
+ * interrupt handler.
+ *
+ * Enabling the video queue returns -EBUSY if the queue is already enabled.
+ *
+ * Disabling the video queue cancels the queue and removes all buffers from
+ * the main queue.
+ *
+ * This function can't be called from interrupt context. Use
+ * uvc_queue_cancel() instead.
+ */
+int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
+{
+	unsigned long flags;
+	int ret;
+
+	mutex_lock(&queue->mutex);
+	if (enable) {
+		ret = vb2_streamon(&queue->queue, queue->queue.type);
+		if (ret < 0)
+			goto done;
+
+		queue->buf_used = 0;
+	} else {
+		ret = vb2_streamoff(&queue->queue, queue->queue.type);
+		if (ret < 0)
+			goto done;
+
+		spin_lock_irqsave(&queue->irqlock, flags);
+		INIT_LIST_HEAD(&queue->irqqueue);
+		spin_unlock_irqrestore(&queue->irqlock, flags);
+	}
+
+done:
+	mutex_unlock(&queue->mutex);
+	return ret;
+}
+
+/*
  * Cancel the video buffers queue.
  *
  * Cancelling the queue marks all buffers on the irq queue as erroneous,
@@ -385,10 +345,17 @@
  */
 void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
 {
+	struct uvc_buffer *buf;
 	unsigned long flags;
 
 	spin_lock_irqsave(&queue->irqlock, flags);
-	uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR);
+	while (!list_empty(&queue->irqqueue)) {
+		buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+				       queue);
+		list_del(&buf->queue);
+		buf->state = UVC_BUF_STATE_ERROR;
+		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+	}
 	/* This must be protected by the irqlock spinlock to avoid race
 	 * conditions between uvc_buffer_queue and the disconnection event that
 	 * could result in an interruptible wait in uvc_dequeue_buffer. Do not
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 9c5cbcf..60a8e2c 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -318,6 +318,7 @@
 	stream->ctrl = probe;
 	stream->cur_format = format;
 	stream->cur_frame = frame;
+	stream->frame_size = fmt->fmt.pix.sizeimage;
 
 done:
 	mutex_unlock(&stream->mutex);
@@ -530,8 +531,10 @@
 	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
 
 	/* Only free resources if this is a privileged handle. */
-	if (uvc_has_privileges(handle))
-		uvc_queue_release(&stream->queue);
+	if (uvc_has_privileges(handle)) {
+		uvc_video_enable(stream, 0);
+		uvc_free_buffers(&stream->queue);
+	}
 
 	/* Release the file handle. */
 	uvc_dismiss_privileges(handle);
@@ -549,628 +552,553 @@
 	return 0;
 }
 
-static int uvc_ioctl_querycap(struct file *file, void *fh,
-			      struct v4l2_capability *cap)
+static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct uvc_fh *handle = file->private_data;
 	struct uvc_video_chain *chain = handle->chain;
 	struct uvc_streaming *stream = handle->stream;
-
-	strlcpy(cap->driver, "uvcvideo", sizeof(cap->driver));
-	strlcpy(cap->card, vdev->name, sizeof(cap->card));
-	usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info));
-	cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
-			  | chain->caps;
-	if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-	else
-		cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
-
-	return 0;
-}
-
-static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
-			      struct v4l2_fmtdesc *fmt)
-{
-	struct uvc_format *format;
-	enum v4l2_buf_type type = fmt->type;
-	__u32 index = fmt->index;
-
-	if (fmt->type != stream->type || fmt->index >= stream->nformats)
-		return -EINVAL;
-
-	memset(fmt, 0, sizeof(*fmt));
-	fmt->index = index;
-	fmt->type = type;
-
-	format = &stream->format[fmt->index];
-	fmt->flags = 0;
-	if (format->flags & UVC_FMT_FLAG_COMPRESSED)
-		fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
-	strlcpy(fmt->description, format->name, sizeof(fmt->description));
-	fmt->description[sizeof(fmt->description) - 1] = 0;
-	fmt->pixelformat = format->fcc;
-	return 0;
-}
-
-static int uvc_ioctl_enum_fmt_vid_cap(struct file *file, void *fh,
-				      struct v4l2_fmtdesc *fmt)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	return uvc_ioctl_enum_fmt(stream, fmt);
-}
-
-static int uvc_ioctl_enum_fmt_vid_out(struct file *file, void *fh,
-				      struct v4l2_fmtdesc *fmt)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	return uvc_ioctl_enum_fmt(stream, fmt);
-}
-
-static int uvc_ioctl_g_fmt_vid_cap(struct file *file, void *fh,
-				   struct v4l2_format *fmt)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	return uvc_v4l2_get_format(stream, fmt);
-}
-
-static int uvc_ioctl_g_fmt_vid_out(struct file *file, void *fh,
-				   struct v4l2_format *fmt)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	return uvc_v4l2_get_format(stream, fmt);
-}
-
-static int uvc_ioctl_s_fmt_vid_cap(struct file *file, void *fh,
-				   struct v4l2_format *fmt)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	int ret;
-
-	ret = uvc_acquire_privileges(handle);
-	if (ret < 0)
-		return ret;
-
-	return uvc_v4l2_set_format(stream, fmt);
-}
-
-static int uvc_ioctl_s_fmt_vid_out(struct file *file, void *fh,
-				   struct v4l2_format *fmt)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	int ret;
-
-	ret = uvc_acquire_privileges(handle);
-	if (ret < 0)
-		return ret;
-
-	return uvc_v4l2_set_format(stream, fmt);
-}
-
-static int uvc_ioctl_try_fmt_vid_cap(struct file *file, void *fh,
-				     struct v4l2_format *fmt)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	struct uvc_streaming_control probe;
-
-	return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
-}
-
-static int uvc_ioctl_try_fmt_vid_out(struct file *file, void *fh,
-				     struct v4l2_format *fmt)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	struct uvc_streaming_control probe;
-
-	return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
-}
-
-static int uvc_ioctl_reqbufs(struct file *file, void *fh,
-			     struct v4l2_requestbuffers *rb)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	int ret;
-
-	ret = uvc_acquire_privileges(handle);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&stream->mutex);
-	ret = uvc_request_buffers(&stream->queue, rb);
-	mutex_unlock(&stream->mutex);
-	if (ret < 0)
-		return ret;
-
-	if (ret == 0)
-		uvc_dismiss_privileges(handle);
-
-	return 0;
-}
-
-static int uvc_ioctl_querybuf(struct file *file, void *fh,
-			      struct v4l2_buffer *buf)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	if (!uvc_has_privileges(handle))
-		return -EBUSY;
-
-	return uvc_query_buffer(&stream->queue, buf);
-}
-
-static int uvc_ioctl_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	if (!uvc_has_privileges(handle))
-		return -EBUSY;
-
-	return uvc_queue_buffer(&stream->queue, buf);
-}
-
-static int uvc_ioctl_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	if (!uvc_has_privileges(handle))
-		return -EBUSY;
-
-	return uvc_dequeue_buffer(&stream->queue, buf,
-				  file->f_flags & O_NONBLOCK);
-}
-
-static int uvc_ioctl_create_bufs(struct file *file, void *fh,
-				  struct v4l2_create_buffers *cb)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	int ret;
-
-	ret = uvc_acquire_privileges(handle);
-	if (ret < 0)
-		return ret;
-
-	return uvc_create_buffers(&stream->queue, cb);
-}
-
-static int uvc_ioctl_streamon(struct file *file, void *fh,
-			      enum v4l2_buf_type type)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	int ret;
-
-	if (!uvc_has_privileges(handle))
-		return -EBUSY;
-
-	mutex_lock(&stream->mutex);
-	ret = uvc_queue_streamon(&stream->queue, type);
-	mutex_unlock(&stream->mutex);
-
-	return ret;
-}
-
-static int uvc_ioctl_streamoff(struct file *file, void *fh,
-			       enum v4l2_buf_type type)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	if (!uvc_has_privileges(handle))
-		return -EBUSY;
-
-	mutex_lock(&stream->mutex);
-	uvc_queue_streamoff(&stream->queue, type);
-	mutex_unlock(&stream->mutex);
-
-	return 0;
-}
-
-static int uvc_ioctl_enum_input(struct file *file, void *fh,
-				struct v4l2_input *input)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
-	const struct uvc_entity *selector = chain->selector;
-	struct uvc_entity *iterm = NULL;
-	u32 index = input->index;
-	int pin = 0;
-
-	if (selector == NULL ||
-	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-		if (index != 0)
-			return -EINVAL;
-		list_for_each_entry(iterm, &chain->entities, chain) {
-			if (UVC_ENTITY_IS_ITERM(iterm))
-				break;
-		}
-		pin = iterm->id;
-	} else if (index < selector->bNrInPins) {
-		pin = selector->baSourceID[index];
-		list_for_each_entry(iterm, &chain->entities, chain) {
-			if (!UVC_ENTITY_IS_ITERM(iterm))
-				continue;
-			if (iterm->id == pin)
-				break;
-		}
-	}
-
-	if (iterm == NULL || iterm->id != pin)
-		return -EINVAL;
-
-	memset(input, 0, sizeof(*input));
-	input->index = index;
-	strlcpy(input->name, iterm->name, sizeof(input->name));
-	if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
-		input->type = V4L2_INPUT_TYPE_CAMERA;
-
-	return 0;
-}
-
-static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
-	int ret;
-	u8 i;
-
-	if (chain->selector == NULL ||
-	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-		*input = 0;
-		return 0;
-	}
-
-	ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
-			     chain->dev->intfnum,  UVC_SU_INPUT_SELECT_CONTROL,
-			     &i, 1);
-	if (ret < 0)
-		return ret;
-
-	*input = i - 1;
-	return 0;
-}
-
-static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
-	int ret;
-	u32 i;
-
-	ret = uvc_acquire_privileges(handle);
-	if (ret < 0)
-		return ret;
-
-	if (chain->selector == NULL ||
-	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-		if (input)
-			return -EINVAL;
-		return 0;
-	}
-
-	if (input >= chain->selector->bNrInPins)
-		return -EINVAL;
-
-	i = input + 1;
-	return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
-			      chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
-			      &i, 1);
-}
-
-static int uvc_ioctl_queryctrl(struct file *file, void *fh,
-			       struct v4l2_queryctrl *qc)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
-
-	return uvc_query_v4l2_ctrl(chain, qc);
-}
-
-static int uvc_ioctl_g_ctrl(struct file *file, void *fh,
-			    struct v4l2_control *ctrl)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
-	struct v4l2_ext_control xctrl;
-	int ret;
-
-	memset(&xctrl, 0, sizeof(xctrl));
-	xctrl.id = ctrl->id;
-
-	ret = uvc_ctrl_begin(chain);
-	if (ret < 0)
-		return ret;
-
-	ret = uvc_ctrl_get(chain, &xctrl);
-	uvc_ctrl_rollback(handle);
-	if (ret < 0)
-		return ret;
-
-	ctrl->value = xctrl.value;
-	return 0;
-}
-
-static int uvc_ioctl_s_ctrl(struct file *file, void *fh,
-			    struct v4l2_control *ctrl)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
-	struct v4l2_ext_control xctrl;
-	int ret;
-
-	memset(&xctrl, 0, sizeof(xctrl));
-	xctrl.id = ctrl->id;
-	xctrl.value = ctrl->value;
-
-	ret = uvc_ctrl_begin(chain);
-	if (ret < 0)
-		return ret;
-
-	ret = uvc_ctrl_set(chain, &xctrl);
-	if (ret < 0) {
-		uvc_ctrl_rollback(handle);
-		return ret;
-	}
-
-	ret = uvc_ctrl_commit(handle, &xctrl, 1);
-	if (ret < 0)
-		return ret;
-
-	ctrl->value = xctrl.value;
-	return 0;
-}
-
-static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
-				 struct v4l2_ext_controls *ctrls)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
-	struct v4l2_ext_control *ctrl = ctrls->controls;
-	unsigned int i;
-	int ret;
-
-	ret = uvc_ctrl_begin(chain);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < ctrls->count; ++ctrl, ++i) {
-		ret = uvc_ctrl_get(chain, ctrl);
-		if (ret < 0) {
-			uvc_ctrl_rollback(handle);
-			ctrls->error_idx = i;
-			return ret;
-		}
-	}
-
-	ctrls->error_idx = 0;
-
-	return uvc_ctrl_rollback(handle);
-}
-
-static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle,
-				     struct v4l2_ext_controls *ctrls,
-				     bool commit)
-{
-	struct v4l2_ext_control *ctrl = ctrls->controls;
-	struct uvc_video_chain *chain = handle->chain;
-	unsigned int i;
-	int ret;
-
-	ret = uvc_ctrl_begin(chain);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < ctrls->count; ++ctrl, ++i) {
-		ret = uvc_ctrl_set(chain, ctrl);
-		if (ret < 0) {
-			uvc_ctrl_rollback(handle);
-			ctrls->error_idx = commit ? ctrls->count : i;
-			return ret;
-		}
-	}
-
-	ctrls->error_idx = 0;
-
-	if (commit)
-		return uvc_ctrl_commit(handle, ctrls->controls, ctrls->count);
-	else
-		return uvc_ctrl_rollback(handle);
-}
-
-static int uvc_ioctl_s_ext_ctrls(struct file *file, void *fh,
-				 struct v4l2_ext_controls *ctrls)
-{
-	struct uvc_fh *handle = fh;
-
-	return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, true);
-}
-
-static int uvc_ioctl_try_ext_ctrls(struct file *file, void *fh,
-				   struct v4l2_ext_controls *ctrls)
-{
-	struct uvc_fh *handle = fh;
-
-	return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, false);
-}
-
-static int uvc_ioctl_querymenu(struct file *file, void *fh,
-			       struct v4l2_querymenu *qm)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
-
-	return uvc_query_v4l2_menu(chain, qm);
-}
-
-static int uvc_ioctl_cropcap(struct file *file, void *fh,
-			     struct v4l2_cropcap *ccap)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	if (ccap->type != stream->type)
-		return -EINVAL;
-
-	ccap->bounds.left = 0;
-	ccap->bounds.top = 0;
-	mutex_lock(&stream->mutex);
-	ccap->bounds.width = stream->cur_frame->wWidth;
-	ccap->bounds.height = stream->cur_frame->wHeight;
-	mutex_unlock(&stream->mutex);
-
-	ccap->defrect = ccap->bounds;
-
-	ccap->pixelaspect.numerator = 1;
-	ccap->pixelaspect.denominator = 1;
-	return 0;
-}
-
-static int uvc_ioctl_g_parm(struct file *file, void *fh,
-			    struct v4l2_streamparm *parm)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-
-	return uvc_v4l2_get_streamparm(stream, parm);
-}
-
-static int uvc_ioctl_s_parm(struct file *file, void *fh,
-			    struct v4l2_streamparm *parm)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	int ret;
-
-	ret = uvc_acquire_privileges(handle);
-	if (ret < 0)
-		return ret;
-
-	return uvc_v4l2_set_streamparm(stream, parm);
-}
-
-static int uvc_ioctl_enum_framesizes(struct file *file, void *fh,
-				     struct v4l2_frmsizeenum *fsize)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	struct uvc_format *format = NULL;
-	struct uvc_frame *frame;
-	int i;
-
-	/* Look for the given pixel format */
-	for (i = 0; i < stream->nformats; i++) {
-		if (stream->format[i].fcc == fsize->pixel_format) {
-			format = &stream->format[i];
-			break;
-		}
-	}
-	if (format == NULL)
-		return -EINVAL;
-
-	if (fsize->index >= format->nframes)
-		return -EINVAL;
-
-	frame = &format->frame[fsize->index];
-	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-	fsize->discrete.width = frame->wWidth;
-	fsize->discrete.height = frame->wHeight;
-	return 0;
-}
-
-static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
-					 struct v4l2_frmivalenum *fival)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_streaming *stream = handle->stream;
-	struct uvc_format *format = NULL;
-	struct uvc_frame *frame = NULL;
-	int i;
-
-	/* Look for the given pixel format and frame size */
-	for (i = 0; i < stream->nformats; i++) {
-		if (stream->format[i].fcc == fival->pixel_format) {
-			format = &stream->format[i];
-			break;
-		}
-	}
-	if (format == NULL)
-		return -EINVAL;
-
-	for (i = 0; i < format->nframes; i++) {
-		if (format->frame[i].wWidth == fival->width &&
-		    format->frame[i].wHeight == fival->height) {
-			frame = &format->frame[i];
-			break;
-		}
-	}
-	if (frame == NULL)
-		return -EINVAL;
-
-	if (frame->bFrameIntervalType) {
-		if (fival->index >= frame->bFrameIntervalType)
-			return -EINVAL;
-
-		fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-		fival->discrete.numerator =
-			frame->dwFrameInterval[fival->index];
-		fival->discrete.denominator = 10000000;
-		uvc_simplify_fraction(&fival->discrete.numerator,
-			&fival->discrete.denominator, 8, 333);
-	} else {
-		fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
-		fival->stepwise.min.numerator = frame->dwFrameInterval[0];
-		fival->stepwise.min.denominator = 10000000;
-		fival->stepwise.max.numerator = frame->dwFrameInterval[1];
-		fival->stepwise.max.denominator = 10000000;
-		fival->stepwise.step.numerator = frame->dwFrameInterval[2];
-		fival->stepwise.step.denominator = 10000000;
-		uvc_simplify_fraction(&fival->stepwise.min.numerator,
-			&fival->stepwise.min.denominator, 8, 333);
-		uvc_simplify_fraction(&fival->stepwise.max.numerator,
-			&fival->stepwise.max.denominator, 8, 333);
-		uvc_simplify_fraction(&fival->stepwise.step.numerator,
-			&fival->stepwise.step.denominator, 8, 333);
-	}
-
-	return 0;
-}
-
-static int uvc_ioctl_subscribe_event(struct v4l2_fh *fh,
-				     const struct v4l2_event_subscription *sub)
-{
-	switch (sub->type) {
-	case V4L2_EVENT_CTRL:
-		return v4l2_event_subscribe(fh, sub, 0, &uvc_ctrl_sub_ev_ops);
-	default:
-		return -EINVAL;
-	}
-}
-
-static long uvc_ioctl_default(struct file *file, void *fh, bool valid_prio,
-			      unsigned int cmd, void *arg)
-{
-	struct uvc_fh *handle = fh;
-	struct uvc_video_chain *chain = handle->chain;
+	long ret = 0;
 
 	switch (cmd) {
-	/* Dynamic controls. */
+	/* Query capabilities */
+	case VIDIOC_QUERYCAP:
+	{
+		struct v4l2_capability *cap = arg;
+
+		memset(cap, 0, sizeof *cap);
+		strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
+		strlcpy(cap->card, vdev->name, sizeof cap->card);
+		usb_make_path(stream->dev->udev,
+			      cap->bus_info, sizeof(cap->bus_info));
+		cap->version = LINUX_VERSION_CODE;
+		cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
+				  | chain->caps;
+		if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
+					 | V4L2_CAP_STREAMING;
+		else
+			cap->device_caps = V4L2_CAP_VIDEO_OUTPUT
+					 | V4L2_CAP_STREAMING;
+		break;
+	}
+
+	/* Priority */
+	case VIDIOC_G_PRIORITY:
+		*(u32 *)arg = v4l2_prio_max(vdev->prio);
+		break;
+
+	case VIDIOC_S_PRIORITY:
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+
+		return v4l2_prio_change(vdev->prio, &handle->vfh.prio,
+					*(u32 *)arg);
+
+	/* Get, Set & Query control */
+	case VIDIOC_QUERYCTRL:
+		return uvc_query_v4l2_ctrl(chain, arg);
+
+	case VIDIOC_G_CTRL:
+	{
+		struct v4l2_control *ctrl = arg;
+		struct v4l2_ext_control xctrl;
+
+		memset(&xctrl, 0, sizeof xctrl);
+		xctrl.id = ctrl->id;
+
+		ret = uvc_ctrl_begin(chain);
+		if (ret < 0)
+			return ret;
+
+		ret = uvc_ctrl_get(chain, &xctrl);
+		uvc_ctrl_rollback(handle);
+		if (ret >= 0)
+			ctrl->value = xctrl.value;
+		break;
+	}
+
+	case VIDIOC_S_CTRL:
+	{
+		struct v4l2_control *ctrl = arg;
+		struct v4l2_ext_control xctrl;
+
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+
+		memset(&xctrl, 0, sizeof xctrl);
+		xctrl.id = ctrl->id;
+		xctrl.value = ctrl->value;
+
+		ret = uvc_ctrl_begin(chain);
+		if (ret < 0)
+			return ret;
+
+		ret = uvc_ctrl_set(chain, &xctrl);
+		if (ret < 0) {
+			uvc_ctrl_rollback(handle);
+			return ret;
+		}
+		ret = uvc_ctrl_commit(handle, &xctrl, 1);
+		if (ret == 0)
+			ctrl->value = xctrl.value;
+		break;
+	}
+
+	case VIDIOC_QUERYMENU:
+		return uvc_query_v4l2_menu(chain, arg);
+
+	case VIDIOC_G_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *ctrls = arg;
+		struct v4l2_ext_control *ctrl = ctrls->controls;
+		unsigned int i;
+
+		ret = uvc_ctrl_begin(chain);
+		if (ret < 0)
+			return ret;
+
+		for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+			ret = uvc_ctrl_get(chain, ctrl);
+			if (ret < 0) {
+				uvc_ctrl_rollback(handle);
+				ctrls->error_idx = i;
+				return ret;
+			}
+		}
+		ctrls->error_idx = 0;
+		ret = uvc_ctrl_rollback(handle);
+		break;
+	}
+
+	case VIDIOC_S_EXT_CTRLS:
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+		/* Fall through */
+	case VIDIOC_TRY_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *ctrls = arg;
+		struct v4l2_ext_control *ctrl = ctrls->controls;
+		unsigned int i;
+
+		ret = uvc_ctrl_begin(chain);
+		if (ret < 0)
+			return ret;
+
+		for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+			ret = uvc_ctrl_set(chain, ctrl);
+			if (ret < 0) {
+				uvc_ctrl_rollback(handle);
+				ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS
+						 ? ctrls->count : i;
+				return ret;
+			}
+		}
+
+		ctrls->error_idx = 0;
+
+		if (cmd == VIDIOC_S_EXT_CTRLS)
+			ret = uvc_ctrl_commit(handle,
+					      ctrls->controls, ctrls->count);
+		else
+			ret = uvc_ctrl_rollback(handle);
+		break;
+	}
+
+	/* Get, Set & Enum input */
+	case VIDIOC_ENUMINPUT:
+	{
+		const struct uvc_entity *selector = chain->selector;
+		struct v4l2_input *input = arg;
+		struct uvc_entity *iterm = NULL;
+		u32 index = input->index;
+		int pin = 0;
+
+		if (selector == NULL ||
+		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+			if (index != 0)
+				return -EINVAL;
+			list_for_each_entry(iterm, &chain->entities, chain) {
+				if (UVC_ENTITY_IS_ITERM(iterm))
+					break;
+			}
+			pin = iterm->id;
+		} else if (index < selector->bNrInPins) {
+			pin = selector->baSourceID[index];
+			list_for_each_entry(iterm, &chain->entities, chain) {
+				if (!UVC_ENTITY_IS_ITERM(iterm))
+					continue;
+				if (iterm->id == pin)
+					break;
+			}
+		}
+
+		if (iterm == NULL || iterm->id != pin)
+			return -EINVAL;
+
+		memset(input, 0, sizeof *input);
+		input->index = index;
+		strlcpy(input->name, iterm->name, sizeof input->name);
+		if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
+			input->type = V4L2_INPUT_TYPE_CAMERA;
+		break;
+	}
+
+	case VIDIOC_G_INPUT:
+	{
+		u8 input;
+
+		if (chain->selector == NULL ||
+		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+			*(int *)arg = 0;
+			break;
+		}
+
+		ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+			chain->selector->id, chain->dev->intfnum,
+			UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
+		if (ret < 0)
+			return ret;
+
+		*(int *)arg = input - 1;
+		break;
+	}
+
+	case VIDIOC_S_INPUT:
+	{
+		u32 input = *(u32 *)arg + 1;
+
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+
+		if ((ret = uvc_acquire_privileges(handle)) < 0)
+			return ret;
+
+		if (chain->selector == NULL ||
+		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+			if (input != 1)
+				return -EINVAL;
+			break;
+		}
+
+		if (input == 0 || input > chain->selector->bNrInPins)
+			return -EINVAL;
+
+		return uvc_query_ctrl(chain->dev, UVC_SET_CUR,
+			chain->selector->id, chain->dev->intfnum,
+			UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
+	}
+
+	/* Try, Get, Set & Enum format */
+	case VIDIOC_ENUM_FMT:
+	{
+		struct v4l2_fmtdesc *fmt = arg;
+		struct uvc_format *format;
+		enum v4l2_buf_type type = fmt->type;
+		__u32 index = fmt->index;
+
+		if (fmt->type != stream->type ||
+		    fmt->index >= stream->nformats)
+			return -EINVAL;
+
+		memset(fmt, 0, sizeof(*fmt));
+		fmt->index = index;
+		fmt->type = type;
+
+		format = &stream->format[fmt->index];
+		fmt->flags = 0;
+		if (format->flags & UVC_FMT_FLAG_COMPRESSED)
+			fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+		strlcpy(fmt->description, format->name,
+			sizeof fmt->description);
+		fmt->description[sizeof fmt->description - 1] = 0;
+		fmt->pixelformat = format->fcc;
+		break;
+	}
+
+	case VIDIOC_TRY_FMT:
+	{
+		struct uvc_streaming_control probe;
+
+		return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL);
+	}
+
+	case VIDIOC_S_FMT:
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+
+		if ((ret = uvc_acquire_privileges(handle)) < 0)
+			return ret;
+
+		return uvc_v4l2_set_format(stream, arg);
+
+	case VIDIOC_G_FMT:
+		return uvc_v4l2_get_format(stream, arg);
+
+	/* Frame size enumeration */
+	case VIDIOC_ENUM_FRAMESIZES:
+	{
+		struct v4l2_frmsizeenum *fsize = arg;
+		struct uvc_format *format = NULL;
+		struct uvc_frame *frame;
+		int i;
+
+		/* Look for the given pixel format */
+		for (i = 0; i < stream->nformats; i++) {
+			if (stream->format[i].fcc ==
+					fsize->pixel_format) {
+				format = &stream->format[i];
+				break;
+			}
+		}
+		if (format == NULL)
+			return -EINVAL;
+
+		if (fsize->index >= format->nframes)
+			return -EINVAL;
+
+		frame = &format->frame[fsize->index];
+		fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+		fsize->discrete.width = frame->wWidth;
+		fsize->discrete.height = frame->wHeight;
+		break;
+	}
+
+	/* Frame interval enumeration */
+	case VIDIOC_ENUM_FRAMEINTERVALS:
+	{
+		struct v4l2_frmivalenum *fival = arg;
+		struct uvc_format *format = NULL;
+		struct uvc_frame *frame = NULL;
+		int i;
+
+		/* Look for the given pixel format and frame size */
+		for (i = 0; i < stream->nformats; i++) {
+			if (stream->format[i].fcc ==
+					fival->pixel_format) {
+				format = &stream->format[i];
+				break;
+			}
+		}
+		if (format == NULL)
+			return -EINVAL;
+
+		for (i = 0; i < format->nframes; i++) {
+			if (format->frame[i].wWidth == fival->width &&
+			    format->frame[i].wHeight == fival->height) {
+				frame = &format->frame[i];
+				break;
+			}
+		}
+		if (frame == NULL)
+			return -EINVAL;
+
+		if (frame->bFrameIntervalType) {
+			if (fival->index >= frame->bFrameIntervalType)
+				return -EINVAL;
+
+			fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+			fival->discrete.numerator =
+				frame->dwFrameInterval[fival->index];
+			fival->discrete.denominator = 10000000;
+			uvc_simplify_fraction(&fival->discrete.numerator,
+				&fival->discrete.denominator, 8, 333);
+		} else {
+			fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+			fival->stepwise.min.numerator =
+				frame->dwFrameInterval[0];
+			fival->stepwise.min.denominator = 10000000;
+			fival->stepwise.max.numerator =
+				frame->dwFrameInterval[1];
+			fival->stepwise.max.denominator = 10000000;
+			fival->stepwise.step.numerator =
+				frame->dwFrameInterval[2];
+			fival->stepwise.step.denominator = 10000000;
+			uvc_simplify_fraction(&fival->stepwise.min.numerator,
+				&fival->stepwise.min.denominator, 8, 333);
+			uvc_simplify_fraction(&fival->stepwise.max.numerator,
+				&fival->stepwise.max.denominator, 8, 333);
+			uvc_simplify_fraction(&fival->stepwise.step.numerator,
+				&fival->stepwise.step.denominator, 8, 333);
+		}
+		break;
+	}
+
+	/* Get & Set streaming parameters */
+	case VIDIOC_G_PARM:
+		return uvc_v4l2_get_streamparm(stream, arg);
+
+	case VIDIOC_S_PARM:
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+
+		if ((ret = uvc_acquire_privileges(handle)) < 0)
+			return ret;
+
+		return uvc_v4l2_set_streamparm(stream, arg);
+
+	/* Cropping and scaling */
+	case VIDIOC_CROPCAP:
+	{
+		struct v4l2_cropcap *ccap = arg;
+
+		if (ccap->type != stream->type)
+			return -EINVAL;
+
+		ccap->bounds.left = 0;
+		ccap->bounds.top = 0;
+
+		mutex_lock(&stream->mutex);
+		ccap->bounds.width = stream->cur_frame->wWidth;
+		ccap->bounds.height = stream->cur_frame->wHeight;
+		mutex_unlock(&stream->mutex);
+
+		ccap->defrect = ccap->bounds;
+
+		ccap->pixelaspect.numerator = 1;
+		ccap->pixelaspect.denominator = 1;
+		break;
+	}
+
+	case VIDIOC_G_CROP:
+	case VIDIOC_S_CROP:
+		return -ENOTTY;
+
+	/* Buffers & streaming */
+	case VIDIOC_REQBUFS:
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+
+		if ((ret = uvc_acquire_privileges(handle)) < 0)
+			return ret;
+
+		mutex_lock(&stream->mutex);
+		ret = uvc_alloc_buffers(&stream->queue, arg);
+		mutex_unlock(&stream->mutex);
+		if (ret < 0)
+			return ret;
+
+		if (ret == 0)
+			uvc_dismiss_privileges(handle);
+
+		ret = 0;
+		break;
+
+	case VIDIOC_QUERYBUF:
+	{
+		struct v4l2_buffer *buf = arg;
+
+		if (!uvc_has_privileges(handle))
+			return -EBUSY;
+
+		return uvc_query_buffer(&stream->queue, buf);
+	}
+
+	case VIDIOC_CREATE_BUFS:
+	{
+		struct v4l2_create_buffers *cb = arg;
+
+		ret = uvc_acquire_privileges(handle);
+		if (ret < 0)
+			return ret;
+
+		return uvc_create_buffers(&stream->queue, cb);
+	}
+
+	case VIDIOC_QBUF:
+		if (!uvc_has_privileges(handle))
+			return -EBUSY;
+
+		return uvc_queue_buffer(&stream->queue, arg);
+
+	case VIDIOC_DQBUF:
+		if (!uvc_has_privileges(handle))
+			return -EBUSY;
+
+		return uvc_dequeue_buffer(&stream->queue, arg,
+			file->f_flags & O_NONBLOCK);
+
+	case VIDIOC_STREAMON:
+	{
+		int *type = arg;
+
+		if (*type != stream->type)
+			return -EINVAL;
+
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+
+		if (!uvc_has_privileges(handle))
+			return -EBUSY;
+
+		mutex_lock(&stream->mutex);
+		ret = uvc_video_enable(stream, 1);
+		mutex_unlock(&stream->mutex);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	case VIDIOC_STREAMOFF:
+	{
+		int *type = arg;
+
+		if (*type != stream->type)
+			return -EINVAL;
+
+		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+		if (ret < 0)
+			return ret;
+
+		if (!uvc_has_privileges(handle))
+			return -EBUSY;
+
+		return uvc_video_enable(stream, 0);
+	}
+
+	case VIDIOC_SUBSCRIBE_EVENT:
+	{
+		struct v4l2_event_subscription *sub = arg;
+
+		switch (sub->type) {
+		case V4L2_EVENT_CTRL:
+			return v4l2_event_subscribe(&handle->vfh, sub, 0,
+						    &uvc_ctrl_sub_ev_ops);
+		default:
+			return -EINVAL;
+		}
+	}
+
+	case VIDIOC_UNSUBSCRIBE_EVENT:
+		return v4l2_event_unsubscribe(&handle->vfh, arg);
+
+	case VIDIOC_DQEVENT:
+		return v4l2_event_dequeue(&handle->vfh, arg,
+					  file->f_flags & O_NONBLOCK);
+
+	/* Analog video standards make no sense for digital cameras. */
+	case VIDIOC_ENUMSTD:
+	case VIDIOC_QUERYSTD:
+	case VIDIOC_G_STD:
+	case VIDIOC_S_STD:
+
+	case VIDIOC_OVERLAY:
+
+	case VIDIOC_ENUMAUDIO:
+	case VIDIOC_ENUMAUDOUT:
+
+	case VIDIOC_ENUMOUTPUT:
+		uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
+		return -ENOTTY;
+
 	case UVCIOC_CTRL_MAP:
 		return uvc_ioctl_ctrl_map(chain, arg);
 
@@ -1178,8 +1106,23 @@
 		return uvc_xu_ctrl_query(chain, arg);
 
 	default:
+		uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd);
 		return -ENOTTY;
 	}
+
+	return ret;
+}
+
+static long uvc_v4l2_ioctl(struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	if (uvc_trace_param & UVC_TRACE_IOCTL) {
+		uvc_printk(KERN_DEBUG, "uvc_v4l2_ioctl(");
+		v4l_printk_ioctl(NULL, cmd);
+		printk(")\n");
+	}
+
+	return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
 }
 
 #ifdef CONFIG_COMPAT
@@ -1362,7 +1305,7 @@
 
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
-	ret = video_ioctl2(file, cmd, (unsigned long)&karg);
+	ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg);
 	set_fs(old_fs);
 
 	if (ret < 0)
@@ -1423,48 +1366,11 @@
 }
 #endif
 
-const struct v4l2_ioctl_ops uvc_ioctl_ops = {
-	.vidioc_querycap = uvc_ioctl_querycap,
-	.vidioc_enum_fmt_vid_cap = uvc_ioctl_enum_fmt_vid_cap,
-	.vidioc_enum_fmt_vid_out = uvc_ioctl_enum_fmt_vid_out,
-	.vidioc_g_fmt_vid_cap = uvc_ioctl_g_fmt_vid_cap,
-	.vidioc_g_fmt_vid_out = uvc_ioctl_g_fmt_vid_out,
-	.vidioc_s_fmt_vid_cap = uvc_ioctl_s_fmt_vid_cap,
-	.vidioc_s_fmt_vid_out = uvc_ioctl_s_fmt_vid_out,
-	.vidioc_try_fmt_vid_cap = uvc_ioctl_try_fmt_vid_cap,
-	.vidioc_try_fmt_vid_out = uvc_ioctl_try_fmt_vid_out,
-	.vidioc_reqbufs = uvc_ioctl_reqbufs,
-	.vidioc_querybuf = uvc_ioctl_querybuf,
-	.vidioc_qbuf = uvc_ioctl_qbuf,
-	.vidioc_dqbuf = uvc_ioctl_dqbuf,
-	.vidioc_create_bufs = uvc_ioctl_create_bufs,
-	.vidioc_streamon = uvc_ioctl_streamon,
-	.vidioc_streamoff = uvc_ioctl_streamoff,
-	.vidioc_enum_input = uvc_ioctl_enum_input,
-	.vidioc_g_input = uvc_ioctl_g_input,
-	.vidioc_s_input = uvc_ioctl_s_input,
-	.vidioc_queryctrl = uvc_ioctl_queryctrl,
-	.vidioc_g_ctrl = uvc_ioctl_g_ctrl,
-	.vidioc_s_ctrl = uvc_ioctl_s_ctrl,
-	.vidioc_g_ext_ctrls = uvc_ioctl_g_ext_ctrls,
-	.vidioc_s_ext_ctrls = uvc_ioctl_s_ext_ctrls,
-	.vidioc_try_ext_ctrls = uvc_ioctl_try_ext_ctrls,
-	.vidioc_querymenu = uvc_ioctl_querymenu,
-	.vidioc_cropcap = uvc_ioctl_cropcap,
-	.vidioc_g_parm = uvc_ioctl_g_parm,
-	.vidioc_s_parm = uvc_ioctl_s_parm,
-	.vidioc_enum_framesizes = uvc_ioctl_enum_framesizes,
-	.vidioc_enum_frameintervals = uvc_ioctl_enum_frameintervals,
-	.vidioc_subscribe_event = uvc_ioctl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-	.vidioc_default = uvc_ioctl_default,
-};
-
 const struct v4l2_file_operations uvc_fops = {
 	.owner		= THIS_MODULE,
 	.open		= uvc_v4l2_open,
 	.release	= uvc_v4l2_release,
-	.unlocked_ioctl	= video_ioctl2,
+	.unlocked_ioctl	= uvc_v4l2_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl32	= uvc_v4l2_compat_ioctl32,
 #endif
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 9637e8b..9ace520 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1021,7 +1021,6 @@
 
 		uvc_video_get_ts(&ts);
 
-		buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
 		buf->buf.v4l2_buf.sequence = stream->sequence;
 		buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
 		buf->buf.v4l2_buf.timestamp.tv_usec =
@@ -1144,7 +1143,7 @@
 static void uvc_video_validate_buffer(const struct uvc_streaming *stream,
 				      struct uvc_buffer *buf)
 {
-	if (stream->ctrl.dwMaxVideoFrameSize != buf->bytesused &&
+	if (stream->frame_size != buf->bytesused &&
 	    !(stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED))
 		buf->error = 1;
 }
@@ -1735,13 +1734,19 @@
 	uvc_video_clock_reset(stream);
 
 	ret = uvc_commit_video(stream, &stream->ctrl);
-	if (ret < 0)
+	if (ret < 0) {
+		uvc_queue_enable(&stream->queue, 0);
 		return ret;
+	}
 
 	if (!uvc_queue_streaming(&stream->queue))
 		return 0;
 
-	return uvc_init_video(stream, GFP_NOIO);
+	ret = uvc_init_video(stream, GFP_NOIO);
+	if (ret < 0)
+		uvc_queue_enable(&stream->queue, 0);
+
+	return ret;
 }
 
 /* ------------------------------------------------------------------------
@@ -1773,6 +1778,11 @@
 
 	atomic_set(&stream->active, 0);
 
+	/* Initialize the video buffers queue. */
+	ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+	if (ret)
+		return ret;
+
 	/* Alternate setting 0 should be the default, yet the XBox Live Vision
 	 * Cam (and possibly other devices) crash or otherwise misbehave if
 	 * they don't receive a SET_INTERFACE request before any other video
@@ -1879,6 +1889,7 @@
 			usb_clear_halt(stream->dev->udev, pipe);
 		}
 
+		uvc_queue_enable(&stream->queue, 0);
 		uvc_video_clock_cleanup(stream);
 		return 0;
 	}
@@ -1887,6 +1898,10 @@
 	if (ret < 0)
 		return ret;
 
+	ret = uvc_queue_enable(&stream->queue, 1);
+	if (ret < 0)
+		goto error_queue;
+
 	/* Commit the streaming parameters. */
 	ret = uvc_commit_video(stream, &stream->ctrl);
 	if (ret < 0)
@@ -1901,6 +1916,8 @@
 error_video:
 	usb_set_interface(stream->dev->udev, stream->intfnum, 0);
 error_commit:
+	uvc_queue_enable(&stream->queue, 0);
+error_queue:
 	uvc_video_clock_cleanup(stream);
 
 	return ret;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 1683a9c..11b6b61 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -148,7 +148,6 @@
 #define UVC_QUIRK_PROBE_DEF		0x00000100
 #define UVC_QUIRK_RESTRICT_FRAME_RATE	0x00000200
 #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT	0x00000400
-#define UVC_QUIRK_FORCE_Y8		0x00000800
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED		0x00000001
@@ -458,6 +457,7 @@
 	struct uvc_format *def_format;
 	struct uvc_format *cur_format;
 	struct uvc_frame *cur_frame;
+	size_t frame_size;
 
 	/* Protect access to ctrl, cur_format, cur_frame and hardware video
 	 * probe control.
@@ -580,6 +580,7 @@
 #define UVC_TRACE_FORMAT	(1 << 3)
 #define UVC_TRACE_CAPTURE	(1 << 4)
 #define UVC_TRACE_CALLS		(1 << 5)
+#define UVC_TRACE_IOCTL		(1 << 6)
 #define UVC_TRACE_FRAME		(1 << 7)
 #define UVC_TRACE_SUSPEND	(1 << 8)
 #define UVC_TRACE_STATUS	(1 << 9)
@@ -623,9 +624,9 @@
 /* Video buffers queue management. */
 extern int uvc_queue_init(struct uvc_video_queue *queue,
 		enum v4l2_buf_type type, int drop_corrupted);
-extern void uvc_queue_release(struct uvc_video_queue *queue);
-extern int uvc_request_buffers(struct uvc_video_queue *queue,
+extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
 		struct v4l2_requestbuffers *rb);
+extern void uvc_free_buffers(struct uvc_video_queue *queue);
 extern int uvc_query_buffer(struct uvc_video_queue *queue,
 		struct v4l2_buffer *v4l2_buf);
 extern int uvc_create_buffers(struct uvc_video_queue *queue,
@@ -634,10 +635,7 @@
 		struct v4l2_buffer *v4l2_buf);
 extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
 		struct v4l2_buffer *v4l2_buf, int nonblocking);
-extern int uvc_queue_streamon(struct uvc_video_queue *queue,
-			      enum v4l2_buf_type type);
-extern int uvc_queue_streamoff(struct uvc_video_queue *queue,
-			       enum v4l2_buf_type type);
+extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
 extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
 extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
 		struct uvc_buffer *buf);
@@ -656,7 +654,6 @@
 }
 
 /* V4L2 interface */
-extern const struct v4l2_ioctl_ops uvc_ioctl_ops;
 extern const struct v4l2_file_operations uvc_fops;
 
 /* Media controller */
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 2276750..52d7b51 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -77,7 +77,7 @@
 
 # Used by drivers that need Videobuf2 modules
 config VIDEOBUF2_CORE
-	select DMA_SHARED_BUFFER if !KERNEL_3_5
+	select DMA_SHARED_BUFFER if !BACKPORT_KERNEL_3_5
 	tristate
 	depends on m
 
@@ -91,14 +91,14 @@
 	depends on HAS_DMA
 	select VIDEOBUF2_CORE
 	select VIDEOBUF2_MEMOPS
-	select DMA_SHARED_BUFFER if !KERNEL_3_5
+	select DMA_SHARED_BUFFER if !BACKPORT_KERNEL_3_5
 
 config VIDEOBUF2_VMALLOC
 	tristate
 	depends on m
 	select VIDEOBUF2_CORE
 	select VIDEOBUF2_MEMOPS
-	select DMA_SHARED_BUFFER if !KERNEL_3_5
+	select DMA_SHARED_BUFFER if !BACKPORT_KERNEL_3_5
 
 config VIDEOBUF2_DMA_SG
 	tristate
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 0d6c1ec..46a938b 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -80,6 +80,36 @@
 
 /* Helper functions for control handling			     */
 
+/* Check for correctness of the ctrl's value based on the data from
+   struct v4l2_queryctrl and the available menu items. Note that
+   menu_items may be NULL, in that case it is ignored. */
+int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
+		const char * const *menu_items)
+{
+	if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
+		return -EINVAL;
+	if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
+		return -EBUSY;
+	if (qctrl->type == V4L2_CTRL_TYPE_STRING)
+		return 0;
+	if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
+	    qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
+	    qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
+		return 0;
+	if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
+		return -ERANGE;
+	if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
+		if (menu_items[ctrl->value] == NULL ||
+		    menu_items[ctrl->value][0] == '\0')
+			return -EINVAL;
+	}
+	if (qctrl->type == V4L2_CTRL_TYPE_BITMASK &&
+			(ctrl->value & ~qctrl->maximum))
+		return -ERANGE;
+	return 0;
+}
+EXPORT_SYMBOL(v4l2_ctrl_check);
+
 /* Fill in a struct v4l2_queryctrl */
 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
 {
@@ -105,6 +135,101 @@
 }
 EXPORT_SYMBOL(v4l2_ctrl_query_fill);
 
+/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
+   the menu. The qctrl pointer may be NULL, in which case it is ignored.
+   If menu_items is NULL, then the menu items are retrieved using
+   v4l2_ctrl_get_menu. */
+int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
+	       const char * const *menu_items)
+{
+	int i;
+
+	qmenu->reserved = 0;
+	if (menu_items == NULL)
+		menu_items = v4l2_ctrl_get_menu(qmenu->id);
+	if (menu_items == NULL ||
+	    (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum)))
+		return -EINVAL;
+	for (i = 0; i < qmenu->index && menu_items[i]; i++) ;
+	if (menu_items[i] == NULL || menu_items[i][0] == '\0')
+		return -EINVAL;
+	strlcpy(qmenu->name, menu_items[qmenu->index], sizeof(qmenu->name));
+	return 0;
+}
+EXPORT_SYMBOL(v4l2_ctrl_query_menu);
+
+/* Fill in a struct v4l2_querymenu based on the specified array of valid
+   menu items (terminated by V4L2_CTRL_MENU_IDS_END).
+   Use this if there are 'holes' in the list of valid menu items. */
+int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids)
+{
+	const char * const *menu_items = v4l2_ctrl_get_menu(qmenu->id);
+
+	qmenu->reserved = 0;
+	if (menu_items == NULL || ids == NULL)
+		return -EINVAL;
+	while (*ids != V4L2_CTRL_MENU_IDS_END) {
+		if (*ids++ == qmenu->index) {
+			strlcpy(qmenu->name, menu_items[qmenu->index],
+					sizeof(qmenu->name));
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items);
+
+/* ctrl_classes points to an array of u32 pointers, the last element is
+   a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
+   Each array must be sorted low to high and belong to the same control
+   class. The array of u32 pointers must also be sorted, from low class IDs
+   to high class IDs.
+
+   This function returns the first ID that follows after the given ID.
+   When no more controls are available 0 is returned. */
+u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
+{
+	u32 ctrl_class = V4L2_CTRL_ID2CLASS(id);
+	const u32 *pctrl;
+
+	if (ctrl_classes == NULL)
+		return 0;
+
+	/* if no query is desired, then check if the ID is part of ctrl_classes */
+	if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) {
+		/* find class */
+		while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class)
+			ctrl_classes++;
+		if (*ctrl_classes == NULL)
+			return 0;
+		pctrl = *ctrl_classes;
+		/* find control ID */
+		while (*pctrl && *pctrl != id) pctrl++;
+		return *pctrl ? id : 0;
+	}
+	id &= V4L2_CTRL_ID_MASK;
+	id++;	/* select next control */
+	/* find first class that matches (or is greater than) the class of
+	   the ID */
+	while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class)
+		ctrl_classes++;
+	/* no more classes */
+	if (*ctrl_classes == NULL)
+		return 0;
+	pctrl = *ctrl_classes;
+	/* find first ctrl within the class that is >= ID */
+	while (*pctrl && *pctrl < id) pctrl++;
+	if (*pctrl)
+		return *pctrl;
+	/* we are at the end of the controls of the current class. */
+	/* continue with next class if available */
+	ctrl_classes++;
+	if (*ctrl_classes == NULL)
+		return 0;
+	return **ctrl_classes;
+}
+EXPORT_SYMBOL(v4l2_ctrl_next);
+
 /* I2C Helper functions */
 
 #if IS_ENABLED(CONFIG_I2C)
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index af63543..e502a5f 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -222,9 +222,6 @@
 
 static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-	if (put_user(kp->type, &up->type))
-		return -EFAULT;
-
 	switch (kp->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -251,7 +248,8 @@
 
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+		put_user(kp->type, &up->type))
 		return -EFAULT;
 	return __put_v4l2_format32(kp, up);
 }
@@ -259,8 +257,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)))
-		return -EFAULT;
+	    copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
+			return -EFAULT;
 	return __put_v4l2_format32(&kp->format, &up->format);
 }
 
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 45c5b47..8601214 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1658,8 +1658,10 @@
 }
 
 /* Validate a new control */
-static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new)
+static int validate_new(const struct v4l2_ctrl *ctrl,
+			struct v4l2_ext_control *c)
 {
+	union v4l2_ctrl_ptr ptr;
 	unsigned idx;
 	int err = 0;
 
@@ -1672,14 +1674,19 @@
 		case V4L2_CTRL_TYPE_BOOLEAN:
 		case V4L2_CTRL_TYPE_BUTTON:
 		case V4L2_CTRL_TYPE_CTRL_CLASS:
+			ptr.p_s32 = &c->value;
+			return ctrl->type_ops->validate(ctrl, 0, ptr);
+
 		case V4L2_CTRL_TYPE_INTEGER64:
-			return ctrl->type_ops->validate(ctrl, 0, p_new);
+			ptr.p_s64 = &c->value64;
+			return ctrl->type_ops->validate(ctrl, 0, ptr);
 		default:
 			break;
 		}
 	}
-	for (idx = 0; !err && idx < ctrl->elems; idx++)
-		err = ctrl->type_ops->validate(ctrl, idx, p_new);
+	ptr.p = c->ptr;
+	for (idx = 0; !err && idx < c->size / ctrl->elem_size; idx++)
+		err = ctrl->type_ops->validate(ctrl, idx, ptr);
 	return err;
 }
 
@@ -3005,7 +3012,6 @@
 	cs->error_idx = cs->count;
 	for (i = 0; i < cs->count; i++) {
 		struct v4l2_ctrl *ctrl = helpers[i].ctrl;
-		union v4l2_ctrl_ptr p_new;
 
 		cs->error_idx = i;
 
@@ -3019,17 +3025,7 @@
 		   best-effort to avoid that. */
 		if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
 			return -EBUSY;
-		/*
-		 * Skip validation for now if the payload needs to be copied
-		 * from userspace into kernelspace. We'll validate those later.
-		 */
-		if (ctrl->is_ptr)
-			continue;
-		if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
-			p_new.p_s64 = &cs->controls[i].value64;
-		else
-			p_new.p_s32 = &cs->controls[i].value;
-		ret = validate_new(ctrl, p_new);
+		ret = validate_new(ctrl, &cs->controls[i]);
 		if (ret)
 			return ret;
 	}
@@ -3124,11 +3120,7 @@
 		/* Copy the new caller-supplied control values.
 		   user_to_new() sets 'is_new' to 1. */
 		do {
-			struct v4l2_ctrl *ctrl = helpers[idx].ctrl;
-
-			ret = user_to_new(cs->controls + idx, ctrl);
-			if (!ret && ctrl->is_ptr)
-				ret = validate_new(ctrl, ctrl->p_new);
+			ret = user_to_new(cs->controls + idx, helpers[idx].ctrl);
 			idx = helpers[idx].next;
 		} while (!ret && idx);
 
@@ -3178,10 +3170,10 @@
 EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls);
 
 /* Helper function for VIDIOC_S_CTRL compatibility */
-static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
+static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
+		    struct v4l2_ext_control *c, u32 ch_flags)
 {
 	struct v4l2_ctrl *master = ctrl->cluster[0];
-	int ret;
 	int i;
 
 	/* Reset the 'is_new' flags of the cluster */
@@ -3189,9 +3181,8 @@
 		if (master->cluster[i])
 			master->cluster[i]->is_new = 0;
 
-	ret = validate_new(ctrl, ctrl->p_new);
-	if (ret)
-		return ret;
+	if (c)
+		user_to_new(c, ctrl);
 
 	/* For autoclusters with volatiles that are switched from auto to
 	   manual mode we have to update the current volatile values since
@@ -3208,14 +3199,15 @@
 static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
 			 struct v4l2_ext_control *c)
 {
-	int ret;
+	int ret = validate_new(ctrl, c);
 
-	v4l2_ctrl_lock(ctrl);
-	user_to_new(c, ctrl);
-	ret = set_ctrl(fh, ctrl, 0);
-	if (!ret)
-		cur_to_user(c, ctrl);
-	v4l2_ctrl_unlock(ctrl);
+	if (!ret) {
+		v4l2_ctrl_lock(ctrl);
+		ret = set_ctrl(fh, ctrl, c, 0);
+		if (!ret)
+			cur_to_user(c, ctrl);
+		v4l2_ctrl_unlock(ctrl);
+	}
 	return ret;
 }
 
@@ -3223,7 +3215,7 @@
 					struct v4l2_control *control)
 {
 	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
-	struct v4l2_ext_control c = { control->id };
+	struct v4l2_ext_control c;
 	int ret;
 
 	if (ctrl == NULL || !ctrl->is_int)
@@ -3252,7 +3244,7 @@
 	/* It's a driver bug if this happens. */
 	WARN_ON(!ctrl->is_int);
 	ctrl->val = val;
-	return set_ctrl(NULL, ctrl, 0);
+	return set_ctrl(NULL, ctrl, NULL, 0);
 }
 EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
 
@@ -3263,7 +3255,7 @@
 	/* It's a driver bug if this happens. */
 	WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
 	*ctrl->p_new.p_s64 = val;
-	return set_ctrl(NULL, ctrl, 0);
+	return set_ctrl(NULL, ctrl, NULL, 0);
 }
 EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
 
@@ -3274,7 +3266,7 @@
 	/* It's a driver bug if this happens. */
 	WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING);
 	strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
-	return set_ctrl(NULL, ctrl, 0);
+	return set_ctrl(NULL, ctrl, NULL, 0);
 }
 EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
 
@@ -3297,8 +3289,8 @@
 int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
 			s64 min, s64 max, u64 step, s64 def)
 {
-	bool changed;
 	int ret;
+	struct v4l2_ext_control c;
 
 	lockdep_assert_held(ctrl->handler->lock);
 
@@ -3325,20 +3317,11 @@
 	ctrl->maximum = max;
 	ctrl->step = step;
 	ctrl->default_value = def;
-	cur_to_new(ctrl);
-	if (validate_new(ctrl, ctrl->p_new)) {
-		if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
-			*ctrl->p_new.p_s64 = def;
-		else
-			*ctrl->p_new.p_s32 = def;
-	}
-
-	if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
-		changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64;
-	else
-		changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32;
-	if (changed)
-		ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
+	c.value = *ctrl->p_cur.p_s32;
+	if (validate_new(ctrl, &c))
+		c.value = def;
+	if (c.value != *ctrl->p_cur.p_s32)
+		ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE);
 	else
 		send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
 	return ret;
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 7385fc2..7953699 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -199,7 +199,7 @@
 	mutex_unlock(&videodev_lock);
 
 #if defined(CPTCFG_MEDIA_CONTROLLER)
-	if (v4l2_dev->mdev &&
+	if (v4l2_dev && v4l2_dev->mdev &&
 	    vdev->vfl_type != VFL_TYPE_SUBDEV)
 		media_device_unregister_entity(&vdev->entity);
 #endif
@@ -212,7 +212,7 @@
 	 * TODO: In the long run all drivers that use v4l2_device should use the
 	 * v4l2_device release callback. This check will then be unnecessary.
 	 */
-	if (v4l2_dev->release == NULL)
+	if (v4l2_dev && v4l2_dev->release == NULL)
 		v4l2_dev = NULL;
 
 	/* Release video_device and perform other
@@ -369,22 +369,27 @@
 		 * hack but it will have to do for those drivers that are not
 		 * yet converted to use unlocked_ioctl.
 		 *
-		 * All drivers implement struct v4l2_device, so we use the
-		 * lock defined there to serialize the ioctls.
+		 * There are two options: if the driver implements struct
+		 * v4l2_device, then the lock defined there is used to
+		 * serialize the ioctls. Otherwise the v4l2 core lock defined
+		 * below is used. This lock is really bad since it serializes
+		 * completely independent devices.
 		 *
-		 * However, if the driver sleeps, then it blocks all ioctls
-		 * since the lock is still held. This is very common for
-		 * VIDIOC_DQBUF since that normally waits for a frame to arrive.
-		 * As a result any other ioctl calls will proceed very, very
-		 * slowly since each call will have to wait for the VIDIOC_QBUF
-		 * to finish. Things that should take 0.01s may now take 10-20
-		 * seconds.
+		 * Both variants suffer from the same problem: if the driver
+		 * sleeps, then it blocks all ioctls since the lock is still
+		 * held. This is very common for VIDIOC_DQBUF since that
+		 * normally waits for a frame to arrive. As a result any other
+		 * ioctl calls will proceed very, very slowly since each call
+		 * will have to wait for the VIDIOC_QBUF to finish. Things that
+		 * should take 0.01s may now take 10-20 seconds.
 		 *
 		 * The workaround is to *not* take the lock for VIDIOC_DQBUF.
 		 * This actually works OK for videobuf-based drivers, since
 		 * videobuf will take its own internal lock.
 		 */
-		struct mutex *m = &vdev->v4l2_dev->ioctl_lock;
+		static DEFINE_MUTEX(v4l2_ioctl_mutex);
+		struct mutex *m = vdev->v4l2_dev ?
+			&vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex;
 
 		if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m))
 			return -ERESTARTSYS;
@@ -942,11 +947,12 @@
 			name_base, nr, video_device_node_name(vdev));
 
 	/* Increase v4l2_device refcount */
-	v4l2_device_get(vdev->v4l2_dev);
+	if (vdev->v4l2_dev)
+		v4l2_device_get(vdev->v4l2_dev);
 
 #if defined(CPTCFG_MEDIA_CONTROLLER)
 	/* Part 5: Register the entity. */
-	if (vdev->v4l2_dev->mdev &&
+	if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
 	    vdev->vfl_type != VFL_TYPE_SUBDEV) {
 		vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
 		vdev->entity.name = vdev->name;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index e20f1c9..a47079b 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -257,7 +257,7 @@
 		pr_cont(", width=%u, height=%u, "
 			"pixelformat=%c%c%c%c, field=%s, "
 			"bytesperline=%u, sizeimage=%u, colorspace=%d, "
-			"flags %x, ycbcr_enc=%u, quantization=%u\n",
+			"flags %u\n",
 			pix->width, pix->height,
 			(pix->pixelformat & 0xff),
 			(pix->pixelformat >>  8) & 0xff,
@@ -265,24 +265,21 @@
 			(pix->pixelformat >> 24) & 0xff,
 			prt_names(pix->field, v4l2_field_names),
 			pix->bytesperline, pix->sizeimage,
-			pix->colorspace, pix->flags, pix->ycbcr_enc,
-			pix->quantization);
+			pix->colorspace, pix->flags);
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		mp = &p->fmt.pix_mp;
 		pr_cont(", width=%u, height=%u, "
 			"format=%c%c%c%c, field=%s, "
-			"colorspace=%d, num_planes=%u, flags=%x, "
-			"ycbcr_enc=%u, quantization=%u\n",
+			"colorspace=%d, num_planes=%u\n",
 			mp->width, mp->height,
 			(mp->pixelformat & 0xff),
 			(mp->pixelformat >>  8) & 0xff,
 			(mp->pixelformat >> 16) & 0xff,
 			(mp->pixelformat >> 24) & 0xff,
 			prt_names(mp->field, v4l2_field_names),
-			mp->colorspace, mp->num_planes, mp->flags,
-			mp->ycbcr_enc, mp->quantization);
+			mp->colorspace, mp->num_planes);
 		for (i = 0; i < mp->num_planes; i++)
 			printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
 					mp->plane_fmt[i].bytesperline,
@@ -1017,12 +1014,6 @@
 	ret = ops->vidioc_querycap(file, fh, cap);
 
 	cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
-	/*
-	 * Drivers MUST fill in device_caps, so check for this and
-	 * warn if it was forgotten.
-	 */
-	WARN_ON(!(cap->capabilities & V4L2_CAP_DEVICE_CAPS) ||
-		!cap->device_caps);
 	cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;
 
 	return ret;
@@ -1049,7 +1040,7 @@
 	if (ops->vidioc_g_priority)
 		return ops->vidioc_g_priority(file, fh, arg);
 	vfd = video_devdata(file);
-	*p = v4l2_prio_max(vfd->prio);
+	*p = v4l2_prio_max(&vfd->v4l2_dev->prio);
 	return 0;
 }
 
@@ -1064,7 +1055,7 @@
 		return ops->vidioc_s_priority(file, fh, *p);
 	vfd = video_devdata(file);
 	vfh = file->private_data;
-	return v4l2_prio_change(vfd->prio, &vfh->prio, *p);
+	return v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
 }
 
 static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c
index 926836d..b91a266 100644
--- a/drivers/media/v4l2-core/videobuf-core.c
+++ b/drivers/media/v4l2-core/videobuf-core.c
@@ -51,8 +51,6 @@
 
 #define CALL(q, f, arg...)						\
 	((q->int_ops->f) ? q->int_ops->f(arg) : 0)
-#define CALLPTR(q, f, arg...)						\
-	((q->int_ops->f) ? q->int_ops->f(arg) : NULL)
 
 struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q)
 {
@@ -833,7 +831,7 @@
 				   char __user *data, size_t count,
 				   int nonblocking)
 {
-	void *vaddr = CALLPTR(q, vaddr, buf);
+	void *vaddr = CALL(q, vaddr, buf);
 
 	/* copy to userspace */
 	if (count > buf->size - q->read_off)
@@ -850,7 +848,7 @@
 				  char __user *data, size_t count, size_t pos,
 				  int vbihack, int nonblocking)
 {
-	unsigned int *fc = CALLPTR(q, vaddr, buf);
+	unsigned int *fc = CALL(q, vaddr, buf);
 
 	if (vbihack) {
 		/* dirty, undocumented hack -- pass the frame counter
diff --git a/drivers/media/v4l2-core/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c
index e02353e..bf80f0f 100644
--- a/drivers/media/v4l2-core/videobuf-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf-dma-contig.c
@@ -305,15 +305,6 @@
 	/* Try to remap memory */
 	size = vma->vm_end - vma->vm_start;
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	/* the "vm_pgoff" is just used in v4l2 to find the
-	 * corresponding buffer data structure which is allocated
-	 * earlier and it does not mean the offset from the physical
-	 * buffer start address as usual. So set it to 0 to pass
-	 * the sanity check in vm_iomap_memory().
-	 */
-	vma->vm_pgoff = 0;
-
 	retval = vm_iomap_memory(vma, mem->dma_handle, size);
 	if (retval) {
 		dev_err(q->dev, "mmap: remap failed with error %d. ",
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index c20bdf7..e9d733e 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -189,8 +189,6 @@
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
 	struct vb2_queue *q = vb->vb2_queue;
-	enum dma_data_direction dma_dir =
-		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 	void *mem_priv;
 	int plane;
 
@@ -202,7 +200,7 @@
 		unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);
 
 		mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane],
-				      size, dma_dir, q->gfp_flags);
+				      size, q->gfp_flags);
 		if (IS_ERR_OR_NULL(mem_priv))
 			goto free;
 
@@ -1368,8 +1366,7 @@
 	void *mem_priv;
 	unsigned int plane;
 	int ret;
-	enum dma_data_direction dma_dir =
-		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+	int write = !V4L2_TYPE_IS_OUTPUT(q->type);
 	bool reacquired = vb->planes[0].mem_priv == NULL;
 
 	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1411,7 +1408,7 @@
 		/* Acquire each plane's memory */
 		mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane],
 				      planes[plane].m.userptr,
-				      planes[plane].length, dma_dir);
+				      planes[plane].length, write);
 		if (IS_ERR_OR_NULL(mem_priv)) {
 			dprintk(1, "failed acquiring userspace "
 						"memory for plane %d\n", plane);
@@ -1473,8 +1470,7 @@
 	void *mem_priv;
 	unsigned int plane;
 	int ret;
-	enum dma_data_direction dma_dir =
-		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+	int write = !V4L2_TYPE_IS_OUTPUT(q->type);
 	bool reacquired = vb->planes[0].mem_priv == NULL;
 
 	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1522,7 +1518,7 @@
 
 		/* Acquire each plane's memory */
 		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
-			dbuf, planes[plane].length, dma_dir);
+			dbuf, planes[plane].length, write);
 		if (IS_ERR(mem_priv)) {
 			dprintk(1, "failed to attach dmabuf\n");
 			ret = PTR_ERR(mem_priv);
@@ -3409,14 +3405,14 @@
 {
 	struct video_device *vdev = video_devdata(file);
 
-	if (lock)
-		mutex_lock(lock);
 	if (file->private_data == vdev->queue->owner) {
+		if (lock)
+			mutex_lock(lock);
 		vb2_queue_release(vdev->queue);
 		vdev->queue->owner = NULL;
+		if (lock)
+			mutex_unlock(lock);
 	}
-	if (lock)
-		mutex_unlock(lock);
 	return v4l2_fh_release(file);
 }
 EXPORT_SYMBOL_GPL(_vb2_fop_release);
@@ -3479,16 +3475,27 @@
 	struct video_device *vdev = video_devdata(file);
 	struct vb2_queue *q = vdev->queue;
 	struct mutex *lock = q->lock ? q->lock : vdev->lock;
+	unsigned long req_events = poll_requested_events(wait);
 	unsigned res;
 	void *fileio;
+	bool must_lock = false;
 
-	/*
-	 * If this helper doesn't know how to lock, then you shouldn't be using
-	 * it but you should write your own.
-	 */
-	WARN_ON(!lock);
+	/* Try to be smart: only lock if polling might start fileio,
+	   otherwise locking will only introduce unwanted delays. */
+	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
+		if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
+				(req_events & (POLLIN | POLLRDNORM)))
+			must_lock = true;
+		else if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
+				(req_events & (POLLOUT | POLLWRNORM)))
+			must_lock = true;
+	}
 
-	if (lock && mutex_lock_interruptible(lock))
+	/* If locking is needed, but this helper doesn't know how, then you
+	   shouldn't be using this helper but you should write your own. */
+	WARN_ON(must_lock && !lock);
+
+	if (must_lock && lock && mutex_lock_interruptible(lock))
 		return POLLERR;
 
 	fileio = q->fileio;
@@ -3496,9 +3503,9 @@
 	res = vb2_poll(vdev->queue, file, wait);
 
 	/* If fileio was started, then we have a new queue owner. */
-	if (!fileio && q->fileio)
+	if (must_lock && !fileio && q->fileio)
 		q->owner = file->private_data;
-	if (lock)
+	if (must_lock && lock)
 		mutex_unlock(lock);
 	return res;
 }
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index d5e28df..058d979 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -157,8 +157,7 @@
 	kfree(buf);
 }
 
-static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size,
-			  enum dma_data_direction dma_dir, gfp_t gfp_flags)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct device *dev = conf->dev;
@@ -179,7 +178,6 @@
 	/* Prevent the device from being released while the buffer is used */
 	buf->dev = get_device(dev);
 	buf->size = size;
-	buf->dma_dir = dma_dir;
 
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_dc_put;
@@ -281,7 +279,7 @@
 
 struct vb2_dc_attachment {
 	struct sg_table sgt;
-	enum dma_data_direction dma_dir;
+	enum dma_data_direction dir;
 };
 
 static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
@@ -316,7 +314,7 @@
 		wr = sg_next(wr);
 	}
 
-	attach->dma_dir = DMA_NONE;
+	attach->dir = DMA_NONE;
 	dbuf_attach->priv = attach;
 
 	return 0;
@@ -334,16 +332,16 @@
 	sgt = &attach->sgt;
 
 	/* release the scatterlist cache */
-	if (attach->dma_dir != DMA_NONE)
+	if (attach->dir != DMA_NONE)
 		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
-			attach->dma_dir);
+			attach->dir);
 	sg_free_table(sgt);
 	kfree(attach);
 	db_attach->priv = NULL;
 }
 
 static struct sg_table *vb2_dc_dmabuf_ops_map(
-	struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
+	struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
 {
 	struct vb2_dc_attachment *attach = db_attach->priv;
 	/* stealing dmabuf mutex to serialize map/unmap operations */
@@ -355,27 +353,27 @@
 
 	sgt = &attach->sgt;
 	/* return previously mapped sg table */
-	if (attach->dma_dir == dma_dir) {
+	if (attach->dir == dir) {
 		mutex_unlock(lock);
 		return sgt;
 	}
 
 	/* release any previous cache */
-	if (attach->dma_dir != DMA_NONE) {
+	if (attach->dir != DMA_NONE) {
 		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
-			attach->dma_dir);
-		attach->dma_dir = DMA_NONE;
+			attach->dir);
+		attach->dir = DMA_NONE;
 	}
 
 	/* mapping to the client with new direction */
-	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
 	if (ret <= 0) {
 		pr_err("failed to map scatterlist\n");
 		mutex_unlock(lock);
 		return ERR_PTR(-EIO);
 	}
 
-	attach->dma_dir = dma_dir;
+	attach->dir = dir;
 
 	mutex_unlock(lock);
 
@@ -383,7 +381,7 @@
 }
 
 static void vb2_dc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
-	struct sg_table *sgt, enum dma_data_direction dma_dir)
+	struct sg_table *sgt, enum dma_data_direction dir)
 {
 	/* nothing to be done here */
 }
@@ -513,8 +511,7 @@
 }
 
 static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
-	int n_pages, struct vm_area_struct *vma,
-	enum dma_data_direction dma_dir)
+	int n_pages, struct vm_area_struct *vma, int write)
 {
 	if (vma_is_io(vma)) {
 		unsigned int i;
@@ -536,7 +533,7 @@
 		int n;
 
 		n = get_user_pages(current, current->mm, start & PAGE_MASK,
-			n_pages, dma_dir == DMA_FROM_DEVICE, 1, pages, NULL);
+			n_pages, write, 1, pages, NULL);
 		/* negative error means that no page was pinned */
 		n = max(n, 0);
 		if (n != n_pages) {
@@ -562,17 +559,7 @@
 	struct sg_table *sgt = buf->dma_sgt;
 
 	if (sgt) {
-		DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-		dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
-		/*
-		 * No need to sync to CPU, it's already synced to the CPU
-		 * since the finish() memop will have been called before this.
-		 */
-		dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
-				   buf->dma_dir, &attrs);
+		dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
 		if (!vma_is_io(buf->vma))
 			vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
 
@@ -615,7 +602,7 @@
 #endif
 
 static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
-	unsigned long size, enum dma_data_direction dma_dir)
+	unsigned long size, int write)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct vb2_dc_buf *buf;
@@ -629,11 +616,6 @@
 	struct sg_table *sgt;
 	unsigned long contig_size;
 	unsigned long dma_align = dma_get_cache_alignment();
-	DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-	dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
 
 	/* Only cache aligned DMA transfers are reliable */
 	if (!IS_ALIGNED(vaddr | size, dma_align)) {
@@ -651,7 +633,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	buf->dev = conf->dev;
-	buf->dma_dir = dma_dir;
+	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 
 	start = vaddr & PAGE_MASK;
 	offset = vaddr & ~PAGE_MASK;
@@ -687,8 +669,7 @@
 	}
 
 	/* extract page list from userspace mapping */
-	ret = vb2_dc_get_user_pages(start, pages, n_pages, vma,
-				    dma_dir == DMA_FROM_DEVICE);
+	ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, write);
 	if (ret) {
 		unsigned long pfn;
 		if (vb2_dc_get_user_pfn(start, n_pages, vma, &pfn) == 0) {
@@ -720,12 +701,8 @@
 	kfree(pages);
 	pages = NULL;
 
-	/*
-	 * No need to sync to the device, this will happen later when the
-	 * prepare() memop is called.
-	 */
-	sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
-				      buf->dma_dir, &attrs);
+	sgt->nents = dma_map_sg(buf->dev, sgt->sgl, sgt->orig_nents,
+		buf->dma_dir);
 	if (sgt->nents <= 0) {
 		pr_err("failed to map scatterlist\n");
 		ret = -EIO;
@@ -747,8 +724,7 @@
 	return buf;
 
 fail_map_sg:
-	dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
-			   buf->dma_dir, &attrs);
+	dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
 
 fail_sgt_init:
 	if (!vma_is_io(buf->vma))
@@ -858,7 +834,7 @@
 }
 
 static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
-	unsigned long size, enum dma_data_direction dma_dir)
+	unsigned long size, int write)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct vb2_dc_buf *buf;
@@ -880,7 +856,7 @@
 		return dba;
 	}
 
-	buf->dma_dir = dma_dir;
+	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 	buf->size = size;
 	buf->db_attach = dba;
 
@@ -931,8 +907,7 @@
 
 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
 {
-	if (!IS_ERR_OR_NULL(alloc_ctx))
-		kfree(alloc_ctx);
+	kfree(alloc_ctx);
 }
 EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx);
 
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 18f9f42..9b163a4 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -30,30 +30,17 @@
 			printk(KERN_DEBUG "vb2-dma-sg: " fmt, ## arg);	\
 	} while (0)
 
-struct vb2_dma_sg_conf {
-	struct device		*dev;
-};
-
 struct vb2_dma_sg_buf {
-	struct device			*dev;
 	void				*vaddr;
 	struct page			**pages;
+	int				write;
 	int				offset;
-	enum dma_data_direction		dma_dir;
 	struct sg_table			sg_table;
-	/*
-	 * This will point to sg_table when used with the MMAP or USERPTR
-	 * memory model, and to the dma_buf sglist when used with the
-	 * DMABUF memory model.
-	 */
-	struct sg_table			*dma_sgt;
 	size_t				size;
 	unsigned int			num_pages;
 	atomic_t			refcount;
 	struct vb2_vmarea_handler	handler;
 	struct vm_area_struct		*vma;
-
-	struct dma_buf_attachment	*db_attach;
 };
 
 static void vb2_dma_sg_put(void *buf_priv);
@@ -99,33 +86,22 @@
 	return 0;
 }
 
-static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
-			      enum dma_data_direction dma_dir, gfp_t gfp_flags)
+static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
-	struct vb2_dma_sg_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
-	struct sg_table *sgt;
 	int ret;
 	int num_pages;
-	DEFINE_DMA_ATTRS(attrs);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-	dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
-
-	if (WARN_ON(alloc_ctx == NULL))
-		return NULL;
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
 		return NULL;
 
 	buf->vaddr = NULL;
-	buf->dma_dir = dma_dir;
+	buf->write = 0;
 	buf->offset = 0;
 	buf->size = size;
 	/* size is already page aligned */
 	buf->num_pages = size >> PAGE_SHIFT;
-	buf->dma_sgt = &buf->sg_table;
 
 	buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
 			     GFP_KERNEL);
@@ -136,23 +112,11 @@
 	if (ret)
 		goto fail_pages_alloc;
 
-	ret = sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
+	ret = sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
 			buf->num_pages, 0, size, GFP_KERNEL);
 	if (ret)
 		goto fail_table_alloc;
 
-	/* Prevent the device from being released while the buffer is used */
-	buf->dev = get_device(conf->dev);
-
-	sgt = &buf->sg_table;
-	/*
-	 * No need to sync to the device, this will happen later when the
-	 * prepare() memop is called.
-	 */
-	if (dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
-			     buf->dma_dir, &attrs) == 0)
-		goto fail_map;
-
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_dma_sg_put;
 	buf->handler.arg = buf;
@@ -163,9 +127,6 @@
 		__func__, buf->num_pages);
 	return buf;
 
-fail_map:
-	put_device(buf->dev);
-	sg_free_table(buf->dma_sgt);
 fail_table_alloc:
 	num_pages = buf->num_pages;
 	while (num_pages--)
@@ -180,85 +141,42 @@
 static void vb2_dma_sg_put(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
-	struct sg_table *sgt = &buf->sg_table;
 	int i = buf->num_pages;
 
 	if (atomic_dec_and_test(&buf->refcount)) {
-		DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-		dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
 		dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
 			buf->num_pages);
-		dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
-				   buf->dma_dir, &attrs);
 		if (buf->vaddr)
 			vm_unmap_ram(buf->vaddr, buf->num_pages);
-		sg_free_table(buf->dma_sgt);
+		sg_free_table(&buf->sg_table);
 		while (--i >= 0)
 			__free_page(buf->pages[i]);
 		kfree(buf->pages);
-		put_device(buf->dev);
 		kfree(buf);
 	}
 }
 
-static void vb2_dma_sg_prepare(void *buf_priv)
-{
-	struct vb2_dma_sg_buf *buf = buf_priv;
-	struct sg_table *sgt = buf->dma_sgt;
-
-	/* DMABUF exporter will flush the cache for us */
-	if (buf->db_attach)
-		return;
-
-	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
-}
-
-static void vb2_dma_sg_finish(void *buf_priv)
-{
-	struct vb2_dma_sg_buf *buf = buf_priv;
-	struct sg_table *sgt = buf->dma_sgt;
-
-	/* DMABUF exporter will flush the cache for us */
-	if (buf->db_attach)
-		return;
-
-	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
-}
-
 static inline int vma_is_io(struct vm_area_struct *vma)
 {
 	return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
 }
 
 static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
-				    unsigned long size,
-				    enum dma_data_direction dma_dir)
+				    unsigned long size, int write)
 {
-	struct vb2_dma_sg_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
 	unsigned long first, last;
 	int num_pages_from_user;
 	struct vm_area_struct *vma;
-	struct sg_table *sgt;
-	DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-	dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
 		return NULL;
 
 	buf->vaddr = NULL;
-	buf->dev = conf->dev;
-	buf->dma_dir = dma_dir;
+	buf->write = write;
 	buf->offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
-	buf->dma_sgt = &buf->sg_table;
 
 	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
 	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
@@ -303,7 +221,7 @@
 		num_pages_from_user = get_user_pages(current, current->mm,
 					     vaddr & PAGE_MASK,
 					     buf->num_pages,
-					     buf->dma_dir == DMA_FROM_DEVICE,
+					     write,
 					     1, /* force */
 					     buf->pages,
 					     NULL);
@@ -311,22 +229,12 @@
 	if (num_pages_from_user != buf->num_pages)
 		goto userptr_fail_get_user_pages;
 
-	if (sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
+	if (sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
 			buf->num_pages, buf->offset, size, 0))
 		goto userptr_fail_alloc_table_from_pages;
 
-	sgt = &buf->sg_table;
-	/*
-	 * No need to sync to the device, this will happen later when the
-	 * prepare() memop is called.
-	 */
-	if (dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
-			     buf->dma_dir, &attrs) == 0)
-		goto userptr_fail_map;
 	return buf;
 
-userptr_fail_map:
-	sg_free_table(&buf->sg_table);
 userptr_fail_alloc_table_from_pages:
 userptr_fail_get_user_pages:
 	dprintk(1, "get_user_pages requested/got: %d/%d]\n",
@@ -349,22 +257,15 @@
 static void vb2_dma_sg_put_userptr(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
-	struct sg_table *sgt = &buf->sg_table;
 	int i = buf->num_pages;
-	DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-	dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
 
 	dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
 	       __func__, buf->num_pages);
-	dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir, &attrs);
 	if (buf->vaddr)
 		vm_unmap_ram(buf->vaddr, buf->num_pages);
-	sg_free_table(buf->dma_sgt);
+	sg_free_table(&buf->sg_table);
 	while (--i >= 0) {
-		if (buf->dma_dir == DMA_FROM_DEVICE)
+		if (buf->write)
 			set_page_dirty_lock(buf->pages[i]);
 		if (!vma_is_io(buf->vma))
 			put_page(buf->pages[i]);
@@ -380,18 +281,14 @@
 
 	BUG_ON(!buf);
 
-	if (!buf->vaddr) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-		if (buf->db_attach)
-			buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
-		else
-#endif
-			buf->vaddr = vm_map_ram(buf->pages,
-					buf->num_pages, -1, PAGE_KERNEL);
-	}
+	if (!buf->vaddr)
+		buf->vaddr = vm_map_ram(buf->pages,
+					buf->num_pages,
+					-1,
+					PAGE_KERNEL);
 
 	/* add offset in case userptr is not page-aligned */
-	return buf->vaddr ? buf->vaddr + buf->offset : NULL;
+	return buf->vaddr + buf->offset;
 }
 
 static unsigned int vb2_dma_sg_num_users(void *buf_priv)
@@ -438,281 +335,11 @@
 	return 0;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-/*********************************************/
-/*         DMABUF ops for exporters          */
-/*********************************************/
-
-struct vb2_dma_sg_attachment {
-	struct sg_table sgt;
-	enum dma_data_direction dma_dir;
-};
-
-static int vb2_dma_sg_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
-	struct dma_buf_attachment *dbuf_attach)
-{
-	struct vb2_dma_sg_attachment *attach;
-	unsigned int i;
-	struct scatterlist *rd, *wr;
-	struct sg_table *sgt;
-	struct vb2_dma_sg_buf *buf = dbuf->priv;
-	int ret;
-
-	attach = kzalloc(sizeof(*attach), GFP_KERNEL);
-	if (!attach)
-		return -ENOMEM;
-
-	sgt = &attach->sgt;
-	/* Copy the buf->base_sgt scatter list to the attachment, as we can't
-	 * map the same scatter list to multiple attachments at the same time.
-	 */
-	ret = sg_alloc_table(sgt, buf->dma_sgt->orig_nents, GFP_KERNEL);
-	if (ret) {
-		kfree(attach);
-		return -ENOMEM;
-	}
-
-	rd = buf->dma_sgt->sgl;
-	wr = sgt->sgl;
-	for (i = 0; i < sgt->orig_nents; ++i) {
-		sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
-		rd = sg_next(rd);
-		wr = sg_next(wr);
-	}
-
-	attach->dma_dir = DMA_NONE;
-	dbuf_attach->priv = attach;
-
-	return 0;
-}
-
-static void vb2_dma_sg_dmabuf_ops_detach(struct dma_buf *dbuf,
-	struct dma_buf_attachment *db_attach)
-{
-	struct vb2_dma_sg_attachment *attach = db_attach->priv;
-	struct sg_table *sgt;
-
-	if (!attach)
-		return;
-
-	sgt = &attach->sgt;
-
-	/* release the scatterlist cache */
-	if (attach->dma_dir != DMA_NONE)
-		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
-			attach->dma_dir);
-	sg_free_table(sgt);
-	kfree(attach);
-	db_attach->priv = NULL;
-}
-
-static struct sg_table *vb2_dma_sg_dmabuf_ops_map(
-	struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
-{
-	struct vb2_dma_sg_attachment *attach = db_attach->priv;
-	/* stealing dmabuf mutex to serialize map/unmap operations */
-	struct mutex *lock = &db_attach->dmabuf->lock;
-	struct sg_table *sgt;
-	int ret;
-
-	mutex_lock(lock);
-
-	sgt = &attach->sgt;
-	/* return previously mapped sg table */
-	if (attach->dma_dir == dma_dir) {
-		mutex_unlock(lock);
-		return sgt;
-	}
-
-	/* release any previous cache */
-	if (attach->dma_dir != DMA_NONE) {
-		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
-			attach->dma_dir);
-		attach->dma_dir = DMA_NONE;
-	}
-
-	/* mapping to the client with new direction */
-	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
-	if (ret <= 0) {
-		pr_err("failed to map scatterlist\n");
-		mutex_unlock(lock);
-		return ERR_PTR(-EIO);
-	}
-
-	attach->dma_dir = dma_dir;
-
-	mutex_unlock(lock);
-
-	return sgt;
-}
-
-static void vb2_dma_sg_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
-	struct sg_table *sgt, enum dma_data_direction dma_dir)
-{
-	/* nothing to be done here */
-}
-
-static void vb2_dma_sg_dmabuf_ops_release(struct dma_buf *dbuf)
-{
-	/* drop reference obtained in vb2_dma_sg_get_dmabuf */
-	vb2_dma_sg_put(dbuf->priv);
-}
-
-static void *vb2_dma_sg_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
-{
-	struct vb2_dma_sg_buf *buf = dbuf->priv;
-
-	return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
-}
-
-static void *vb2_dma_sg_dmabuf_ops_vmap(struct dma_buf *dbuf)
-{
-	struct vb2_dma_sg_buf *buf = dbuf->priv;
-
-	return vb2_dma_sg_vaddr(buf);
-}
-
-static int vb2_dma_sg_dmabuf_ops_mmap(struct dma_buf *dbuf,
-	struct vm_area_struct *vma)
-{
-	return vb2_dma_sg_mmap(dbuf->priv, vma);
-}
-
-static struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
-	.attach = vb2_dma_sg_dmabuf_ops_attach,
-	.detach = vb2_dma_sg_dmabuf_ops_detach,
-	.map_dma_buf = vb2_dma_sg_dmabuf_ops_map,
-	.unmap_dma_buf = vb2_dma_sg_dmabuf_ops_unmap,
-	.kmap = vb2_dma_sg_dmabuf_ops_kmap,
-	.kmap_atomic = vb2_dma_sg_dmabuf_ops_kmap,
-	.vmap = vb2_dma_sg_dmabuf_ops_vmap,
-	.mmap = vb2_dma_sg_dmabuf_ops_mmap,
-	.release = vb2_dma_sg_dmabuf_ops_release,
-};
-
-static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags)
-{
-	struct vb2_dma_sg_buf *buf = buf_priv;
-	struct dma_buf *dbuf;
-
-	if (WARN_ON(!buf->dma_sgt))
-		return NULL;
-
-	dbuf = dma_buf_export(buf, &vb2_dma_sg_dmabuf_ops, buf->size, flags, NULL);
-	if (IS_ERR(dbuf))
-		return NULL;
-
-	/* dmabuf keeps reference to vb2 buffer */
-	atomic_inc(&buf->refcount);
-
-	return dbuf;
-}
-
-/*********************************************/
-/*       callbacks for DMABUF buffers        */
-/*********************************************/
-
-static int vb2_dma_sg_map_dmabuf(void *mem_priv)
-{
-	struct vb2_dma_sg_buf *buf = mem_priv;
-	struct sg_table *sgt;
-
-	if (WARN_ON(!buf->db_attach)) {
-		pr_err("trying to pin a non attached buffer\n");
-		return -EINVAL;
-	}
-
-	if (WARN_ON(buf->dma_sgt)) {
-		pr_err("dmabuf buffer is already pinned\n");
-		return 0;
-	}
-
-	/* get the associated scatterlist for this buffer */
-	sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
-	if (IS_ERR(sgt)) {
-		pr_err("Error getting dmabuf scatterlist\n");
-		return -EINVAL;
-	}
-
-	buf->dma_sgt = sgt;
-	buf->vaddr = NULL;
-
-	return 0;
-}
-
-static void vb2_dma_sg_unmap_dmabuf(void *mem_priv)
-{
-	struct vb2_dma_sg_buf *buf = mem_priv;
-	struct sg_table *sgt = buf->dma_sgt;
-
-	if (WARN_ON(!buf->db_attach)) {
-		pr_err("trying to unpin a not attached buffer\n");
-		return;
-	}
-
-	if (WARN_ON(!sgt)) {
-		pr_err("dmabuf buffer is already unpinned\n");
-		return;
-	}
-
-	if (buf->vaddr) {
-		dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
-		buf->vaddr = NULL;
-	}
-	dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
-
-	buf->dma_sgt = NULL;
-}
-
-static void vb2_dma_sg_detach_dmabuf(void *mem_priv)
-{
-	struct vb2_dma_sg_buf *buf = mem_priv;
-
-	/* if vb2 works correctly you should never detach mapped buffer */
-	if (WARN_ON(buf->dma_sgt))
-		vb2_dma_sg_unmap_dmabuf(buf);
-
-	/* detach this attachment */
-	dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
-	kfree(buf);
-}
-
-static void *vb2_dma_sg_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
-	unsigned long size, enum dma_data_direction dma_dir)
-{
-	struct vb2_dma_sg_conf *conf = alloc_ctx;
-	struct vb2_dma_sg_buf *buf;
-	struct dma_buf_attachment *dba;
-
-	if (dbuf->size < size)
-		return ERR_PTR(-EFAULT);
-
-	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
-	if (!buf)
-		return ERR_PTR(-ENOMEM);
-
-	buf->dev = conf->dev;
-	/* create attachment for the dmabuf with the user device */
-	dba = dma_buf_attach(dbuf, buf->dev);
-	if (IS_ERR(dba)) {
-		pr_err("failed to attach dmabuf\n");
-		kfree(buf);
-		return dba;
-	}
-
-	buf->dma_dir = dma_dir;
-	buf->size = size;
-	buf->db_attach = dba;
-
-	return buf;
-}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) */
-
 static void *vb2_dma_sg_cookie(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
 
-	return buf->dma_sgt;
+	return &buf->sg_table;
 }
 
 const struct vb2_mem_ops vb2_dma_sg_memops = {
@@ -720,43 +347,13 @@
 	.put		= vb2_dma_sg_put,
 	.get_userptr	= vb2_dma_sg_get_userptr,
 	.put_userptr	= vb2_dma_sg_put_userptr,
-	.prepare	= vb2_dma_sg_prepare,
-	.finish		= vb2_dma_sg_finish,
 	.vaddr		= vb2_dma_sg_vaddr,
 	.mmap		= vb2_dma_sg_mmap,
 	.num_users	= vb2_dma_sg_num_users,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-	.get_dmabuf	= vb2_dma_sg_get_dmabuf,
-	.map_dmabuf	= vb2_dma_sg_map_dmabuf,
-	.unmap_dmabuf	= vb2_dma_sg_unmap_dmabuf,
-	.attach_dmabuf	= vb2_dma_sg_attach_dmabuf,
-	.detach_dmabuf	= vb2_dma_sg_detach_dmabuf,
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) */
 	.cookie		= vb2_dma_sg_cookie,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
 
-void *vb2_dma_sg_init_ctx(struct device *dev)
-{
-	struct vb2_dma_sg_conf *conf;
-
-	conf = kzalloc(sizeof(*conf), GFP_KERNEL);
-	if (!conf)
-		return ERR_PTR(-ENOMEM);
-
-	conf->dev = dev;
-
-	return conf;
-}
-EXPORT_SYMBOL_GPL(vb2_dma_sg_init_ctx);
-
-void vb2_dma_sg_cleanup_ctx(void *alloc_ctx)
-{
-	if (!IS_ERR_OR_NULL(alloc_ctx))
-		kfree(alloc_ctx);
-}
-EXPORT_SYMBOL_GPL(vb2_dma_sg_cleanup_ctx);
-
 MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2");
 MODULE_AUTHOR("Andrzej Pietrasiewicz");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 272a83d..59ef98c 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -25,7 +25,7 @@
 	void				*vaddr;
 	struct page			**pages;
 	struct vm_area_struct		*vma;
-	enum dma_data_direction		dma_dir;
+	int				write;
 	unsigned long			size;
 	unsigned int			n_pages;
 	atomic_t			refcount;
@@ -37,8 +37,7 @@
 
 static void vb2_vmalloc_put(void *buf_priv);
 
-static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size,
-			       enum dma_data_direction dma_dir, gfp_t gfp_flags)
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
 	struct vb2_vmalloc_buf *buf;
 
@@ -48,7 +47,6 @@
 
 	buf->size = size;
 	buf->vaddr = vmalloc_user(buf->size);
-	buf->dma_dir = dma_dir;
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_vmalloc_put;
 	buf->handler.arg = buf;
@@ -74,8 +72,7 @@
 }
 
 static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr,
-				     unsigned long size,
-				     enum dma_data_direction dma_dir)
+				     unsigned long size, int write)
 {
 	struct vb2_vmalloc_buf *buf;
 	unsigned long first, last;
@@ -87,7 +84,7 @@
 	if (!buf)
 		return NULL;
 
-	buf->dma_dir = dma_dir;
+	buf->write = write;
 	offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
 
@@ -112,8 +109,7 @@
 		/* current->mm->mmap_sem is taken by videobuf2 core */
 		n_pages = get_user_pages(current, current->mm,
 					 vaddr & PAGE_MASK, buf->n_pages,
-					 dma_dir == DMA_FROM_DEVICE,
-					 1, /* force */
+					 write, 1, /* force */
 					 buf->pages, NULL);
 		if (n_pages != buf->n_pages)
 			goto fail_get_user_pages;
@@ -150,13 +146,14 @@
 		if (vaddr)
 			vm_unmap_ram((void *)vaddr, buf->n_pages);
 		for (i = 0; i < buf->n_pages; ++i) {
-			if (buf->dma_dir == DMA_FROM_DEVICE)
+			if (buf->write)
 				set_page_dirty_lock(buf->pages[i]);
 			put_page(buf->pages[i]);
 		}
 		kfree(buf->pages);
 	} else {
-		vb2_put_vma(buf->vma);
+		if (buf->vma)
+			vb2_put_vma(buf->vma);
 		iounmap(buf->vaddr);
 	}
 	kfree(buf);
@@ -213,177 +210,7 @@
 	return 0;
 }
 
-/*********************************************/
-/*         DMABUF ops for exporters          */
-/*********************************************/
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-struct vb2_vmalloc_attachment {
-	struct sg_table sgt;
-	enum dma_data_direction dma_dir;
-};
-
-static int vb2_vmalloc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
-	struct dma_buf_attachment *dbuf_attach)
-{
-	struct vb2_vmalloc_attachment *attach;
-	struct vb2_vmalloc_buf *buf = dbuf->priv;
-	int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE;
-	struct sg_table *sgt;
-	struct scatterlist *sg;
-	void *vaddr = buf->vaddr;
-	int ret;
-	int i;
-
-	attach = kzalloc(sizeof(*attach), GFP_KERNEL);
-	if (!attach)
-		return -ENOMEM;
-
-	sgt = &attach->sgt;
-	ret = sg_alloc_table(sgt, num_pages, GFP_KERNEL);
-	if (ret) {
-		kfree(attach);
-		return ret;
-	}
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		struct page *page = vmalloc_to_page(vaddr);
-
-		if (!page) {
-			sg_free_table(sgt);
-			kfree(attach);
-			return -ENOMEM;
-		}
-		sg_set_page(sg, page, PAGE_SIZE, 0);
-		vaddr += PAGE_SIZE;
-	}
-
-	attach->dma_dir = DMA_NONE;
-	dbuf_attach->priv = attach;
-	return 0;
-}
-
-static void vb2_vmalloc_dmabuf_ops_detach(struct dma_buf *dbuf,
-	struct dma_buf_attachment *db_attach)
-{
-	struct vb2_vmalloc_attachment *attach = db_attach->priv;
-	struct sg_table *sgt;
-
-	if (!attach)
-		return;
-
-	sgt = &attach->sgt;
-
-	/* release the scatterlist cache */
-	if (attach->dma_dir != DMA_NONE)
-		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
-			attach->dma_dir);
-	sg_free_table(sgt);
-	kfree(attach);
-	db_attach->priv = NULL;
-}
-
-static struct sg_table *vb2_vmalloc_dmabuf_ops_map(
-	struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
-{
-	struct vb2_vmalloc_attachment *attach = db_attach->priv;
-	/* stealing dmabuf mutex to serialize map/unmap operations */
-	struct mutex *lock = &db_attach->dmabuf->lock;
-	struct sg_table *sgt;
-	int ret;
-
-	mutex_lock(lock);
-
-	sgt = &attach->sgt;
-	/* return previously mapped sg table */
-	if (attach->dma_dir == dma_dir) {
-		mutex_unlock(lock);
-		return sgt;
-	}
-
-	/* release any previous cache */
-	if (attach->dma_dir != DMA_NONE) {
-		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
-			attach->dma_dir);
-		attach->dma_dir = DMA_NONE;
-	}
-
-	/* mapping to the client with new direction */
-	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
-	if (ret <= 0) {
-		pr_err("failed to map scatterlist\n");
-		mutex_unlock(lock);
-		return ERR_PTR(-EIO);
-	}
-
-	attach->dma_dir = dma_dir;
-
-	mutex_unlock(lock);
-
-	return sgt;
-}
-
-static void vb2_vmalloc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
-	struct sg_table *sgt, enum dma_data_direction dma_dir)
-{
-	/* nothing to be done here */
-}
-
-static void vb2_vmalloc_dmabuf_ops_release(struct dma_buf *dbuf)
-{
-	/* drop reference obtained in vb2_vmalloc_get_dmabuf */
-	vb2_vmalloc_put(dbuf->priv);
-}
-
-static void *vb2_vmalloc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
-{
-	struct vb2_vmalloc_buf *buf = dbuf->priv;
-
-	return buf->vaddr + pgnum * PAGE_SIZE;
-}
-
-static void *vb2_vmalloc_dmabuf_ops_vmap(struct dma_buf *dbuf)
-{
-	struct vb2_vmalloc_buf *buf = dbuf->priv;
-
-	return buf->vaddr;
-}
-
-static int vb2_vmalloc_dmabuf_ops_mmap(struct dma_buf *dbuf,
-	struct vm_area_struct *vma)
-{
-	return vb2_vmalloc_mmap(dbuf->priv, vma);
-}
-
-static struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {
-	.attach = vb2_vmalloc_dmabuf_ops_attach,
-	.detach = vb2_vmalloc_dmabuf_ops_detach,
-	.map_dma_buf = vb2_vmalloc_dmabuf_ops_map,
-	.unmap_dma_buf = vb2_vmalloc_dmabuf_ops_unmap,
-	.kmap = vb2_vmalloc_dmabuf_ops_kmap,
-	.kmap_atomic = vb2_vmalloc_dmabuf_ops_kmap,
-	.vmap = vb2_vmalloc_dmabuf_ops_vmap,
-	.mmap = vb2_vmalloc_dmabuf_ops_mmap,
-	.release = vb2_vmalloc_dmabuf_ops_release,
-};
-
-static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flags)
-{
-	struct vb2_vmalloc_buf *buf = buf_priv;
-	struct dma_buf *dbuf;
-
-	if (WARN_ON(!buf->vaddr))
-		return NULL;
-
-	dbuf = dma_buf_export(buf, &vb2_vmalloc_dmabuf_ops, buf->size, flags, NULL);
-	if (IS_ERR(dbuf))
-		return NULL;
-
-	/* dmabuf keeps reference to vb2 buffer */
-	atomic_inc(&buf->refcount);
-
-	return dbuf;
-}
-
 /*********************************************/
 /*       callbacks for DMABUF buffers        */
 /*********************************************/
@@ -416,7 +243,7 @@
 }
 
 static void *vb2_vmalloc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
-	unsigned long size, enum dma_data_direction dma_dir)
+	unsigned long size, int write)
 {
 	struct vb2_vmalloc_buf *buf;
 
@@ -428,7 +255,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	buf->dbuf = dbuf;
-	buf->dma_dir = dma_dir;
+	buf->write = write;
 	buf->size = size;
 
 	return buf;
@@ -442,7 +269,6 @@
 	.get_userptr	= vb2_vmalloc_get_userptr,
 	.put_userptr	= vb2_vmalloc_put_userptr,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-	.get_dmabuf	= vb2_vmalloc_get_dmabuf,
 	.map_dmabuf	= vb2_vmalloc_map_dmabuf,
 	.unmap_dmabuf	= vb2_vmalloc_unmap_dmabuf,
 	.attach_dmabuf	= vb2_vmalloc_attach_dmabuf,
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 61deb80..0607b55 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -90,7 +90,7 @@
 	depends on m
 	depends on PCI
 	depends on CRC32
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  This driver supports the PCI-Express gigabit ethernet adapters
 	  based on JMicron JMC250 chipset.
@@ -128,7 +128,7 @@
 	depends on m
 	depends on PCI
 	depends on CRC32
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  Say Y here to support the Myson MTD-800 family of PCI-based Ethernet
 	  cards. <http://www.myson.com.tw/>
@@ -140,7 +140,7 @@
 	depends on n
 	tristate "NetX Ethernet support"
 	depends on m
-	select BPAUTO_MII
+	select BACKPORT_MII
 	depends on ARCH_NETX
 	---help---
 	  This is support for the Hilscher netX builtin Ethernet ports
@@ -159,7 +159,7 @@
 	tristate "OpenCores 10/100 Mbps Ethernet MAC support"
 	depends on m
 	depends on HAS_IOMEM && HAS_DMA
-	select BPAUTO_MII
+	select BACKPORT_MII
 	depends on PHYLIB
 	depends on CRC32
 	depends on BITREVERSE
@@ -173,7 +173,6 @@
 #source "drivers/net/ethernet/realtek/Kconfig"
 #source "drivers/net/ethernet/renesas/Kconfig"
 #source "drivers/net/ethernet/rdc/Kconfig"
-#source "drivers/net/ethernet/rocker/Kconfig"
 
 config S6GMAC
 	depends on n
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index be78a41..ef26a25 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -65,7 +65,6 @@
 #obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
 #obj-$(CONFIG_SH_ETH) += renesas/
 #obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
-#obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/
 #obj-$(CPTCFG_S6GMAC) += s6gmac.o
 #obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/
 #obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/
diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
index 35840c9..77f036c 100644
--- a/drivers/net/ethernet/atheros/Kconfig
+++ b/drivers/net/ethernet/atheros/Kconfig
@@ -23,7 +23,7 @@
 	depends on m
 	depends on PCI
 	depends on CRC32
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  This driver supports the Atheros L2 fast ethernet adapter.
 
@@ -35,7 +35,7 @@
 	depends on m
 	depends on PCI
 	depends on CRC32
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  This driver supports the Atheros/Attansic L1 gigabit ethernet
 	  adapter.
@@ -48,7 +48,7 @@
 	depends on m
 	depends on PCI
 	depends on CRC32
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  This driver supports the Atheros L1E gigabit ethernet adapter.
 
@@ -56,12 +56,12 @@
 	  will be called atl1e.
 
 config ATL1C
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_5
 	tristate "Atheros L1C Gigabit Ethernet support"
 	depends on m
 	depends on PCI
 	depends on CRC32
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  This driver supports the Atheros L1C gigabit ethernet adapter.
 
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 8ca9e3e..d540d29 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -48,7 +48,7 @@
 
 MODULE_AUTHOR("Jie Yang");
 MODULE_AUTHOR("Qualcomm Atheros Inc., <nic-devel@qualcomm.com>");
-MODULE_DESCRIPTION("Qualcomm Atheros 100/1000M Ethernet Network Driver");
+MODULE_DESCRIPTION("Qualcom Atheros 100/1000M Ethernet Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(ATL1C_DRV_VERSION);
 
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 9d17913..276237c 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -23,7 +23,7 @@
 	depends on m
 	depends on SSB_POSSIBLE && HAS_DMA
 	select SSB
-	select BPAUTO_MII
+	select BACKPORT_MII
 	depends on PHYLIB
 	---help---
 	  If you have a network (Ethernet) controller of this type, say Y
@@ -57,7 +57,7 @@
 	tristate "Broadcom 63xx internal mac support"
 	depends on m
 	depends on BCM63XX
-	select BPAUTO_MII
+	select BACKPORT_MII
 	depends on PHYLIB
 	help
 	  This driver supports the ethernet MACs in the Broadcom 63xx
@@ -67,9 +67,10 @@
 	depends on n
 	tristate "Broadcom GENET internal MAC support"
 	depends on m
-	select BPAUTO_MII
+	depends on OF
+	select BACKPORT_MII
 	depends on PHYLIB
-	depends on FIXED_PHY
+	select FIXED_PHY if BCMGENET=y
 	depends on BCM7XXX_PHY
 	help
 	  This driver supports the built-in Ethernet MACs found in the
@@ -172,9 +173,9 @@
 	tristate "Broadcom SYSTEMPORT internal MAC support"
 	depends on m
 	depends on OF
-	select BPAUTO_MII
+	select BACKPORT_MII
 	depends on PHYLIB
-	depends on FIXED_PHY
+	select FIXED_PHY if SYSTEMPORT=y
 	help
 	  This driver supports the built-in Ethernet MACs found in the
 	  Broadcom BCM7xxx Set Top Box family chipset using an internal
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 290bf08..f098a3f 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -836,7 +836,7 @@
 			struct sk_buff *copy_skb;
 
 			b44_recycle_rx(bp, cons, bp->rx_prod);
-			copy_skb = napi_alloc_skb(&bp->napi, len);
+			copy_skb = netdev_alloc_skb_ip_align(bp->dev, len);
 			if (copy_skb == NULL)
 				goto drop_it_no_recycle;
 
@@ -2104,7 +2104,6 @@
 		bp->flags &= ~B44_FLAG_WOL_ENABLE;
 	spin_unlock_irq(&bp->lock);
 
-	device_set_wakeup_enable(bp->sdev->dev, wol->wolopts & WAKE_MAGIC);
 	return 0;
 }
 
@@ -2453,7 +2452,6 @@
 		}
 	}
 
-	device_set_wakeup_capable(sdev->dev, true);
 	netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
 
 	return 0;
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 538d75f..3099c28 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -22,7 +22,7 @@
 	tristate "Intel(R) PRO/100+ support"
 	depends on m
 	depends on PCI
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  This driver supports Intel(R) PRO/100 family of adapters.
 	  To verify that your adapter is supported, find the board ID number
@@ -92,7 +92,6 @@
 	  will be called e1000e.
 
 config IGB
-	depends on !KERNEL_3_5
 	tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
 	depends on m
 	depends on PCI
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 813ab10..196b2bf 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2860,10 +2860,7 @@
 	return IGB_RETA_SIZE;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-static int igb_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
-			u8 *hfunc)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
 static int igb_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
 #else
 static int igb_get_rxfh(struct net_device *netdev, u32 *indir)
@@ -2872,12 +2869,6 @@
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	int i;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-	if (hfunc)
-		*hfunc = ETH_RSS_HASH_TOP;
-#endif
-	if (!indir)
-		return 0;
 	for (i = 0; i < IGB_RETA_SIZE; i++)
 		indir[i] = adapter->rss_indir_tbl[i];
 
@@ -2921,10 +2912,7 @@
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-static int igb_set_rxfh(struct net_device *netdev, const u32 *indir,
-			const u8 *key, const u8 hfunc)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
 static int igb_set_rxfh(struct net_device *netdev, const u32 *indir,
 			const u8 *key)
 #else
@@ -2936,15 +2924,6 @@
 	int i;
 	u32 num_queues;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-	/* We do not allow change in unsupported parameters */
-	if (key ||
-	    (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
-		return -EOPNOTSUPP;
-#endif
-	if (!indir)
-		return 0;
-
 	num_queues = adapter->rss_queues;
 
 	switch (hw->mac.type) {
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 84f0acb..18d60a2 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -200,9 +200,11 @@
 static int igb_suspend(struct device *);
 #endif
 static int igb_resume(struct device *);
+#ifdef CONFIG_PM_RUNTIME
 static int igb_runtime_suspend(struct device *dev);
 static int igb_runtime_resume(struct device *dev);
 static int igb_runtime_idle(struct device *dev);
+#endif
 static const struct dev_pm_ops igb_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume)
 	SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume,
@@ -1032,8 +1034,7 @@
 	/* igb_get_stats64() might access the rings on this vector,
 	 * we must wait a grace period before freeing it.
 	 */
-	if (q_vector)
-		kfree_rcu(q_vector, rcu);
+	kfree_rcu(q_vector, rcu);
 }
 
 /**
@@ -1813,10 +1814,8 @@
 	adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE;
 
 	for (i = 0; i < adapter->num_q_vectors; i++) {
-		if (adapter->q_vector[i]) {
-			napi_synchronize(&adapter->q_vector[i]->napi);
-			napi_disable(&adapter->q_vector[i]->napi);
-		}
+		napi_synchronize(&(adapter->q_vector[i]->napi));
+		napi_disable(&(adapter->q_vector[i]->napi));
 	}
 
 
@@ -3401,11 +3400,14 @@
 	struct e1000_hw *hw = &adapter->hw;
 	u32 mrqc, rxcsum;
 	u32 j, num_rx_queues;
-	u32 rss_key[10];
+	static const u32 rsskey[10] = { 0xDA565A6D, 0xC20E5B25, 0x3D256741,
+					0xB08FA343, 0xCB2BCAD0, 0xB4307BAE,
+					0xA32DCB77, 0x0CF23080, 0x3BB7426A,
+					0xFA01ACBE };
 
-	netdev_rss_key_fill(rss_key, sizeof(rss_key));
+	/* Fill out hash function seeds */
 	for (j = 0; j < 10; j++)
-		wr32(E1000_RSSRK(j), rss_key[j]);
+		wr32(E1000_RSSRK(j), rsskey[j]);
 
 	num_rx_queues = adapter->rss_queues;
 
@@ -3743,8 +3745,7 @@
 	int i;
 
 	for (i = 0; i < adapter->num_tx_queues; i++)
-		if (adapter->tx_ring[i])
-			igb_free_tx_resources(adapter->tx_ring[i]);
+		igb_free_tx_resources(adapter->tx_ring[i]);
 }
 
 void igb_unmap_and_free_tx_resource(struct igb_ring *ring,
@@ -3809,8 +3810,7 @@
 	int i;
 
 	for (i = 0; i < adapter->num_tx_queues; i++)
-		if (adapter->tx_ring[i])
-			igb_clean_tx_ring(adapter->tx_ring[i]);
+		igb_clean_tx_ring(adapter->tx_ring[i]);
 }
 
 /**
@@ -3847,8 +3847,7 @@
 	int i;
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
-		if (adapter->rx_ring[i])
-			igb_free_rx_resources(adapter->rx_ring[i]);
+		igb_free_rx_resources(adapter->rx_ring[i]);
 }
 
 /**
@@ -3903,8 +3902,7 @@
 	int i;
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
-		if (adapter->rx_ring[i])
-			igb_clean_rx_ring(adapter->rx_ring[i]);
+		igb_clean_rx_ring(adapter->rx_ring[i]);
 }
 
 /**
@@ -5121,8 +5119,12 @@
 	/* The minimum packet size with TCTL.PSP set is 17 so pad the skb
 	 * in order to meet this minimum size requirement.
 	 */
-	if (skb_put_padto(skb, 17))
-		return NETDEV_TX_OK;
+	if (unlikely(skb->len < 17)) {
+		if (skb_pad(skb, 17 - skb->len))
+			return NETDEV_TX_OK;
+		skb->len = 17;
+		skb_set_tail_pointer(skb, 17);
+	}
 
 	return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
 }
@@ -6567,11 +6569,6 @@
 	if (unlikely(page_to_nid(page) != numa_node_id()))
 		return false;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-	if (unlikely(page->pfmemalloc))
-		return false;
-#endif
-
 #if (PAGE_SIZE < 8192)
 	/* if we are only owner of page we can reuse it */
 	if (unlikely(page_count(page) != 1))
@@ -6638,12 +6635,7 @@
 		memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
 
 		/* we can reuse buffer as-is, just make sure it is local */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-		if (likely((page_to_nid(page) == numa_node_id()) &&
-			   !page->pfmemalloc))
-#else
 		if (likely(page_to_nid(page) == numa_node_id()))
-#endif
 			return true;
 
 		/* this page cannot be reused so discard it */
@@ -6680,7 +6672,8 @@
 #endif
 
 		/* allocate a skb to store the frags */
-		skb = napi_alloc_skb(&rx_ring->q_vector->napi, IGB_RX_HDR_LEN);
+		skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+						IGB_RX_HDR_LEN);
 		if (unlikely(!skb)) {
 			rx_ring->rx_stats.alloc_failed++;
 			return NULL;
@@ -6881,9 +6874,14 @@
 	if (skb_is_nonlinear(skb))
 		igb_pull_tail(rx_ring, rx_desc, skb);
 
-	/* if eth_skb_pad returns an error the skb was freed */
-	if (eth_skb_pad(skb))
-		return true;
+	/* if skb_pad returns an error the skb was freed */
+	if (unlikely(skb->len < 60)) {
+		int pad_len = 60 - skb->len;
+
+		if (skb_pad(skb, pad_len))
+			return true;
+		__skb_put(skb, pad_len);
+	}
 
 	return false;
 }
@@ -6948,14 +6946,14 @@
 
 		rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-		if (!rx_desc->wb.upper.status_error)
+		if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD))
 			break;
 
 		/* This memory barrier is needed to keep us from reading
 		 * any other fields out of the rx_desc until we know the
-		 * descriptor has been written back
+		 * RXD_STAT_DD bit is set
 		 */
-		dma_rmb();
+		rmb();
 
 		/* retrieve a buffer from the ring */
 		skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
@@ -7018,7 +7016,7 @@
 		return true;
 
 	/* alloc new page for storage */
-	page = dev_alloc_page();
+	page = __skb_alloc_page(GFP_ATOMIC | __GFP_COLD, NULL);
 	if (unlikely(!page)) {
 		rx_ring->rx_stats.alloc_failed++;
 		return false;
@@ -7454,8 +7452,6 @@
 	pci_restore_state(pdev);
 	pci_save_state(pdev);
 
-	if (!pci_device_is_present(pdev))
-		return -ENODEV;
 	err = pci_enable_device_mem(pdev);
 	if (err) {
 		dev_err(&pdev->dev,
@@ -7493,6 +7489,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
 static int igb_runtime_idle(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -7529,7 +7526,8 @@
 {
 	return igb_resume(dev);
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_RUNTIME */
+#endif
 
 static void igb_shutdown(struct pci_dev *pdev)
 {
diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
index 271a167..47e5bf2 100644
--- a/drivers/net/ieee802154/Kconfig
+++ b/drivers/net/ieee802154/Kconfig
@@ -11,6 +11,17 @@
 	  If you say N, all options in this submenu will be skipped and
 	  disabled.
 
+config IEEE802154_FAKEHARD
+	tristate "Fake LR-WPAN driver with several interconnected devices"
+	depends on m
+	depends on  IEEE802154_DRIVERS
+	---help---
+	  Say Y here to enable the fake driver that serves as an example
+	  of HardMAC device driver.
+
+	  This driver can also be built as a module. To do so say M here.
+	  The module will be called 'fakehard'.
+
 config IEEE802154_FAKELB
 	depends on IEEE802154_DRIVERS && MAC802154
 	tristate "IEEE 802.15.4 loopback driver"
@@ -23,7 +34,7 @@
 	  The module will be called 'fakelb'.
 
 config IEEE802154_AT86RF230
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	depends on IEEE802154_DRIVERS && MAC802154
 	tristate "AT86RF230/231/233/212 transceiver driver"
 	depends on m
@@ -37,7 +48,7 @@
 	  the module will be called 'at86rf230'.
 
 config IEEE802154_MRF24J40
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_5
 	tristate "Microchip MRF24J40 transceiver driver"
 	depends on m
 	depends on IEEE802154_DRIVERS && MAC802154
@@ -50,7 +61,7 @@
 	  the module will be called 'mrf24j40'.
 
 config IEEE802154_CC2520
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_5
 	depends on IEEE802154_DRIVERS && MAC802154
 	tristate "CC2520 transceiver driver"
 	depends on m
diff --git a/drivers/net/ieee802154/Makefile b/drivers/net/ieee802154/Makefile
index cf29a74..ee1bafc 100644
--- a/drivers/net/ieee802154/Makefile
+++ b/drivers/net/ieee802154/Makefile
@@ -1,3 +1,4 @@
+obj-$(CPTCFG_IEEE802154_FAKEHARD) += fakehard.o
 obj-$(CPTCFG_IEEE802154_FAKELB) += fakelb.o
 obj-$(CPTCFG_IEEE802154_AT86RF230) += at86rf230.o
 obj-$(CPTCFG_IEEE802154_MRF24J40) += mrf24j40.o
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 1c01356..c9d2a75 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
@@ -29,10 +33,10 @@
 #include <linux/regmap.h>
 #include <linux/skbuff.h>
 #include <linux/of_gpio.h>
-#include <linux/ieee802154.h>
 
+#include <net/ieee802154.h>
 #include <net/mac802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
 
 struct at86rf230_local;
 /* at86rf2xx chip depend data.
@@ -46,11 +50,15 @@
 	u16 t_off_to_tx_on;
 	u16 t_frame;
 	u16 t_p_ack;
+	/* short interframe spacing time */
+	u16 t_sifs;
+	/* long interframe spacing time */
+	u16 t_lifs;
 	/* completion timeout for tx in msecs */
 	u16 t_tx_timeout;
 	int rssi_base_val;
 
-	int (*set_channel)(struct at86rf230_local *, u8, u8);
+	int (*set_channel)(struct at86rf230_local *, int, int);
 	int (*get_desense_steps)(struct at86rf230_local *, s32);
 };
 
@@ -66,14 +74,12 @@
 	void (*complete)(void *context);
 	u8 from_state;
 	u8 to_state;
-
-	bool irq_enable;
 };
 
 struct at86rf230_local {
 	struct spi_device *spi;
 
-	struct ieee802154_hw *hw;
+	struct ieee802154_dev *dev;
 	struct at86rf2xx_chip_data *data;
 	struct regmap *regmap;
 
@@ -83,10 +89,10 @@
 	struct at86rf230_state_change irq;
 
 	bool tx_aret;
-	s8 max_frame_retries;
 	bool is_tx;
 	/* spinlock for is_tx protection */
 	spinlock_t lock;
+	struct completion tx_complete;
 	struct sk_buff *tx_skb;
 	struct at86rf230_state_change tx;
 };
@@ -285,11 +291,10 @@
 
 #define AT86RF2XX_NUMREGS 0x3F
 
-static void
+static int
 at86rf230_async_state_change(struct at86rf230_local *lp,
 			     struct at86rf230_state_change *ctx,
-			     const u8 state, void (*complete)(void *context),
-			     const bool irq_enable);
+			     const u8 state, void (*complete)(void *context));
 
 static inline int
 __at86rf230_write(struct at86rf230_local *lp,
@@ -446,8 +451,7 @@
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
 
-	at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL, false);
-	ieee802154_wake_queue(lp->hw);
+	at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL);
 }
 
 static void
@@ -457,31 +461,21 @@
 	dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
 
 	at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
-				     at86rf230_async_error_recover, false);
+				     at86rf230_async_error_recover);
 }
 
 /* Generic function to get some register value in async mode */
-static void
+static int
 at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
 			 struct at86rf230_state_change *ctx,
-			 void (*complete)(void *context),
-			 const bool irq_enable)
+			 void (*complete)(void *context))
 {
-	int rc;
-
 	u8 *tx_buf = ctx->buf;
 
 	tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
 	ctx->trx.len = 2;
 	ctx->msg.complete = complete;
-	ctx->irq_enable = irq_enable;
-	rc = spi_async(lp->spi, &ctx->msg);
-	if (rc) {
-		if (irq_enable)
-			enable_irq(lp->spi->irq);
-
-		at86rf230_async_error(lp, ctx, rc);
-	}
+	return spi_async(lp->spi, &ctx->msg);
 }
 
 static void
@@ -518,8 +512,7 @@
 			if (ctx->to_state == STATE_TX_ON) {
 				at86rf230_async_state_change(lp, ctx,
 							     STATE_FORCE_TX_ON,
-							     ctx->complete,
-							     ctx->irq_enable);
+							     ctx->complete);
 				return;
 			}
 		}
@@ -542,6 +535,7 @@
 	struct at86rf230_local *lp = ctx->lp;
 	struct at86rf2xx_chip_data *c = lp->data;
 	bool force = false;
+	int rc;
 
 	/* The force state changes are will show as normal states in the
 	 * state status subregister. We change the to_state to the
@@ -610,9 +604,10 @@
 	udelay(1);
 
 change:
-	at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
-				 at86rf230_async_state_assert,
-				 ctx->irq_enable);
+	rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+				      at86rf230_async_state_assert);
+	if (rc)
+		dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
 }
 
 static void
@@ -627,9 +622,10 @@
 	/* Check for "possible" STATE_TRANSITION_IN_PROGRESS */
 	if (trx_state == STATE_TRANSITION_IN_PROGRESS) {
 		udelay(1);
-		at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
-					 at86rf230_async_state_change_start,
-					 ctx->irq_enable);
+		rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+					      at86rf230_async_state_change_start);
+		if (rc)
+			dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
 		return;
 	}
 
@@ -651,27 +647,20 @@
 	ctx->trx.len = 2;
 	ctx->msg.complete = at86rf230_async_state_delay;
 	rc = spi_async(lp->spi, &ctx->msg);
-	if (rc) {
-		if (ctx->irq_enable)
-			enable_irq(lp->spi->irq);
-
-		at86rf230_async_error(lp, &lp->state, rc);
-	}
+	if (rc)
+		dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
 }
 
-static void
+static int
 at86rf230_async_state_change(struct at86rf230_local *lp,
 			     struct at86rf230_state_change *ctx,
-			     const u8 state, void (*complete)(void *context),
-			     const bool irq_enable)
+			     const u8 state, void (*complete)(void *context))
 {
 	/* Initialization for the state change context */
 	ctx->to_state = state;
 	ctx->complete = complete;
-	ctx->irq_enable = irq_enable;
-	at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
-				 at86rf230_async_state_change_start,
-				 irq_enable);
+	return at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+					at86rf230_async_state_change_start);
 }
 
 static void
@@ -692,16 +681,17 @@
 {
 	int rc;
 
-	at86rf230_async_state_change(lp, &lp->state, state,
-				     at86rf230_sync_state_change_complete,
-				     false);
+	rc = at86rf230_async_state_change(lp, &lp->state, state,
+					  at86rf230_sync_state_change_complete);
+	if (rc) {
+		at86rf230_async_error(lp, &lp->state, rc);
+		return rc;
+	}
 
 	rc = wait_for_completion_timeout(&lp->state_complete,
 					 msecs_to_jiffies(100));
-	if (!rc) {
-		at86rf230_async_error(lp, &lp->state, -ETIMEDOUT);
+	if (!rc)
 		return -ETIMEDOUT;
-	}
 
 	return 0;
 }
@@ -711,14 +701,8 @@
 {
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
-	struct sk_buff *skb = lp->tx_skb;
 
-	enable_irq(lp->spi->irq);
-
-	if (lp->max_frame_retries <= 0)
-		ieee802154_xmit_complete(lp->hw, skb, true);
-	else
-		ieee802154_xmit_complete(lp->hw, skb, false);
+	complete(&lp->tx_complete);
 }
 
 static void
@@ -726,9 +710,12 @@
 {
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
-	at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON,
-				     at86rf230_tx_complete, true);
+	rc = at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON,
+					  at86rf230_tx_complete);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
 }
 
 static void
@@ -736,9 +723,12 @@
 {
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
-	at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
-				     at86rf230_tx_on, true);
+	rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+					  at86rf230_tx_on);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
 }
 
 static void
@@ -748,14 +738,17 @@
 	struct at86rf230_local *lp = ctx->lp;
 	const u8 *buf = ctx->buf;
 	const u8 trac = (buf[1] & 0xe0) >> 5;
+	int rc;
 
 	/* If trac status is different than zero we need to do a state change
 	 * to STATE_FORCE_TRX_OFF then STATE_TX_ON to recover the transceiver
 	 * state to TX_ON.
 	 */
 	if (trac) {
-		at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
-					     at86rf230_tx_trac_error, true);
+		rc = at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
+						  at86rf230_tx_trac_error);
+		if (rc)
+			at86rf230_async_error(lp, ctx, rc);
 		return;
 	}
 
@@ -768,29 +761,51 @@
 {
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
-	at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
-				 at86rf230_tx_trac_check, true);
+	rc = at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
+				      at86rf230_tx_trac_check);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
 }
 
 static void
 at86rf230_rx(struct at86rf230_local *lp,
-	     const u8 *data, const u8 len, const u8 lqi)
+	     const u8 *data, u8 len)
 {
+	u8 lqi;
 	struct sk_buff *skb;
 	u8 rx_local_buf[AT86RF2XX_MAX_BUF];
 
+	if (len < 2)
+		return;
+
+	/* read full frame buffer and invalid lqi value to lowest
+	 * indicator if frame was is in a corrupted state.
+	 */
+	if (len > IEEE802154_MTU) {
+		lqi = 0;
+		len = IEEE802154_MTU;
+		dev_vdbg(&lp->spi->dev, "corrupted frame received\n");
+	} else {
+		lqi = data[len];
+	}
+
 	memcpy(rx_local_buf, data, len);
 	enable_irq(lp->spi->irq);
 
-	skb = dev_alloc_skb(IEEE802154_MTU);
+	skb = alloc_skb(IEEE802154_MTU, GFP_ATOMIC);
 	if (!skb) {
 		dev_vdbg(&lp->spi->dev, "failed to allocate sk_buff\n");
 		return;
 	}
 
 	memcpy(skb_put(skb, len), rx_local_buf, len);
-	ieee802154_rx_irqsafe(lp->hw, skb, lqi);
+
+	/* We do not put CRC into the frame */
+	skb_trim(skb, len - 2);
+
+	ieee802154_rx_irqsafe(lp->dev, skb, lqi);
 }
 
 static void
@@ -799,31 +814,20 @@
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
 	const u8 *buf = lp->irq.buf;
-	u8 len = buf[1];
+	const u8 len = buf[1];
 
-	if (!ieee802154_is_valid_psdu_len(len)) {
-		dev_vdbg(&lp->spi->dev, "corrupted frame received\n");
-		len = IEEE802154_MTU;
-	}
-
-	at86rf230_rx(lp, buf + 2, len, buf[2 + len]);
+	at86rf230_rx(lp, buf + 2, len);
 }
 
-static void
+static int
 at86rf230_rx_read_frame(struct at86rf230_local *lp)
 {
-	int rc;
-
 	u8 *buf = lp->irq.buf;
 
 	buf[0] = CMD_FB;
 	lp->irq.trx.len = AT86RF2XX_MAX_BUF;
 	lp->irq.msg.complete = at86rf230_rx_read_frame_complete;
-	rc = spi_async(lp->spi, &lp->irq.msg);
-	if (rc) {
-		enable_irq(lp->spi->irq);
-		at86rf230_async_error(lp, &lp->irq, rc);
-	}
+	return spi_async(lp->spi, &lp->irq.msg);
 }
 
 static void
@@ -831,6 +835,7 @@
 {
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
 	/* Possible check on trac status here. This could be useful to make
 	 * some stats why receive is failed. Not used at the moment, but it's
@@ -838,31 +843,34 @@
 	 * The programming guide say do it so.
 	 */
 
-	at86rf230_rx_read_frame(lp);
+	rc = at86rf230_rx_read_frame(lp);
+	if (rc) {
+		enable_irq(lp->spi->irq);
+		at86rf230_async_error(lp, ctx, rc);
+	}
 }
 
-static void
+static int
 at86rf230_irq_trx_end(struct at86rf230_local *lp)
 {
 	spin_lock(&lp->lock);
 	if (lp->is_tx) {
 		lp->is_tx = 0;
 		spin_unlock(&lp->lock);
+		enable_irq(lp->spi->irq);
 
 		if (lp->tx_aret)
-			at86rf230_async_state_change(lp, &lp->irq,
-						     STATE_FORCE_TX_ON,
-						     at86rf230_tx_trac_status,
-						     true);
+			return at86rf230_async_state_change(lp, &lp->irq,
+							    STATE_FORCE_TX_ON,
+							    at86rf230_tx_trac_status);
 		else
-			at86rf230_async_state_change(lp, &lp->irq,
-						     STATE_RX_AACK_ON,
-						     at86rf230_tx_complete,
-						     true);
+			return at86rf230_async_state_change(lp, &lp->irq,
+							    STATE_RX_AACK_ON,
+							    at86rf230_tx_complete);
 	} else {
 		spin_unlock(&lp->lock);
-		at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
-					 at86rf230_rx_trac_check, true);
+		return at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
+						at86rf230_rx_trac_check);
 	}
 }
 
@@ -873,9 +881,12 @@
 	struct at86rf230_local *lp = ctx->lp;
 	const u8 *buf = lp->irq.buf;
 	const u8 irq = buf[1];
+	int rc;
 
 	if (irq & IRQ_TRX_END) {
-		at86rf230_irq_trx_end(lp);
+		rc = at86rf230_irq_trx_end(lp);
+		if (rc)
+			at86rf230_async_error(lp, ctx, rc);
 	} else {
 		enable_irq(lp->spi->irq);
 		dev_err(&lp->spi->dev, "not supported irq %02x received\n",
@@ -890,14 +901,13 @@
 	u8 *buf = ctx->buf;
 	int rc;
 
-	disable_irq_nosync(irq);
+	disable_irq_nosync(lp->spi->irq);
 
 	buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
 	ctx->trx.len = 2;
 	ctx->msg.complete = at86rf230_irq_status;
 	rc = spi_async(lp->spi, &ctx->msg);
 	if (rc) {
-		enable_irq(irq);
 		at86rf230_async_error(lp, ctx, rc);
 		return IRQ_NONE;
 	}
@@ -950,18 +960,22 @@
 {
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
+	int rc;
 
-	at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
-				     at86rf230_write_frame, false);
+	rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
+					  at86rf230_write_frame);
+	if (rc)
+		at86rf230_async_error(lp, ctx, rc);
 }
 
 static int
-at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
+at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 	struct at86rf230_state_change *ctx = &lp->tx;
 
 	void (*tx_complete)(void *context) = at86rf230_write_frame;
+	int rc;
 
 	lp->tx_skb = skb;
 
@@ -972,39 +986,61 @@
 	if (lp->tx_aret)
 		tx_complete = at86rf230_xmit_tx_on;
 
-	at86rf230_async_state_change(lp, ctx, STATE_TX_ON, tx_complete, false);
+	rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+					  tx_complete);
+	if (rc) {
+		at86rf230_async_error(lp, ctx, rc);
+		return rc;
+	}
+	rc = wait_for_completion_interruptible_timeout(&lp->tx_complete,
+						       msecs_to_jiffies(lp->data->t_tx_timeout));
+	if (!rc) {
+		at86rf230_async_error(lp, ctx, rc);
+		return -ETIMEDOUT;
+	}
+
+	/* Interfame spacing time, which is phy depend.
+	 * TODO
+	 * Move this handling in MAC 802.15.4 layer.
+	 * This is currently a workaround to avoid fragmenation issues.
+	 */
+	if (skb->len > 18)
+		usleep_range(lp->data->t_lifs, lp->data->t_lifs + 10);
+	else
+		usleep_range(lp->data->t_sifs, lp->data->t_sifs + 10);
 
 	return 0;
 }
 
 static int
-at86rf230_ed(struct ieee802154_hw *hw, u8 *level)
+at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
 {
+	might_sleep();
 	BUG_ON(!level);
 	*level = 0xbe;
 	return 0;
 }
 
 static int
-at86rf230_start(struct ieee802154_hw *hw)
+at86rf230_start(struct ieee802154_dev *dev)
 {
-	return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON);
+	return at86rf230_sync_state_change(dev->priv, STATE_RX_AACK_ON);
 }
 
 static void
-at86rf230_stop(struct ieee802154_hw *hw)
+at86rf230_stop(struct ieee802154_dev *dev)
 {
-	at86rf230_sync_state_change(hw->priv, STATE_FORCE_TRX_OFF);
+	at86rf230_sync_state_change(dev->priv, STATE_FORCE_TRX_OFF);
 }
 
 static int
-at86rf23x_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
+at86rf23x_set_channel(struct at86rf230_local *lp, int page, int channel)
 {
 	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
 }
 
 static int
-at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
+at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel)
 {
 	int rc;
 
@@ -1025,60 +1061,44 @@
 	if (rc < 0)
 		return rc;
 
-	/* This sets the symbol_duration according frequency on the 212.
-	 * TODO move this handling while set channel and page in cfg802154.
-	 * We can do that, this timings are according 802.15.4 standard.
-	 * If we do that in cfg802154, this is a more generic calculation.
-	 *
-	 * This should also protected from ifs_timer. Means cancel timer and
-	 * init with a new value. For now, this is okay.
-	 */
-	if (channel == 0) {
-		if (page == 0) {
-			/* SUB:0 and BPSK:0 -> BPSK-20 */
-			lp->hw->phy->symbol_duration = 50;
-		} else {
-			/* SUB:1 and BPSK:0 -> BPSK-40 */
-			lp->hw->phy->symbol_duration = 25;
-		}
-	} else {
-		if (page == 0)
-			/* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */
-			lp->hw->phy->symbol_duration = 40;
-		else
-			/* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */
-			lp->hw->phy->symbol_duration = 16;
-	}
-
-	lp->hw->phy->lifs_period = IEEE802154_LIFS_PERIOD *
-				   lp->hw->phy->symbol_duration;
-	lp->hw->phy->sifs_period = IEEE802154_SIFS_PERIOD *
-				   lp->hw->phy->symbol_duration;
-
 	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
 }
 
 static int
-at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 	int rc;
 
+	might_sleep();
+
+	if (page < 0 || page > 31 ||
+	    !(lp->dev->phy->channels_supported[page] & BIT(channel))) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
 	rc = lp->data->set_channel(lp, page, channel);
+	if (rc < 0)
+		return rc;
+
 	/* Wait for PLL */
 	usleep_range(lp->data->t_channel_switch,
 		     lp->data->t_channel_switch + 10);
-	return rc;
+	dev->phy->current_channel = channel;
+	dev->phy->current_page = page;
+
+	return 0;
 }
 
 static int
-at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw,
+at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
 			   struct ieee802154_hw_addr_filt *filt,
 			   unsigned long changed)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 
-	if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
+	if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
 		u16 addr = le16_to_cpu(filt->short_addr);
 
 		dev_vdbg(&lp->spi->dev,
@@ -1087,7 +1107,7 @@
 		__at86rf230_write(lp, RG_SHORT_ADDR_1, addr >> 8);
 	}
 
-	if (changed & IEEE802154_AFILT_PANID_CHANGED) {
+	if (changed & IEEE802515_AFILT_PANID_CHANGED) {
 		u16 pan = le16_to_cpu(filt->pan_id);
 
 		dev_vdbg(&lp->spi->dev,
@@ -1096,7 +1116,7 @@
 		__at86rf230_write(lp, RG_PAN_ID_1, pan >> 8);
 	}
 
-	if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
+	if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
 		u8 i, addr[8];
 
 		memcpy(addr, &filt->ieee_addr, 8);
@@ -1106,7 +1126,7 @@
 			__at86rf230_write(lp, RG_IEEE_ADDR_0 + i, addr[i]);
 	}
 
-	if (changed & IEEE802154_AFILT_PANC_CHANGED) {
+	if (changed & IEEE802515_AFILT_PANC_CHANGED) {
 		dev_vdbg(&lp->spi->dev,
 			"at86rf230_set_hw_addr_filt called for panc change\n");
 		if (filt->pan_coord)
@@ -1119,9 +1139,9 @@
 }
 
 static int
-at86rf230_set_txpower(struct ieee802154_hw *hw, int db)
+at86rf230_set_txpower(struct ieee802154_dev *dev, int db)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 
 	/* typical maximum output is 5dBm with RG_PHY_TX_PWR 0x60, lower five
 	 * bits decrease power in 1dB steps. 0x60 represents extra PA gain of
@@ -1138,17 +1158,17 @@
 }
 
 static int
-at86rf230_set_lbt(struct ieee802154_hw *hw, bool on)
+at86rf230_set_lbt(struct ieee802154_dev *dev, bool on)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 
 	return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on);
 }
 
 static int
-at86rf230_set_cca_mode(struct ieee802154_hw *hw, u8 mode)
+at86rf230_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 
 	return at86rf230_write_subreg(lp, SR_CCA_MODE, mode);
 }
@@ -1166,9 +1186,9 @@
 }
 
 static int
-at86rf230_set_cca_ed_level(struct ieee802154_hw *hw, s32 level)
+at86rf230_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 
 	if (level < lp->data->rssi_base_val || level > 30)
 		return -EINVAL;
@@ -1178,12 +1198,15 @@
 }
 
 static int
-at86rf230_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be,
+at86rf230_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
 			  u8 retries)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 	int rc;
 
+	if (min_be > max_be || max_be > 8 || retries > 5)
+		return -EINVAL;
+
 	rc = at86rf230_write_subreg(lp, SR_MIN_BE, min_be);
 	if (rc)
 		return rc;
@@ -1196,13 +1219,15 @@
 }
 
 static int
-at86rf230_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
+at86rf230_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
 {
-	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_local *lp = dev->priv;
 	int rc = 0;
 
+	if (retries < -1 || retries > 15)
+		return -EINVAL;
+
 	lp->tx_aret = retries >= 0;
-	lp->max_frame_retries = retries;
 
 	if (retries >= 0)
 		rc = at86rf230_write_subreg(lp, SR_MAX_FRAME_RETRIES, retries);
@@ -1210,36 +1235,9 @@
 	return rc;
 }
 
-static int
-at86rf230_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
-{
-	struct at86rf230_local *lp = hw->priv;
-	int rc;
-
-	if (on) {
-		rc = at86rf230_write_subreg(lp, SR_AACK_DIS_ACK, 1);
-		if (rc < 0)
-			return rc;
-
-		rc = at86rf230_write_subreg(lp, SR_AACK_PROM_MODE, 1);
-		if (rc < 0)
-			return rc;
-	} else {
-		rc = at86rf230_write_subreg(lp, SR_AACK_PROM_MODE, 0);
-		if (rc < 0)
-			return rc;
-
-		rc = at86rf230_write_subreg(lp, SR_AACK_DIS_ACK, 0);
-		if (rc < 0)
-			return rc;
-	}
-
-	return 0;
-}
-
-static const struct ieee802154_ops at86rf230_ops = {
+static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
-	.xmit_async = at86rf230_xmit,
+	.xmit = at86rf230_xmit,
 	.ed = at86rf230_ed,
 	.set_channel = at86rf230_channel,
 	.start = at86rf230_start,
@@ -1251,7 +1249,6 @@
 	.set_cca_ed_level = at86rf230_set_cca_ed_level,
 	.set_csma_params = at86rf230_set_csma_params,
 	.set_frame_retries = at86rf230_set_frame_retries,
-	.set_promiscuous_mode = at86rf230_set_promiscuous_mode,
 };
 
 static struct at86rf2xx_chip_data at86rf233_data = {
@@ -1262,6 +1259,8 @@
 	.t_off_to_tx_on = 80,
 	.t_frame = 4096,
 	.t_p_ack = 545,
+	.t_sifs = 192,
+	.t_lifs = 480,
 	.t_tx_timeout = 2000,
 	.rssi_base_val = -91,
 	.set_channel = at86rf23x_set_channel,
@@ -1276,6 +1275,8 @@
 	.t_off_to_tx_on = 110,
 	.t_frame = 4096,
 	.t_p_ack = 545,
+	.t_sifs = 192,
+	.t_lifs = 480,
 	.t_tx_timeout = 2000,
 	.rssi_base_val = -91,
 	.set_channel = at86rf23x_set_channel,
@@ -1290,6 +1291,8 @@
 	.t_off_to_tx_on = 200,
 	.t_frame = 4096,
 	.t_p_ack = 545,
+	.t_sifs = 192,
+	.t_lifs = 480,
 	.t_tx_timeout = 2000,
 	.rssi_base_val = -100,
 	.set_channel = at86rf212_set_channel,
@@ -1351,11 +1354,7 @@
 		return -EINVAL;
 	}
 
-	/* Force setting slotted operation bit to 0. Sometimes the atben
-	 * sets this bit and I don't know why. We set this always force
-	 * to zero while probing.
-	 */
-	return at86rf230_write_subreg(lp, SR_SLOTTED_OPERATION, 0);
+	return 0;
 }
 
 static struct at86rf230_platform_data *
@@ -1410,10 +1409,9 @@
 		return -EINVAL;
 	}
 
-	lp->hw->extra_tx_headroom = 0;
-	lp->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AACK |
-			IEEE802154_HW_TXPOWER | IEEE802154_HW_ARET |
-			IEEE802154_HW_AFILT | IEEE802154_HW_PROMISCUOUS;
+	lp->dev->extra_tx_headroom = 0;
+	lp->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |
+			 IEEE802154_HW_TXPOWER | IEEE802154_HW_CSMA;
 
 	switch (part) {
 	case 2:
@@ -1423,19 +1421,15 @@
 	case 3:
 		chip = "at86rf231";
 		lp->data = &at86rf231_data;
-		lp->hw->phy->channels_supported[0] = 0x7FFF800;
-		lp->hw->phy->current_channel = 11;
-		lp->hw->phy->symbol_duration = 16;
+		lp->dev->phy->channels_supported[0] = 0x7FFF800;
 		break;
 	case 7:
 		chip = "at86rf212";
 		if (version == 1) {
 			lp->data = &at86rf212_data;
-			lp->hw->flags |= IEEE802154_HW_LBT;
-			lp->hw->phy->channels_supported[0] = 0x00007FF;
-			lp->hw->phy->channels_supported[2] = 0x00007FF;
-			lp->hw->phy->current_channel = 5;
-			lp->hw->phy->symbol_duration = 25;
+			lp->dev->flags |= IEEE802154_HW_LBT;
+			lp->dev->phy->channels_supported[0] = 0x00007FF;
+			lp->dev->phy->channels_supported[2] = 0x00007FF;
 		} else {
 			rc = -ENOTSUPP;
 		}
@@ -1443,9 +1437,7 @@
 	case 11:
 		chip = "at86rf233";
 		lp->data = &at86rf233_data;
-		lp->hw->phy->channels_supported[0] = 0x7FFF800;
-		lp->hw->phy->current_channel = 13;
-		lp->hw->phy->symbol_duration = 16;
+		lp->dev->phy->channels_supported[0] = 0x7FFF800;
 		break;
 	default:
 		chip = "unkown";
@@ -1486,7 +1478,7 @@
 static int at86rf230_probe(struct spi_device *spi)
 {
 	struct at86rf230_platform_data *pdata;
-	struct ieee802154_hw *hw;
+	struct ieee802154_dev *dev;
 	struct at86rf230_local *lp;
 	unsigned int status;
 	int rc, irq_type;
@@ -1525,16 +1517,14 @@
 		usleep_range(120, 240);
 	}
 
-	hw = ieee802154_alloc_hw(sizeof(*lp), &at86rf230_ops);
-	if (!hw)
+	dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
+	if (!dev)
 		return -ENOMEM;
 
-	lp = hw->priv;
-	lp->hw = hw;
+	lp = dev->priv;
+	lp->dev = dev;
 	lp->spi = spi;
-	hw->parent = &spi->dev;
-	hw->vif_data_size = sizeof(*lp);
-	ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
+	dev->parent = &spi->dev;
 
 	lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config);
 	if (IS_ERR(lp->regmap)) {
@@ -1551,6 +1541,7 @@
 		goto free_dev;
 
 	spin_lock_init(&lp->lock);
+	init_completion(&lp->tx_complete);
 	init_completion(&lp->state_complete);
 
 	spi_set_drvdata(spi, lp);
@@ -1573,14 +1564,14 @@
 	if (rc)
 		goto free_dev;
 
-	rc = ieee802154_register_hw(lp->hw);
+	rc = ieee802154_register_device(lp->dev);
 	if (rc)
 		goto free_dev;
 
 	return rc;
 
 free_dev:
-	ieee802154_free_hw(lp->hw);
+	ieee802154_free_device(lp->dev);
 
 	return rc;
 }
@@ -1591,8 +1582,8 @@
 
 	/* mask all at86rf230 irq's */
 	at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
-	ieee802154_unregister_hw(lp->hw);
-	ieee802154_free_hw(lp->hw);
+	ieee802154_unregister_device(lp->dev);
+	ieee802154_free_device(lp->dev);
 	dev_dbg(&spi->dev, "unregistered at86rf230\n");
 
 	return 0;
diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c
index f9df9fa..8a5ac7a 100644
--- a/drivers/net/ieee802154/cc2520.c
+++ b/drivers/net/ieee802154/cc2520.c
@@ -21,10 +21,10 @@
 #include <linux/skbuff.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/of_gpio.h>
-#include <linux/ieee802154.h>
 
 #include <net/mac802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
+#include <net/ieee802154.h>
 
 #define	SPI_COMMAND_BUFFER	3
 #define	HIGH			1
@@ -193,7 +193,7 @@
 /* Driver private information */
 struct cc2520_private {
 	struct spi_device *spi;		/* SPI device structure */
-	struct ieee802154_hw *hw;	/* IEEE-802.15.4 device */
+	struct ieee802154_dev *dev;	/* IEEE-802.15.4 device */
 	u8 *buf;			/* SPI TX/Rx data buffer */
 	struct mutex buffer_mutex;	/* SPI buffer mutex */
 	bool is_tx;			/* Flag for sync b/w Tx and Rx */
@@ -453,20 +453,20 @@
 	return status;
 }
 
-static int cc2520_start(struct ieee802154_hw *hw)
+static int cc2520_start(struct ieee802154_dev *dev)
 {
-	return cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRXON);
+	return cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRXON);
 }
 
-static void cc2520_stop(struct ieee802154_hw *hw)
+static void cc2520_stop(struct ieee802154_dev *dev)
 {
-	cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRFOFF);
+	cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRFOFF);
 }
 
 static int
-cc2520_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
+cc2520_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
 {
-	struct cc2520_private *priv = hw->priv;
+	struct cc2520_private *priv = dev->priv;
 	unsigned long flags;
 	int rc;
 	u8 status = 0;
@@ -524,7 +524,7 @@
 	if (len < 2 || len > IEEE802154_MTU)
 		return -EINVAL;
 
-	skb = dev_alloc_skb(len);
+	skb = alloc_skb(len, GFP_KERNEL);
 	if (!skb)
 		return -ENOMEM;
 
@@ -536,7 +536,7 @@
 
 	skb_trim(skb, skb->len - 2);
 
-	ieee802154_rx_irqsafe(priv->hw, skb, lqi);
+	ieee802154_rx_irqsafe(priv->dev, skb, lqi);
 
 	dev_vdbg(&priv->spi->dev, "RXFIFO: %x %x\n", len, lqi);
 
@@ -544,9 +544,9 @@
 }
 
 static int
-cc2520_ed(struct ieee802154_hw *hw, u8 *level)
+cc2520_ed(struct ieee802154_dev *dev, u8 *level)
 {
-	struct cc2520_private *priv = hw->priv;
+	struct cc2520_private *priv = dev->priv;
 	u8 status = 0xff;
 	u8 rssi;
 	int ret;
@@ -569,11 +569,12 @@
 }
 
 static int
-cc2520_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+cc2520_set_channel(struct ieee802154_dev *dev, int page, int channel)
 {
-	struct cc2520_private *priv = hw->priv;
+	struct cc2520_private *priv = dev->priv;
 	int ret;
 
+	might_sleep();
 	dev_dbg(&priv->spi->dev, "trying to set channel\n");
 
 	BUG_ON(page != 0);
@@ -587,12 +588,12 @@
 }
 
 static int
-cc2520_filter(struct ieee802154_hw *hw,
+cc2520_filter(struct ieee802154_dev *dev,
 	      struct ieee802154_hw_addr_filt *filt, unsigned long changed)
 {
-	struct cc2520_private *priv = hw->priv;
+	struct cc2520_private *priv = dev->priv;
 
-	if (changed & IEEE802154_AFILT_PANID_CHANGED) {
+	if (changed & IEEE802515_AFILT_PANID_CHANGED) {
 		u16 panid = le16_to_cpu(filt->pan_id);
 
 		dev_vdbg(&priv->spi->dev,
@@ -601,7 +602,7 @@
 				 sizeof(panid), (u8 *)&panid);
 	}
 
-	if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
+	if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
 		dev_vdbg(&priv->spi->dev,
 			 "cc2520_filter called for IEEE addr\n");
 		cc2520_write_ram(priv, CC2520RAM_IEEEADDR,
@@ -609,7 +610,7 @@
 				 (u8 *)&filt->ieee_addr);
 	}
 
-	if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
+	if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
 		u16 addr = le16_to_cpu(filt->short_addr);
 
 		dev_vdbg(&priv->spi->dev,
@@ -618,7 +619,7 @@
 				 sizeof(addr), (u8 *)&addr);
 	}
 
-	if (changed & IEEE802154_AFILT_PANC_CHANGED) {
+	if (changed & IEEE802515_AFILT_PANC_CHANGED) {
 		dev_vdbg(&priv->spi->dev,
 			 "cc2520_filter called for panc change\n");
 		if (filt->pan_coord)
@@ -630,11 +631,11 @@
 	return 0;
 }
 
-static const struct ieee802154_ops cc2520_ops = {
+static struct ieee802154_ops cc2520_ops = {
 	.owner = THIS_MODULE,
 	.start = cc2520_start,
 	.stop = cc2520_stop,
-	.xmit_sync = cc2520_tx,
+	.xmit = cc2520_tx,
 	.ed = cc2520_ed,
 	.set_channel = cc2520_set_channel,
 	.set_hw_addr_filt = cc2520_filter,
@@ -644,29 +645,27 @@
 {
 	int ret = -ENOMEM;
 
-	priv->hw = ieee802154_alloc_hw(sizeof(*priv), &cc2520_ops);
-	if (!priv->hw)
+	priv->dev = ieee802154_alloc_device(sizeof(*priv), &cc2520_ops);
+	if (!priv->dev)
 		goto err_ret;
 
-	priv->hw->priv = priv;
-	priv->hw->parent = &priv->spi->dev;
-	priv->hw->extra_tx_headroom = 0;
-	priv->hw->vif_data_size = sizeof(*priv);
+	priv->dev->priv = priv;
+	priv->dev->parent = &priv->spi->dev;
+	priv->dev->extra_tx_headroom = 0;
 
 	/* We do support only 2.4 Ghz */
-	priv->hw->phy->channels_supported[0] = 0x7FFF800;
-	priv->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |
-			  IEEE802154_HW_AFILT;
+	priv->dev->phy->channels_supported[0] = 0x7FFF800;
+	priv->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
 
 	dev_vdbg(&priv->spi->dev, "registered cc2520\n");
-	ret = ieee802154_register_hw(priv->hw);
+	ret = ieee802154_register_device(priv->dev);
 	if (ret)
 		goto err_free_device;
 
 	return 0;
 
 err_free_device:
-	ieee802154_free_hw(priv->hw);
+	ieee802154_free_device(priv->dev);
 err_ret:
 	return ret;
 }
@@ -858,7 +857,7 @@
 	pinctrl = devm_pinctrl_get_select_default(&spi->dev);
 	if (IS_ERR(pinctrl))
 		dev_warn(&spi->dev,
-			 "pinctrl pins are not configured\n");
+			 "pinctrl pins are not configured");
 
 	pdata = cc2520_get_platform_data(spi);
 	if (!pdata) {
@@ -1003,8 +1002,8 @@
 	mutex_destroy(&priv->buffer_mutex);
 	flush_work(&priv->fifop_irqwork);
 
-	ieee802154_unregister_hw(priv->hw);
-	ieee802154_free_hw(priv->hw);
+	ieee802154_unregister_device(priv->dev);
+	ieee802154_free_device(priv->dev);
 
 	return 0;
 }
diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c
new file mode 100644
index 0000000..9ce854f
--- /dev/null
+++ b/drivers/net/ieee802154/fakehard.c
@@ -0,0 +1,427 @@
+/*
+ * Sample driver for HardMAC IEEE 802.15.4 devices
+ *
+ * Copyright (C) 2009 Siemens AG
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+
+#include <net/af_ieee802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/ieee802154.h>
+#include <net/nl802154.h>
+#include <net/wpan-phy.h>
+
+struct fakehard_priv {
+	struct wpan_phy *phy;
+};
+
+static struct wpan_phy *fake_to_phy(const struct net_device *dev)
+{
+	struct fakehard_priv *priv = netdev_priv(dev);
+	return priv->phy;
+}
+
+/**
+ * fake_get_phy - Return a phy corresponding to this device.
+ * @dev: The network device for which to return the wan-phy object
+ *
+ * This function returns a wpan-phy object corresponding to the passed
+ * network device. Reference counter for wpan-phy object is incremented,
+ * so when the wpan-phy isn't necessary, you should drop the reference
+ * via @wpan_phy_put() call.
+ */
+static struct wpan_phy *fake_get_phy(const struct net_device *dev)
+{
+	struct wpan_phy *phy = fake_to_phy(dev);
+	return to_phy(get_device(&phy->dev));
+}
+
+/**
+ * fake_get_pan_id - Retrieve the PAN ID of the device.
+ * @dev: The network device to retrieve the PAN of.
+ *
+ * Return the ID of the PAN from the PIB.
+ */
+static __le16 fake_get_pan_id(const struct net_device *dev)
+{
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return cpu_to_le16(0xeba1);
+}
+
+/**
+ * fake_get_short_addr - Retrieve the short address of the device.
+ * @dev: The network device to retrieve the short address of.
+ *
+ * Returns the IEEE 802.15.4 short-form address cached for this
+ * device. If the device has not yet had a short address assigned
+ * then this should return 0xFFFF to indicate a lack of association.
+ */
+static __le16 fake_get_short_addr(const struct net_device *dev)
+{
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return cpu_to_le16(0x1);
+}
+
+/**
+ * fake_get_dsn - Retrieve the DSN of the device.
+ * @dev: The network device to retrieve the DSN for.
+ *
+ * Returns the IEEE 802.15.4 DSN for the network device.
+ * The DSN is the sequence number which will be added to each
+ * packet or MAC command frame by the MAC during transmission.
+ *
+ * DSN means 'Data Sequence Number'.
+ *
+ * Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
+ *       document.
+ */
+static u8 fake_get_dsn(const struct net_device *dev)
+{
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return 0x00; /* DSN are implemented in HW, so return just 0 */
+}
+
+/**
+ * fake_assoc_req - Make an association request to the HW.
+ * @dev: The network device which we are associating to a network.
+ * @addr: The coordinator with which we wish to associate.
+ * @channel: The channel on which to associate.
+ * @cap: The capability information field to use in the association.
+ *
+ * Start an association with a coordinator. The coordinator's address
+ * and PAN ID can be found in @addr.
+ *
+ * Note: This is in section 7.3.1 and 7.5.3.1 of the IEEE
+ *       802.15.4-2006 document.
+ */
+static int fake_assoc_req(struct net_device *dev,
+		struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
+{
+	struct wpan_phy *phy = fake_to_phy(dev);
+
+	mutex_lock(&phy->pib_lock);
+	phy->current_channel = channel;
+	phy->current_page = page;
+	mutex_unlock(&phy->pib_lock);
+
+	/* We simply emulate it here */
+	return ieee802154_nl_assoc_confirm(dev, fake_get_short_addr(dev),
+			IEEE802154_SUCCESS);
+}
+
+/**
+ * fake_assoc_resp - Send an association response to a device.
+ * @dev: The network device on which to send the response.
+ * @addr: The address of the device to respond to.
+ * @short_addr: The assigned short address for the device (if any).
+ * @status: The result of the association request.
+ *
+ * Queue the association response of the coordinator to another
+ * device's attempt to associate with the network which we
+ * coordinate. This is then added to the indirect-send queue to be
+ * transmitted to the end device when it polls for data.
+ *
+ * Note: This is in section 7.3.2 and 7.5.3.1 of the IEEE
+ *       802.15.4-2006 document.
+ */
+static int fake_assoc_resp(struct net_device *dev,
+		struct ieee802154_addr *addr, __le16 short_addr, u8 status)
+{
+	return 0;
+}
+
+/**
+ * fake_disassoc_req - Disassociate a device from a network.
+ * @dev: The network device on which we're disassociating a device.
+ * @addr: The device to disassociate from the network.
+ * @reason: The reason to give to the device for being disassociated.
+ *
+ * This sends a disassociation notification to the device being
+ * disassociated from the network.
+ *
+ * Note: This is in section 7.5.3.2 of the IEEE 802.15.4-2006
+ *       document, with the reason described in 7.3.3.2.
+ */
+static int fake_disassoc_req(struct net_device *dev,
+		struct ieee802154_addr *addr, u8 reason)
+{
+	return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS);
+}
+
+/**
+ * fake_start_req - Start an IEEE 802.15.4 PAN.
+ * @dev: The network device on which to start the PAN.
+ * @addr: The coordinator address to use when starting the PAN.
+ * @channel: The channel on which to start the PAN.
+ * @bcn_ord: Beacon order.
+ * @sf_ord: Superframe order.
+ * @pan_coord: Whether or not we are the PAN coordinator or just
+ *             requesting a realignment perhaps?
+ * @blx: Battery Life Extension feature bitfield.
+ * @coord_realign: Something to realign something else.
+ *
+ * If pan_coord is non-zero then this starts a network with the
+ * provided parameters, otherwise it attempts a coordinator
+ * realignment of the stated network instead.
+ *
+ * Note: This is in section 7.5.2.3 of the IEEE 802.15.4-2006
+ * document, with 7.3.8 describing coordinator realignment.
+ */
+static int fake_start_req(struct net_device *dev,
+			  struct ieee802154_addr *addr, u8 channel, u8 page,
+			  u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
+			  u8 coord_realign)
+{
+	struct wpan_phy *phy = fake_to_phy(dev);
+
+	mutex_lock(&phy->pib_lock);
+	phy->current_channel = channel;
+	phy->current_page = page;
+	mutex_unlock(&phy->pib_lock);
+
+	/* We don't emulate beacons here at all, so START should fail */
+	ieee802154_nl_start_confirm(dev, IEEE802154_INVALID_PARAMETER);
+	return 0;
+}
+
+/**
+ * fake_scan_req - Start a channel scan.
+ * @dev: The network device on which to perform a channel scan.
+ * @type: The type of scan to perform.
+ * @channels: The channel bitmask to scan.
+ * @duration: How long to spend on each channel.
+ *
+ * This starts either a passive (energy) scan or an active (PAN) scan
+ * on the channels indicated in the @channels bitmask. The duration of
+ * the scan is measured in terms of superframe duration. Specifically,
+ * the scan will spend aBaseSuperFrameDuration * ((2^n) + 1) on each
+ * channel.
+ *
+ * Note: This is in section 7.5.2.1 of the IEEE 802.15.4-2006 document.
+ */
+static int fake_scan_req(struct net_device *dev, u8 type, u32 channels,
+		u8 page, u8 duration)
+{
+	u8 edl[27] = {};
+	return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type,
+			channels, page,
+			type == IEEE802154_MAC_SCAN_ED ? edl : NULL);
+}
+
+static struct ieee802154_mlme_ops fake_mlme = {
+	.assoc_req = fake_assoc_req,
+	.assoc_resp = fake_assoc_resp,
+	.disassoc_req = fake_disassoc_req,
+	.start_req = fake_start_req,
+	.scan_req = fake_scan_req,
+
+	.get_phy = fake_get_phy,
+
+	.get_pan_id = fake_get_pan_id,
+	.get_short_addr = fake_get_short_addr,
+	.get_dsn = fake_get_dsn,
+};
+
+static int ieee802154_fake_open(struct net_device *dev)
+{
+	netif_start_queue(dev);
+	return 0;
+}
+
+static int ieee802154_fake_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	return 0;
+}
+
+static netdev_tx_t ieee802154_fake_xmit(struct sk_buff *skb,
+					      struct net_device *dev)
+{
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	/* FIXME: do hardware work here ... */
+
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+
+static int ieee802154_fake_ioctl(struct net_device *dev, struct ifreq *ifr,
+		int cmd)
+{
+	struct sockaddr_ieee802154 *sa =
+		(struct sockaddr_ieee802154 *)&ifr->ifr_addr;
+	u16 pan_id, short_addr;
+
+	switch (cmd) {
+	case SIOCGIFADDR:
+		/* FIXME: fixed here, get from device IRL */
+		pan_id = le16_to_cpu(fake_get_pan_id(dev));
+		short_addr = le16_to_cpu(fake_get_short_addr(dev));
+		if (pan_id == IEEE802154_PANID_BROADCAST ||
+		    short_addr == IEEE802154_ADDR_BROADCAST)
+			return -EADDRNOTAVAIL;
+
+		sa->family = AF_IEEE802154;
+		sa->addr.addr_type = IEEE802154_ADDR_SHORT;
+		sa->addr.pan_id = pan_id;
+		sa->addr.short_addr = short_addr;
+		return 0;
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int ieee802154_fake_mac_addr(struct net_device *dev, void *p)
+{
+	return -EBUSY; /* HW address is built into the device */
+}
+
+static const struct net_device_ops fake_ops = {
+	.ndo_open		= ieee802154_fake_open,
+	.ndo_stop		= ieee802154_fake_close,
+	.ndo_start_xmit		= ieee802154_fake_xmit,
+	.ndo_do_ioctl		= ieee802154_fake_ioctl,
+	.ndo_set_mac_address	= ieee802154_fake_mac_addr,
+};
+
+static void ieee802154_fake_destruct(struct net_device *dev)
+{
+	struct wpan_phy *phy = fake_to_phy(dev);
+
+	wpan_phy_unregister(phy);
+	free_netdev(dev);
+	wpan_phy_free(phy);
+}
+
+static void ieee802154_fake_setup(struct net_device *dev)
+{
+	dev->addr_len		= IEEE802154_ADDR_LEN;
+	memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
+	dev->features		= NETIF_F_HW_CSUM;
+	dev->needed_tailroom	= 2; /* FCS */
+	dev->mtu		= 127;
+	dev->tx_queue_len	= 10;
+	dev->type		= ARPHRD_IEEE802154;
+	dev->flags		= IFF_NOARP | IFF_BROADCAST;
+	dev->watchdog_timeo	= 0;
+	dev->destructor		= ieee802154_fake_destruct;
+}
+
+
+static int ieee802154fake_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct fakehard_priv *priv;
+	struct wpan_phy *phy = wpan_phy_alloc(0);
+	int err;
+
+	if (!phy)
+		return -ENOMEM;
+
+	dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d",
+			   NET_NAME_UNKNOWN, ieee802154_fake_setup);
+	if (!dev) {
+		wpan_phy_free(phy);
+		return -ENOMEM;
+	}
+
+	memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
+			dev->addr_len);
+
+	/*
+	 * For now we'd like to emulate 2.4 GHz-only device,
+	 * both O-QPSK and CSS
+	 */
+	/* 2.4 GHz O-QPSK 802.15.4-2003 */
+	phy->channels_supported[0] |= 0x7FFF800;
+	/* 2.4 GHz CSS 802.15.4a-2007 */
+	phy->channels_supported[3] |= 0x3fff;
+
+	phy->transmit_power = 0xbf;
+
+	dev->netdev_ops = &fake_ops;
+	dev->ml_priv = &fake_mlme;
+
+	priv = netdev_priv(dev);
+	priv->phy = phy;
+
+	wpan_phy_set_dev(phy, &pdev->dev);
+	SET_NETDEV_DEV(dev, &phy->dev);
+
+	platform_set_drvdata(pdev, dev);
+
+	err = wpan_phy_register(phy);
+	if (err)
+		goto out;
+
+	err = register_netdev(dev);
+	if (err < 0)
+		goto out;
+
+	dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n");
+	return 0;
+
+out:
+	unregister_netdev(dev);
+	return err;
+}
+
+static int ieee802154fake_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	unregister_netdev(dev);
+	return 0;
+}
+
+static struct platform_device *ieee802154fake_dev;
+
+static struct platform_driver ieee802154fake_driver = {
+	.probe = ieee802154fake_probe,
+	.remove = ieee802154fake_remove,
+	.driver = {
+			.name = "ieee802154hardmac",
+			.owner = THIS_MODULE,
+	},
+};
+
+static __init int fake_init(void)
+{
+	ieee802154fake_dev = platform_device_register_simple(
+			"ieee802154hardmac", -1, NULL, 0);
+	return platform_driver_register(&ieee802154fake_driver);
+}
+
+static __exit void fake_exit(void)
+{
+	platform_driver_unregister(&ieee802154fake_driver);
+	platform_device_unregister(ieee802154fake_dev);
+}
+
+module_init(fake_init);
+module_exit(fake_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
index dc2bfb6..27d8320 100644
--- a/drivers/net/ieee802154/fakelb.c
+++ b/drivers/net/ieee802154/fakelb.c
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -25,12 +29,12 @@
 #include <linux/device.h>
 #include <linux/spinlock.h>
 #include <net/mac802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
 
 static int numlbs = 1;
 
 struct fakelb_dev_priv {
-	struct ieee802154_hw *hw;
+	struct ieee802154_dev *dev;
 
 	struct list_head list;
 	struct fakelb_priv *fake;
@@ -45,8 +49,9 @@
 };
 
 static int
-fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)
+fakelb_hw_ed(struct ieee802154_dev *dev, u8 *level)
 {
+	might_sleep();
 	BUG_ON(!level);
 	*level = 0xbe;
 
@@ -54,10 +59,14 @@
 }
 
 static int
-fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+fakelb_hw_channel(struct ieee802154_dev *dev, int page, int channel)
 {
 	pr_debug("set channel to %d\n", channel);
 
+	might_sleep();
+	dev->phy->current_page = page;
+	dev->phy->current_channel = channel;
+
 	return 0;
 }
 
@@ -69,17 +78,19 @@
 	spin_lock(&priv->lock);
 	if (priv->working) {
 		newskb = pskb_copy(skb, GFP_ATOMIC);
-		ieee802154_rx_irqsafe(priv->hw, newskb, 0xcc);
+		ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc);
 	}
 	spin_unlock(&priv->lock);
 }
 
 static int
-fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
+fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
 {
-	struct fakelb_dev_priv *priv = hw->priv;
+	struct fakelb_dev_priv *priv = dev->priv;
 	struct fakelb_priv *fake = priv->fake;
 
+	might_sleep();
+
 	read_lock_bh(&fake->lock);
 	if (priv->list.next == priv->list.prev) {
 		/* we are the only one device */
@@ -88,8 +99,8 @@
 		struct fakelb_dev_priv *dp;
 		list_for_each_entry(dp, &priv->fake->list, list) {
 			if (dp != priv &&
-			    (dp->hw->phy->current_channel ==
-			     priv->hw->phy->current_channel))
+			    (dp->dev->phy->current_channel ==
+			     priv->dev->phy->current_channel))
 				fakelb_hw_deliver(dp, skb);
 		}
 	}
@@ -99,8 +110,8 @@
 }
 
 static int
-fakelb_hw_start(struct ieee802154_hw *hw) {
-	struct fakelb_dev_priv *priv = hw->priv;
+fakelb_hw_start(struct ieee802154_dev *dev) {
+	struct fakelb_dev_priv *priv = dev->priv;
 	int ret = 0;
 
 	spin_lock(&priv->lock);
@@ -114,17 +125,17 @@
 }
 
 static void
-fakelb_hw_stop(struct ieee802154_hw *hw) {
-	struct fakelb_dev_priv *priv = hw->priv;
+fakelb_hw_stop(struct ieee802154_dev *dev) {
+	struct fakelb_dev_priv *priv = dev->priv;
 
 	spin_lock(&priv->lock);
 	priv->working = 0;
 	spin_unlock(&priv->lock);
 }
 
-static const struct ieee802154_ops fakelb_ops = {
+static struct ieee802154_ops fakelb_ops = {
 	.owner = THIS_MODULE,
-	.xmit_sync = fakelb_hw_xmit,
+	.xmit = fakelb_hw_xmit,
 	.ed = fakelb_hw_ed,
 	.set_channel = fakelb_hw_channel,
 	.start = fakelb_hw_start,
@@ -139,54 +150,54 @@
 {
 	struct fakelb_dev_priv *priv;
 	int err;
-	struct ieee802154_hw *hw;
+	struct ieee802154_dev *ieee;
 
-	hw = ieee802154_alloc_hw(sizeof(*priv), &fakelb_ops);
-	if (!hw)
+	ieee = ieee802154_alloc_device(sizeof(*priv), &fakelb_ops);
+	if (!ieee)
 		return -ENOMEM;
 
-	priv = hw->priv;
-	priv->hw = hw;
+	priv = ieee->priv;
+	priv->dev = ieee;
 
 	/* 868 MHz BPSK	802.15.4-2003 */
-	hw->phy->channels_supported[0] |= 1;
+	ieee->phy->channels_supported[0] |= 1;
 	/* 915 MHz BPSK	802.15.4-2003 */
-	hw->phy->channels_supported[0] |= 0x7fe;
+	ieee->phy->channels_supported[0] |= 0x7fe;
 	/* 2.4 GHz O-QPSK 802.15.4-2003 */
-	hw->phy->channels_supported[0] |= 0x7FFF800;
+	ieee->phy->channels_supported[0] |= 0x7FFF800;
 	/* 868 MHz ASK 802.15.4-2006 */
-	hw->phy->channels_supported[1] |= 1;
+	ieee->phy->channels_supported[1] |= 1;
 	/* 915 MHz ASK 802.15.4-2006 */
-	hw->phy->channels_supported[1] |= 0x7fe;
+	ieee->phy->channels_supported[1] |= 0x7fe;
 	/* 868 MHz O-QPSK 802.15.4-2006 */
-	hw->phy->channels_supported[2] |= 1;
+	ieee->phy->channels_supported[2] |= 1;
 	/* 915 MHz O-QPSK 802.15.4-2006 */
-	hw->phy->channels_supported[2] |= 0x7fe;
+	ieee->phy->channels_supported[2] |= 0x7fe;
 	/* 2.4 GHz CSS 802.15.4a-2007 */
-	hw->phy->channels_supported[3] |= 0x3fff;
+	ieee->phy->channels_supported[3] |= 0x3fff;
 	/* UWB Sub-gigahertz 802.15.4a-2007 */
-	hw->phy->channels_supported[4] |= 1;
+	ieee->phy->channels_supported[4] |= 1;
 	/* UWB Low band 802.15.4a-2007 */
-	hw->phy->channels_supported[4] |= 0x1e;
+	ieee->phy->channels_supported[4] |= 0x1e;
 	/* UWB High band 802.15.4a-2007 */
-	hw->phy->channels_supported[4] |= 0xffe0;
+	ieee->phy->channels_supported[4] |= 0xffe0;
 	/* 750 MHz O-QPSK 802.15.4c-2009 */
-	hw->phy->channels_supported[5] |= 0xf;
+	ieee->phy->channels_supported[5] |= 0xf;
 	/* 750 MHz MPSK 802.15.4c-2009 */
-	hw->phy->channels_supported[5] |= 0xf0;
+	ieee->phy->channels_supported[5] |= 0xf0;
 	/* 950 MHz BPSK 802.15.4d-2009 */
-	hw->phy->channels_supported[6] |= 0x3ff;
+	ieee->phy->channels_supported[6] |= 0x3ff;
 	/* 950 MHz GFSK 802.15.4d-2009 */
-	hw->phy->channels_supported[6] |= 0x3ffc00;
+	ieee->phy->channels_supported[6] |= 0x3ffc00;
 
 	INIT_LIST_HEAD(&priv->list);
 	priv->fake = fake;
 
 	spin_lock_init(&priv->lock);
 
-	hw->parent = dev;
+	ieee->parent = dev;
 
-	err = ieee802154_register_hw(hw);
+	err = ieee802154_register_device(ieee);
 	if (err)
 		goto err_reg;
 
@@ -197,7 +208,7 @@
 	return 0;
 
 err_reg:
-	ieee802154_free_hw(priv->hw);
+	ieee802154_free_device(priv->dev);
 	return err;
 }
 
@@ -207,8 +218,8 @@
 	list_del(&priv->list);
 	write_unlock_bh(&priv->fake->lock);
 
-	ieee802154_unregister_hw(priv->hw);
-	ieee802154_free_hw(priv->hw);
+	ieee802154_unregister_device(priv->dev);
+	ieee802154_free_device(priv->dev);
 }
 
 static int fakelb_probe(struct platform_device *pdev)
@@ -261,6 +272,7 @@
 	.remove = fakelb_remove,
 	.driver = {
 			.name = "ieee802154fakelb",
+			.owner = THIS_MODULE,
 	},
 };
 
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index a200fa1..07e0b88 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -13,14 +13,18 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/spi/spi.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/ieee802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
 #include <net/mac802154.h>
+#include <net/ieee802154.h>
 
 /* MRF24J40 Short Address Registers */
 #define REG_RXMCR    0x00  /* Receive MAC control */
@@ -39,8 +43,6 @@
 #define REG_TXSTBL   0x2E  /* TX Stabilization */
 #define REG_INTSTAT  0x31  /* Interrupt Status */
 #define REG_INTCON   0x32  /* Interrupt Control */
-#define REG_GPIO     0x33  /* GPIO */
-#define REG_TRISGPIO 0x34  /* GPIO direction */
 #define REG_RFCTL    0x36  /* RF Control Mode Register */
 #define REG_BBREG1   0x39  /* Baseband Registers */
 #define REG_BBREG2   0x3A  /* */
@@ -61,7 +63,6 @@
 #define REG_SLPCON1    0x220
 #define REG_WAKETIMEL  0x222  /* Wake-up Time Match Value Low */
 #define REG_WAKETIMEH  0x223  /* Wake-up Time Match Value High */
-#define REG_TESTMODE   0x22F  /* Test mode */
 #define REG_RX_FIFO    0x300  /* Receive FIFO */
 
 /* Device configuration: Only channels 11-26 on page 0 are supported. */
@@ -74,12 +75,10 @@
 #define RX_FIFO_SIZE 144 /* From datasheet */
 #define SET_CHANNEL_DELAY_US 192 /* From datasheet */
 
-enum mrf24j40_modules { MRF24J40, MRF24J40MA, MRF24J40MC };
-
 /* Device Private Data */
 struct mrf24j40 {
 	struct spi_device *spi;
-	struct ieee802154_hw *hw;
+	struct ieee802154_dev *dev;
 
 	struct mutex buffer_mutex; /* only used to protect buf */
 	struct completion tx_complete;
@@ -332,9 +331,9 @@
 	return ret;
 }
 
-static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
+static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
 {
-	struct mrf24j40 *devrec = hw->priv;
+	struct mrf24j40 *devrec = dev->priv;
 	u8 val;
 	int ret = 0;
 
@@ -383,7 +382,7 @@
 	return ret;
 }
 
-static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
+static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level)
 {
 	/* TODO: */
 	pr_warn("mrf24j40: ed not implemented\n");
@@ -391,9 +390,9 @@
 	return 0;
 }
 
-static int mrf24j40_start(struct ieee802154_hw *hw)
+static int mrf24j40_start(struct ieee802154_dev *dev)
 {
-	struct mrf24j40 *devrec = hw->priv;
+	struct mrf24j40 *devrec = dev->priv;
 	u8 val;
 	int ret;
 
@@ -408,9 +407,9 @@
 	return 0;
 }
 
-static void mrf24j40_stop(struct ieee802154_hw *hw)
+static void mrf24j40_stop(struct ieee802154_dev *dev)
 {
-	struct mrf24j40 *devrec = hw->priv;
+	struct mrf24j40 *devrec = dev->priv;
 	u8 val;
 	int ret;
 
@@ -423,9 +422,10 @@
 	write_short_reg(devrec, REG_INTCON, val);
 }
 
-static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+static int mrf24j40_set_channel(struct ieee802154_dev *dev,
+				int page, int channel)
 {
-	struct mrf24j40 *devrec = hw->priv;
+	struct mrf24j40 *devrec = dev->priv;
 	u8 val;
 	int ret;
 
@@ -453,15 +453,15 @@
 	return 0;
 }
 
-static int mrf24j40_filter(struct ieee802154_hw *hw,
+static int mrf24j40_filter(struct ieee802154_dev *dev,
 			   struct ieee802154_hw_addr_filt *filt,
 			   unsigned long changed)
 {
-	struct mrf24j40 *devrec = hw->priv;
+	struct mrf24j40 *devrec = dev->priv;
 
 	dev_dbg(printdev(devrec), "filter\n");
 
-	if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
+	if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
 		/* Short Addr */
 		u8 addrh, addrl;
 
@@ -474,7 +474,7 @@
 			"Set short addr to %04hx\n", filt->short_addr);
 	}
 
-	if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
+	if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
 		/* Device Address */
 		u8 i, addr[8];
 
@@ -490,7 +490,7 @@
 #endif
 	}
 
-	if (changed & IEEE802154_AFILT_PANID_CHANGED) {
+	if (changed & IEEE802515_AFILT_PANID_CHANGED) {
 		/* PAN ID */
 		u8 panidl, panidh;
 
@@ -502,7 +502,7 @@
 		dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
 	}
 
-	if (changed & IEEE802154_AFILT_PANC_CHANGED) {
+	if (changed & IEEE802515_AFILT_PANC_CHANGED) {
 		/* Pan Coordinator */
 		u8 val;
 		int ret;
@@ -543,7 +543,7 @@
 	val |= 4; /* SET RXDECINV */
 	write_short_reg(devrec, REG_BBREG1, val);
 
-	skb = dev_alloc_skb(len);
+	skb = alloc_skb(len, GFP_KERNEL);
 	if (!skb) {
 		ret = -ENOMEM;
 		goto out;
@@ -563,7 +563,7 @@
 	/* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040,
 	 * also from a workqueue).  I think irqsafe is not necessary here.
 	 * Can someone confirm? */
-	ieee802154_rx_irqsafe(devrec->hw, skb, lqi);
+	ieee802154_rx_irqsafe(devrec->dev, skb, lqi);
 
 	dev_dbg(printdev(devrec), "RX Handled\n");
 
@@ -578,9 +578,9 @@
 	return ret;
 }
 
-static const struct ieee802154_ops mrf24j40_ops = {
+static struct ieee802154_ops mrf24j40_ops = {
 	.owner = THIS_MODULE,
-	.xmit_sync = mrf24j40_tx,
+	.xmit = mrf24j40_tx,
 	.ed = mrf24j40_ed,
 	.start = mrf24j40_start,
 	.stop = mrf24j40_stop,
@@ -691,28 +691,6 @@
 	if (ret)
 		goto err_ret;
 
-	if (spi_get_device_id(devrec->spi)->driver_data == MRF24J40MC) {
-		/* Enable external amplifier.
-		 * From MRF24J40MC datasheet section 1.3: Operation.
-		 */
-		read_long_reg(devrec, REG_TESTMODE, &val);
-		val |= 0x7; /* Configure GPIO 0-2 to control amplifier */
-		write_long_reg(devrec, REG_TESTMODE, val);
-
-		read_short_reg(devrec, REG_TRISGPIO, &val);
-		val |= 0x8; /* Set GPIO3 as output. */
-		write_short_reg(devrec, REG_TRISGPIO, val);
-
-		read_short_reg(devrec, REG_GPIO, &val);
-		val |= 0x8; /* Set GPIO3 HIGH to enable U5 voltage regulator */
-		write_short_reg(devrec, REG_GPIO, val);
-
-		/* Reduce TX pwr to meet FCC requirements.
-		 * From MRF24J40MC datasheet section 3.1.1
-		 */
-		write_long_reg(devrec, REG_RFCON3, 0x28);
-	}
-
 	return 0;
 
 err_ret:
@@ -744,18 +722,17 @@
 
 	/* Register with the 802154 subsystem */
 
-	devrec->hw = ieee802154_alloc_hw(0, &mrf24j40_ops);
-	if (!devrec->hw)
+	devrec->dev = ieee802154_alloc_device(0, &mrf24j40_ops);
+	if (!devrec->dev)
 		goto err_ret;
 
-	devrec->hw->priv = devrec;
-	devrec->hw->parent = &devrec->spi->dev;
-	devrec->hw->phy->channels_supported[0] = CHANNEL_MASK;
-	devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |
-			    IEEE802154_HW_AFILT;
+	devrec->dev->priv = devrec;
+	devrec->dev->parent = &devrec->spi->dev;
+	devrec->dev->phy->channels_supported[0] = CHANNEL_MASK;
+	devrec->dev->flags = IEEE802154_HW_OMIT_CKSUM|IEEE802154_HW_AACK;
 
 	dev_dbg(printdev(devrec), "registered mrf24j40\n");
-	ret = ieee802154_register_hw(devrec->hw);
+	ret = ieee802154_register_device(devrec->dev);
 	if (ret)
 		goto err_register_device;
 
@@ -780,9 +757,9 @@
 
 err_irq:
 err_hw_init:
-	ieee802154_unregister_hw(devrec->hw);
+	ieee802154_unregister_device(devrec->dev);
 err_register_device:
-	ieee802154_free_hw(devrec->hw);
+	ieee802154_free_device(devrec->dev);
 err_ret:
 	return ret;
 }
@@ -793,8 +770,8 @@
 
 	dev_dbg(printdev(devrec), "remove\n");
 
-	ieee802154_unregister_hw(devrec->hw);
-	ieee802154_free_hw(devrec->hw);
+	ieee802154_unregister_device(devrec->dev);
+	ieee802154_free_device(devrec->dev);
 	/* TODO: Will ieee802154_free_device() wait until ->xmit() is
 	 * complete? */
 
@@ -802,9 +779,8 @@
 }
 
 static const struct spi_device_id mrf24j40_ids[] = {
-	{ "mrf24j40", MRF24J40 },
-	{ "mrf24j40ma", MRF24J40MA },
-	{ "mrf24j40mc", MRF24J40MC },
+	{ "mrf24j40", 0 },
+	{ "mrf24j40ma", 0 },
 	{ },
 };
 MODULE_DEVICE_TABLE(spi, mrf24j40_ids);
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index d6683dd..c45c011 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -78,7 +78,7 @@
 	depends on n
 	tristate "USB Pegasus/Pegasus-II based ethernet device support"
 	depends on m
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  Say Y here if you know you have Pegasus or Pegasus-II based adapter.
 	  If in doubt then look at <file:drivers/net/usb/pegasus.h> for the
@@ -95,7 +95,7 @@
 	depends on n
 	tristate "USB RTL8150 based ethernet device support"
 	depends on m
-	select BPAUTO_MII
+	select BACKPORT_MII
 	help
 	  Say Y here if you have RTL8150 based usb-ethernet adapter.
 	  Send me <petkan@users.sourceforge.net> any comments you may have.
@@ -108,7 +108,7 @@
 	depends on n
 	tristate "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
 	depends on m
-	select BPAUTO_MII
+	select BACKPORT_MII
 	help
 	  This option adds support for Realtek RTL8152 based USB 2.0
 	  10/100 Ethernet adapters and RTL8153 based USB 3.0 10/100/1000
@@ -120,7 +120,7 @@
 config USB_USBNET
 	tristate "Multi-purpose USB Networking Framework"
 	depends on m
-	select BPAUTO_MII
+	select BACKPORT_MII
 	---help---
 	  This driver supports several kinds of network links over USB,
 	  with "minidrivers" built around a common network driver core
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 80a714b..c582a86 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -67,36 +67,6 @@
 	0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
 };
 
-static void usbnet_cdc_update_filter(struct usbnet *dev)
-{
-	struct cdc_state	*info = (void *) &dev->data;
-	struct usb_interface	*intf = info->control;
-	struct net_device	*net = dev->net;
-
-	u16 cdc_filter = USB_CDC_PACKET_TYPE_DIRECTED
-			| USB_CDC_PACKET_TYPE_BROADCAST;
-
-	/* filtering on the device is an optional feature and not worth
-	 * the hassle so we just roughly care about snooping and if any
-	 * multicast is requested, we take every multicast
-	 */
-	if (net->flags & IFF_PROMISC)
-		cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS;
-	if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI))
-		cdc_filter |= USB_CDC_PACKET_TYPE_ALL_MULTICAST;
-
-	usb_control_msg(dev->udev,
-			usb_sndctrlpipe(dev->udev, 0),
-			USB_CDC_SET_ETHERNET_PACKET_FILTER,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-			cdc_filter,
-			intf->cur_altsetting->desc.bInterfaceNumber,
-			NULL,
-			0,
-			USB_CTRL_SET_TIMEOUT
-		);
-}
-
 /* probes control interface, claims data interface, collects the bulk
  * endpoints, activates data interface (if needed), maybe sets MTU.
  * all pure cdc, except for certain firmware workarounds, and knowing
@@ -377,8 +347,16 @@
 	 * don't do reset all the way. So the packet filter should
 	 * be set to a sane initial value.
 	 */
-	usbnet_cdc_update_filter(dev);
-
+	usb_control_msg(dev->udev,
+			usb_sndctrlpipe(dev->udev, 0),
+			USB_CDC_SET_ETHERNET_PACKET_FILTER,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			USB_CDC_PACKET_TYPE_ALL_MULTICAST | USB_CDC_PACKET_TYPE_DIRECTED | USB_CDC_PACKET_TYPE_BROADCAST,
+			intf->cur_altsetting->desc.bInterfaceNumber,
+			NULL,
+			0,
+			USB_CTRL_SET_TIMEOUT
+		);
 	return 0;
 
 bad_desc:
@@ -490,6 +468,10 @@
 		return status;
 	}
 
+	/* FIXME cdc-ether has some multicast code too, though it complains
+	 * in routine cases.  info->ether describes the multicast support.
+	 * Implement that here, manipulating the cdc filter as needed.
+	 */
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
@@ -500,7 +482,6 @@
 	.bind =		usbnet_cdc_bind,
 	.unbind =	usbnet_cdc_unbind,
 	.status =	usbnet_cdc_status,
-	.set_rx_mode =	usbnet_cdc_update_filter,
 	.manage_power =	usbnet_manage_power,
 };
 
@@ -510,7 +491,6 @@
 	.bind =		usbnet_cdc_bind,
 	.unbind =	usbnet_cdc_unbind,
 	.status =	usbnet_cdc_status,
-	.set_rx_mode =	usbnet_cdc_update_filter,
 	.manage_power =	usbnet_manage_power,
 };
 
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index e330332..6fb0384 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -422,7 +422,7 @@
 
 	/* map MBIM session to VLAN */
 	if (tci)
-		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tci);
+		vlan_put_tag(skb, htons(ETH_P_8021Q), tci);
 err:
 	return skb;
 }
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index c138280..80fa223 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -780,7 +780,6 @@
 	{QMI_FIXED_INTF(0x413c, 0x81a4, 8)},	/* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
 	{QMI_FIXED_INTF(0x413c, 0x81a8, 8)},	/* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
 	{QMI_FIXED_INTF(0x413c, 0x81a9, 8)},	/* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
-	{QMI_FIXED_INTF(0x03f0, 0x581d, 4)},	/* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
 
 	/* 4. Gobi 1000 devices */
 	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index a0dcb2f..d8bc646 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1054,21 +1054,6 @@
 	clear_bit(EVENT_LINK_CHANGE, &dev->flags);
 }
 
-static void usbnet_set_rx_mode(struct net_device *net)
-{
-	struct usbnet		*dev = netdev_priv(net);
-
-	usbnet_defer_kevent(dev, EVENT_SET_RX_MODE);
-}
-
-static void __handle_set_rx_mode(struct usbnet *dev)
-{
-	if (dev->driver_info->set_rx_mode)
-		(dev->driver_info->set_rx_mode)(dev);
-
-	clear_bit(EVENT_SET_RX_MODE, &dev->flags);
-}
-
 /* work that cannot be done in interrupt context uses keventd.
  *
  * NOTE:  with 2.5 we could do more of this using completion callbacks,
@@ -1174,10 +1159,6 @@
 	if (test_bit (EVENT_LINK_CHANGE, &dev->flags))
 		__handle_link_change(dev);
 
-	if (test_bit (EVENT_SET_RX_MODE, &dev->flags))
-		__handle_set_rx_mode(dev);
-
-
 	if (dev->flags)
 		netdev_dbg(dev->net, "kevent done, flags = 0x%lx\n", dev->flags);
 }
@@ -1564,7 +1545,6 @@
 	.ndo_stop		= usbnet_stop,
 	.ndo_start_xmit		= usbnet_start_xmit,
 	.ndo_tx_timeout		= usbnet_tx_timeout,
-	.ndo_set_rx_mode	= usbnet_set_rx_mode,
 	.ndo_change_mtu		= usbnet_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 74d4104..c937dac 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -28,7 +28,7 @@
 	  Right now only ath9k makes use of this.
 
 config ATH_TRACEPOINTS
-	depends on !KERNEL_3_1
+	depends on !BACKPORT_KERNEL_3_1
        bool "Atheros wireless tracing"
        depends on ATH_DEBUG
        depends on EVENT_TRACING
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 6d58a3e..91c1893 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -80,7 +80,6 @@
 
 struct ath_regulatory {
 	char alpha2[2];
-	enum nl80211_dfs_regions region;
 	u16 country_code;
 	u16 max_power_level;
 	u16 current_rd;
@@ -135,11 +134,6 @@
 struct ath_common;
 struct ath_bus_ops;
 
-struct ath_ps_ops {
-	void (*wakeup)(struct ath_common *common);
-	void (*restore)(struct ath_common *common);
-};
-
 struct ath_common {
 	void *ah;
 	void *priv;
@@ -153,7 +147,7 @@
 	u16 cachelsz;
 	u16 curaid;
 	u8 macaddr[ETH_ALEN];
-	u8 curbssid[ETH_ALEN] __aligned(2);
+	u8 curbssid[ETH_ALEN];
 	u8 bssidmask[ETH_ALEN];
 
 	u32 rx_bufsize;
@@ -174,7 +168,6 @@
 	struct ath_regulatory reg_world_copy;
 	const struct ath_ops *ops;
 	const struct ath_bus_ops *bus_ops;
-	const struct ath_ps_ops *ps_ops;
 
 	bool btcoex_enabled;
 	bool disable_ani;
@@ -184,11 +177,6 @@
 	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
 };
 
-static inline const struct ath_ps_ops *ath_ps_ops(struct ath_common *common)
-{
-	return common->ps_ops;
-}
-
 struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
 				u32 len,
 				gfp_t gfp_mask);
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index bf01fad..eb8ecdf 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -34,7 +34,7 @@
 	  If unsure, say Y to make it easier to debug problems.
 
 config ATH10K_TRACING
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	bool "Atheros ath10k tracing support"
 	depends on ATH10K
 	depends on EVENT_TRACING
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 842d941..de7426a 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -445,12 +445,12 @@
  * Guts of ath10k_ce_completed_recv_next.
  * The caller takes responsibility for any necessary locking.
  */
-int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
-					 void **per_transfer_contextp,
-					 u32 *bufferp,
-					 unsigned int *nbytesp,
-					 unsigned int *transfer_idp,
-					 unsigned int *flagsp)
+static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
+						void **per_transfer_contextp,
+						u32 *bufferp,
+						unsigned int *nbytesp,
+						unsigned int *transfer_idp,
+						unsigned int *flagsp)
 {
 	struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
 	unsigned int nentries_mask = dest_ring->nentries_mask;
@@ -560,7 +560,6 @@
 
 		/* sanity */
 		dest_ring->per_transfer_context[sw_index] = NULL;
-		desc->nbytes = 0;
 
 		/* Update sw_index */
 		sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
@@ -579,11 +578,11 @@
  * Guts of ath10k_ce_completed_send_next.
  * The caller takes responsibility for any necessary locking.
  */
-int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
-					 void **per_transfer_contextp,
-					 u32 *bufferp,
-					 unsigned int *nbytesp,
-					 unsigned int *transfer_idp)
+static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
+						void **per_transfer_contextp,
+						u32 *bufferp,
+						unsigned int *nbytesp,
+						unsigned int *transfer_idp)
 {
 	struct ath10k_ce_ring *src_ring = ce_state->src_ring;
 	u32 ctrl_addr = ce_state->ctrl_addr;
@@ -820,10 +819,7 @@
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	int ce_id;
 
-	/* Skip the last copy engine, CE7 the diagnostic window, as that
-	 * uses polling and isn't initialized for interrupts.
-	 */
-	for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++)
+	for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
 		ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
 }
 
@@ -838,8 +834,8 @@
 
 	nentries = roundup_pow_of_two(attr->src_nentries);
 
-	memset(src_ring->base_addr_owner_space, 0,
-	       nentries * sizeof(struct ce_desc));
+	memset(src_ring->per_transfer_context, 0,
+	       nentries * sizeof(*src_ring->per_transfer_context));
 
 	src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
 	src_ring->sw_index &= src_ring->nentries_mask;
@@ -875,8 +871,8 @@
 
 	nentries = roundup_pow_of_two(attr->dest_nentries);
 
-	memset(dest_ring->base_addr_owner_space, 0,
-	       nentries * sizeof(struct ce_desc));
+	memset(dest_ring->per_transfer_context, 0,
+	       nentries * sizeof(*dest_ring->per_transfer_context));
 
 	dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr);
 	dest_ring->sw_index &= dest_ring->nentries_mask;
@@ -1034,10 +1030,37 @@
  * initialized by software/firmware.
  */
 int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
-			const struct ce_attr *attr)
+			const struct ce_attr *attr,
+			void (*send_cb)(struct ath10k_ce_pipe *),
+			void (*recv_cb)(struct ath10k_ce_pipe *))
 {
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
 	int ret;
 
+	/*
+	 * Make sure there's enough CE ringbuffer entries for HTT TX to avoid
+	 * additional TX locking checks.
+	 *
+	 * For the lack of a better place do the check here.
+	 */
+	BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
+		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
+	BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
+		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
+
+	spin_lock_bh(&ar_pci->ce_lock);
+	ce_state->ar = ar;
+	ce_state->id = ce_id;
+	ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
+	ce_state->attr_flags = attr->flags;
+	ce_state->src_sz_max = attr->src_sz_max;
+	if (attr->src_nentries)
+		ce_state->send_cb = send_cb;
+	if (attr->dest_nentries)
+		ce_state->recv_cb = recv_cb;
+	spin_unlock_bh(&ar_pci->ce_lock);
+
 	if (attr->src_nentries) {
 		ret = ath10k_ce_init_src_ring(ar, ce_id, attr);
 		if (ret) {
@@ -1085,37 +1108,12 @@
 }
 
 int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
-			 const struct ce_attr *attr,
-			 void (*send_cb)(struct ath10k_ce_pipe *),
-			 void (*recv_cb)(struct ath10k_ce_pipe *))
+			 const struct ce_attr *attr)
 {
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
 	int ret;
 
-	/*
-	 * Make sure there's enough CE ringbuffer entries for HTT TX to avoid
-	 * additional TX locking checks.
-	 *
-	 * For the lack of a better place do the check here.
-	 */
-	BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
-		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
-	BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
-		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
-
-	ce_state->ar = ar;
-	ce_state->id = ce_id;
-	ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
-	ce_state->attr_flags = attr->flags;
-	ce_state->src_sz_max = attr->src_sz_max;
-
-	if (attr->src_nentries)
-		ce_state->send_cb = send_cb;
-
-	if (attr->dest_nentries)
-		ce_state->recv_cb = recv_cb;
-
 	if (attr->src_nentries) {
 		ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr);
 		if (IS_ERR(ce_state->src_ring)) {
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index 617a151..329b734 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -192,21 +192,15 @@
 				  unsigned int *nbytesp,
 				  unsigned int *transfer_idp);
 
-int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
-					 void **per_transfer_contextp,
-					 u32 *bufferp,
-					 unsigned int *nbytesp,
-					 unsigned int *transfer_idp);
-
 /*==================CE Engine Initialization=======================*/
 
 int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
-			const struct ce_attr *attr);
+			const struct ce_attr *attr,
+			void (*send_cb)(struct ath10k_ce_pipe *),
+			void (*recv_cb)(struct ath10k_ce_pipe *));
 void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
 int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
-			 const struct ce_attr *attr,
-			 void (*send_cb)(struct ath10k_ce_pipe *),
-			 void (*recv_cb)(struct ath10k_ce_pipe *));
+			 const struct ce_attr *attr);
 void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);
 
 /*==================CE Engine Shutdown=======================*/
@@ -219,13 +213,6 @@
 			       void **per_transfer_contextp,
 			       u32 *bufferp);
 
-int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
-					 void **per_transfer_contextp,
-					 u32 *bufferp,
-					 unsigned int *nbytesp,
-					 unsigned int *transfer_idp,
-					 unsigned int *flagsp);
-
 /*
  * Support clean shutdown by allowing the caller to cancel
  * pending sends.  Target DMA must be stopped before using
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 4a9bfdc..5a08f55 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -31,17 +31,12 @@
 unsigned int ath10k_debug_mask;
 static bool uart_print;
 static unsigned int ath10k_p2p;
-static bool skip_otp;
-
 module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
 module_param(uart_print, bool, 0644);
 module_param_named(p2p, ath10k_p2p, uint, 0644);
-module_param(skip_otp, bool, 0644);
-
 MODULE_PARM_DESC(debug_mask, "Debugging mask");
 MODULE_PARM_DESC(uart_print, "Uart target debugging");
 MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
-MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
 
 static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 	{
@@ -143,8 +138,7 @@
 	return fw;
 }
 
-static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
-				      size_t data_len)
+static int ath10k_push_board_ext_data(struct ath10k *ar)
 {
 	u32 board_data_size = QCA988X_BOARD_DATA_SZ;
 	u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ;
@@ -165,14 +159,14 @@
 	if (board_ext_data_addr == 0)
 		return 0;
 
-	if (data_len != (board_data_size + board_ext_data_size)) {
+	if (ar->board_len != (board_data_size + board_ext_data_size)) {
 		ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n",
-			   data_len, board_data_size, board_ext_data_size);
+			   ar->board_len, board_data_size, board_ext_data_size);
 		return -EINVAL;
 	}
 
 	ret = ath10k_bmi_write_memory(ar, board_ext_data_addr,
-				      data + board_data_size,
+				      ar->board_data + board_data_size,
 				      board_ext_data_size);
 	if (ret) {
 		ath10k_err(ar, "could not write board ext data (%d)\n", ret);
@@ -190,14 +184,13 @@
 	return 0;
 }
 
-static int ath10k_download_board_data(struct ath10k *ar, const void *data,
-				      size_t data_len)
+static int ath10k_download_board_data(struct ath10k *ar)
 {
 	u32 board_data_size = QCA988X_BOARD_DATA_SZ;
 	u32 address;
 	int ret;
 
-	ret = ath10k_push_board_ext_data(ar, data, data_len);
+	ret = ath10k_push_board_ext_data(ar);
 	if (ret) {
 		ath10k_err(ar, "could not push board ext data (%d)\n", ret);
 		goto exit;
@@ -209,9 +202,9 @@
 		goto exit;
 	}
 
-	ret = ath10k_bmi_write_memory(ar, address, data,
+	ret = ath10k_bmi_write_memory(ar, address, ar->board_data,
 				      min_t(u32, board_data_size,
-					    data_len));
+					    ar->board_len));
 	if (ret) {
 		ath10k_err(ar, "could not write board data (%d)\n", ret);
 		goto exit;
@@ -227,39 +220,11 @@
 	return ret;
 }
 
-static int ath10k_download_cal_file(struct ath10k *ar)
-{
-	int ret;
-
-	if (!ar->cal_file)
-		return -ENOENT;
-
-	if (IS_ERR(ar->cal_file))
-		return PTR_ERR(ar->cal_file);
-
-	ret = ath10k_download_board_data(ar, ar->cal_file->data,
-					 ar->cal_file->size);
-	if (ret) {
-		ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
-		return ret;
-	}
-
-	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");
-
-	return 0;
-}
-
 static int ath10k_download_and_run_otp(struct ath10k *ar)
 {
 	u32 result, address = ar->hw_params.patch_load_addr;
 	int ret;
 
-	ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
-	if (ret) {
-		ath10k_err(ar, "failed to download board data: %d\n", ret);
-		return ret;
-	}
-
 	/* OTP is optional */
 
 	if (!ar->otp_data || !ar->otp_len) {
@@ -285,7 +250,7 @@
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
 
-	if (!skip_otp && result != 0) {
+	if (result != 0) {
 		ath10k_err(ar, "otp calibration failed: %d", result);
 		return -EINVAL;
 	}
@@ -343,9 +308,6 @@
 	if (ar->firmware && !IS_ERR(ar->firmware))
 		release_firmware(ar->firmware);
 
-	if (ar->cal_file && !IS_ERR(ar->cal_file))
-		release_firmware(ar->cal_file);
-
 	ar->board = NULL;
 	ar->board_data = NULL;
 	ar->board_len = 0;
@@ -357,27 +319,6 @@
 	ar->firmware = NULL;
 	ar->firmware_data = NULL;
 	ar->firmware_len = 0;
-
-	ar->cal_file = NULL;
-}
-
-static int ath10k_fetch_cal_file(struct ath10k *ar)
-{
-	char filename[100];
-
-	/* cal-<bus>-<id>.bin */
-	scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
-		  ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
-
-	ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
-	if (IS_ERR(ar->cal_file))
-		/* calibration file is optional, don't print any warnings */
-		return PTR_ERR(ar->cal_file);
-
-	ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
-		   ATH10K_FW_DIR, filename);
-
-	return 0;
 }
 
 static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
@@ -621,9 +562,6 @@
 {
 	int ret;
 
-	/* calibration file is optional, don't check for any errors */
-	ath10k_fetch_cal_file(ar);
-
 	ar->fw_api = 3;
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
 
@@ -651,32 +589,30 @@
 	return 0;
 }
 
-static int ath10k_download_cal_data(struct ath10k *ar)
+static int ath10k_init_download_firmware(struct ath10k *ar,
+					 enum ath10k_firmware_mode mode)
 {
 	int ret;
 
-	ret = ath10k_download_cal_file(ar);
-	if (ret == 0) {
-		ar->cal_mode = ATH10K_CAL_MODE_FILE;
-		goto done;
+	ret = ath10k_download_board_data(ar);
+	if (ret) {
+		ath10k_err(ar, "failed to download board data: %d\n", ret);
+		return ret;
 	}
 
-	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-		   "boot did not find a calibration file, try OTP next: %d\n",
-		   ret);
-
 	ret = ath10k_download_and_run_otp(ar);
 	if (ret) {
 		ath10k_err(ar, "failed to run otp: %d\n", ret);
 		return ret;
 	}
 
-	ar->cal_mode = ATH10K_CAL_MODE_OTP;
+	ret = ath10k_download_fw(ar, mode);
+	if (ret) {
+		ath10k_err(ar, "failed to download firmware: %d\n", ret);
+		return ret;
+	}
 
-done:
-	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
-		   ath10k_cal_mode_str(ar->cal_mode));
-	return 0;
+	return ret;
 }
 
 static int ath10k_init_uart(struct ath10k *ar)
@@ -759,25 +695,6 @@
 		ath10k_err(ar, "failed to execute ath10k-reset.  trying driver-level reset.\n");
 	}
 
-	set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
-
-	/* Place a barrier to make sure the compiler doesn't reorder
-	 * CRASH_FLUSH and calling other functions.
-	 */
-	barrier();
-
-	ieee80211_stop_queues(ar->hw);
-	ath10k_drain_tx(ar);
-	complete_all(&ar->scan.started);
-	complete_all(&ar->scan.completed);
-	complete_all(&ar->scan.on_channel);
-	complete_all(&ar->offchan_tx_completed);
-	complete_all(&ar->install_key_done);
-	complete_all(&ar->vdev_setup_done);
-	wake_up(&ar->htt.empty_tx_wq);
-	wake_up(&ar->wmi.tx_credits_wq);
-	wake_up(&ar->peer_mapping_wq);
-
 	mutex_lock(&ar->conf_mutex);
 
 	switch (ar->state) {
@@ -809,25 +726,12 @@
 	mutex_unlock(&ar->conf_mutex);
 }
 
-static void ath10k_core_init_max_sta_count(struct ath10k *ar)
-{
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-		ar->max_num_peers = TARGET_10X_NUM_PEERS;
-		ar->max_num_stations = TARGET_10X_NUM_STATIONS;
-	} else {
-		ar->max_num_peers = TARGET_NUM_PEERS;
-		ar->max_num_stations = TARGET_NUM_STATIONS;
-	}
-}
-
 int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
 {
 	int status;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
-
 	ath10k_bmi_start(ar);
 
 	if (ath10k_init_configure_target(ar)) {
@@ -835,11 +739,7 @@
 		goto err;
 	}
 
-	status = ath10k_download_cal_data(ar);
-	if (status)
-		goto err;
-
-	status = ath10k_download_fw(ar, mode);
+	status = ath10k_init_download_firmware(ar, mode);
 	if (status)
 		goto err;
 
@@ -956,9 +856,9 @@
 		goto err_hif_stop;
 
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
+		ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
 	else
-		ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
+		ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
 
 	INIT_LIST_HEAD(&ar->arvifs);
 
@@ -1056,8 +956,6 @@
 		return ret;
 	}
 
-	ath10k_core_init_max_sta_count(ar);
-
 	mutex_lock(&ar->conf_mutex);
 
 	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
@@ -1196,7 +1094,6 @@
 EXPORT_SYMBOL(ath10k_core_unregister);
 
 struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
-				  enum ath10k_bus bus,
 				  const struct ath10k_hif_ops *hif_ops)
 {
 	struct ath10k *ar;
@@ -1213,7 +1110,6 @@
 	ar->dev = dev;
 
 	ar->hif.ops = hif_ops;
-	ar->hif.bus = bus;
 
 	init_completion(&ar->scan.started);
 	init_completion(&ar->scan.completed);
@@ -1234,8 +1130,6 @@
 
 	INIT_LIST_HEAD(&ar->peers);
 	init_waitqueue_head(&ar->peer_mapping_wq);
-	init_waitqueue_head(&ar->htt.empty_tx_wq);
-	init_waitqueue_head(&ar->wmi.tx_credits_wq);
 
 	init_completion(&ar->offchan_tx_completed);
 	INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index a20240c..8164721 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -63,28 +63,12 @@
 
 struct ath10k;
 
-enum ath10k_bus {
-	ATH10K_BUS_PCI,
-};
-
-static inline const char *ath10k_bus_str(enum ath10k_bus bus)
-{
-	switch (bus) {
-	case ATH10K_BUS_PCI:
-		return "pci";
-	}
-
-	return "unknown";
-}
-
 struct ath10k_skb_cb {
 	dma_addr_t paddr;
-	u8 eid;
 	u8 vdev_id;
 
 	struct {
 		u8 tid;
-		u16 freq;
 		bool is_offchan;
 		struct ath10k_htt_txbuf *txbuf;
 		u32 txbuf_paddr;
@@ -112,6 +96,8 @@
 	bool done_sent;
 };
 
+#define ATH10K_MAX_MEM_REQS 16
+
 struct ath10k_mem_chunk {
 	void *vaddr;
 	dma_addr_t paddr;
@@ -124,27 +110,22 @@
 	struct completion service_ready;
 	struct completion unified_ready;
 	wait_queue_head_t tx_credits_wq;
-	DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
 	struct wmi_cmd_map *cmd;
 	struct wmi_vdev_param_map *vdev_param;
 	struct wmi_pdev_param_map *pdev_param;
 
 	u32 num_mem_chunks;
-	struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
+	struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS];
 };
 
-struct ath10k_fw_stats_peer {
-	struct list_head list;
-
+struct ath10k_peer_stat {
 	u8 peer_macaddr[ETH_ALEN];
 	u32 peer_rssi;
 	u32 peer_tx_rate;
 	u32 peer_rx_rate; /* 10x only */
 };
 
-struct ath10k_fw_stats_pdev {
-	struct list_head list;
-
+struct ath10k_target_stats {
 	/* PDEV stats */
 	s32 ch_noise_floor;
 	u32 tx_frame_count;
@@ -199,11 +180,15 @@
 	s32 phy_errs;
 	s32 phy_err_drop;
 	s32 mpdu_errs;
-};
 
-struct ath10k_fw_stats {
-	struct list_head pdevs;
-	struct list_head peers;
+	/* VDEV STATS */
+
+	/* PEER STATS */
+	u8 peers;
+	struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS];
+
+	/* TODO: Beacon filter stats */
+
 };
 
 struct ath10k_dfs_stats {
@@ -226,8 +211,6 @@
 
 	/* protected by data_lock */
 	DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
-
-	/* protected by ar->data_lock */
 	struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
 };
 
@@ -256,8 +239,6 @@
 	struct sk_buff *beacon;
 	/* protected by data_lock */
 	bool beacon_sent;
-	void *beacon_buf;
-	dma_addr_t beacon_paddr;
 
 	struct ath10k *ar;
 	struct ieee80211_vif *vif;
@@ -297,7 +278,6 @@
 	u8 force_sgi;
 	bool use_cts_prot;
 	int num_legacy_stations;
-	int txpower;
 };
 
 struct ath10k_vif_iter {
@@ -317,19 +297,17 @@
 struct ath10k_debug {
 	struct dentry *debugfs_phy;
 
-	struct ath10k_fw_stats fw_stats;
-	struct completion fw_stats_complete;
-	bool fw_stats_done;
+	struct ath10k_target_stats target_stats;
+	DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
+
+	struct completion event_stats_compl;
 
 	unsigned long htt_stats_mask;
 	struct delayed_work htt_stats_dwork;
 	struct ath10k_dfs_stats dfs_stats;
 	struct ath_dfs_pool_stats dfs_pool_stats;
 
-	/* protected by conf_mutex */
 	u32 fw_dbglog_mask;
-	u32 pktlog_filter;
-	u32 reg_addr;
 
 	u8 htt_max_amsdu;
 	u8 htt_max_ampdu;
@@ -348,7 +326,7 @@
 	 * stopped in ath10k_core_restart() work holding conf_mutex. The state
 	 * RESTARTED means that the device is up and mac80211 has started hw
 	 * reconfiguration. Once mac80211 is done with the reconfiguration we
-	 * set the state to STATE_ON in reconfig_complete(). */
+	 * set the state to STATE_ON in restart_complete(). */
 	ATH10K_STATE_RESTARTING,
 	ATH10K_STATE_RESTARTED,
 
@@ -396,30 +374,8 @@
 	/* Indicates that ath10k device is during CAC phase of DFS */
 	ATH10K_CAC_RUNNING,
 	ATH10K_FLAG_CORE_REGISTERED,
-
-	/* Device has crashed and needs to restart. This indicates any pending
-	 * waiters should immediately cancel instead of waiting for a time out.
-	 */
-	ATH10K_FLAG_CRASH_FLUSH,
 };
 
-enum ath10k_cal_mode {
-	ATH10K_CAL_MODE_FILE,
-	ATH10K_CAL_MODE_OTP,
-};
-
-static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
-{
-	switch (mode) {
-	case ATH10K_CAL_MODE_FILE:
-		return "file";
-	case ATH10K_CAL_MODE_OTP:
-		return "otp";
-	}
-
-	return "unknown";
-}
-
 enum ath10k_scan_state {
 	ATH10K_SCAN_IDLE,
 	ATH10K_SCAN_STARTING,
@@ -470,7 +426,6 @@
 	bool p2p;
 
 	struct {
-		enum ath10k_bus bus;
 		const struct ath10k_hif_ops *ops;
 	} hif;
 
@@ -506,10 +461,7 @@
 	const void *firmware_data;
 	size_t firmware_len;
 
-	const struct firmware *cal_file;
-
 	int fw_api;
-	enum ath10k_cal_mode cal_mode;
 
 	struct {
 		struct completion started;
@@ -535,7 +487,7 @@
 	/* current operating channel definition */
 	struct cfg80211_chan_def chandef;
 
-	unsigned long long free_vdev_map;
+	int free_vdev_map;
 	bool monitor;
 	int monitor_vdev_id;
 	bool monitor_started;
@@ -570,12 +522,8 @@
 	struct list_head peers;
 	wait_queue_head_t peer_mapping_wq;
 
-	/* protected by conf_mutex */
+	/* number of created peers; protected by data_lock */
 	int num_peers;
-	int num_stations;
-
-	int max_num_peers;
-	int max_num_stations;
 
 	struct work_struct offchan_tx_work;
 	struct sk_buff_head offchan_tx_queue;
@@ -621,19 +569,11 @@
 		bool utf_monitor;
 	} testmode;
 
-	struct {
-		/* protected by data_lock */
-		u32 fw_crash_counter;
-		u32 fw_warm_reset_counter;
-		u32 fw_cold_reset_counter;
-	} stats;
-
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
 };
 
 struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
-				  enum ath10k_bus bus,
 				  const struct ath10k_hif_ops *hif_ops);
 void ath10k_core_destroy(struct ath10k *ar);
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index ee7f8c1..f9a7cc3 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -17,12 +17,12 @@
 
 #include <linux/module.h>
 #include <linux/debugfs.h>
+#include <linux/version.h>
+#include <linux/vermagic.h>
 #include <linux/vmalloc.h>
-#include <linux/utsname.h>
 
 #include "core.h"
 #include "debug.h"
-#include "hif.h"
 
 /* ms */
 #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
@@ -106,37 +106,34 @@
 	u8 data[0];
 } __packed;
 
-void ath10k_info(struct ath10k *ar, const char *fmt, ...)
+int ath10k_info(struct ath10k *ar, const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
+	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	dev_info(ar->dev, "%pV", &vaf);
+	ret = dev_info(ar->dev, "%pV", &vaf);
 	trace_ath10k_log_info(ar, &vaf);
 	va_end(args);
+
+	return ret;
 }
 EXPORT_SYMBOL(ath10k_info);
 
 void ath10k_print_driver_info(struct ath10k *ar)
 {
-	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s max_sta %d\n",
+	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
 		    ar->hw_params.name,
 		    ar->target_version,
 		    ar->chip_id,
 		    ar->hw->wiphy->fw_version,
 		    ar->fw_api,
 		    ar->htt.target_version_major,
-		    ar->htt.target_version_minor,
-		    ar->fw_version_major,
-		    ar->fw_version_minor,
-		    ar->fw_version_release,
-		    ar->fw_version_build,
-		    ath10k_cal_mode_str(ar->cal_mode),
-		    ar->max_num_stations);
+		    ar->htt.target_version_minor);
 	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
 		    config_enabled(CPTCFG_ATH10K_DEBUG),
 		    config_enabled(CPTCFG_ATH10K_DEBUGFS),
@@ -146,22 +143,25 @@
 }
 EXPORT_SYMBOL(ath10k_print_driver_info);
 
-void ath10k_err(struct ath10k *ar, const char *fmt, ...)
+int ath10k_err(struct ath10k *ar, const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
+	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	dev_err(ar->dev, "%pV", &vaf);
+	ret = dev_err(ar->dev, "%pV", &vaf);
 	trace_ath10k_log_err(ar, &vaf);
 	va_end(args);
+
+	return ret;
 }
 EXPORT_SYMBOL(ath10k_err);
 
-void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
+int ath10k_warn(struct ath10k *ar, const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
@@ -174,11 +174,20 @@
 	trace_ath10k_log_warn(ar, &vaf);
 
 	va_end(args);
+
+	return 0;
 }
 EXPORT_SYMBOL(ath10k_warn);
 
 #ifdef CPTCFG_ATH10K_DEBUGFS
 
+void ath10k_debug_read_service_map(struct ath10k *ar,
+				   void *service_map,
+				   size_t map_size)
+{
+	memcpy(ar->debug.wmi_service_bitmap, service_map, map_size);
+}
+
 static ssize_t ath10k_read_wmi_services(struct file *file,
 					char __user *user_buf,
 					size_t count, loff_t *ppos)
@@ -200,9 +209,8 @@
 	if (len > buf_len)
 		len = buf_len;
 
-	spin_lock_bh(&ar->data_lock);
 	for (i = 0; i < WMI_SERVICE_MAX; i++) {
-		enabled = test_bit(i, ar->wmi.svc_map);
+		enabled = test_bit(i, ar->debug.wmi_service_bitmap);
 		name = wmi_service_name(i);
 
 		if (!name) {
@@ -218,7 +226,6 @@
 				 "%-40s %s\n",
 				 name, enabled ? "enabled" : "-");
 	}
-	spin_unlock_bh(&ar->data_lock);
 
 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
 
@@ -235,182 +242,169 @@
 	.llseek = default_llseek,
 };
 
-static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
+void ath10k_debug_read_target_stats(struct ath10k *ar,
+				    struct wmi_stats_event *ev)
 {
-	struct ath10k_fw_stats_pdev *i, *tmp;
+	u8 *tmp = ev->data;
+	struct ath10k_target_stats *stats;
+	int num_pdev_stats, num_vdev_stats, num_peer_stats;
+	struct wmi_pdev_stats_10x *ps;
+	int i;
 
-	list_for_each_entry_safe(i, tmp, head, list) {
-		list_del(&i->list);
-		kfree(i);
-	}
-}
-
-static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
-{
-	struct ath10k_fw_stats_peer *i, *tmp;
-
-	list_for_each_entry_safe(i, tmp, head, list) {
-		list_del(&i->list);
-		kfree(i);
-	}
-}
-
-static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
-{
 	spin_lock_bh(&ar->data_lock);
-	ar->debug.fw_stats_done = false;
-	ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
-	ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
+
+	stats = &ar->debug.target_stats;
+
+	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */
+	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */
+	num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */
+
+	if (num_pdev_stats) {
+		ps = (struct wmi_pdev_stats_10x *)tmp;
+
+		stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf);
+		stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count);
+		stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count);
+		stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count);
+		stats->cycle_count = __le32_to_cpu(ps->cycle_count);
+		stats->phy_err_count = __le32_to_cpu(ps->phy_err_count);
+		stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr);
+
+		stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued);
+		stats->comp_delivered =
+			__le32_to_cpu(ps->wal.tx.comp_delivered);
+		stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued);
+		stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued);
+		stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop);
+		stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued);
+		stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed);
+		stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued);
+		stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped);
+		stats->underrun = __le32_to_cpu(ps->wal.tx.underrun);
+		stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort);
+		stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed);
+		stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko);
+		stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc);
+		stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers);
+		stats->sw_retry_failure =
+			__le32_to_cpu(ps->wal.tx.sw_retry_failure);
+		stats->illgl_rate_phy_err =
+			__le32_to_cpu(ps->wal.tx.illgl_rate_phy_err);
+		stats->pdev_cont_xretry =
+			__le32_to_cpu(ps->wal.tx.pdev_cont_xretry);
+		stats->pdev_tx_timeout =
+			__le32_to_cpu(ps->wal.tx.pdev_tx_timeout);
+		stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets);
+		stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun);
+		stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf);
+
+		stats->mid_ppdu_route_change =
+			__le32_to_cpu(ps->wal.rx.mid_ppdu_route_change);
+		stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd);
+		stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags);
+		stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags);
+		stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags);
+		stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags);
+		stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus);
+		stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus);
+		stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus);
+		stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus);
+		stats->oversize_amsdu =
+			__le32_to_cpu(ps->wal.rx.oversize_amsdu);
+		stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs);
+		stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop);
+		stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs);
+
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10X,
+			     ar->fw_features)) {
+			stats->ack_rx_bad = __le32_to_cpu(ps->ack_rx_bad);
+			stats->rts_bad = __le32_to_cpu(ps->rts_bad);
+			stats->rts_good = __le32_to_cpu(ps->rts_good);
+			stats->fcs_bad = __le32_to_cpu(ps->fcs_bad);
+			stats->no_beacons = __le32_to_cpu(ps->no_beacons);
+			stats->mib_int_count = __le32_to_cpu(ps->mib_int_count);
+			tmp += sizeof(struct wmi_pdev_stats_10x);
+		} else {
+			tmp += sizeof(struct wmi_pdev_stats_old);
+		}
+	}
+
+	/* 0 or max vdevs */
+	/* Currently firmware does not support VDEV stats */
+	if (num_vdev_stats) {
+		struct wmi_vdev_stats *vdev_stats;
+
+		for (i = 0; i < num_vdev_stats; i++) {
+			vdev_stats = (struct wmi_vdev_stats *)tmp;
+			tmp += sizeof(struct wmi_vdev_stats);
+		}
+	}
+
+	if (num_peer_stats) {
+		struct wmi_peer_stats_10x *peer_stats;
+		struct ath10k_peer_stat *s;
+
+		stats->peers = num_peer_stats;
+
+		for (i = 0; i < num_peer_stats; i++) {
+			peer_stats = (struct wmi_peer_stats_10x *)tmp;
+			s = &stats->peer_stat[i];
+
+			memcpy(s->peer_macaddr, &peer_stats->peer_macaddr.addr,
+			       ETH_ALEN);
+			s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi);
+			s->peer_tx_rate =
+				__le32_to_cpu(peer_stats->peer_tx_rate);
+			if (test_bit(ATH10K_FW_FEATURE_WMI_10X,
+				     ar->fw_features)) {
+				s->peer_rx_rate =
+					__le32_to_cpu(peer_stats->peer_rx_rate);
+				tmp += sizeof(struct wmi_peer_stats_10x);
+
+			} else {
+				tmp += sizeof(struct wmi_peer_stats_old);
+			}
+		}
+	}
+
 	spin_unlock_bh(&ar->data_lock);
+	complete(&ar->debug.event_stats_compl);
 }
 
-static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
+static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
 {
-	struct ath10k_fw_stats_peer *i;
-	size_t num = 0;
-
-	list_for_each_entry(i, head, list)
-		++num;
-
-	return num;
-}
-
-void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
-{
-	struct ath10k_fw_stats stats = {};
-	bool is_start, is_started, is_end;
-	size_t num_peers;
+	struct ath10k *ar = file->private_data;
+	struct ath10k_target_stats *fw_stats;
+	char *buf = NULL;
+	unsigned int len = 0, buf_len = 8000;
+	ssize_t ret_cnt = 0;
+	long left;
+	int i;
 	int ret;
 
-	INIT_LIST_HEAD(&stats.pdevs);
-	INIT_LIST_HEAD(&stats.peers);
+	fw_stats = &ar->debug.target_stats;
 
-	spin_lock_bh(&ar->data_lock);
-	ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_ON)
+		goto exit;
+
+	buf = kzalloc(buf_len, GFP_KERNEL|__GFP_REPEAT|__GFP_HIGH);
+	if (!buf)
+		goto exit;
+
+	ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
 	if (ret) {
-		ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
-		goto unlock;
+		ath10k_warn(ar, "could not request stats (%d)\n", ret);
+		goto exit;
 	}
 
-	/* Stat data may exceed htc-wmi buffer limit. In such case firmware
-	 * splits the stats data and delivers it in a ping-pong fashion of
-	 * request cmd-update event.
-	 *
-	 * However there is no explicit end-of-data. Instead start-of-data is
-	 * used as an implicit one. This works as follows:
-	 *  a) discard stat update events until one with pdev stats is
-	 *     delivered - this skips session started at end of (b)
-	 *  b) consume stat update events until another one with pdev stats is
-	 *     delivered which is treated as end-of-data and is itself discarded
-	 */
-
-	if (ar->debug.fw_stats_done) {
-		ath10k_warn(ar, "received unsolicited stats update event\n");
-		goto free;
-	}
-
-	num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
-	is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
-		    !list_empty(&stats.pdevs));
-	is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
-		  !list_empty(&stats.pdevs));
-
-	if (is_start)
-		list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
-
-	if (is_end)
-		ar->debug.fw_stats_done = true;
-
-	is_started = !list_empty(&ar->debug.fw_stats.pdevs);
-
-	if (is_started && !is_end) {
-		if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
-			/* Although this is unlikely impose a sane limit to
-			 * prevent firmware from DoS-ing the host.
-			 */
-			ath10k_warn(ar, "dropping fw peer stats\n");
-			goto free;
-		}
-
-		list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
-	}
-
-	complete(&ar->debug.fw_stats_complete);
-
-free:
-	/* In some cases lists have been spliced and cleared. Free up
-	 * resources if that is not the case.
-	 */
-	ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
-	ath10k_debug_fw_stats_peers_free(&stats.peers);
-
-unlock:
-	spin_unlock_bh(&ar->data_lock);
-}
-
-static int ath10k_debug_fw_stats_request(struct ath10k *ar)
-{
-	unsigned long timeout;
-	int ret;
-
-	lockdep_assert_held(&ar->conf_mutex);
-
-	timeout = jiffies + msecs_to_jiffies(1*HZ);
-
-	ath10k_debug_fw_stats_reset(ar);
-
-	for (;;) {
-		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
-
-		reinit_completion(&ar->debug.fw_stats_complete);
-
-		ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
-		if (ret) {
-			ath10k_warn(ar, "could not request stats (%d)\n", ret);
-			return ret;
-		}
-
-		ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete,
-						  1*HZ);
-		if (ret <= 0)
-			return -ETIMEDOUT;
-
-		spin_lock_bh(&ar->data_lock);
-		if (ar->debug.fw_stats_done) {
-			spin_unlock_bh(&ar->data_lock);
-			break;
-		}
-		spin_unlock_bh(&ar->data_lock);
-	}
-
-	return 0;
-}
-
-/* FIXME: How to calculate the buffer size sanely? */
-#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
-
-static void ath10k_fw_stats_fill(struct ath10k *ar,
-				 struct ath10k_fw_stats *fw_stats,
-				 char *buf)
-{
-	unsigned int len = 0;
-	unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
-	const struct ath10k_fw_stats_pdev *pdev;
-	const struct ath10k_fw_stats_peer *peer;
-	size_t num_peers;
+	left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
+	if (left <= 0)
+		goto exit;
 
 	spin_lock_bh(&ar->data_lock);
-
-	pdev = list_first_entry_or_null(&fw_stats->pdevs,
-					struct ath10k_fw_stats_pdev, list);
-	if (!pdev) {
-		ath10k_warn(ar, "failed to get pdev stats\n");
-		goto unlock;
-	}
-
-	num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
-
 	len += scnprintf(buf + len, buf_len - len, "\n");
 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
 			 "ath10k PDEV stats");
@@ -418,29 +412,29 @@
 				 "=================");
 
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Channel noise floor", pdev->ch_noise_floor);
+			 "Channel noise floor", fw_stats->ch_noise_floor);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "Channel TX power", pdev->chan_tx_power);
+			 "Channel TX power", fw_stats->chan_tx_power);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "TX frame count", pdev->tx_frame_count);
+			 "TX frame count", fw_stats->tx_frame_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "RX frame count", pdev->rx_frame_count);
+			 "RX frame count", fw_stats->rx_frame_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "RX clear count", pdev->rx_clear_count);
+			 "RX clear count", fw_stats->rx_clear_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "Cycle count", pdev->cycle_count);
+			 "Cycle count", fw_stats->cycle_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "PHY error count", pdev->phy_err_count);
+			 "PHY error count", fw_stats->phy_err_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "RTS bad count", pdev->rts_bad);
+			 "RTS bad count", fw_stats->rts_bad);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "RTS good count", pdev->rts_good);
+			 "RTS good count", fw_stats->rts_good);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "FCS bad count", pdev->fcs_bad);
+			 "FCS bad count", fw_stats->fcs_bad);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "No beacon count", pdev->no_beacons);
+			 "No beacon count", fw_stats->no_beacons);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "MIB int count", pdev->mib_int_count);
+			 "MIB int count", fw_stats->mib_int_count);
 
 	len += scnprintf(buf + len, buf_len - len, "\n");
 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
@@ -449,51 +443,51 @@
 				 "=================");
 
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "HTT cookies queued", pdev->comp_queued);
+			 "HTT cookies queued", fw_stats->comp_queued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "HTT cookies disp.", pdev->comp_delivered);
+			 "HTT cookies disp.", fw_stats->comp_delivered);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MSDU queued", pdev->msdu_enqued);
+			 "MSDU queued", fw_stats->msdu_enqued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDU queued", pdev->mpdu_enqued);
+			 "MPDU queued", fw_stats->mpdu_enqued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MSDUs dropped", pdev->wmm_drop);
+			 "MSDUs dropped", fw_stats->wmm_drop);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Local enqued", pdev->local_enqued);
+			 "Local enqued", fw_stats->local_enqued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Local freed", pdev->local_freed);
+			 "Local freed", fw_stats->local_freed);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "HW queued", pdev->hw_queued);
+			 "HW queued", fw_stats->hw_queued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PPDUs reaped", pdev->hw_reaped);
+			 "PPDUs reaped", fw_stats->hw_reaped);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Num underruns", pdev->underrun);
+			 "Num underruns", fw_stats->underrun);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PPDUs cleaned", pdev->tx_abort);
+			 "PPDUs cleaned", fw_stats->tx_abort);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDUs requed", pdev->mpdus_requed);
+			 "MPDUs requed", fw_stats->mpdus_requed);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Excessive retries", pdev->tx_ko);
+			 "Excessive retries", fw_stats->tx_ko);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "HW rate", pdev->data_rc);
+			 "HW rate", fw_stats->data_rc);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Sched self tiggers", pdev->self_triggers);
+			 "Sched self tiggers", fw_stats->self_triggers);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
 			 "Dropped due to SW retries",
-			 pdev->sw_retry_failure);
+			 fw_stats->sw_retry_failure);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
 			 "Illegal rate phy errors",
-			 pdev->illgl_rate_phy_err);
+			 fw_stats->illgl_rate_phy_err);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Pdev continous xretry", pdev->pdev_cont_xretry);
+			 "Pdev continous xretry", fw_stats->pdev_cont_xretry);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "TX timeout", pdev->pdev_tx_timeout);
+			 "TX timeout", fw_stats->pdev_tx_timeout);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PDEV resets", pdev->pdev_resets);
+			 "PDEV resets", fw_stats->pdev_resets);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PHY underrun", pdev->phy_underrun);
+			 "PHY underrun", fw_stats->phy_underrun);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDU is more than txop limit", pdev->txop_ovf);
+			 "MPDU is more than txop limit", fw_stats->txop_ovf);
 
 	len += scnprintf(buf + len, buf_len - len, "\n");
 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
@@ -503,161 +497,70 @@
 
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
 			 "Mid PPDU route change",
-			 pdev->mid_ppdu_route_change);
+			 fw_stats->mid_ppdu_route_change);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Tot. number of statuses", pdev->status_rcvd);
+			 "Tot. number of statuses", fw_stats->status_rcvd);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Extra frags on rings 0", pdev->r0_frags);
+			 "Extra frags on rings 0", fw_stats->r0_frags);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Extra frags on rings 1", pdev->r1_frags);
+			 "Extra frags on rings 1", fw_stats->r1_frags);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Extra frags on rings 2", pdev->r2_frags);
+			 "Extra frags on rings 2", fw_stats->r2_frags);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Extra frags on rings 3", pdev->r3_frags);
+			 "Extra frags on rings 3", fw_stats->r3_frags);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MSDUs delivered to HTT", pdev->htt_msdus);
+			 "MSDUs delivered to HTT", fw_stats->htt_msdus);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDUs delivered to HTT", pdev->htt_mpdus);
+			 "MPDUs delivered to HTT", fw_stats->htt_mpdus);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MSDUs delivered to stack", pdev->loc_msdus);
+			 "MSDUs delivered to stack", fw_stats->loc_msdus);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDUs delivered to stack", pdev->loc_mpdus);
+			 "MPDUs delivered to stack", fw_stats->loc_mpdus);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Oversized AMSUs", pdev->oversize_amsdu);
+			 "Oversized AMSUs", fw_stats->oversize_amsdu);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PHY errors", pdev->phy_errs);
+			 "PHY errors", fw_stats->phy_errs);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PHY errors drops", pdev->phy_err_drop);
+			 "PHY errors drops", fw_stats->phy_err_drop);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
+			 "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs);
 
 	len += scnprintf(buf + len, buf_len - len, "\n");
-	len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
-			 "ath10k PEER stats", num_peers);
+	len += scnprintf(buf + len, buf_len - len, "%30s (%d)\n",
+			 "ath10k PEER stats", fw_stats->peers);
 	len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
 				 "=================");
 
-	list_for_each_entry(peer, &fw_stats->peers, list) {
+	for (i = 0; i < fw_stats->peers; i++) {
 		len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
-				 "Peer MAC address", peer->peer_macaddr);
+				 "Peer MAC address",
+				 fw_stats->peer_stat[i].peer_macaddr);
 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-				 "Peer RSSI", peer->peer_rssi);
+				 "Peer RSSI", fw_stats->peer_stat[i].peer_rssi);
 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-				 "Peer TX rate", peer->peer_tx_rate);
+				 "Peer TX rate",
+				 fw_stats->peer_stat[i].peer_tx_rate);
 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-				 "Peer RX rate", peer->peer_rx_rate);
+				 "Peer RX rate",
+				 fw_stats->peer_stat[i].peer_rx_rate);
 		len += scnprintf(buf + len, buf_len - len, "\n");
 	}
-
-unlock:
 	spin_unlock_bh(&ar->data_lock);
 
-	if (len >= buf_len)
-		buf[len - 1] = 0;
-	else
-		buf[len] = 0;
-}
+	if (len > buf_len)
+		len = buf_len;
 
-static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
-{
-	struct ath10k *ar = inode->i_private;
-	void *buf = NULL;
-	int ret;
+	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
 
-	mutex_lock(&ar->conf_mutex);
-
-	if (ar->state != ATH10K_STATE_ON) {
-		ret = -ENETDOWN;
-		goto err_unlock;
-	}
-
-	buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto err_unlock;
-	}
-
-	ret = ath10k_debug_fw_stats_request(ar);
-	if (ret) {
-		ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
-		goto err_free;
-	}
-
-	ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
-	file->private_data = buf;
-
+exit:
 	mutex_unlock(&ar->conf_mutex);
-	return 0;
-
-err_free:
-	vfree(buf);
-
-err_unlock:
-	mutex_unlock(&ar->conf_mutex);
-	return ret;
-}
-
-static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
-{
-	vfree(file->private_data);
-
-	return 0;
-}
-
-static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
-				    size_t count, loff_t *ppos)
-{
-	const char *buf = file->private_data;
-	unsigned int len = strlen(buf);
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+	return ret_cnt;
 }
 
 static const struct file_operations fops_fw_stats = {
-	.open = ath10k_fw_stats_open,
-	.release = ath10k_fw_stats_release,
-	.read = ath10k_fw_stats_read,
-	.owner = THIS_MODULE,
-	.llseek = default_llseek,
-};
-
-static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
-						char __user *user_buf,
-						size_t count, loff_t *ppos)
-{
-	struct ath10k *ar = file->private_data;
-	int ret, len, buf_len;
-	char *buf;
-
-	buf_len = 500;
-	buf = kmalloc(buf_len, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	spin_lock_bh(&ar->data_lock);
-
-	len = 0;
-	len += scnprintf(buf + len, buf_len - len,
-			 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
-	len += scnprintf(buf + len, buf_len - len,
-			 "fw_warm_reset_counter\t\t%d\n",
-			 ar->stats.fw_warm_reset_counter);
-	len += scnprintf(buf + len, buf_len - len,
-			 "fw_cold_reset_counter\t\t%d\n",
-			 ar->stats.fw_cold_reset_counter);
-
-	spin_unlock_bh(&ar->data_lock);
-
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-
-	kfree(buf);
-
-	return ret;
-}
-
-static const struct file_operations fops_fw_reset_stats = {
+	.read = ath10k_read_fw_stats,
 	.open = simple_open,
-	.read = ath10k_debug_fw_reset_stats_read,
 	.owner = THIS_MODULE,
 	.llseek = default_llseek,
 };
@@ -690,8 +593,7 @@
 		"To simulate firmware crash write one of the keywords to this file:\n"
 		"`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
 		"`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
-		"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
-		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
+		"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n";
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
 }
@@ -745,10 +647,6 @@
 	} else if (!strcmp(buf, "assert")) {
 		ath10k_info(ar, "simulating firmware assert crash\n");
 		ret = ath10k_debug_fw_assert(ar);
-	} else if (!strcmp(buf, "hw-restart")) {
-		ath10k_info(ar, "user requested hw restart\n");
-		queue_work(ar->workqueue, &ar->restart_work);
-		ret = 0;
 	} else {
 		ret = -EINVAL;
 		goto exit;
@@ -862,8 +760,8 @@
 	strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
 		sizeof(dump_data->fw_ver));
 
-	dump_data->kernel_ver_code = 0;
-	strlcpy(dump_data->kernel_ver, init_utsname()->release,
+	dump_data->kernel_ver_code = cpu_to_le32(LINUX_VERSION_CODE);
+	strlcpy(dump_data->kernel_ver, VERMAGIC_STRING,
 		sizeof(dump_data->kernel_ver));
 
 	dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
@@ -925,236 +823,6 @@
 	.llseek = default_llseek,
 };
 
-static ssize_t ath10k_reg_addr_read(struct file *file,
-				    char __user *user_buf,
-				    size_t count, loff_t *ppos)
-{
-	struct ath10k *ar = file->private_data;
-	u8 buf[32];
-	unsigned int len = 0;
-	u32 reg_addr;
-
-	mutex_lock(&ar->conf_mutex);
-	reg_addr = ar->debug.reg_addr;
-	mutex_unlock(&ar->conf_mutex);
-
-	len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t ath10k_reg_addr_write(struct file *file,
-				     const char __user *user_buf,
-				     size_t count, loff_t *ppos)
-{
-	struct ath10k *ar = file->private_data;
-	u32 reg_addr;
-	int ret;
-
-	ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
-	if (ret)
-		return ret;
-
-	if (!IS_ALIGNED(reg_addr, 4))
-		return -EFAULT;
-
-	mutex_lock(&ar->conf_mutex);
-	ar->debug.reg_addr = reg_addr;
-	mutex_unlock(&ar->conf_mutex);
-
-	return count;
-}
-
-static const struct file_operations fops_reg_addr = {
-	.read = ath10k_reg_addr_read,
-	.write = ath10k_reg_addr_write,
-	.open = simple_open,
-	.owner = THIS_MODULE,
-	.llseek = default_llseek,
-};
-
-static ssize_t ath10k_reg_value_read(struct file *file,
-				     char __user *user_buf,
-				     size_t count, loff_t *ppos)
-{
-	struct ath10k *ar = file->private_data;
-	u8 buf[48];
-	unsigned int len;
-	u32 reg_addr, reg_val;
-	int ret;
-
-	mutex_lock(&ar->conf_mutex);
-
-	if (ar->state != ATH10K_STATE_ON &&
-	    ar->state != ATH10K_STATE_UTF) {
-		ret = -ENETDOWN;
-		goto exit;
-	}
-
-	reg_addr = ar->debug.reg_addr;
-
-	reg_val = ath10k_hif_read32(ar, reg_addr);
-	len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
-
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-
-exit:
-	mutex_unlock(&ar->conf_mutex);
-
-	return ret;
-}
-
-static ssize_t ath10k_reg_value_write(struct file *file,
-				      const char __user *user_buf,
-				      size_t count, loff_t *ppos)
-{
-	struct ath10k *ar = file->private_data;
-	u32 reg_addr, reg_val;
-	int ret;
-
-	mutex_lock(&ar->conf_mutex);
-
-	if (ar->state != ATH10K_STATE_ON &&
-	    ar->state != ATH10K_STATE_UTF) {
-		ret = -ENETDOWN;
-		goto exit;
-	}
-
-	reg_addr = ar->debug.reg_addr;
-
-	ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
-	if (ret)
-		goto exit;
-
-	ath10k_hif_write32(ar, reg_addr, reg_val);
-
-	ret = count;
-
-exit:
-	mutex_unlock(&ar->conf_mutex);
-
-	return ret;
-}
-
-static const struct file_operations fops_reg_value = {
-	.read = ath10k_reg_value_read,
-	.write = ath10k_reg_value_write,
-	.open = simple_open,
-	.owner = THIS_MODULE,
-	.llseek = default_llseek,
-};
-
-static ssize_t ath10k_mem_value_read(struct file *file,
-				     char __user *user_buf,
-				     size_t count, loff_t *ppos)
-{
-	struct ath10k *ar = file->private_data;
-	u8 *buf;
-	int ret;
-
-	if (*ppos < 0)
-		return -EINVAL;
-
-	if (!count)
-		return 0;
-
-	mutex_lock(&ar->conf_mutex);
-
-	buf = vmalloc(count);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	if (ar->state != ATH10K_STATE_ON &&
-	    ar->state != ATH10K_STATE_UTF) {
-		ret = -ENETDOWN;
-		goto exit;
-	}
-
-	ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
-	if (ret) {
-		ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
-			    (u32)(*ppos), ret);
-		goto exit;
-	}
-
-	ret = copy_to_user(user_buf, buf, count);
-	if (ret) {
-		ret = -EFAULT;
-		goto exit;
-	}
-
-	count -= ret;
-	*ppos += count;
-	ret = count;
-
-exit:
-	vfree(buf);
-	mutex_unlock(&ar->conf_mutex);
-
-	return ret;
-}
-
-static ssize_t ath10k_mem_value_write(struct file *file,
-				      const char __user *user_buf,
-				      size_t count, loff_t *ppos)
-{
-	struct ath10k *ar = file->private_data;
-	u8 *buf;
-	int ret;
-
-	if (*ppos < 0)
-		return -EINVAL;
-
-	if (!count)
-		return 0;
-
-	mutex_lock(&ar->conf_mutex);
-
-	buf = vmalloc(count);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	if (ar->state != ATH10K_STATE_ON &&
-	    ar->state != ATH10K_STATE_UTF) {
-		ret = -ENETDOWN;
-		goto exit;
-	}
-
-	ret = copy_from_user(buf, user_buf, count);
-	if (ret) {
-		ret = -EFAULT;
-		goto exit;
-	}
-
-	ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
-	if (ret) {
-		ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
-			    (u32)(*ppos), ret);
-		goto exit;
-	}
-
-	*ppos += count;
-	ret = count;
-
-exit:
-	vfree(buf);
-	mutex_unlock(&ar->conf_mutex);
-
-	return ret;
-}
-
-static const struct file_operations fops_mem_value = {
-	.read = ath10k_mem_value_read,
-	.write = ath10k_mem_value_write,
-	.open = simple_open,
-	.owner = THIS_MODULE,
-	.llseek = default_llseek,
-};
-
 static int ath10k_debug_htt_stats_req(struct ath10k *ar)
 {
 	u64 cookie;
@@ -1362,166 +1030,6 @@
 	return ret;
 }
 
-/* TODO:  Would be nice to always support ethtool stats, would need to
- * move the stats storage out of ath10k_debug, or always have ath10k_debug
- * struct available..
- */
-
-/* This generally cooresponds to the debugfs fw_stats file */
-static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
-	"tx_pkts_nic",
-	"tx_bytes_nic",
-	"rx_pkts_nic",
-	"rx_bytes_nic",
-	"d_noise_floor",
-	"d_cycle_count",
-	"d_phy_error",
-	"d_rts_bad",
-	"d_rts_good",
-	"d_tx_power", /* in .5 dbM I think */
-	"d_rx_crc_err", /* fcs_bad */
-	"d_no_beacon",
-	"d_tx_mpdus_queued",
-	"d_tx_msdu_queued",
-	"d_tx_msdu_dropped",
-	"d_local_enqued",
-	"d_local_freed",
-	"d_tx_ppdu_hw_queued",
-	"d_tx_ppdu_reaped",
-	"d_tx_fifo_underrun",
-	"d_tx_ppdu_abort",
-	"d_tx_mpdu_requed",
-	"d_tx_excessive_retries",
-	"d_tx_hw_rate",
-	"d_tx_dropped_sw_retries",
-	"d_tx_illegal_rate",
-	"d_tx_continuous_xretries",
-	"d_tx_timeout",
-	"d_tx_mpdu_txop_limit",
-	"d_pdev_resets",
-	"d_rx_mid_ppdu_route_change",
-	"d_rx_status",
-	"d_rx_extra_frags_ring0",
-	"d_rx_extra_frags_ring1",
-	"d_rx_extra_frags_ring2",
-	"d_rx_extra_frags_ring3",
-	"d_rx_msdu_htt",
-	"d_rx_mpdu_htt",
-	"d_rx_msdu_stack",
-	"d_rx_mpdu_stack",
-	"d_rx_phy_err",
-	"d_rx_phy_err_drops",
-	"d_rx_mpdu_errors", /* FCS, MIC, ENC */
-	"d_fw_crash_count",
-	"d_fw_warm_reset_count",
-	"d_fw_cold_reset_count",
-};
-
-#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
-
-void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif,
-				 u32 sset, u8 *data)
-{
-	if (sset == ETH_SS_STATS)
-		memcpy(data, *ath10k_gstrings_stats,
-		       sizeof(ath10k_gstrings_stats));
-}
-
-int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif, int sset)
-{
-	if (sset == ETH_SS_STATS)
-		return ATH10K_SSTATS_LEN;
-
-	return 0;
-}
-
-void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       struct ethtool_stats *stats, u64 *data)
-{
-	struct ath10k *ar = hw->priv;
-	static const struct ath10k_fw_stats_pdev zero_stats = {};
-	const struct ath10k_fw_stats_pdev *pdev_stats;
-	int i = 0, ret;
-
-	mutex_lock(&ar->conf_mutex);
-
-	if (ar->state == ATH10K_STATE_ON) {
-		ret = ath10k_debug_fw_stats_request(ar);
-		if (ret) {
-			/* just print a warning and try to use older results */
-			ath10k_warn(ar,
-				    "failed to get fw stats for ethtool: %d\n",
-				    ret);
-		}
-	}
-
-	pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
-					      struct ath10k_fw_stats_pdev,
-					      list);
-	if (!pdev_stats) {
-		/* no results available so just return zeroes */
-		pdev_stats = &zero_stats;
-	}
-
-	spin_lock_bh(&ar->data_lock);
-
-	data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
-	data[i++] = 0; /* tx bytes */
-	data[i++] = pdev_stats->htt_mpdus;
-	data[i++] = 0; /* rx bytes */
-	data[i++] = pdev_stats->ch_noise_floor;
-	data[i++] = pdev_stats->cycle_count;
-	data[i++] = pdev_stats->phy_err_count;
-	data[i++] = pdev_stats->rts_bad;
-	data[i++] = pdev_stats->rts_good;
-	data[i++] = pdev_stats->chan_tx_power;
-	data[i++] = pdev_stats->fcs_bad;
-	data[i++] = pdev_stats->no_beacons;
-	data[i++] = pdev_stats->mpdu_enqued;
-	data[i++] = pdev_stats->msdu_enqued;
-	data[i++] = pdev_stats->wmm_drop;
-	data[i++] = pdev_stats->local_enqued;
-	data[i++] = pdev_stats->local_freed;
-	data[i++] = pdev_stats->hw_queued;
-	data[i++] = pdev_stats->hw_reaped;
-	data[i++] = pdev_stats->underrun;
-	data[i++] = pdev_stats->tx_abort;
-	data[i++] = pdev_stats->mpdus_requed;
-	data[i++] = pdev_stats->tx_ko;
-	data[i++] = pdev_stats->data_rc;
-	data[i++] = pdev_stats->sw_retry_failure;
-	data[i++] = pdev_stats->illgl_rate_phy_err;
-	data[i++] = pdev_stats->pdev_cont_xretry;
-	data[i++] = pdev_stats->pdev_tx_timeout;
-	data[i++] = pdev_stats->txop_ovf;
-	data[i++] = pdev_stats->pdev_resets;
-	data[i++] = pdev_stats->mid_ppdu_route_change;
-	data[i++] = pdev_stats->status_rcvd;
-	data[i++] = pdev_stats->r0_frags;
-	data[i++] = pdev_stats->r1_frags;
-	data[i++] = pdev_stats->r2_frags;
-	data[i++] = pdev_stats->r3_frags;
-	data[i++] = pdev_stats->htt_msdus;
-	data[i++] = pdev_stats->htt_mpdus;
-	data[i++] = pdev_stats->loc_msdus;
-	data[i++] = pdev_stats->loc_mpdus;
-	data[i++] = pdev_stats->phy_errs;
-	data[i++] = pdev_stats->phy_err_drop;
-	data[i++] = pdev_stats->mpdu_errs;
-	data[i++] = ar->stats.fw_crash_counter;
-	data[i++] = ar->stats.fw_warm_reset_counter;
-	data[i++] = ar->stats.fw_cold_reset_counter;
-
-	spin_unlock_bh(&ar->data_lock);
-
-	mutex_unlock(&ar->conf_mutex);
-
-	WARN_ON(i != ATH10K_SSTATS_LEN);
-}
-
 static const struct file_operations fops_fw_dbglog = {
 	.read = ath10k_read_fw_dbglog,
 	.write = ath10k_write_fw_dbglog,
@@ -1530,84 +1038,6 @@
 	.llseek = default_llseek,
 };
 
-static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
-{
-	struct ath10k *ar = inode->i_private;
-	void *buf;
-	u32 hi_addr;
-	__le32 addr;
-	int ret;
-
-	mutex_lock(&ar->conf_mutex);
-
-	if (ar->state != ATH10K_STATE_ON &&
-	    ar->state != ATH10K_STATE_UTF) {
-		ret = -ENETDOWN;
-		goto err;
-	}
-
-	buf = vmalloc(QCA988X_CAL_DATA_LEN);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
-
-	ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
-	if (ret) {
-		ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
-		goto err_vfree;
-	}
-
-	ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
-				   QCA988X_CAL_DATA_LEN);
-	if (ret) {
-		ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
-		goto err_vfree;
-	}
-
-	file->private_data = buf;
-
-	mutex_unlock(&ar->conf_mutex);
-
-	return 0;
-
-err_vfree:
-	vfree(buf);
-
-err:
-	mutex_unlock(&ar->conf_mutex);
-
-	return ret;
-}
-
-static ssize_t ath10k_debug_cal_data_read(struct file *file,
-					  char __user *user_buf,
-					  size_t count, loff_t *ppos)
-{
-	void *buf = file->private_data;
-
-	return simple_read_from_buffer(user_buf, count, ppos,
-				       buf, QCA988X_CAL_DATA_LEN);
-}
-
-static int ath10k_debug_cal_data_release(struct inode *inode,
-					 struct file *file)
-{
-	vfree(file->private_data);
-
-	return 0;
-}
-
-static const struct file_operations fops_cal_data = {
-	.open = ath10k_debug_cal_data_open,
-	.read = ath10k_debug_cal_data_read,
-	.release = ath10k_debug_cal_data_release,
-	.owner = THIS_MODULE,
-	.llseek = default_llseek,
-};
-
 int ath10k_debug_start(struct ath10k *ar)
 {
 	int ret;
@@ -1628,22 +1058,7 @@
 				    ret);
 	}
 
-	if (ar->debug.pktlog_filter) {
-		ret = ath10k_wmi_pdev_pktlog_enable(ar,
-						    ar->debug.pktlog_filter);
-		if (ret)
-			/* not serious */
-			ath10k_warn(ar,
-				    "failed to enable pktlog filter %x: %d\n",
-				    ar->debug.pktlog_filter, ret);
-	} else {
-		ret = ath10k_wmi_pdev_pktlog_disable(ar);
-		if (ret)
-			/* not serious */
-			ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
-	}
-
-	return ret;
+	return 0;
 }
 
 void ath10k_debug_stop(struct ath10k *ar)
@@ -1658,8 +1073,6 @@
 
 	ar->debug.htt_max_amsdu = 0;
 	ar->debug.htt_max_ampdu = 0;
-
-	ath10k_wmi_pdev_pktlog_disable(ar);
 }
 
 static ssize_t ath10k_write_simulate_radar(struct file *file,
@@ -1742,78 +1155,12 @@
 	.llseek = default_llseek,
 };
 
-static ssize_t ath10k_write_pktlog_filter(struct file *file,
-					  const char __user *ubuf,
-					  size_t count, loff_t *ppos)
-{
-	struct ath10k *ar = file->private_data;
-	u32 filter;
-	int ret;
-
-	if (kstrtouint_from_user(ubuf, count, 0, &filter))
-		return -EINVAL;
-
-	mutex_lock(&ar->conf_mutex);
-
-	if (ar->state != ATH10K_STATE_ON) {
-		ar->debug.pktlog_filter = filter;
-		ret = count;
-		goto out;
-	}
-
-	if (filter && (filter != ar->debug.pktlog_filter)) {
-		ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
-		if (ret) {
-			ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
-				    ar->debug.pktlog_filter, ret);
-			goto out;
-		}
-	} else {
-		ret = ath10k_wmi_pdev_pktlog_disable(ar);
-		if (ret) {
-			ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
-			goto out;
-		}
-	}
-
-	ar->debug.pktlog_filter = filter;
-	ret = count;
-
-out:
-	mutex_unlock(&ar->conf_mutex);
-	return ret;
-}
-
-static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
-					 size_t count, loff_t *ppos)
-{
-	char buf[32];
-	struct ath10k *ar = file->private_data;
-	int len = 0;
-
-	mutex_lock(&ar->conf_mutex);
-	len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
-			ar->debug.pktlog_filter);
-	mutex_unlock(&ar->conf_mutex);
-
-	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
-}
-
-static const struct file_operations fops_pktlog_filter = {
-	.read = ath10k_read_pktlog_filter,
-	.write = ath10k_write_pktlog_filter,
-	.open = simple_open
-};
-
 int ath10k_debug_create(struct ath10k *ar)
 {
 	ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
 	if (!ar->debug.fw_crash_data)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
-	INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
-
 	return 0;
 }
 
@@ -1821,8 +1168,6 @@
 {
 	vfree(ar->debug.fw_crash_data);
 	ar->debug.fw_crash_data = NULL;
-
-	ath10k_debug_fw_stats_reset(ar);
 }
 
 int ath10k_debug_register(struct ath10k *ar)
@@ -1839,14 +1184,11 @@
 	INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
 			  ath10k_debug_htt_stats_dwork);
 
-	init_completion(&ar->debug.fw_stats_complete);
+	init_completion(&ar->debug.event_stats_compl);
 
 	debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
 			    &fops_fw_stats);
 
-	debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
-			    ar, &fops_fw_reset_stats);
-
 	debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
 			    &fops_wmi_services);
 
@@ -1856,15 +1198,6 @@
 	debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_fw_crash_dump);
 
-	debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
-			    ar->debug.debugfs_phy, ar, &fops_reg_addr);
-
-	debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
-			    ar->debug.debugfs_phy, ar, &fops_reg_value);
-
-	debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
-			    ar->debug.debugfs_phy, ar, &fops_mem_value);
-
 	debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_chip_id);
 
@@ -1878,9 +1211,6 @@
 	debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_fw_dbglog);
 
-	debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
-			    ar, &fops_cal_data);
-
 	if (config_enabled(CPTCFG_ATH10K_DFS_CERTIFIED)) {
 		debugfs_create_file("dfs_simulate_radar", S_IWUSR,
 				    ar->debug.debugfs_phy, ar,
@@ -1895,9 +1225,6 @@
 				    &fops_dfs_stats);
 	}
 
-	debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
-			    ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
-
 	return 0;
 }
 
@@ -1934,26 +1261,11 @@
 		     const char *msg, const char *prefix,
 		     const void *buf, size_t len)
 {
-	char linebuf[256];
-	unsigned int linebuflen;
-	const void *ptr;
-
 	if (ath10k_debug_mask & mask) {
 		if (msg)
 			ath10k_dbg(ar, mask, "%s\n", msg);
 
-		for (ptr = buf; (ptr - buf) < len; ptr += 16) {
-			linebuflen = 0;
-			linebuflen += scnprintf(linebuf + linebuflen,
-						sizeof(linebuf) - linebuflen,
-						"%s%08x: ",
-						(prefix ? prefix : ""),
-						(unsigned int)(ptr - buf));
-			hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
-					   linebuf + linebuflen,
-					   sizeof(linebuf) - linebuflen, true);
-			dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
-		}
+		print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
 	}
 
 	/* tracing code doesn't like null strings :/ */
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index d9408e6..06923b4 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -35,27 +35,17 @@
 	ATH10K_DBG_BMI		= 0x00000400,
 	ATH10K_DBG_REGULATORY	= 0x00000800,
 	ATH10K_DBG_TESTMODE	= 0x00001000,
-	ATH10K_DBG_WMI_PRINT	= 0x00002000,
 	ATH10K_DBG_ANY		= 0xffffffff,
 
 	// Use high bit so conflicts are less likely with upstream updates.
 	ATH10K_DBG_BEACON	= 0x10000000,
 };
 
-enum ath10k_pktlog_filter {
-	ATH10K_PKTLOG_RX         = 0x000000001,
-	ATH10K_PKTLOG_TX         = 0x000000002,
-	ATH10K_PKTLOG_RCFIND     = 0x000000004,
-	ATH10K_PKTLOG_RCUPDATE   = 0x000000008,
-	ATH10K_PKTLOG_DBG_PRINT  = 0x000000010,
-	ATH10K_PKTLOG_ANY        = 0x00000001f,
-};
-
 extern unsigned int ath10k_debug_mask;
 
-__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
-__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
-__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) int ath10k_info(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) int ath10k_err(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) int ath10k_warn(struct ath10k *ar, const char *fmt, ...);
 void ath10k_print_driver_info(struct ath10k *ar);
 
 #ifdef CPTCFG_ATH10K_DEBUGFS
@@ -65,21 +55,17 @@
 void ath10k_debug_destroy(struct ath10k *ar);
 int ath10k_debug_register(struct ath10k *ar);
 void ath10k_debug_unregister(struct ath10k *ar);
-void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_debug_read_service_map(struct ath10k *ar,
+				   void *service_map,
+				   size_t map_size);
+void ath10k_debug_read_target_stats(struct ath10k *ar,
+				    struct wmi_stats_event *ev);
 struct ath10k_fw_crash_data *
 ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
 
 void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
-#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
 
-void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif,
-				 u32 sset, u8 *data);
-int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif, int sset);
-void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       struct ethtool_stats *stats, u64 *data);
+#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
 
 #else
 static inline int ath10k_debug_start(struct ath10k *ar)
@@ -109,8 +95,14 @@
 {
 }
 
-static inline void ath10k_debug_fw_stats_process(struct ath10k *ar,
-						 struct sk_buff *skb)
+static inline void ath10k_debug_read_service_map(struct ath10k *ar,
+						 void *service_map,
+						 size_t map_size)
+{
+}
+
+static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
+						  struct wmi_stats_event *ev)
 {
 }
 
@@ -127,10 +119,6 @@
 
 #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
 
-#define ath10k_debug_get_et_strings NULL
-#define ath10k_debug_get_et_sset_count NULL
-#define ath10k_debug_get_et_stats NULL
-
 #endif /* CPTCFG_ATH10K_DEBUGFS */
 
 #ifdef CPTCFG_ATH10K_DEBUG
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 0c92e02..62323fe 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -20,7 +20,6 @@
 
 #include <linux/kernel.h>
 #include "core.h"
-#include "debug.h"
 
 struct ath10k_hif_sg_item {
 	u16 transfer_id;
@@ -32,9 +31,11 @@
 
 struct ath10k_hif_cb {
 	int (*tx_completion)(struct ath10k *ar,
-			     struct sk_buff *wbuf);
+			     struct sk_buff *wbuf,
+			     unsigned transfer_id);
 	int (*rx_completion)(struct ath10k *ar,
-			     struct sk_buff *wbuf);
+			     struct sk_buff *wbuf,
+			     u8 pipe_id);
 };
 
 struct ath10k_hif_ops {
@@ -42,12 +43,6 @@
 	int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
 		     struct ath10k_hif_sg_item *items, int n_items);
 
-	/* read firmware memory through the diagnose interface */
-	int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
-			 size_t buf_len);
-
-	int (*diag_write)(struct ath10k *ar, u32 address, const void *data,
-			  int nbytes);
 	/*
 	 * API to handle HIF-specific BMI message exchanges, this API is
 	 * synchronous and only allowed to be called from a context that
@@ -85,10 +80,6 @@
 
 	u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
 
-	u32 (*read32)(struct ath10k *ar, u32 address);
-
-	void (*write32)(struct ath10k *ar, u32 address, u32 value);
-
 	/* Power up the device and enter BMI transfer mode for FW download */
 	int (*power_up)(struct ath10k *ar);
 
@@ -107,21 +98,6 @@
 	return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
 }
 
-static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
-				       size_t buf_len)
-{
-	return ar->hif.ops->diag_read(ar, address, buf, buf_len);
-}
-
-static inline int ath10k_hif_diag_write(struct ath10k *ar, u32 address,
-					const void *data, int nbytes)
-{
-	if (!ar->hif.ops->diag_write)
-		return -EOPNOTSUPP;
-
-	return ar->hif.ops->diag_write(ar, address, data, nbytes);
-}
-
 static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
 					      void *request, u32 request_len,
 					      void *response, u32 *response_len)
@@ -201,25 +177,4 @@
 	return ar->hif.ops->resume(ar);
 }
 
-static inline u32 ath10k_hif_read32(struct ath10k *ar, u32 address)
-{
-	if (!ar->hif.ops->read32) {
-		ath10k_warn(ar, "hif read32 not supported\n");
-		return 0xdeaddead;
-	}
-
-	return ar->hif.ops->read32(ar, address);
-}
-
-static inline void ath10k_hif_write32(struct ath10k *ar,
-				      u32 address, u32 data)
-{
-	if (!ar->hif.ops->write32) {
-		ath10k_warn(ar, "hif write32 not supported\n");
-		return;
-	}
-
-	ar->hif.ops->write32(ar, address, data);
-}
-
 #endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 580917b..769d594 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -165,7 +165,6 @@
 
 	ath10k_htc_prepare_tx_skb(ep, skb);
 
-	skb_cb->eid = eid;
 	skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
 	ret = dma_mapping_error(dev, skb_cb->paddr);
 	if (ret)
@@ -203,18 +202,15 @@
 }
 
 static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
-					    struct sk_buff *skb)
+					    struct sk_buff *skb,
+					    unsigned int eid)
 {
 	struct ath10k_htc *htc = &ar->htc;
-	struct ath10k_skb_cb *skb_cb;
-	struct ath10k_htc_ep *ep;
+	struct ath10k_htc_ep *ep = &htc->endpoint[eid];
 
 	if (WARN_ON_ONCE(!skb))
 		return 0;
 
-	skb_cb = ATH10K_SKB_CB(skb);
-	ep = &htc->endpoint[skb_cb->eid];
-
 	ath10k_htc_notify_tx_completion(ep, skb);
 	/* the skb now belongs to the completion handler */
 
@@ -326,7 +322,8 @@
 }
 
 static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
-					    struct sk_buff *skb)
+					    struct sk_buff *skb,
+					    u8 pipe_id)
 {
 	int status = 0;
 	struct ath10k_htc *htc = &ar->htc;
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 1bd0dbf..063fdeb 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -126,7 +126,6 @@
  *                  (HL hosts manage queues on the host )
  *       more_in_batch: only for HL hosts. indicates if more packets are
  *                      pending. this allows target to wait and aggregate
- *       freq: 0 means home channel of given vdev. intended for offchannel
  */
 struct htt_data_tx_desc {
 	u8 flags0; /* %HTT_DATA_TX_DESC_FLAGS0_ */
@@ -134,8 +133,7 @@
 	__le16 len;
 	__le16 id;
 	__le32 frags_paddr;
-	__le16 peerid;
-	__le16 freq;
+	__le32 peerid;
 	u8 prefetch[0]; /* start of frame, for FW classification engine */
 } __packed;
 
@@ -158,9 +156,6 @@
 	HTT_RX_RING_FLAGS_PHY_DATA_RX  = 1 << 15
 };
 
-#define HTT_RX_RING_SIZE_MIN 128
-#define HTT_RX_RING_SIZE_MAX 2048
-
 struct htt_rx_ring_setup_ring {
 	__le32 fw_idx_shadow_reg_paddr;
 	__le32 rx_ring_base_paddr;
@@ -730,7 +725,7 @@
  */
 struct htt_pktlog_msg {
 	u8 pad[3];
-	u8 payload[0];
+	__le32 payload[1 /* or more */];
 } __packed;
 
 struct htt_dbg_stats_rx_reorder_stats {
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index b999d3f..18fa269 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -25,8 +25,19 @@
 
 #include <linux/log2.h>
 
-#define HTT_RX_RING_SIZE 1024
-#define HTT_RX_RING_FILL_LEVEL 1000
+/* slightly larger than one large A-MPDU */
+#define HTT_RX_RING_SIZE_MIN 128
+
+/* roughly 20 ms @ 1 Gbps of 1500B MSDUs */
+#define HTT_RX_RING_SIZE_MAX 2048
+
+#define HTT_RX_AVG_FRM_BYTES 1000
+
+/* ms, very conservative */
+#define HTT_RX_HOST_LATENCY_MAX_MS 20
+
+/* ms, conservative */
+#define HTT_RX_HOST_LATENCY_WORST_LIKELY_MS 10
 
 /* when under memory pressure rx ring refill may fail and needs a retry */
 #define HTT_RX_RING_REFILL_RETRY_MS 50
@@ -34,6 +45,68 @@
 static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
 static void ath10k_htt_txrx_compl_task(unsigned long ptr);
 
+static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt)
+{
+	int size;
+
+	/*
+	 * It is expected that the host CPU will typically be able to
+	 * service the rx indication from one A-MPDU before the rx
+	 * indication from the subsequent A-MPDU happens, roughly 1-2 ms
+	 * later. However, the rx ring should be sized very conservatively,
+	 * to accomodate the worst reasonable delay before the host CPU
+	 * services a rx indication interrupt.
+	 *
+	 * The rx ring need not be kept full of empty buffers. In theory,
+	 * the htt host SW can dynamically track the low-water mark in the
+	 * rx ring, and dynamically adjust the level to which the rx ring
+	 * is filled with empty buffers, to dynamically meet the desired
+	 * low-water mark.
+	 *
+	 * In contrast, it's difficult to resize the rx ring itself, once
+	 * it's in use. Thus, the ring itself should be sized very
+	 * conservatively, while the degree to which the ring is filled
+	 * with empty buffers should be sized moderately conservatively.
+	 */
+
+	/* 1e6 bps/mbps / 1e3 ms per sec = 1000 */
+	size =
+	    htt->max_throughput_mbps *
+	    1000  /
+	    (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_MAX_MS;
+
+	if (size < HTT_RX_RING_SIZE_MIN)
+		size = HTT_RX_RING_SIZE_MIN;
+
+	if (size > HTT_RX_RING_SIZE_MAX)
+		size = HTT_RX_RING_SIZE_MAX;
+
+	size = roundup_pow_of_two(size);
+
+	return size;
+}
+
+static int ath10k_htt_rx_ring_fill_level(struct ath10k_htt *htt)
+{
+	int size;
+
+	/* 1e6 bps/mbps / 1e3 ms per sec = 1000 */
+	size =
+	    htt->max_throughput_mbps *
+	    1000  /
+	    (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_WORST_LIKELY_MS;
+
+	/*
+	 * Make sure the fill level is at least 1 less than the ring size.
+	 * Leaving 1 element empty allows the SW to easily distinguish
+	 * between a full ring vs. an empty ring.
+	 */
+	if (size >= htt->rx_ring.size)
+		size = htt->rx_ring.size - 1;
+
+	return size;
+}
+
 static void ath10k_htt_rx_ring_free(struct ath10k_htt *htt)
 {
 	struct sk_buff *skb;
@@ -223,38 +296,50 @@
 	htt->rx_ring.sw_rd_idx.msdu_payld = idx;
 	htt->rx_ring.fill_cnt--;
 
-	dma_unmap_single(htt->ar->dev,
-			 ATH10K_SKB_CB(msdu)->paddr,
-			 msdu->len + skb_tailroom(msdu),
-			 DMA_FROM_DEVICE);
-	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ",
-			msdu->data, msdu->len + skb_tailroom(msdu));
-
 	return msdu;
 }
 
+static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb)
+{
+	struct sk_buff *next;
+
+	while (skb) {
+		next = skb->next;
+		dev_kfree_skb_any(skb);
+		skb = next;
+	}
+}
+
 /* return: < 0 fatal error, 0 - non chained msdu, 1 chained msdu */
 static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 				   u8 **fw_desc, int *fw_desc_len,
-				   struct sk_buff_head *amsdu)
+				   struct sk_buff **head_msdu,
+				   struct sk_buff **tail_msdu,
+				   u32 *attention)
 {
 	struct ath10k *ar = htt->ar;
 	int msdu_len, msdu_chaining = 0;
-	struct sk_buff *msdu;
+	struct sk_buff *msdu, *next;
 	struct htt_rx_desc *rx_desc;
 
 	lockdep_assert_held(&htt->rx_ring.lock);
 
-	for (;;) {
+	if (htt->rx_confused) {
+		ath10k_warn(ar, "htt is confused. refusing rx\n");
+		return -1;
+	}
+
+	msdu = *head_msdu = ath10k_htt_rx_netbuf_pop(htt);
+	while (msdu) {
 		int last_msdu, msdu_len_invalid, msdu_chained;
 
-		msdu = ath10k_htt_rx_netbuf_pop(htt);
-		if (!msdu) {
-			__skb_queue_purge(amsdu);
-			return -ENOENT;
-		}
+		dma_unmap_single(htt->ar->dev,
+				 ATH10K_SKB_CB(msdu)->paddr,
+				 msdu->len + skb_tailroom(msdu),
+				 DMA_FROM_DEVICE);
 
-		__skb_queue_tail(amsdu, msdu);
+		ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ",
+				msdu->data, msdu->len + skb_tailroom(msdu));
 
 		rx_desc = (struct htt_rx_desc *)msdu->data;
 
@@ -273,10 +358,19 @@
 		 */
 		if (!(__le32_to_cpu(rx_desc->attention.flags)
 				& RX_ATTENTION_FLAGS_MSDU_DONE)) {
-			__skb_queue_purge(amsdu);
-			return -EIO;
+			ath10k_htt_rx_free_msdu_chain(*head_msdu);
+			*head_msdu = NULL;
+			msdu = NULL;
+			ath10k_err(ar, "htt rx stopped. cannot recover\n");
+			htt->rx_confused = true;
+			break;
 		}
 
+		*attention |= __le32_to_cpu(rx_desc->attention.flags) &
+					    (RX_ATTENTION_FLAGS_TKIP_MIC_ERR |
+					     RX_ATTENTION_FLAGS_DECRYPT_ERR |
+					     RX_ATTENTION_FLAGS_FCS_ERR |
+					     RX_ATTENTION_FLAGS_MGMT_TYPE);
 		/*
 		 * Copy the FW rx descriptor for this MSDU from the rx
 		 * indication message into the MSDU's netbuf. HL uses the
@@ -333,32 +427,43 @@
 		skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE));
 		msdu_len -= msdu->len;
 
-		/* Note: Chained buffers do not contain rx descriptor */
+		/* FIXME: Do chained buffers include htt_rx_desc or not? */
 		while (msdu_chained--) {
-			msdu = ath10k_htt_rx_netbuf_pop(htt);
-			if (!msdu) {
-				__skb_queue_purge(amsdu);
-				return -ENOENT;
-			}
+			struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);
 
-			__skb_queue_tail(amsdu, msdu);
-			skb_trim(msdu, 0);
-			skb_put(msdu, min(msdu_len, HTT_RX_BUF_SIZE));
-			msdu_len -= msdu->len;
+			dma_unmap_single(htt->ar->dev,
+					 ATH10K_SKB_CB(next)->paddr,
+					 next->len + skb_tailroom(next),
+					 DMA_FROM_DEVICE);
+
+			ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
+					"htt rx chained: ", next->data,
+					next->len + skb_tailroom(next));
+
+			skb_trim(next, 0);
+			skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE));
+			msdu_len -= next->len;
+
+			msdu->next = next;
+			msdu = next;
 			msdu_chaining = 1;
 		}
 
 		last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
 				RX_MSDU_END_INFO0_LAST_MSDU;
 
-		trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
-					 sizeof(*rx_desc) - sizeof(u32));
-
-		if (last_msdu)
+		if (last_msdu) {
+			msdu->next = NULL;
 			break;
-	}
+		}
 
-	if (skb_queue_empty(amsdu))
+		next = ath10k_htt_rx_netbuf_pop(htt);
+		msdu->next = next;
+		msdu = next;
+	}
+	*tail_msdu = msdu;
+
+	if (*head_msdu == NULL)
 		msdu_chaining = -1;
 
 	/*
@@ -392,20 +497,25 @@
 	size_t size;
 	struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
 
-	htt->rx_confused = false;
-
-	/* XXX: The fill level could be changed during runtime in response to
-	 * the host processing latency. Is this really worth it?
-	 */
-	htt->rx_ring.size = HTT_RX_RING_SIZE;
-	htt->rx_ring.size_mask = htt->rx_ring.size - 1;
-	htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL;
-
+	htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
 	if (!is_power_of_2(htt->rx_ring.size)) {
 		ath10k_warn(ar, "htt rx ring size is not power of 2\n");
 		return -EINVAL;
 	}
 
+	htt->rx_ring.size_mask = htt->rx_ring.size - 1;
+
+	/*
+	 * Set the initial value for the level to which the rx ring
+	 * should be filled, based on the max throughput and the
+	 * worst likely latency for the host to fill the rx ring
+	 * with new buffers. In theory, this fill level can be
+	 * dynamically adjusted from the initial value set here, to
+	 * reflect the actual host latency rather than a
+	 * conservative assumption about the host latency.
+	 */
+	htt->rx_ring.fill_level = ath10k_htt_rx_ring_fill_level(htt);
+
 	htt->rx_ring.netbufs_ring =
 		kzalloc(htt->rx_ring.size * sizeof(struct sk_buff *),
 			GFP_KERNEL|__GFP_REPEAT|__GFP_HIGH);
@@ -477,50 +587,73 @@
 					  enum htt_rx_mpdu_encrypt_type type)
 {
 	switch (type) {
-	case HTT_RX_MPDU_ENCRYPT_NONE:
-		return 0;
 	case HTT_RX_MPDU_ENCRYPT_WEP40:
 	case HTT_RX_MPDU_ENCRYPT_WEP104:
-		return IEEE80211_WEP_IV_LEN;
+		return 4;
 	case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
+	case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */
 	case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
-		return IEEE80211_TKIP_IV_LEN;
+	case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */
 	case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
-		return IEEE80211_CCMP_HDR_LEN;
-	case HTT_RX_MPDU_ENCRYPT_WEP128:
-	case HTT_RX_MPDU_ENCRYPT_WAPI:
-		break;
+		return 8;
+	case HTT_RX_MPDU_ENCRYPT_NONE:
+		return 0;
 	}
 
-	ath10k_warn(ar, "unsupported encryption type %d\n", type);
+	ath10k_warn(ar, "unknown encryption type %d\n", type);
 	return 0;
 }
 
-#define MICHAEL_MIC_LEN 8
-
 static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
 					 enum htt_rx_mpdu_encrypt_type type)
 {
 	switch (type) {
 	case HTT_RX_MPDU_ENCRYPT_NONE:
-		return 0;
 	case HTT_RX_MPDU_ENCRYPT_WEP40:
 	case HTT_RX_MPDU_ENCRYPT_WEP104:
-		return IEEE80211_WEP_ICV_LEN;
-	case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
-	case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
-		return IEEE80211_TKIP_ICV_LEN;
-	case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
-		return IEEE80211_CCMP_MIC_LEN;
 	case HTT_RX_MPDU_ENCRYPT_WEP128:
 	case HTT_RX_MPDU_ENCRYPT_WAPI:
-		break;
+		return 0;
+	case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
+	case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
+		return 4;
+	case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
+		return 8;
 	}
 
-	ath10k_warn(ar, "unsupported encryption type %d\n", type);
+	ath10k_warn(ar, "unknown encryption type %d\n", type);
 	return 0;
 }
 
+/* Applies for first msdu in chain, before altering it. */
+static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb)
+{
+	struct htt_rx_desc *rxd;
+	enum rx_msdu_decap_format fmt;
+
+	rxd = (void *)skb->data - sizeof(*rxd);
+	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
+		 RX_MSDU_START_INFO1_DECAP_FORMAT);
+
+	if (fmt == RX_MSDU_DECAP_RAW)
+		return (void *)skb->data;
+
+	return (void *)skb->data - RX_HTT_HDR_STATUS_LEN;
+}
+
+/* This function only applies for first msdu in an msdu chain */
+static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr)
+{
+	u8 *qc;
+
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		if (qc[0] & 0x80)
+			return true;
+	}
+	return false;
+}
+
 struct rfc1042_hdr {
 	u8 llc_dsap;
 	u8 llc_ssap;
@@ -555,34 +688,23 @@
 };
 
 static void ath10k_htt_rx_h_rates(struct ath10k *ar,
-				  struct ieee80211_rx_status *status,
-				  struct htt_rx_desc *rxd)
+				  enum ieee80211_band band,
+				  u8 info0, u32 info1, u32 info2,
+				  struct ieee80211_rx_status *status)
 {
-	enum ieee80211_band band;
 	u8 cck, rate, rate_idx, bw, sgi, mcs, nss;
 	u8 preamble = 0;
-	u32 info1, info2, info3;
 
-	/* Band value can't be set as undefined but freq can be 0 - use that to
-	 * determine whether band is provided.
-	 *
-	 * FIXME: Perhaps this can go away if CCK rate reporting is a little
-	 * reworked?
-	 */
-	if (!status->freq)
+	/* Check if valid fields */
+	if (!(info0 & HTT_RX_INDICATION_INFO0_START_VALID))
 		return;
 
-	band = status->band;
-	info1 = __le32_to_cpu(rxd->ppdu_start.info1);
-	info2 = __le32_to_cpu(rxd->ppdu_start.info2);
-	info3 = __le32_to_cpu(rxd->ppdu_start.info3);
-
-	preamble = MS(info1, RX_PPDU_START_INFO1_PREAMBLE_TYPE);
+	preamble = MS(info1, HTT_RX_INDICATION_INFO1_PREAMBLE_TYPE);
 
 	switch (preamble) {
 	case HTT_RX_LEGACY:
-		cck = info1 & RX_PPDU_START_INFO1_L_SIG_RATE_SELECT;
-		rate = MS(info1, RX_PPDU_START_INFO1_L_SIG_RATE);
+		cck = info0 & HTT_RX_INDICATION_INFO0_LEGACY_RATE_CCK;
+		rate = MS(info0, HTT_RX_INDICATION_INFO0_LEGACY_RATE);
 		rate_idx = 0;
 
 		if (rate < 0x08 || rate > 0x0F)
@@ -609,11 +731,11 @@
 		break;
 	case HTT_RX_HT:
 	case HTT_RX_HT_WITH_TXBF:
-		/* HT-SIG - Table 20-11 in info2 and info3 */
-		mcs = info2 & 0x1F;
+		/* HT-SIG - Table 20-11 in info1 and info2 */
+		mcs = info1 & 0x1F;
 		nss = mcs >> 3;
-		bw = (info2 >> 7) & 1;
-		sgi = (info3 >> 7) & 1;
+		bw = (info1 >> 7) & 1;
+		sgi = (info2 >> 7) & 1;
 
 		status->rate_idx = mcs;
 		status->flag |= RX_FLAG_HT;
@@ -624,12 +746,12 @@
 		break;
 	case HTT_RX_VHT:
 	case HTT_RX_VHT_WITH_TXBF:
-		/* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3
+		/* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2
 		   TODO check this */
-		mcs = (info3 >> 4) & 0x0F;
-		nss = ((info2 >> 10) & 0x07) + 1;
-		bw = info2 & 3;
-		sgi = info3 & 1;
+		mcs = (info2 >> 4) & 0x0F;
+		nss = ((info1 >> 10) & 0x07) + 1;
+		bw = info1 & 3;
+		sgi = info2 & 1;
 
 		status->rate_idx = mcs;
 		status->vht_nss = nss;
@@ -657,6 +779,41 @@
 	}
 }
 
+static void ath10k_htt_rx_h_protected(struct ath10k_htt *htt,
+				      struct ieee80211_rx_status *rx_status,
+				      struct sk_buff *skb,
+				      enum htt_rx_mpdu_encrypt_type enctype,
+				      enum rx_msdu_decap_format fmt,
+				      bool dot11frag)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+	rx_status->flag &= ~(RX_FLAG_DECRYPTED |
+			     RX_FLAG_IV_STRIPPED |
+			     RX_FLAG_MMIC_STRIPPED);
+
+	if (enctype == HTT_RX_MPDU_ENCRYPT_NONE)
+		return;
+
+	/*
+	 * There's no explicit rx descriptor flag to indicate whether a given
+	 * frame has been decrypted or not. We're forced to use the decap
+	 * format as an implicit indication. However fragmentation rx is always
+	 * raw and it probably never reports undecrypted raws.
+	 *
+	 * This makes sure sniffed frames are reported as-is without stripping
+	 * the protected flag.
+	 */
+	if (fmt == RX_MSDU_DECAP_RAW && !dot11frag)
+		return;
+
+	rx_status->flag |= RX_FLAG_DECRYPTED |
+			   RX_FLAG_IV_STRIPPED |
+			   RX_FLAG_MMIC_STRIPPED;
+	hdr->frame_control = __cpu_to_le16(__le16_to_cpu(hdr->frame_control) &
+					   ~IEEE80211_FCTL_PROTECTED);
+}
+
 static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
 				    struct ieee80211_rx_status *status)
 {
@@ -677,72 +834,6 @@
 	return true;
 }
 
-static void ath10k_htt_rx_h_signal(struct ath10k *ar,
-				   struct ieee80211_rx_status *status,
-				   struct htt_rx_desc *rxd)
-{
-	/* FIXME: Get real NF */
-	status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
-			 rxd->ppdu_start.rssi_comb;
-	status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
-}
-
-static void ath10k_htt_rx_h_mactime(struct ath10k *ar,
-				    struct ieee80211_rx_status *status,
-				    struct htt_rx_desc *rxd)
-{
-	/* FIXME: TSF is known only at the end of PPDU, in the last MPDU. This
-	 * means all prior MSDUs in a PPDU are reported to mac80211 without the
-	 * TSF. Is it worth holding frames until end of PPDU is known?
-	 *
-	 * FIXME: Can we get/compute 64bit TSF?
-	 */
-	status->mactime = __le32_to_cpu(rxd->ppdu_end.tsf_timestamp);
-	status->flag |= RX_FLAG_MACTIME_END;
-}
-
-static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
-				 struct sk_buff_head *amsdu,
-				 struct ieee80211_rx_status *status)
-{
-	struct sk_buff *first;
-	struct htt_rx_desc *rxd;
-	bool is_first_ppdu;
-	bool is_last_ppdu;
-
-	if (skb_queue_empty(amsdu))
-		return;
-
-	first = skb_peek(amsdu);
-	rxd = (void *)first->data - sizeof(*rxd);
-
-	is_first_ppdu = !!(rxd->attention.flags &
-			   __cpu_to_le32(RX_ATTENTION_FLAGS_FIRST_MPDU));
-	is_last_ppdu = !!(rxd->attention.flags &
-			  __cpu_to_le32(RX_ATTENTION_FLAGS_LAST_MPDU));
-
-	if (is_first_ppdu) {
-		/* New PPDU starts so clear out the old per-PPDU status. */
-		status->freq = 0;
-		status->rate_idx = 0;
-		status->vht_nss = 0;
-		status->vht_flag &= ~RX_VHT_FLAG_80MHZ;
-		status->flag &= ~(RX_FLAG_HT |
-				  RX_FLAG_VHT |
-				  RX_FLAG_SHORT_GI |
-				  RX_FLAG_40MHZ |
-				  RX_FLAG_MACTIME_END);
-		status->flag |= RX_FLAG_NO_SIGNAL_VAL;
-
-		ath10k_htt_rx_h_signal(ar, status, rxd);
-		ath10k_htt_rx_h_channel(ar, status);
-		ath10k_htt_rx_h_rates(ar, status, rxd);
-	}
-
-	if (is_last_ppdu)
-		ath10k_htt_rx_h_mactime(ar, status, rxd);
-}
-
 static const char * const tid_to_ac[] = {
 	"BE",
 	"BK",
@@ -807,8 +898,6 @@
 		   !!(status->flag & RX_FLAG_AMSDU_MORE));
 	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
 			skb->data, skb->len);
-	trace_ath10k_rx_hdr(ar, skb->data, skb->len);
-	trace_ath10k_rx_payload(ar, skb->data, skb->len);
 
 	ieee80211_rx(ar->hw, skb);
 }
@@ -819,263 +908,187 @@
 	return round_up(ieee80211_hdrlen(hdr->frame_control), 4);
 }
 
-static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
-					struct sk_buff *msdu,
-					struct ieee80211_rx_status *status,
-					enum htt_rx_mpdu_encrypt_type enctype,
-					bool is_decrypted)
+static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
+				struct ieee80211_rx_status *rx_status,
+				struct sk_buff *skb_in)
 {
-	struct ieee80211_hdr *hdr;
+	struct ath10k *ar = htt->ar;
 	struct htt_rx_desc *rxd;
-	size_t hdr_len;
-	size_t crypto_len;
-	bool is_first;
-	bool is_last;
-
-	rxd = (void *)msdu->data - sizeof(*rxd);
-	is_first = !!(rxd->msdu_end.info0 &
-		      __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
-	is_last = !!(rxd->msdu_end.info0 &
-		     __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
-
-	/* Delivered decapped frame:
-	 * [802.11 header]
-	 * [crypto param] <-- can be trimmed if !fcs_err &&
-	 *                    !decrypt_err && !peer_idx_invalid
-	 * [amsdu header] <-- only if A-MSDU
-	 * [rfc1042/llc]
-	 * [payload]
-	 * [FCS] <-- at end, needs to be trimmed
-	 */
-
-	/* This probably shouldn't happen but warn just in case */
-	if (unlikely(WARN_ON_ONCE(!is_first)))
-		return;
-
-	/* This probably shouldn't happen but warn just in case */
-	if (unlikely(WARN_ON_ONCE(!(is_first && is_last))))
-		return;
-
-	skb_trim(msdu, msdu->len - FCS_LEN);
-
-	/* In most cases this will be true for sniffed frames. It makes sense
-	 * to deliver them as-is without stripping the crypto param. This would
-	 * also make sense for software based decryption (which is not
-	 * implemented in ath10k).
-	 *
-	 * If there's no error then the frame is decrypted. At least that is
-	 * the case for frames that come in via fragmented rx indication.
-	 */
-	if (!is_decrypted)
-		return;
-
-	/* The payload is decrypted so strip crypto params. Start from tail
-	 * since hdr is used to compute some stuff.
-	 */
-
-	hdr = (void *)msdu->data;
-
-	/* Tail */
-	skb_trim(msdu, msdu->len - ath10k_htt_rx_crypto_tail_len(ar, enctype));
-
-	/* MMIC */
-	if (!ieee80211_has_morefrags(hdr->frame_control) &&
-	    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
-		skb_trim(msdu, msdu->len - 8);
-
-	/* Head */
-	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-	crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
-
-	memmove((void *)msdu->data + crypto_len,
-		(void *)msdu->data, hdr_len);
-	skb_pull(msdu, crypto_len);
-}
-
-static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
-					  struct sk_buff *msdu,
-					  struct ieee80211_rx_status *status,
-					  const u8 first_hdr[64])
-{
+	struct sk_buff *skb = skb_in;
+	struct sk_buff *first;
+	enum rx_msdu_decap_format fmt;
+	enum htt_rx_mpdu_encrypt_type enctype;
 	struct ieee80211_hdr *hdr;
-	size_t hdr_len;
-	u8 da[ETH_ALEN];
-	u8 sa[ETH_ALEN];
+	u8 hdr_buf[64], da[ETH_ALEN], sa[ETH_ALEN], *qos;
+	unsigned int hdr_len;
 
-	/* Delivered decapped frame:
-	 * [nwifi 802.11 header] <-- replaced with 802.11 hdr
-	 * [rfc1042/llc]
-	 *
-	 * Note: The nwifi header doesn't have QoS Control and is
-	 * (always?) a 3addr frame.
-	 *
-	 * Note2: There's no A-MSDU subframe header. Even if it's part
-	 * of an A-MSDU.
-	 */
+	rxd = (void *)skb->data - sizeof(*rxd);
+	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
 
-	/* pull decapped header and copy SA & DA */
-	hdr = (struct ieee80211_hdr *)msdu->data;
-	hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
-	ether_addr_copy(da, ieee80211_get_DA(hdr));
-	ether_addr_copy(sa, ieee80211_get_SA(hdr));
-	skb_pull(msdu, hdr_len);
-
-	/* push original 802.11 header */
-	hdr = (struct ieee80211_hdr *)first_hdr;
+	hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
 	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-	memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
+	memcpy(hdr_buf, hdr, hdr_len);
+	hdr = (struct ieee80211_hdr *)hdr_buf;
 
-	/* original 802.11 header has a different DA and in
-	 * case of 4addr it may also have different SA
-	 */
-	hdr = (struct ieee80211_hdr *)msdu->data;
-	ether_addr_copy(ieee80211_get_DA(hdr), da);
-	ether_addr_copy(ieee80211_get_SA(hdr), sa);
-}
+	first = skb;
+	while (skb) {
+		void *decap_hdr;
+		int len;
 
-static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar,
-					  struct sk_buff *msdu,
-					  enum htt_rx_mpdu_encrypt_type enctype)
-{
-	struct ieee80211_hdr *hdr;
-	struct htt_rx_desc *rxd;
-	size_t hdr_len, crypto_len;
-	void *rfc1042;
-	bool is_first, is_last, is_amsdu;
+		rxd = (void *)skb->data - sizeof(*rxd);
+		fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
+			 RX_MSDU_START_INFO1_DECAP_FORMAT);
+		decap_hdr = (void *)rxd->rx_hdr_status;
 
-	rxd = (void *)msdu->data - sizeof(*rxd);
-	hdr = (void *)rxd->rx_hdr_status;
+		skb->ip_summed = ath10k_htt_rx_get_csum_state(skb);
 
-	is_first = !!(rxd->msdu_end.info0 &
-		      __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
-	is_last = !!(rxd->msdu_end.info0 &
-		     __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
-	is_amsdu = !(is_first && is_last);
+		/* First frame in an A-MSDU chain has more decapped data. */
+		if (skb == first) {
+			len = round_up(ieee80211_hdrlen(hdr->frame_control), 4);
+			len += round_up(ath10k_htt_rx_crypto_param_len(ar,
+						enctype), 4);
+			decap_hdr += len;
+		}
 
-	rfc1042 = hdr;
+		switch (fmt) {
+		case RX_MSDU_DECAP_RAW:
+			/* remove trailing FCS */
+			skb_trim(skb, skb->len - FCS_LEN);
+			break;
+		case RX_MSDU_DECAP_NATIVE_WIFI:
+			/* pull decapped header and copy SA & DA */
+			hdr = (struct ieee80211_hdr *)skb->data;
+			hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
+			ether_addr_copy(da, ieee80211_get_DA(hdr));
+			ether_addr_copy(sa, ieee80211_get_SA(hdr));
+			skb_pull(skb, hdr_len);
 
-	if (is_first) {
-		hdr_len = ieee80211_hdrlen(hdr->frame_control);
-		crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
+			/* push original 802.11 header */
+			hdr = (struct ieee80211_hdr *)hdr_buf;
+			hdr_len = ieee80211_hdrlen(hdr->frame_control);
+			memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
 
-		rfc1042 += round_up(hdr_len, 4) +
-			   round_up(crypto_len, 4);
+			/* original A-MSDU header has the bit set but we're
+			 * not including A-MSDU subframe header */
+			hdr = (struct ieee80211_hdr *)skb->data;
+			qos = ieee80211_get_qos_ctl(hdr);
+			qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+
+			/* original 802.11 header has a different DA and in
+			 * case of 4addr it may also have different SA
+			 */
+			ether_addr_copy(ieee80211_get_DA(hdr), da);
+			ether_addr_copy(ieee80211_get_SA(hdr), sa);
+			break;
+		case RX_MSDU_DECAP_ETHERNET2_DIX:
+			/* strip ethernet header and insert decapped 802.11
+			 * header, amsdu subframe header and rfc1042 header */
+
+			len = 0;
+			len += sizeof(struct rfc1042_hdr);
+			len += sizeof(struct amsdu_subframe_hdr);
+
+			skb_pull(skb, sizeof(struct ethhdr));
+			memcpy(skb_push(skb, len), decap_hdr, len);
+			memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
+			break;
+		case RX_MSDU_DECAP_8023_SNAP_LLC:
+			/* insert decapped 802.11 header making a singly
+			 * A-MSDU */
+			memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
+			break;
+		}
+
+		skb_in = skb;
+		ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype, fmt,
+					  false);
+		skb = skb->next;
+		skb_in->next = NULL;
+
+		if (skb)
+			rx_status->flag |= RX_FLAG_AMSDU_MORE;
+		else
+			rx_status->flag &= ~RX_FLAG_AMSDU_MORE;
+
+		ath10k_process_rx(htt->ar, rx_status, skb_in);
 	}
 
-	if (is_amsdu)
-		rfc1042 += sizeof(struct amsdu_subframe_hdr);
-
-	return rfc1042;
+	/* FIXME: It might be nice to re-assemble the A-MSDU when there's a
+	 * monitor interface active for sniffing purposes. */
 }
 
-static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
-					struct sk_buff *msdu,
-					struct ieee80211_rx_status *status,
-					const u8 first_hdr[64],
-					enum htt_rx_mpdu_encrypt_type enctype)
+static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
+			       struct ieee80211_rx_status *rx_status,
+			       struct sk_buff *skb)
 {
-	struct ieee80211_hdr *hdr;
-	struct ethhdr *eth;
-	size_t hdr_len;
-	void *rfc1042;
-	u8 da[ETH_ALEN];
-	u8 sa[ETH_ALEN];
-
-	/* Delivered decapped frame:
-	 * [eth header] <-- replaced with 802.11 hdr & rfc1042/llc
-	 * [payload]
-	 */
-
-	rfc1042 = ath10k_htt_rx_h_find_rfc1042(ar, msdu, enctype);
-	if (WARN_ON_ONCE(!rfc1042))
-		return;
-
-	/* pull decapped header and copy SA & DA */
-	eth = (struct ethhdr *)msdu->data;
-	ether_addr_copy(da, eth->h_dest);
-	ether_addr_copy(sa, eth->h_source);
-	skb_pull(msdu, sizeof(struct ethhdr));
-
-	/* push rfc1042/llc/snap */
-	memcpy(skb_push(msdu, sizeof(struct rfc1042_hdr)), rfc1042,
-	       sizeof(struct rfc1042_hdr));
-
-	/* push original 802.11 header */
-	hdr = (struct ieee80211_hdr *)first_hdr;
-	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-	memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
-
-	/* original 802.11 header has a different DA and in
-	 * case of 4addr it may also have different SA
-	 */
-	hdr = (struct ieee80211_hdr *)msdu->data;
-	ether_addr_copy(ieee80211_get_DA(hdr), da);
-	ether_addr_copy(ieee80211_get_SA(hdr), sa);
-}
-
-static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
-					 struct sk_buff *msdu,
-					 struct ieee80211_rx_status *status,
-					 const u8 first_hdr[64])
-{
-	struct ieee80211_hdr *hdr;
-	size_t hdr_len;
-
-	/* Delivered decapped frame:
-	 * [amsdu header] <-- replaced with 802.11 hdr
-	 * [rfc1042/llc]
-	 * [payload]
-	 */
-
-	skb_pull(msdu, sizeof(struct amsdu_subframe_hdr));
-
-	hdr = (struct ieee80211_hdr *)first_hdr;
-	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-	memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
-}
-
-static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
-				    struct sk_buff *msdu,
-				    struct ieee80211_rx_status *status,
-				    u8 first_hdr[64],
-				    enum htt_rx_mpdu_encrypt_type enctype,
-				    bool is_decrypted)
-{
+	struct ath10k *ar = htt->ar;
 	struct htt_rx_desc *rxd;
-	enum rx_msdu_decap_format decap;
 	struct ieee80211_hdr *hdr;
+	enum rx_msdu_decap_format fmt;
+	enum htt_rx_mpdu_encrypt_type enctype;
+	int hdr_len;
+	void *rfc1042;
 
-	/* First msdu's decapped header:
-	 * [802.11 header] <-- padded to 4 bytes long
-	 * [crypto param] <-- padded to 4 bytes long
-	 * [amsdu header] <-- only if A-MSDU
-	 * [rfc1042/llc]
-	 *
-	 * Other (2nd, 3rd, ..) msdu's decapped header:
-	 * [amsdu header] <-- only if A-MSDU
-	 * [rfc1042/llc]
-	 */
+	/* This shouldn't happen. If it does than it may be a FW bug. */
+	if (skb->next) {
+		ath10k_warn(ar, "htt rx received chained non A-MSDU frame\n");
+		ath10k_htt_rx_free_msdu_chain(skb->next);
+		skb->next = NULL;
+	}
 
-	rxd = (void *)msdu->data - sizeof(*rxd);
-	hdr = (void *)rxd->rx_hdr_status;
-	decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
-		   RX_MSDU_START_INFO1_DECAP_FORMAT);
+	rxd = (void *)skb->data - sizeof(*rxd);
+	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
+		 RX_MSDU_START_INFO1_DECAP_FORMAT);
+	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+	hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
+	hdr_len = ieee80211_hdrlen(hdr->frame_control);
 
-	switch (decap) {
+	skb->ip_summed = ath10k_htt_rx_get_csum_state(skb);
+
+	switch (fmt) {
 	case RX_MSDU_DECAP_RAW:
-		ath10k_htt_rx_h_undecap_raw(ar, msdu, status, enctype,
-					    is_decrypted);
+		/* remove trailing FCS */
+		skb_trim(skb, skb->len - FCS_LEN);
 		break;
 	case RX_MSDU_DECAP_NATIVE_WIFI:
-		ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr);
+		/* Pull decapped header */
+		hdr = (struct ieee80211_hdr *)skb->data;
+		hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
+		skb_pull(skb, hdr_len);
+
+		/* Push original header */
+		hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
+		hdr_len = ieee80211_hdrlen(hdr->frame_control);
+		memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
 		break;
 	case RX_MSDU_DECAP_ETHERNET2_DIX:
-		ath10k_htt_rx_h_undecap_eth(ar, msdu, status, first_hdr, enctype);
+		/* strip ethernet header and insert decapped 802.11 header and
+		 * rfc1042 header */
+
+		rfc1042 = hdr;
+		rfc1042 += roundup(hdr_len, 4);
+		rfc1042 += roundup(ath10k_htt_rx_crypto_param_len(ar,
+					enctype), 4);
+
+		skb_pull(skb, sizeof(struct ethhdr));
+		memcpy(skb_push(skb, sizeof(struct rfc1042_hdr)),
+		       rfc1042, sizeof(struct rfc1042_hdr));
+		memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
 		break;
 	case RX_MSDU_DECAP_8023_SNAP_LLC:
-		ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr);
+		/* remove A-MSDU subframe header and insert
+		 * decapped 802.11 header. rfc1042 header is already there */
+
+		skb_pull(skb, sizeof(struct amsdu_subframe_hdr));
+		memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
 		break;
 	}
+
+	ath10k_htt_rx_h_protected(htt, rx_status, skb, enctype, fmt, false);
+
+	ath10k_process_rx(htt->ar, rx_status, skb);
 }
 
 static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
@@ -1109,128 +1122,10 @@
 	return CHECKSUM_UNNECESSARY;
 }
 
-static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
+static int ath10k_unchain_msdu(struct sk_buff *msdu_head)
 {
-	msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
-}
-
-static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
-				 struct sk_buff_head *amsdu,
-				 struct ieee80211_rx_status *status)
-{
-	struct sk_buff *first;
-	struct sk_buff *last;
-	struct sk_buff *msdu;
-	struct htt_rx_desc *rxd;
-	struct ieee80211_hdr *hdr;
-	enum htt_rx_mpdu_encrypt_type enctype;
-	u8 first_hdr[64];
-	u8 *qos;
-	size_t hdr_len;
-	bool has_fcs_err;
-	bool has_crypto_err;
-	bool has_tkip_err;
-	bool has_peer_idx_invalid;
-	bool is_decrypted;
-	u32 attention;
-
-	if (skb_queue_empty(amsdu))
-		return;
-
-	first = skb_peek(amsdu);
-	rxd = (void *)first->data - sizeof(*rxd);
-
-	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
-		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
-
-	/* First MSDU's Rx descriptor in an A-MSDU contains full 802.11
-	 * decapped header. It'll be used for undecapping of each MSDU.
-	 */
-	hdr = (void *)rxd->rx_hdr_status;
-	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-	memcpy(first_hdr, hdr, hdr_len);
-
-	/* Each A-MSDU subframe will use the original header as the base and be
-	 * reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl.
-	 */
-	hdr = (void *)first_hdr;
-	qos = ieee80211_get_qos_ctl(hdr);
-	qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
-
-	/* Some attention flags are valid only in the last MSDU. */
-	last = skb_peek_tail(amsdu);
-	rxd = (void *)last->data - sizeof(*rxd);
-	attention = __le32_to_cpu(rxd->attention.flags);
-
-	has_fcs_err = !!(attention & RX_ATTENTION_FLAGS_FCS_ERR);
-	has_crypto_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
-	has_tkip_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
-	has_peer_idx_invalid = !!(attention & RX_ATTENTION_FLAGS_PEER_IDX_INVALID);
-
-	/* Note: If hardware captures an encrypted frame that it can't decrypt,
-	 * e.g. due to fcs error, missing peer or invalid key data it will
-	 * report the frame as raw.
-	 */
-	is_decrypted = (enctype != HTT_RX_MPDU_ENCRYPT_NONE &&
-			!has_fcs_err &&
-			!has_crypto_err &&
-			!has_peer_idx_invalid);
-
-	/* Clear per-MPDU flags while leaving per-PPDU flags intact. */
-	status->flag &= ~(RX_FLAG_FAILED_FCS_CRC |
-			  RX_FLAG_MMIC_ERROR |
-			  RX_FLAG_DECRYPTED |
-			  RX_FLAG_IV_STRIPPED |
-			  RX_FLAG_MMIC_STRIPPED);
-
-	if (has_fcs_err)
-		status->flag |= RX_FLAG_FAILED_FCS_CRC;
-
-	if (has_tkip_err)
-		status->flag |= RX_FLAG_MMIC_ERROR;
-
-	if (is_decrypted)
-		status->flag |= RX_FLAG_DECRYPTED |
-				RX_FLAG_IV_STRIPPED |
-				RX_FLAG_MMIC_STRIPPED;
-
-	skb_queue_walk(amsdu, msdu) {
-		ath10k_htt_rx_h_csum_offload(msdu);
-		ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
-					is_decrypted);
-
-		/* Undecapping involves copying the original 802.11 header back
-		 * to sk_buff. If frame is protected and hardware has decrypted
-		 * it then remove the protected bit.
-		 */
-		if (!is_decrypted)
-			continue;
-
-		hdr = (void *)msdu->data;
-		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-	}
-}
-
-static void ath10k_htt_rx_h_deliver(struct ath10k *ar,
-				    struct sk_buff_head *amsdu,
-				    struct ieee80211_rx_status *status)
-{
-	struct sk_buff *msdu;
-
-	while ((msdu = __skb_dequeue(amsdu))) {
-		/* Setup per-MSDU flags */
-		if (skb_queue_empty(amsdu))
-			status->flag &= ~RX_FLAG_AMSDU_MORE;
-		else
-			status->flag |= RX_FLAG_AMSDU_MORE;
-
-		ath10k_process_rx(ar, status, msdu);
-	}
-}
-
-static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
-{
-	struct sk_buff *skb, *first;
+	struct sk_buff *next = msdu_head->next;
+	struct sk_buff *to_free = next;
 	int space;
 	int total_len = 0;
 
@@ -1241,142 +1136,113 @@
 	 * skb?
 	 */
 
-	first = __skb_dequeue(amsdu);
+	msdu_head->next = NULL;
 
 	/* Allocate total length all at once. */
-	skb_queue_walk(amsdu, skb)
-		total_len += skb->len;
+	while (next) {
+		total_len += next->len;
+		next = next->next;
+	}
 
-	space = total_len - skb_tailroom(first);
+	space = total_len - skb_tailroom(msdu_head);
 	if ((space > 0) &&
-	    (pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0)) {
+	    (pskb_expand_head(msdu_head, 0, space, GFP_ATOMIC) < 0)) {
 		/* TODO:  bump some rx-oom error stat */
 		/* put it back together so we can free the
 		 * whole list at once.
 		 */
-		__skb_queue_head(amsdu, first);
+		msdu_head->next = to_free;
 		return -1;
 	}
 
 	/* Walk list again, copying contents into
 	 * msdu_head
 	 */
-	while ((skb = __skb_dequeue(amsdu))) {
-		skb_copy_from_linear_data(skb, skb_put(first, skb->len),
-					  skb->len);
-		dev_kfree_skb_any(skb);
+	next = to_free;
+	while (next) {
+		skb_copy_from_linear_data(next, skb_put(msdu_head, next->len),
+					  next->len);
+		next = next->next;
 	}
 
-	__skb_queue_head(amsdu, first);
+	/* If here, we have consolidated skb.  Free the
+	 * fragments and pass the main skb on up the
+	 * stack.
+	 */
+	ath10k_htt_rx_free_msdu_chain(to_free);
 	return 0;
 }
 
-static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
-				    struct sk_buff_head *amsdu,
-				    bool chained)
+static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
+					struct sk_buff *head,
+					enum htt_rx_mpdu_status status,
+					bool channel_set,
+					u32 attention)
 {
-	struct sk_buff *first;
-	struct htt_rx_desc *rxd;
-	enum rx_msdu_decap_format decap;
+	struct ath10k *ar = htt->ar;
 
-	first = skb_peek(amsdu);
-	rxd = (void *)first->data - sizeof(*rxd);
-	decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
-		   RX_MSDU_START_INFO1_DECAP_FORMAT);
-
-	if (!chained)
-		return;
-
-	/* FIXME: Current unchaining logic can only handle simple case of raw
-	 * msdu chaining. If decapping is other than raw the chaining may be
-	 * more complex and this isn't handled by the current code. Don't even
-	 * try re-constructing such frames - it'll be pretty much garbage.
-	 */
-	if (decap != RX_MSDU_DECAP_RAW ||
-	    skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) {
-		__skb_queue_purge(amsdu);
-		return;
-	}
-
-	ath10k_unchain_msdu(amsdu);
-}
-
-static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
-					struct sk_buff_head *amsdu,
-					struct ieee80211_rx_status *rx_status)
-{
-	struct sk_buff *msdu;
-	struct htt_rx_desc *rxd;
-	bool is_mgmt;
-	bool has_fcs_err;
-
-	msdu = skb_peek(amsdu);
-	rxd = (void *)msdu->data - sizeof(*rxd);
-
-	/* FIXME: It might be a good idea to do some fuzzy-testing to drop
-	 * invalid/dangerous frames.
-	 */
-
-	if (!rx_status->freq) {
-		ath10k_warn(ar, "no channel configured; ignoring frame(s)!\n");
+	if (head->len == 0) {
+		ath10k_dbg(ar, ATH10K_DBG_HTT,
+			   "htt rx dropping due to zero-len\n");
 		return false;
 	}
 
-	is_mgmt = !!(rxd->attention.flags &
-		     __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE));
-	has_fcs_err = !!(rxd->attention.flags &
-			 __cpu_to_le32(RX_ATTENTION_FLAGS_FCS_ERR));
+	if (attention & RX_ATTENTION_FLAGS_DECRYPT_ERR) {
+		ath10k_dbg(ar, ATH10K_DBG_HTT,
+			   "htt rx dropping due to decrypt-err\n");
+		return false;
+	}
 
-	/* Management frames are handled via WMI events. The pros of such
-	 * approach is that channel is explicitly provided in WMI events
-	 * whereas HTT doesn't provide channel information for Rxed frames.
-	 *
-	 * However some firmware revisions don't report corrupted frames via
-	 * WMI so don't drop them.
-	 */
-	if (is_mgmt && !has_fcs_err) {
+	if (!channel_set) {
+		ath10k_warn(ar, "no channel configured; ignoring frame!\n");
+		return false;
+	}
+
+	/* Skip mgmt frames while we handle this in WMI */
+	if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL ||
+	    attention & RX_ATTENTION_FLAGS_MGMT_TYPE) {
 		ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
 		return false;
 	}
 
-	if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
-		ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx cac running\n");
+	if (status != HTT_RX_IND_MPDU_STATUS_OK &&
+	    status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR &&
+	    status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER &&
+	    !htt->ar->monitor_started) {
+		ath10k_dbg(ar, ATH10K_DBG_HTT,
+			   "htt rx ignoring frame w/ status %d\n",
+			   status);
+		return false;
+	}
+
+	if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
+		ath10k_dbg(ar, ATH10K_DBG_HTT,
+			   "htt rx CAC running\n");
 		return false;
 	}
 
 	return true;
 }
 
-static void ath10k_htt_rx_h_filter(struct ath10k *ar,
-				   struct sk_buff_head *amsdu,
-				   struct ieee80211_rx_status *rx_status)
-{
-	if (skb_queue_empty(amsdu))
-		return;
-
-	if (ath10k_htt_rx_amsdu_allowed(ar, amsdu, rx_status))
-		return;
-
-	__skb_queue_purge(amsdu);
-}
-
 static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
 				  struct htt_rx_indication *rx)
 {
 	struct ath10k *ar = htt->ar;
 	struct ieee80211_rx_status *rx_status = &htt->rx_status;
 	struct htt_rx_indication_mpdu_range *mpdu_ranges;
-	struct sk_buff_head amsdu;
+	struct htt_rx_desc *rxd;
+	enum htt_rx_mpdu_status status;
+	struct ieee80211_hdr *hdr;
 	int num_mpdu_ranges;
+	u32 attention;
 	int fw_desc_len;
 	u8 *fw_desc;
-	int i, ret, mpdu_count = 0;
+	bool channel_set;
+	int i, j;
+	int ret;
 
 	lockdep_assert_held(&htt->rx_ring.lock);
 
-	if (htt->rx_confused)
-		return;
-
 	fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes);
 	fw_desc = (u8 *)&rx->fw_desc;
 
@@ -1384,33 +1250,92 @@
 			     HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
 	mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx);
 
+	/* Fill this once, while this is per-ppdu */
+	if (rx->ppdu.info0 & HTT_RX_INDICATION_INFO0_START_VALID) {
+		memset(rx_status, 0, sizeof(*rx_status));
+		rx_status->signal  = ATH10K_DEFAULT_NOISE_FLOOR +
+				     rx->ppdu.combined_rssi;
+	}
+
+	if (rx->ppdu.info0 & HTT_RX_INDICATION_INFO0_END_VALID) {
+		/* TSF available only in 32-bit */
+		rx_status->mactime = __le32_to_cpu(rx->ppdu.tsf) & 0xffffffff;
+		rx_status->flag |= RX_FLAG_MACTIME_END;
+	}
+
+	channel_set = ath10k_htt_rx_h_channel(htt->ar, rx_status);
+
+	if (channel_set) {
+		ath10k_htt_rx_h_rates(htt->ar, rx_status->band,
+				      rx->ppdu.info0,
+				      __le32_to_cpu(rx->ppdu.info1),
+				      __le32_to_cpu(rx->ppdu.info2),
+				      rx_status);
+	}
+
 	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ",
 			rx, sizeof(*rx) +
 			(sizeof(struct htt_rx_indication_mpdu_range) *
 				num_mpdu_ranges));
 
-	for (i = 0; i < num_mpdu_ranges; i++)
-		mpdu_count += mpdu_ranges[i].mpdu_count;
+	for (i = 0; i < num_mpdu_ranges; i++) {
+		status = mpdu_ranges[i].mpdu_range_status;
 
-	while (mpdu_count--) {
-		__skb_queue_head_init(&amsdu);
-		ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc,
-					      &fw_desc_len, &amsdu);
-		if (ret < 0) {
-			ath10k_warn(ar, "rx ring became corrupted: %d\n", ret);
-			__skb_queue_purge(&amsdu);
-			/* FIXME: It's probably a good idea to reboot the
-			 * device instead of leaving it inoperable.
-			 */
-			htt->rx_confused = true;
-			break;
+		for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
+			struct sk_buff *msdu_head, *msdu_tail;
+
+			attention = 0;
+			msdu_head = NULL;
+			msdu_tail = NULL;
+			ret = ath10k_htt_rx_amsdu_pop(htt,
+						      &fw_desc,
+						      &fw_desc_len,
+						      &msdu_head,
+						      &msdu_tail,
+						      &attention);
+
+			if (ret < 0) {
+				ath10k_warn(ar, "failed to pop amsdu from htt rx ring %d\n",
+					    ret);
+				ath10k_htt_rx_free_msdu_chain(msdu_head);
+				continue;
+			}
+
+			rxd = container_of((void *)msdu_head->data,
+					   struct htt_rx_desc,
+					   msdu_payload);
+
+			if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
+							 status,
+							 channel_set,
+							 attention)) {
+				ath10k_htt_rx_free_msdu_chain(msdu_head);
+				continue;
+			}
+
+			if (ret > 0 &&
+			    ath10k_unchain_msdu(msdu_head) < 0) {
+				ath10k_htt_rx_free_msdu_chain(msdu_head);
+				continue;
+			}
+
+			if (attention & RX_ATTENTION_FLAGS_FCS_ERR)
+				rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+			else
+				rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
+
+			if (attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR)
+				rx_status->flag |= RX_FLAG_MMIC_ERROR;
+			else
+				rx_status->flag &= ~RX_FLAG_MMIC_ERROR;
+
+			hdr = ath10k_htt_rx_skb_get_hdr(msdu_head);
+
+			if (ath10k_htt_rx_hdr_is_amsdu(hdr))
+				ath10k_htt_rx_amsdu(htt, rx_status, msdu_head);
+			else
+				ath10k_htt_rx_msdu(htt, rx_status, msdu_head);
 		}
-
-		ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
-		ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
-		ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
-		ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
-		ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
 	}
 
 	tasklet_schedule(&htt->rx_replenish_task);
@@ -1420,44 +1345,108 @@
 				       struct htt_rx_fragment_indication *frag)
 {
 	struct ath10k *ar = htt->ar;
+	struct sk_buff *msdu_head, *msdu_tail;
+	enum htt_rx_mpdu_encrypt_type enctype;
+	struct htt_rx_desc *rxd;
+	enum rx_msdu_decap_format fmt;
 	struct ieee80211_rx_status *rx_status = &htt->rx_status;
-	struct sk_buff_head amsdu;
+	struct ieee80211_hdr *hdr;
 	int ret;
+	bool tkip_mic_err;
+	bool decrypt_err;
 	u8 *fw_desc;
-	int fw_desc_len;
+	int fw_desc_len, hdrlen, paramlen;
+	int trim;
+	u32 attention = 0;
 
 	fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
 	fw_desc = (u8 *)frag->fw_msdu_rx_desc;
 
-	__skb_queue_head_init(&amsdu);
+	msdu_head = NULL;
+	msdu_tail = NULL;
 
 	spin_lock_bh(&htt->rx_ring.lock);
 	ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
-				      &amsdu);
+				      &msdu_head, &msdu_tail,
+				      &attention);
 	spin_unlock_bh(&htt->rx_ring.lock);
 
-	tasklet_schedule(&htt->rx_replenish_task);
-
 	ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
 
 	if (ret) {
 		ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n",
 			    ret);
-		__skb_queue_purge(&amsdu);
+		ath10k_htt_rx_free_msdu_chain(msdu_head);
 		return;
 	}
 
-	if (skb_queue_len(&amsdu) != 1) {
-		ath10k_warn(ar, "failed to pop frag amsdu: too many msdus\n");
-		__skb_queue_purge(&amsdu);
-		return;
+	/* FIXME: implement signal strength */
+	rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+
+	hdr = (struct ieee80211_hdr *)msdu_head->data;
+	rxd = (void *)msdu_head->data - sizeof(*rxd);
+	tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
+	decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
+	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
+		 RX_MSDU_START_INFO1_DECAP_FORMAT);
+
+	if (fmt != RX_MSDU_DECAP_RAW) {
+		ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n");
+		dev_kfree_skb_any(msdu_head);
+		goto end;
 	}
 
-	ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
-	ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
-	ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
-	ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
+	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+	ath10k_htt_rx_h_protected(htt, rx_status, msdu_head, enctype, fmt,
+				  true);
+	msdu_head->ip_summed = ath10k_htt_rx_get_csum_state(msdu_head);
 
+	if (tkip_mic_err)
+		ath10k_warn(ar, "tkip mic error\n");
+
+	if (decrypt_err) {
+		ath10k_warn(ar, "decryption err in fragmented rx\n");
+		dev_kfree_skb_any(msdu_head);
+		goto end;
+	}
+
+	if (enctype != HTT_RX_MPDU_ENCRYPT_NONE) {
+		hdrlen = ieee80211_hdrlen(hdr->frame_control);
+		paramlen = ath10k_htt_rx_crypto_param_len(ar, enctype);
+
+		/* It is more efficient to move the header than the payload */
+		memmove((void *)msdu_head->data + paramlen,
+			(void *)msdu_head->data,
+			hdrlen);
+		skb_pull(msdu_head, paramlen);
+		hdr = (struct ieee80211_hdr *)msdu_head->data;
+	}
+
+	/* remove trailing FCS */
+	trim  = 4;
+
+	/* remove crypto trailer */
+	trim += ath10k_htt_rx_crypto_tail_len(ar, enctype);
+
+	/* last fragment of TKIP frags has MIC */
+	if (!ieee80211_has_morefrags(hdr->frame_control) &&
+	    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
+		trim += 8;
+
+	if (trim > msdu_head->len) {
+		ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n");
+		dev_kfree_skb_any(msdu_head);
+		goto end;
+	}
+
+	skb_trim(msdu_head, msdu_head->len - trim);
+
+	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ",
+			msdu_head->data, msdu_head->len);
+	ath10k_process_rx(htt->ar, rx_status, msdu_head);
+
+end:
 	if (fw_desc_len > 0) {
 		ath10k_dbg(ar, ATH10K_DBG_HTT,
 			   "expecting more fragmented rx in one indication %d\n",
@@ -1685,15 +1674,6 @@
 	case HTT_T2H_MSG_TYPE_RX_DELBA:
 		ath10k_htt_rx_delba(ar, resp);
 		break;
-	case HTT_T2H_MSG_TYPE_PKTLOG: {
-		struct ath10k_pktlog_hdr *hdr =
-			(struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload;
-
-		trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload,
-					sizeof(*hdr) +
-					__le16_to_cpu(hdr->size));
-		break;
-	}
 	case HTT_T2H_MSG_TYPE_RX_FLUSH: {
 		/* Ignore this event because mac80211 takes care of Rx
 		 * aggregation reordering.
@@ -1701,8 +1681,8 @@
 		break;
 	}
 	default:
-		ath10k_warn(ar, "htt event (%d) not handled\n",
-			    resp->hdr.msg_type);
+		ath10k_dbg(ar, ATH10K_DBG_HTT, "htt event (%d) not handled\n",
+			   resp->hdr.msg_type);
 		ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
 				skb->data, skb->len);
 		break;
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index a0f8a0b..c6768e2 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -74,8 +74,8 @@
 {
 	struct ath10k *ar = htt->ar;
 	int tx_idx;
-
 	spin_lock_init(&htt->tx_msdu_pool_lock);
+	init_waitqueue_head(&htt->empty_tx_wq);
 
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features))
 		htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
@@ -549,18 +549,14 @@
 	skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
 	skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
 	skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
-	skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID);
-	skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq);
+	skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID);
 
-	trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
 	ath10k_dbg(ar, ATH10K_DBG_HTT,
-		   "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu freq %hu\n",
+		   "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n",
 		   flags0, flags1, msdu->len, msdu_id, frags_paddr,
-		   (u32)skb_cb->paddr, vdev_id, tid, skb_cb->htt.freq);
+		   (u32)skb_cb->paddr, vdev_id, tid);
 	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
 			msdu->data, msdu->len);
-	trace_ath10k_tx_hdr(ar, msdu->data, msdu->len);
-	trace_ath10k_tx_payload(ar, msdu->data, msdu->len);
 
 	sg_items[0].transfer_id = 0;
 	sg_items[0].transfer_context = NULL;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index dfedfd0..3cf5702 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -20,16 +20,15 @@
 
 #include "targaddrs.h"
 
-#define ATH10K_FW_DIR			"ath10k"
-
 /* QCA988X 1.0 definitions (unsupported) */
 #define QCA988X_HW_1_0_CHIP_ID_REV	0x0
 
 /* QCA988X 2.0 definitions */
 #define QCA988X_HW_2_0_VERSION		0x4100016c
 #define QCA988X_HW_2_0_CHIP_ID_REV	0x2
-#define QCA988X_HW_2_0_FW_DIR		ATH10K_FW_DIR "/QCA988X/hw2.0"
+#define QCA988X_HW_2_0_FW_DIR		"ath10k/QCA988X/hw2.0"
 #define QCA988X_HW_2_0_FW_FILE		"firmware.bin"
+#define QCA988X_HW_2_0_FW_3_FILE	"firmware-3.bin"
 #define QCA988X_HW_2_0_OTP_FILE		"otp.bin"
 #define QCA988X_HW_2_0_BOARD_DATA_FILE	"board.bin"
 #define QCA988X_HW_2_0_PATCH_LOAD_ADDR	0x1234
@@ -44,8 +43,6 @@
 
 #define REG_DUMP_COUNT_QCA988X 60
 
-#define QCA988X_CAL_DATA_LEN		2116
-
 struct ath10k_fw_ie {
 	__le32 id;
 	__le32 len;
@@ -81,15 +78,6 @@
 	ATH10K_MCAST2UCAST_ENABLED = 1,
 };
 
-struct ath10k_pktlog_hdr {
-	__le16 flags;
-	__le16 missed_cnt;
-	__le16 log_type;
-	__le16 size;
-	__le32 timestamp;
-	u8 payload[0];
-} __packed;
-
 /* Target specific defines for MAIN firmware */
 #define TARGET_NUM_VDEVS			8
 #define TARGET_NUM_PEER_AST			2
@@ -97,13 +85,11 @@
 #define TARGET_DMA_BURST_SIZE			0
 #define TARGET_MAC_AGGR_DELIM			0
 #define TARGET_AST_SKID_LIMIT			16
-#define TARGET_NUM_STATIONS			16
-#define TARGET_NUM_PEERS			((TARGET_NUM_STATIONS) + \
-						 (TARGET_NUM_VDEVS))
+#define TARGET_NUM_PEERS			16
 #define TARGET_NUM_OFFLOAD_PEERS		0
 #define TARGET_NUM_OFFLOAD_REORDER_BUFS         0
 #define TARGET_NUM_PEER_KEYS			2
-#define TARGET_NUM_TIDS				((TARGET_NUM_PEERS) * 2)
+#define TARGET_NUM_TIDS		(2 * ((TARGET_NUM_PEERS) + (TARGET_NUM_VDEVS)))
 #define TARGET_TX_CHAIN_MASK			(BIT(0) | BIT(1) | BIT(2))
 #define TARGET_RX_CHAIN_MASK			(BIT(0) | BIT(1) | BIT(2))
 #define TARGET_RX_TIMEOUT_LO_PRI		100
@@ -134,15 +120,12 @@
 #define TARGET_10X_DMA_BURST_SIZE		0
 #define TARGET_10X_MAC_AGGR_DELIM		0
 #define TARGET_10X_AST_SKID_LIMIT		16
-#define TARGET_10X_NUM_STATIONS			128
-#define TARGET_10X_NUM_PEERS			((TARGET_10X_NUM_STATIONS) + \
-						 (TARGET_10X_NUM_VDEVS))
+#define TARGET_10X_NUM_PEERS			(128 + (TARGET_10X_NUM_VDEVS))
+#define TARGET_10X_NUM_PEERS_MAX		128
 #define TARGET_10X_NUM_OFFLOAD_PEERS		0
 #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS	0
 #define TARGET_10X_NUM_PEER_KEYS		2
-#define TARGET_10X_NUM_TIDS_MAX			256
-#define TARGET_10X_NUM_TIDS			min((TARGET_10X_NUM_TIDS_MAX), \
-						    (TARGET_10X_NUM_PEERS) * 2)
+#define TARGET_10X_NUM_TIDS			256
 #define TARGET_10X_TX_CHAIN_MASK		(BIT(0) | BIT(1) | BIT(2))
 #define TARGET_10X_RX_CHAIN_MASK		(BIT(0) | BIT(1) | BIT(2))
 #define TARGET_10X_RX_TIMEOUT_LO_PRI		100
@@ -296,7 +279,6 @@
 #define SI_RX_DATA1_OFFSET			0x00000014
 
 #define CORE_CTRL_CPU_INTR_MASK			0x00002000
-#define CORE_CTRL_PCIE_REG_31_MASK		0x00000800
 #define CORE_CTRL_ADDRESS			0x0000
 #define PCIE_INTR_ENABLE_ADDRESS		0x0008
 #define PCIE_INTR_CAUSE_ADDRESS			0x000c
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 351235e..a001051 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -136,9 +136,7 @@
 		if (ret)
 			return ret;
 
-		spin_lock_bh(&ar->data_lock);
 		peer->keys[i] = arvif->wep_keys[i];
-		spin_unlock_bh(&ar->data_lock);
 	}
 
 	return 0;
@@ -175,39 +173,12 @@
 			ath10k_warn(ar, "failed to remove peer wep key %d: %d\n",
 				    i, ret);
 
-		spin_lock_bh(&ar->data_lock);
 		peer->keys[i] = NULL;
-		spin_unlock_bh(&ar->data_lock);
 	}
 
 	return first_errno;
 }
 
-bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
-				    u8 keyidx)
-{
-	struct ath10k_peer *peer;
-	int i;
-
-	lockdep_assert_held(&ar->data_lock);
-
-	/* We don't know which vdev this peer belongs to,
-	 * since WMI doesn't give us that information.
-	 *
-	 * FIXME: multi-bss needs to be handled.
-	 */
-	peer = ath10k_peer_find(ar, 0, addr);
-	if (!peer)
-		return false;
-
-	for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
-		if (peer->keys[i] && peer->keys[i]->keyidx == keyidx)
-			return true;
-	}
-
-	return false;
-}
-
 static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
 				 struct ieee80211_key_conf *key)
 {
@@ -351,30 +322,61 @@
 
 static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr)
 {
+	struct ath10k_peer *peer;
 	int ret;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	if (ar->num_peers >= ar->max_num_peers)
-		return -ENOBUFS;
+	peer = ath10k_peer_find(ar, vdev_id, addr);
+	if (peer) {
+		ath10k_warn(ar, "peer %pM on vdev %i already exists\n",
+			    addr, vdev_id);
+		return -EINVAL;
+	}
+
+	peer = kzalloc(sizeof(*peer), GFP_KERNEL);
+	if (!peer) {
+		ath10k_warn(ar, "failed to allocate peer %pM on vdev %i: not enough memory\n",
+			    addr, vdev_id);
+		return -ENOMEM;
+	}
+
+	peer->vdev_id = vdev_id;
+	memcpy(peer->addr, addr, ETH_ALEN);
+
+	spin_lock_bh(&ar->data_lock);
+	list_add(&peer->list, &ar->peers);
+	spin_unlock_bh(&ar->data_lock);
 
 	ret = ath10k_wmi_peer_create(ar, vdev_id, addr);
 	if (ret) {
 		ath10k_warn(ar, "failed to create wmi peer %pM on vdev %i: %i\n",
 			    addr, vdev_id, ret);
-		return ret;
+		goto err_free;
 	}
 
 	ret = ath10k_wait_for_peer_created(ar, vdev_id, addr);
 	if (ret) {
 		ath10k_warn(ar, "failed to wait for created wmi peer %pM on vdev %i: %i\n",
 			    addr, vdev_id, ret);
-		return ret;
+		goto err_free;
 	}
-
+	spin_lock_bh(&ar->data_lock);
 	ar->num_peers++;
+	spin_unlock_bh(&ar->data_lock);
 
 	return 0;
+
+err_free:
+	spin_lock_bh(&ar->data_lock);
+	list_del(&peer->list);
+	/* very unlikely, but check anyway */
+	if (!bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS))
+		ath10k_warn(ar, "removing peer %pM on vdev %i still being mapped in firmware\n",
+			    addr, vdev_id);
+	spin_unlock_bh(&ar->data_lock);
+	kfree(peer);
+	return ret;
 }
 
 static int ath10k_mac_set_kickout(struct ath10k_vif *arvif)
@@ -422,11 +424,15 @@
 	return 0;
 }
 
-static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
+static int  ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
 {
 	struct ath10k *ar = arvif->ar;
 	u32 vdev_param;
 
+	if (value != 0xFFFFFFFF)
+		value = min_t(u32, arvif->ar->hw->wiphy->rts_threshold,
+			      ATH10K_RTS_MAX);
+
 	vdev_param = ar->wmi.vdev_param->rts_threshold;
 	return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value);
 }
@@ -473,7 +479,9 @@
 		goto out;
 	}
 
+	spin_lock_bh(&ar->data_lock);
 	ar->num_peers--;
+	spin_unlock_bh(&ar->data_lock);
 
 out:
 	spin_lock_bh(&ar->data_lock);
@@ -520,59 +528,20 @@
 		list_del(&peer->list);
 		kfree(peer);
 	}
-	spin_unlock_bh(&ar->data_lock);
-
 	ar->num_peers = 0;
-	ar->num_stations = 0;
+	spin_unlock_bh(&ar->data_lock);
 }
 
 /************************/
 /* Interface management */
 /************************/
 
-void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif)
-{
-	struct ath10k *ar = arvif->ar;
-
-	lockdep_assert_held(&ar->data_lock);
-
-	if (!arvif->beacon)
-		return;
-
-	if (!arvif->beacon_buf)
-		dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr,
-				 arvif->beacon->len, DMA_TO_DEVICE);
-
-	dev_kfree_skb_any(arvif->beacon);
-
-	arvif->beacon = NULL;
-	arvif->beacon_sent = false;
-}
-
-static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif)
-{
-	struct ath10k *ar = arvif->ar;
-
-	lockdep_assert_held(&ar->data_lock);
-
-	ath10k_mac_vif_beacon_free(arvif);
-
-	if (arvif->beacon_buf) {
-		dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
-				  arvif->beacon_buf, arvif->beacon_paddr);
-		arvif->beacon_buf = NULL;
-	}
-}
-
 static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
 {
 	int ret;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
-		return -ESHUTDOWN;
-
 	ret = wait_for_completion_timeout(&ar->vdev_setup_done,
 					  ATH10K_VDEV_SETUP_TIMEOUT_HZ);
 	if (ret == 0)
@@ -605,8 +574,6 @@
 	arg.channel.max_reg_power = channel->max_reg_power * 2;
 	arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
 
-	reinit_completion(&ar->vdev_setup_done);
-
 	ret = ath10k_wmi_vdev_start(ar, &arg);
 	if (ret) {
 		ath10k_warn(ar, "failed to request monitor vdev %i start: %d\n",
@@ -654,8 +621,6 @@
 		ath10k_warn(ar, "failed to put down monitor vdev %i: %d\n",
 			    ar->monitor_vdev_id, ret);
 
-	reinit_completion(&ar->vdev_setup_done);
-
 	ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
 	if (ret)
 		ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n",
@@ -682,9 +647,9 @@
 		return -ENOMEM;
 	}
 
-	bit = __ffs64(ar->free_vdev_map);
+	bit = ffs(ar->free_vdev_map);
 
-	ar->monitor_vdev_id = bit;
+	ar->monitor_vdev_id = bit - 1;
 
 	ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id,
 				     WMI_VDEV_TYPE_MONITOR,
@@ -695,7 +660,7 @@
 		return ret;
 	}
 
-	ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
+	ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id);
 	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n",
 		   ar->monitor_vdev_id);
 
@@ -715,7 +680,7 @@
 		return ret;
 	}
 
-	ar->free_vdev_map |= 1LL << ar->monitor_vdev_id;
+	ar->free_vdev_map |= 1 << ar->monitor_vdev_id;
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n",
 		   ar->monitor_vdev_id);
@@ -1003,7 +968,15 @@
 		arvif->is_up = false;
 
 		spin_lock_bh(&arvif->ar->data_lock);
-		ath10k_mac_vif_beacon_free(arvif);
+		if (arvif->beacon) {
+			dma_unmap_single(arvif->ar->dev,
+					 ATH10K_SKB_CB(arvif->beacon)->paddr,
+					 arvif->beacon->len, DMA_TO_DEVICE);
+			dev_kfree_skb_any(arvif->beacon);
+
+			arvif->beacon = NULL;
+			arvif->beacon_sent = false;
+		}
 		spin_unlock_bh(&arvif->ar->data_lock);
 
 		return;
@@ -1052,6 +1025,14 @@
 		if (is_zero_ether_addr(arvif->bssid))
 			return;
 
+		ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id,
+					 arvif->bssid);
+		if (ret) {
+			ath10k_warn(ar, "failed to delete IBSS BSSID peer %pM for vdev %d: %d\n",
+				    arvif->bssid, arvif->vdev_id, ret);
+			return;
+		}
+
 		memset(arvif->bssid, 0, ETH_ALEN);
 
 		return;
@@ -1120,45 +1101,51 @@
 /* Station management */
 /**********************/
 
-static u32 ath10k_peer_assoc_h_listen_intval(struct ath10k *ar,
-					     struct ieee80211_vif *vif)
-{
-	/* Some firmware revisions have unstable STA powersave when listen
-	 * interval is set too high (e.g. 5). The symptoms are firmware doesn't
-	 * generate NullFunc frames properly even if buffered frames have been
-	 * indicated in Beacon TIM. Firmware would seldom wake up to pull
-	 * buffered frames. Often pinging the device from AP would simply fail.
-	 *
-	 * As a workaround set it to 1.
-	 */
-	if (vif->type == NL80211_IFTYPE_STATION)
-		return 1;
-
-	return ar->hw->conf.listen_interval;
-}
-
 static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
-				      struct ieee80211_vif *vif,
+				      struct ath10k_vif *arvif,
 				      struct ieee80211_sta *sta,
+				      struct ieee80211_bss_conf *bss_conf,
 				      struct wmi_peer_assoc_complete_arg *arg)
 {
-	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-
 	lockdep_assert_held(&ar->conf_mutex);
 
 	ether_addr_copy(arg->addr, sta->addr);
 	arg->vdev_id = arvif->vdev_id;
 	arg->peer_aid = sta->aid;
 	arg->peer_flags |= WMI_PEER_AUTH;
-	arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif);
+
+	if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
+		/*
+		 * Seems FW have problems with Power Save in STA
+		 * mode when we setup this parameter to high (eg. 5).
+		 * Often we see that FW don't send NULL (with clean P flags)
+		 * frame even there is info about buffered frames in beacons.
+		 * Sometimes we have to wait more than 10 seconds before FW
+		 * will wakeup. Often sending one ping from AP to our device
+		 * just fail (more than 50%).
+		 *
+		 * Seems setting this FW parameter to 1 couse FW
+		 * will check every beacon and will wakup immediately
+		 * after detection buffered data.
+		 */
+		arg->peer_listen_intval = 1;
+	else
+		arg->peer_listen_intval = ar->hw->conf.listen_interval;
+
 	arg->peer_num_spatial_streams = 1;
-	arg->peer_caps = vif->bss_conf.assoc_capability;
+
+	/*
+	 * The assoc capabilities are available only in managed mode.
+	 */
+	if (arvif->vdev_type == WMI_VDEV_TYPE_STA && bss_conf)
+		arg->peer_caps = bss_conf->assoc_capability;
 }
 
 static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
-				       struct ieee80211_vif *vif,
+				       struct ath10k_vif *arvif,
 				       struct wmi_peer_assoc_complete_arg *arg)
 {
+	struct ieee80211_vif *vif = arvif->vif;
 	struct ieee80211_bss_conf *info = &vif->bss_conf;
 	struct cfg80211_bss *bss;
 	const u8 *rsnie = NULL;
@@ -1415,12 +1402,11 @@
 }
 
 static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
-				    struct ieee80211_vif *vif,
+				    struct ath10k_vif *arvif,
 				    struct ieee80211_sta *sta,
+				    struct ieee80211_bss_conf *bss_conf,
 				    struct wmi_peer_assoc_complete_arg *arg)
 {
-	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-
 	switch (arvif->vdev_type) {
 	case WMI_VDEV_TYPE_AP:
 		if (sta->wme)
@@ -1432,7 +1418,7 @@
 		}
 		break;
 	case WMI_VDEV_TYPE_STA:
-		if (vif->bss_conf.qos)
+		if (bss_conf->qos)
 			arg->peer_flags |= WMI_PEER_QOS;
 		break;
 	default:
@@ -1441,7 +1427,7 @@
 }
 
 static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
-					struct ieee80211_vif *vif,
+					struct ath10k_vif *arvif,
 					struct ieee80211_sta *sta,
 					struct wmi_peer_assoc_complete_arg *arg)
 {
@@ -1492,21 +1478,22 @@
 }
 
 static int ath10k_peer_assoc_prepare(struct ath10k *ar,
-				     struct ieee80211_vif *vif,
+				     struct ath10k_vif *arvif,
 				     struct ieee80211_sta *sta,
+				     struct ieee80211_bss_conf *bss_conf,
 				     struct wmi_peer_assoc_complete_arg *arg)
 {
 	lockdep_assert_held(&ar->conf_mutex);
 
 	memset(arg, 0, sizeof(*arg));
 
-	ath10k_peer_assoc_h_basic(ar, vif, sta, arg);
-	ath10k_peer_assoc_h_crypto(ar, vif, arg);
+	ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg);
+	ath10k_peer_assoc_h_crypto(ar, arvif, arg);
 	ath10k_peer_assoc_h_rates(ar, sta, arg);
 	ath10k_peer_assoc_h_ht(ar, sta, arg);
 	ath10k_peer_assoc_h_vht(ar, sta, arg);
-	ath10k_peer_assoc_h_qos(ar, vif, sta, arg);
-	ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
+	ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg);
+	ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg);
 
 	return 0;
 }
@@ -1552,9 +1539,6 @@
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
-		   arvif->vdev_id, arvif->bssid, arvif->aid);
-
 	rcu_read_lock();
 
 	ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
@@ -1569,7 +1553,8 @@
 	 * before calling ath10k_setup_peer_smps() which might sleep. */
 	ht_cap = ap_sta->ht_cap;
 
-	ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
+	ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta,
+					bss_conf, &peer_arg);
 	if (ret) {
 		ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n",
 			    bss_conf->bssid, arvif->vdev_id, ret);
@@ -1597,8 +1582,6 @@
 		   "mac vdev %d up (associated) bssid %pM aid %d\n",
 		   arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
 
-	WARN_ON(arvif->is_up);
-
 	arvif->aid = bss_conf->aid;
 	ether_addr_copy(arvif->bssid, bss_conf->bssid);
 
@@ -1612,6 +1595,9 @@
 	arvif->is_up = true;
 }
 
+/*
+ * FIXME: flush TIDs
+ */
 static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
 				struct ieee80211_vif *vif)
 {
@@ -1621,30 +1607,45 @@
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
-		   arvif->vdev_id, arvif->bssid);
+	/*
+	 * For some reason, calling VDEV-DOWN before VDEV-STOP
+	 * makes the FW to send frames via HTT after disassociation.
+	 * No idea why this happens, even though VDEV-DOWN is supposed
+	 * to be analogous to link down, so just stop the VDEV.
+	 */
+	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d stop (disassociated\n",
+		   arvif->vdev_id);
 
+	/* FIXME: check return value */
+	ret = ath10k_vdev_stop(arvif);
+
+	/*
+	 * If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and
+	 * report beacons from previously associated network through HTT.
+	 * This in turn would spam mac80211 WARN_ON if we bring down all
+	 * interfaces as it expects there is no rx when no interface is
+	 * running.
+	 */
+	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d down\n", arvif->vdev_id);
+
+	/* FIXME: why don't we print error if wmi call fails? */
 	ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
-	if (ret)
-		ath10k_warn(ar, "faield to down vdev %i: %d\n",
-			    arvif->vdev_id, ret);
 
 	arvif->def_wep_key_idx = 0;
+
+	arvif->is_started = false;
 	arvif->is_up = false;
 }
 
-static int ath10k_station_assoc(struct ath10k *ar,
-				struct ieee80211_vif *vif,
-				struct ieee80211_sta *sta,
-				bool reassoc)
+static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
+				struct ieee80211_sta *sta, bool reassoc)
 {
-	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	struct wmi_peer_assoc_complete_arg peer_arg;
 	int ret = 0;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	ret = ath10k_peer_assoc_prepare(ar, vif, sta, &peer_arg);
+	ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg);
 	if (ret) {
 		ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n",
 			    sta->addr, arvif->vdev_id, ret);
@@ -1659,51 +1660,43 @@
 		return ret;
 	}
 
-	/* Re-assoc is run only to update supported rates for given station. It
-	 * doesn't make much sense to reconfigure the peer completely.
-	 */
-	if (!reassoc) {
-		ret = ath10k_setup_peer_smps(ar, arvif, sta->addr,
-					     &sta->ht_cap);
-		if (ret) {
-			ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
-				    arvif->vdev_id, ret);
-			return ret;
-		}
+	ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap);
+	if (ret) {
+		ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
+			    arvif->vdev_id, ret);
+		return ret;
+	}
 
-		ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
+	if (!sta->wme && !reassoc) {
+		arvif->num_legacy_stations++;
+		ret  = ath10k_recalc_rtscts_prot(arvif);
 		if (ret) {
-			ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n",
-				    sta->addr, arvif->vdev_id, ret);
-			return ret;
-		}
-
-		if (!sta->wme) {
-			arvif->num_legacy_stations++;
-			ret  = ath10k_recalc_rtscts_prot(arvif);
-			if (ret) {
-				ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
-					    arvif->vdev_id, ret);
-				return ret;
-			}
-		}
-
-		ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
-		if (ret) {
-			ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
+			ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
 				    arvif->vdev_id, ret);
 			return ret;
 		}
 	}
 
+	ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
+	if (ret) {
+		ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
+			    arvif->vdev_id, ret);
+		return ret;
+	}
+
+	ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
+	if (ret) {
+		ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n",
+			    sta->addr, arvif->vdev_id, ret);
+		return ret;
+	}
+
 	return ret;
 }
 
-static int ath10k_station_disassoc(struct ath10k *ar,
-				   struct ieee80211_vif *vif,
+static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif,
 				   struct ieee80211_sta *sta)
 {
-	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	int ret = 0;
 
 	lockdep_assert_held(&ar->conf_mutex);
@@ -1795,7 +1788,6 @@
 			ch->passive = passive;
 
 			ch->freq = channel->center_freq;
-			ch->band_center_freq1 = channel->center_freq;
 			ch->min_power = 0;
 			ch->max_power = channel->max_power * 2;
 			ch->max_reg_power = channel->max_reg_power * 2;
@@ -2050,18 +2042,6 @@
 	}
 }
 
-static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
-{
-	/* FIXME: Not really sure since when the behaviour changed. At some
-	 * point new firmware stopped requiring creation of peer entries for
-	 * offchannel tx (and actually creating them causes issues with wmi-htc
-	 * tx credit replenishment and reliability). Assuming it's at least 3.4
-	 * because that's when the `freq` was introduced to TX_FRM HTT command.
-	 */
-	return !(ar->htt.target_version_major >= 3 &&
-		 ar->htt.target_version_minor >= 4);
-}
-
 static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -2333,10 +2313,10 @@
 	case ATH10K_SCAN_IDLE:
 		break;
 	case ATH10K_SCAN_RUNNING:
+	case ATH10K_SCAN_ABORTING:
 		if (ar->scan.is_roc)
 			ieee80211_remain_on_channel_expired(ar->hw);
-	case ATH10K_SCAN_ABORTING:
-		if (!ar->scan.is_roc)
+		else
 			ieee80211_scan_completed(ar->hw,
 						 (ar->scan.state ==
 						  ATH10K_SCAN_ABORTING));
@@ -2502,28 +2482,23 @@
 
 	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
 		spin_lock_bh(&ar->data_lock);
-		ATH10K_SKB_CB(skb)->htt.freq = ar->scan.roc_freq;
+		ATH10K_SKB_CB(skb)->htt.is_offchan = true;
 		ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id;
 		spin_unlock_bh(&ar->data_lock);
 
-		if (ath10k_mac_need_offchan_tx_work(ar)) {
-			ATH10K_SKB_CB(skb)->htt.freq = 0;
-			ATH10K_SKB_CB(skb)->htt.is_offchan = true;
+		ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
+			   skb);
 
-			ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
-				   skb);
-
-			skb_queue_tail(&ar->offchan_tx_queue, skb);
-			ieee80211_queue_work(hw, &ar->offchan_tx_work);
-			return;
-		}
+		skb_queue_tail(&ar->offchan_tx_queue, skb);
+		ieee80211_queue_work(hw, &ar->offchan_tx_work);
+		return;
 	}
 
 	ath10k_tx_htt(ar, skb);
 }
 
 /* Must not be called with conf_mutex held as workers can use that also. */
-void ath10k_drain_tx(struct ath10k *ar)
+static void ath10k_drain_tx(struct ath10k *ar)
 {
 	/* make sure rcu-protected mac80211 tx path itself is drained */
 	synchronize_net();
@@ -2556,8 +2531,16 @@
 	ath10k_hif_power_down(ar);
 
 	spin_lock_bh(&ar->data_lock);
-	list_for_each_entry(arvif, &ar->arvifs, list)
-		ath10k_mac_vif_beacon_cleanup(arvif);
+	list_for_each_entry(arvif, &ar->arvifs, list) {
+		if (!arvif->beacon)
+			continue;
+
+		dma_unmap_single(arvif->ar->dev,
+				 ATH10K_SKB_CB(arvif->beacon)->paddr,
+				 arvif->beacon->len, DMA_TO_DEVICE);
+		dev_kfree_skb_any(arvif->beacon);
+		arvif->beacon = NULL;
+	}
 	spin_unlock_bh(&ar->data_lock);
 }
 
@@ -2580,28 +2563,12 @@
 	return 0;
 }
 
-static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg)
-{
-	/* It is not clear that allowing gaps in chainmask
-	 * is helpful.  Probably it will not do what user
-	 * is hoping for, so warn in that case.
-	 */
-	if (cm == 15 || cm == 7 || cm == 3 || cm == 1 || cm == 0)
-		return;
-
-	ath10k_warn(ar, "mac %s antenna chainmask may be invalid: 0x%x.  Suggested values: 15, 7, 3, 1 or 0.\n",
-		    dbg, cm);
-}
-
 static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
 {
 	int ret;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	ath10k_check_chain_mask(ar, tx_ant, "tx");
-	ath10k_check_chain_mask(ar, rx_ant, "rx");
-
 	ar->cfg_tx_chainmask = tx_ant;
 	ar->cfg_rx_chainmask = rx_ant;
 
@@ -2865,68 +2832,12 @@
 	ath10k_monitor_recalc(ar);
 }
 
-static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
-{
-	int ret;
-	u32 param;
-
-	lockdep_assert_held(&ar->conf_mutex);
-
-	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac txpower %d\n", txpower);
-
-	param = ar->wmi.pdev_param->txpower_limit2g;
-	ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2);
-	if (ret) {
-		ath10k_warn(ar, "failed to set 2g txpower %d: %d\n",
-			    txpower, ret);
-		return ret;
-	}
-
-	param = ar->wmi.pdev_param->txpower_limit5g;
-	ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2);
-	if (ret) {
-		ath10k_warn(ar, "failed to set 5g txpower %d: %d\n",
-			    txpower, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int ath10k_mac_txpower_recalc(struct ath10k *ar)
-{
-	struct ath10k_vif *arvif;
-	int ret, txpower = -1;
-
-	lockdep_assert_held(&ar->conf_mutex);
-
-	list_for_each_entry(arvif, &ar->arvifs, list) {
-		WARN_ON(arvif->txpower < 0);
-
-		if (txpower == -1)
-			txpower = arvif->txpower;
-		else
-			txpower = min(txpower, arvif->txpower);
-	}
-
-	if (WARN_ON(txpower == -1))
-		return -EINVAL;
-
-	ret = ath10k_mac_txpower_setup(ar, txpower);
-	if (ret) {
-		ath10k_warn(ar, "failed to setup tx power %d: %d\n",
-			    txpower, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
 static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ath10k *ar = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
 	int ret = 0;
+	u32 param;
 
 	mutex_lock(&ar->conf_mutex);
 
@@ -2950,6 +2861,25 @@
 		}
 	}
 
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac config power %d\n",
+			   hw->conf.power_level);
+
+		param = ar->wmi.pdev_param->txpower_limit2g;
+		ret = ath10k_wmi_pdev_set_param(ar, param,
+						hw->conf.power_level * 2);
+		if (ret)
+			ath10k_warn(ar, "failed to set 2g txpower %d: %d\n",
+				    hw->conf.power_level, ret);
+
+		param = ar->wmi.pdev_param->txpower_limit5g;
+		ret = ath10k_wmi_pdev_set_param(ar, param,
+						hw->conf.power_level * 2);
+		if (ret)
+			ath10k_warn(ar, "failed to set 5g txpower %d: %d\n",
+				    hw->conf.power_level, ret);
+	}
+
 	if (changed & IEEE80211_CONF_CHANGE_PS)
 		ath10k_config_ps(ar);
 
@@ -2964,17 +2894,6 @@
 	return ret;
 }
 
-static u32 get_nss_from_chainmask(u16 chain_mask)
-{
-	if ((chain_mask & 0x15) == 0x15)
-		return 4;
-	else if ((chain_mask & 0x7) == 0x7)
-		return 3;
-	else if ((chain_mask & 0x3) == 0x3)
-		return 2;
-	return 1;
-}
-
 /*
  * TODO:
  * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
@@ -3008,12 +2927,9 @@
 		ret = -EBUSY;
 		goto err;
 	}
-	bit = __ffs64(ar->free_vdev_map);
+	bit = ffs(ar->free_vdev_map);
 
-	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac create vdev %i map %llx\n",
-		   bit, ar->free_vdev_map);
-
-	arvif->vdev_id = bit;
+	arvif->vdev_id = bit - 1;
 	arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
 
 	if (ar->p2p)
@@ -3043,39 +2959,8 @@
 		break;
 	}
 
-	/* Some firmware revisions don't wait for beacon tx completion before
-	 * sending another SWBA event. This could lead to hardware using old
-	 * (freed) beacon data in some cases, e.g. tx credit starvation
-	 * combined with missed TBTT. This is very very rare.
-	 *
-	 * On non-IOMMU-enabled hosts this could be a possible security issue
-	 * because hw could beacon some random data on the air.  On
-	 * IOMMU-enabled hosts DMAR faults would occur in most cases and target
-	 * device would crash.
-	 *
-	 * Since there are no beacon tx completions (implicit nor explicit)
-	 * propagated to host the only workaround for this is to allocate a
-	 * DMA-coherent buffer for a lifetime of a vif and use it for all
-	 * beacon tx commands. Worst case for this approach is some beacons may
-	 * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap.
-	 */
-	if (vif->type == NL80211_IFTYPE_ADHOC ||
-	    vif->type == NL80211_IFTYPE_AP) {
-		arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
-							IEEE80211_MAX_FRAME_LEN,
-							&arvif->beacon_paddr,
-							GFP_ATOMIC);
-		if (!arvif->beacon_buf) {
-			ret = -ENOMEM;
-			ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
-				    ret);
-			goto err;
-		}
-	}
-
-	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n",
-		   arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
-		   arvif->beacon_buf ? "single-buf" : "per-skb");
+	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n",
+		   arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype);
 
 	ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type,
 				     arvif->vdev_subtype, vif->addr);
@@ -3085,7 +2970,7 @@
 		goto err;
 	}
 
-	ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
+	ar->free_vdev_map &= ~(1 << arvif->vdev_id);
 	list_add(&arvif->list, &ar->arvifs);
 
 	vdev_param = ar->wmi.vdev_param->def_keyid;
@@ -3107,20 +2992,6 @@
 		goto err_vdev_delete;
 	}
 
-	if (ar->cfg_tx_chainmask) {
-		u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
-
-		vdev_param = ar->wmi.vdev_param->nss;
-		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-						nss);
-		if (ret) {
-			ath10k_warn(ar, "failed to set vdev %i chainmask 0x%x, nss %i: %d\n",
-				    arvif->vdev_id, ar->cfg_tx_chainmask, nss,
-				    ret);
-			goto err_vdev_delete;
-		}
-	}
-
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
 		ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr);
 		if (ret) {
@@ -3183,13 +3054,6 @@
 		goto err_peer_delete;
 	}
 
-	arvif->txpower = vif->bss_conf.txpower;
-	ret = ath10k_mac_txpower_recalc(ar);
-	if (ret) {
-		ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
-		goto err_peer_delete;
-	}
-
 	mutex_unlock(&ar->conf_mutex);
 	return 0;
 
@@ -3199,16 +3063,10 @@
 
 err_vdev_delete:
 	ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
-	ar->free_vdev_map |= 1LL << arvif->vdev_id;
+	ar->free_vdev_map |= 1 << arvif->vdev_id;
 	list_del(&arvif->list);
 
 err:
-	if (arvif->beacon_buf) {
-		dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
-				  arvif->beacon_buf, arvif->beacon_paddr);
-		arvif->beacon_buf = NULL;
-	}
-
 	mutex_unlock(&ar->conf_mutex);
 
 	return ret;
@@ -3221,12 +3079,19 @@
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	int ret;
 
-	cancel_work_sync(&arvif->wep_key_work);
-
 	mutex_lock(&ar->conf_mutex);
 
+	cancel_work_sync(&arvif->wep_key_work);
+
 	spin_lock_bh(&ar->data_lock);
-	ath10k_mac_vif_beacon_cleanup(arvif);
+	if (arvif->beacon) {
+		dma_unmap_single(arvif->ar->dev,
+				 ATH10K_SKB_CB(arvif->beacon)->paddr,
+				 arvif->beacon->len, DMA_TO_DEVICE);
+		dev_kfree_skb_any(arvif->beacon);
+		arvif->beacon = NULL;
+	}
+
 	spin_unlock_bh(&ar->data_lock);
 
 	ret = ath10k_spectral_vif_stop(arvif);
@@ -3234,7 +3099,7 @@
 		ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n",
 			    arvif->vdev_id, ret);
 
-	ar->free_vdev_map |= 1LL << arvif->vdev_id;
+	ar->free_vdev_map |= 1 << arvif->vdev_id;
 	list_del(&arvif->list);
 
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
@@ -3358,8 +3223,54 @@
 		arvif->u.ap.hidden_ssid = info->hidden_ssid;
 	}
 
-	if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
-		ether_addr_copy(arvif->bssid, info->bssid);
+	/*
+	 * Firmware manages AP self-peer internally so make sure to not create
+	 * it in driver. Otherwise AP self-peer deletion may timeout later.
+	 */
+	if (changed & BSS_CHANGED_BSSID &&
+	    vif->type != NL80211_IFTYPE_AP) {
+		if (!is_zero_ether_addr(info->bssid)) {
+			ath10k_dbg(ar, ATH10K_DBG_MAC,
+				   "mac vdev %d create peer %pM\n",
+				   arvif->vdev_id, info->bssid);
+
+			ret = ath10k_peer_create(ar, arvif->vdev_id,
+						 info->bssid);
+			if (ret)
+				ath10k_warn(ar, "failed to add peer %pM for vdev %d when changing bssid: %i\n",
+					    info->bssid, arvif->vdev_id, ret);
+
+			if (vif->type == NL80211_IFTYPE_STATION) {
+				/*
+				 * this is never erased as we it for crypto key
+				 * clearing; this is FW requirement
+				 */
+				ether_addr_copy(arvif->bssid, info->bssid);
+
+				ath10k_dbg(ar, ATH10K_DBG_MAC,
+					   "mac vdev %d start %pM\n",
+					   arvif->vdev_id, info->bssid);
+
+				ret = ath10k_vdev_start(arvif);
+				if (ret) {
+					ath10k_warn(ar, "failed to start vdev %i: %d\n",
+						    arvif->vdev_id, ret);
+					goto exit;
+				}
+
+				arvif->is_started = true;
+			}
+
+			/*
+			 * Mac80211 does not keep IBSS bssid when leaving IBSS,
+			 * so driver need to store it. It is needed when leaving
+			 * IBSS in order to remove BSSID peer.
+			 */
+			if (vif->type == NL80211_IFTYPE_ADHOC)
+				memcpy(arvif->bssid, info->bssid,
+				       ETH_ALEN);
+		}
+	}
 
 	if (changed & BSS_CHANGED_BEACON_ENABLED)
 		ath10k_control_beaconing(arvif, info);
@@ -3421,21 +3332,10 @@
 				ath10k_monitor_stop(ar);
 			ath10k_bss_assoc(hw, vif, info);
 			ath10k_monitor_recalc(ar);
-		} else {
-			ath10k_bss_disassoc(hw, vif);
 		}
 	}
 
-	if (changed & BSS_CHANGED_TXPOWER) {
-		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev_id %i txpower %d\n",
-			   arvif->vdev_id, info->txpower);
-
-		arvif->txpower = info->txpower;
-		ret = ath10k_mac_txpower_recalc(ar);
-		if (ret)
-			ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
-	}
-
+exit:
 	mutex_unlock(&ar->conf_mutex);
 }
 
@@ -3521,10 +3421,9 @@
 	struct ath10k *ar = hw->priv;
 
 	mutex_lock(&ar->conf_mutex);
+	cancel_delayed_work_sync(&ar->scan.timeout);
 	ath10k_scan_abort(ar);
 	mutex_unlock(&ar->conf_mutex);
-
-	cancel_delayed_work_sync(&ar->scan.timeout);
 }
 
 static void ath10k_set_key_h_def_keyidx(struct ath10k *ar,
@@ -3709,7 +3608,7 @@
 		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n",
 			   sta->addr);
 
-		err = ath10k_station_assoc(ar, arvif->vif, sta, true);
+		err = ath10k_station_assoc(ar, arvif, sta, true);
 		if (err)
 			ath10k_warn(ar, "failed to reassociate station: %pM\n",
 				    sta->addr);
@@ -3718,37 +3617,6 @@
 	mutex_unlock(&ar->conf_mutex);
 }
 
-static int ath10k_mac_inc_num_stations(struct ath10k_vif *arvif)
-{
-	struct ath10k *ar = arvif->ar;
-
-	lockdep_assert_held(&ar->conf_mutex);
-
-	if (arvif->vdev_type != WMI_VDEV_TYPE_AP &&
-	    arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
-		return 0;
-
-	if (ar->num_stations >= ar->max_num_stations)
-		return -ENOBUFS;
-
-	ar->num_stations++;
-
-	return 0;
-}
-
-static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif)
-{
-	struct ath10k *ar = arvif->ar;
-
-	lockdep_assert_held(&ar->conf_mutex);
-
-	if (arvif->vdev_type != WMI_VDEV_TYPE_AP &&
-	    arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
-		return;
-
-	ar->num_stations--;
-}
-
 static int ath10k_sta_state(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    struct ieee80211_sta *sta,
@@ -3758,6 +3626,7 @@
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+	int max_num_peers;
 	int ret = 0;
 
 	if (old_state == IEEE80211_STA_NOTEXIST &&
@@ -3775,46 +3644,31 @@
 	mutex_lock(&ar->conf_mutex);
 
 	if (old_state == IEEE80211_STA_NOTEXIST &&
-	    new_state == IEEE80211_STA_NONE) {
+	    new_state == IEEE80211_STA_NONE &&
+	    vif->type != NL80211_IFTYPE_STATION) {
 		/*
 		 * New station addition.
 		 */
-		ath10k_dbg(ar, ATH10K_DBG_MAC,
-			   "mac vdev %d peer create %pM (new sta) sta %d / %d peer %d / %d\n",
-			   arvif->vdev_id, sta->addr,
-			   ar->num_stations + 1, ar->max_num_stations,
-			   ar->num_peers + 1, ar->max_num_peers);
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+			max_num_peers = TARGET_10X_NUM_PEERS_MAX - 1;
+		else
+			max_num_peers = TARGET_NUM_PEERS;
 
-		ret = ath10k_mac_inc_num_stations(arvif);
-		if (ret) {
-			ath10k_warn(ar, "refusing to associate station: too many connected already (%d)\n",
-				    ar->max_num_stations);
+		if (ar->num_peers >= max_num_peers) {
+			ath10k_warn(ar, "number of peers exceeded: peers number %d (max peers %d)\n",
+				    ar->num_peers, max_num_peers);
+			ret = -ENOBUFS;
 			goto exit;
 		}
 
+		ath10k_dbg(ar, ATH10K_DBG_MAC,
+			   "mac vdev %d peer create %pM (new sta) num_peers %d\n",
+			   arvif->vdev_id, sta->addr, ar->num_peers);
+
 		ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr);
-		if (ret) {
+		if (ret)
 			ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n",
 				    sta->addr, arvif->vdev_id, ret);
-			ath10k_mac_dec_num_stations(arvif);
-			goto exit;
-		}
-
-		if (vif->type == NL80211_IFTYPE_STATION) {
-			WARN_ON(arvif->is_started);
-
-			ret = ath10k_vdev_start(arvif);
-			if (ret) {
-				ath10k_warn(ar, "failed to start vdev %i: %d\n",
-					    arvif->vdev_id, ret);
-				WARN_ON(ath10k_peer_delete(ar, arvif->vdev_id,
-							   sta->addr));
-				ath10k_mac_dec_num_stations(arvif);
-				goto exit;
-			}
-
-			arvif->is_started = true;
-		}
 	} else if ((old_state == IEEE80211_STA_NONE &&
 		    new_state == IEEE80211_STA_NOTEXIST)) {
 		/*
@@ -3823,24 +3677,13 @@
 		ath10k_dbg(ar, ATH10K_DBG_MAC,
 			   "mac vdev %d peer delete %pM (sta gone)\n",
 			   arvif->vdev_id, sta->addr);
-
-		if (vif->type == NL80211_IFTYPE_STATION) {
-			WARN_ON(!arvif->is_started);
-
-			ret = ath10k_vdev_stop(arvif);
-			if (ret)
-				ath10k_warn(ar, "failed to stop vdev %i: %d\n",
-					    arvif->vdev_id, ret);
-
-			arvif->is_started = false;
-		}
-
 		ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
 		if (ret)
 			ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n",
 				    sta->addr, arvif->vdev_id, ret);
 
-		ath10k_mac_dec_num_stations(arvif);
+		if (vif->type == NL80211_IFTYPE_STATION)
+			ath10k_bss_disassoc(hw, vif);
 	} else if (old_state == IEEE80211_STA_AUTH &&
 		   new_state == IEEE80211_STA_ASSOC &&
 		   (vif->type == NL80211_IFTYPE_AP ||
@@ -3851,7 +3694,7 @@
 		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n",
 			   sta->addr);
 
-		ret = ath10k_station_assoc(ar, vif, sta, false);
+		ret = ath10k_station_assoc(ar, arvif, sta, false);
 		if (ret)
 			ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n",
 				    sta->addr, arvif->vdev_id, ret);
@@ -3865,7 +3708,7 @@
 		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n",
 			   sta->addr);
 
-		ret = ath10k_station_disassoc(ar, vif, sta);
+		ret = ath10k_station_disassoc(ar, arvif, sta);
 		if (ret)
 			ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n",
 				    sta->addr, arvif->vdev_id, ret);
@@ -4029,8 +3872,6 @@
 	if (ret)
 		goto exit;
 
-	duration = max(duration, WMI_SCAN_CHAN_MIN_TIME_MSEC);
-
 	memset(&arg, 0, sizeof(arg));
 	ath10k_wmi_start_scan_init(ar, &arg);
 	arg.vdev_id = arvif->vdev_id;
@@ -4075,11 +3916,10 @@
 	struct ath10k *ar = hw->priv;
 
 	mutex_lock(&ar->conf_mutex);
+	cancel_delayed_work_sync(&ar->scan.timeout);
 	ath10k_scan_abort(ar);
 	mutex_unlock(&ar->conf_mutex);
 
-	cancel_delayed_work_sync(&ar->scan.timeout);
-
 	return 0;
 }
 
@@ -4122,7 +3962,7 @@
 		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n",
 			   arvif->vdev_id, value);
 
-		ret = ath10k_mac_set_frag(arvif, value);
+		ret = ath10k_mac_set_rts(arvif, value);
 		if (ret) {
 			ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n",
 				    arvif->vdev_id, ret);
@@ -4170,9 +4010,7 @@
 			spin_unlock_irqrestore(&ar->wmi_mgmt_tx_queue.lock,
 					       flags);
 
-			skip = (ar->state == ATH10K_STATE_WEDGED) ||
-			       test_bit(ATH10K_FLAG_CRASH_FLUSH,
-					&ar->dev_flags);
+			skip = (ar->state == ATH10K_STATE_WEDGED);
 
 			((htt_empty && wmi_empty) || skip);
 		}), ATH10K_FLUSH_TIMEOUT_HZ);
@@ -4314,14 +4152,10 @@
 }
 #endif
 
-static void ath10k_reconfig_complete(struct ieee80211_hw *hw,
-				     enum ieee80211_reconfig_type reconfig_type)
+static void ath10k_restart_complete(struct ieee80211_hw *hw)
 {
 	struct ath10k *ar = hw->priv;
 
-	if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
-		return;
-
 	mutex_lock(&ar->conf_mutex);
 
 	/* If device failed to restart it will be in a different state, e.g.
@@ -4329,7 +4163,6 @@
 	if (ar->state == ATH10K_STATE_RESTARTED) {
 		ath10k_info(ar, "device successfully recovered\n");
 		ar->state = ATH10K_STATE_ON;
-		ieee80211_wake_queues(ar->hw);
 	}
 
 	mutex_unlock(&ar->conf_mutex);
@@ -4365,9 +4198,6 @@
 
 	survey->channel = &sband->channels[idx];
 
-	if (ar->rx_channel == survey->channel)
-		survey->filled |= SURVEY_INFO_IN_USE;
-
 exit:
 	mutex_unlock(&ar->conf_mutex);
 	return ret;
@@ -4415,10 +4245,6 @@
 	u32 legacy = 0x00ff;
 	u8 ht = 0xff, i;
 	u16 vht = 0x3ff;
-	u16 nrf = ar->num_rf_chains;
-
-	if (ar->cfg_tx_chainmask)
-		nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
 	switch (band) {
 	case IEEE80211_BAND_2GHZ:
@@ -4434,11 +4260,11 @@
 	if (mask->control[band].legacy != legacy)
 		return false;
 
-	for (i = 0; i < nrf; i++)
+	for (i = 0; i < ar->num_rf_chains; i++)
 		if (mask->control[band].ht_mcs[i] != ht)
 			return false;
 
-	for (i = 0; i < nrf; i++)
+	for (i = 0; i < ar->num_rf_chains; i++)
 		if (mask->control[band].vht_mcs[i] != vht)
 			return false;
 
@@ -4689,9 +4515,6 @@
 	u8 fixed_nss = ar->num_rf_chains;
 	u8 force_sgi;
 
-	if (ar->cfg_tx_chainmask)
-		fixed_nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
-
 	force_sgi = mask->control[band].gi;
 	if (force_sgi == NL80211_TXRATE_FORCE_LGI)
 		return -EINVAL;
@@ -4850,15 +4673,12 @@
 	.tx_last_beacon			= ath10k_tx_last_beacon,
 	.set_antenna			= ath10k_set_antenna,
 	.get_antenna			= ath10k_get_antenna,
-	.reconfig_complete		= ath10k_reconfig_complete,
+	.restart_complete		= ath10k_restart_complete,
 	.get_survey			= ath10k_get_survey,
 	.set_bitrate_mask		= ath10k_set_bitrate_mask,
 	.sta_rc_update			= ath10k_sta_rc_update,
 	.get_tsf			= ath10k_get_tsf,
 	.ampdu_action			= ath10k_ampdu_action,
-	.get_et_sset_count		= ath10k_debug_get_et_sset_count,
-	.get_et_stats			= ath10k_debug_get_et_stats,
-	.get_et_strings			= ath10k_debug_get_et_strings,
 
 	CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
 
@@ -5203,6 +5023,15 @@
 		BIT(NL80211_IFTYPE_STATION) |
 		BIT(NL80211_IFTYPE_AP);
 
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		/* TODO:  Have to deal with 2x2 chips if/when the come out. */
+		ar->supp_tx_chainmask = TARGET_10X_TX_CHAIN_MASK;
+		ar->supp_rx_chainmask = TARGET_10X_RX_CHAIN_MASK;
+	} else {
+		ar->supp_tx_chainmask = TARGET_TX_CHAIN_MASK;
+		ar->supp_rx_chainmask = TARGET_RX_CHAIN_MASK;
+	}
+
 	ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
 	ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
 
@@ -5221,6 +5050,10 @@
 			IEEE80211_HW_AP_LINK_PS |
 			IEEE80211_HW_SPECTRUM_MGMT;
 
+	/* MSDU can have HTT TX fragment pushed in front. The additional 4
+	 * bytes is used for padding/alignment if necessary. */
+	ar->hw->extra_tx_headroom += sizeof(struct htt_data_tx_desc_frag)*2 + 4;
+
 	ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
 
 	if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
@@ -5244,8 +5077,6 @@
 	ar->hw->wiphy->max_remain_on_channel_duration = 5000;
 
 	ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
-	ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
-
 	/*
 	 * on LL hardware queues are managed entirely by the FW
 	 * so we only advertise to mac we can do the queues thing
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index 6829611..6c80eea 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -21,8 +21,6 @@
 #include <net/mac80211.h>
 #include "core.h"
 
-#define WEP_KEYID_SHIFT 6
-
 struct ath10k_generic_iter {
 	struct ath10k *ar;
 	int ret;
@@ -41,10 +39,6 @@
 void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar);
 void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work);
 void ath10k_halt(struct ath10k *ar);
-void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif);
-void ath10k_drain_tx(struct ath10k *ar);
-bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
-				    u8 keyidx);
 
 static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
 {
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 7269de6..0d70674 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -490,8 +490,6 @@
 	void *data_buf = NULL;
 	int i;
 
-	spin_lock_bh(&ar_pci->ce_lock);
-
 	ce_diag = ar_pci->ce_diag;
 
 	/*
@@ -518,7 +516,7 @@
 		nbytes = min_t(unsigned int, remaining_bytes,
 			       DIAG_TRANSFER_LIMIT);
 
-		ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
+		ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
 		if (ret != 0)
 			goto done;
 
@@ -534,15 +532,15 @@
 		address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem,
 						     address);
 
-		ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
-					    0);
+		ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
+				     0);
 		if (ret)
 			goto done;
 
 		i = 0;
-		while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
-							    &completed_nbytes,
-							    &id) != 0) {
+		while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
+						     &completed_nbytes,
+						     &id) != 0) {
 			mdelay(1);
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
 				ret = -EBUSY;
@@ -561,9 +559,9 @@
 		}
 
 		i = 0;
-		while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
-							    &completed_nbytes,
-							    &id, &flags) != 0) {
+		while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
+						     &completed_nbytes,
+						     &id, &flags) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -598,8 +596,6 @@
 		dma_free_coherent(ar->dev, orig_nbytes, data_buf,
 				  ce_data_base);
 
-	spin_unlock_bh(&ar_pci->ce_lock);
-
 	return ret;
 }
 
@@ -657,8 +653,6 @@
 	dma_addr_t ce_data_base = 0;
 	int i;
 
-	spin_lock_bh(&ar_pci->ce_lock);
-
 	ce_diag = ar_pci->ce_diag;
 
 	/*
@@ -699,7 +693,7 @@
 		nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
 
 		/* Set up to receive directly into Target(!) address */
-		ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address);
+		ret = ath10k_ce_rx_post_buf(ce_diag, NULL, address);
 		if (ret != 0)
 			goto done;
 
@@ -707,15 +701,15 @@
 		 * Request CE to send caller-supplied data that
 		 * was copied to bounce buffer to Target(!) address.
 		 */
-		ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data,
-					    nbytes, 0, 0);
+		ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
+				     nbytes, 0, 0);
 		if (ret != 0)
 			goto done;
 
 		i = 0;
-		while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
-							    &completed_nbytes,
-							    &id) != 0) {
+		while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
+						     &completed_nbytes,
+						     &id) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -735,9 +729,9 @@
 		}
 
 		i = 0;
-		while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
-							    &completed_nbytes,
-							    &id, &flags) != 0) {
+		while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
+						     &completed_nbytes,
+						     &id, &flags) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -771,8 +765,6 @@
 		ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n",
 			    address, ret);
 
-	spin_unlock_bh(&ar_pci->ce_lock);
-
 	return ret;
 }
 
@@ -828,24 +820,20 @@
 	struct ath10k *ar = ce_state->ar;
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
-	struct sk_buff_head list;
-	struct sk_buff *skb;
+	void *transfer_context;
 	u32 ce_data;
 	unsigned int nbytes;
 	unsigned int transfer_id;
 
-	__skb_queue_head_init(&list);
-	while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
-					     &nbytes, &transfer_id) == 0) {
+	while (ath10k_ce_completed_send_next(ce_state, &transfer_context,
+					     &ce_data, &nbytes,
+					     &transfer_id) == 0) {
 		/* no need to call tx completion for NULL pointers */
-		if (skb == NULL)
+		if (transfer_context == NULL)
 			continue;
 
-		__skb_queue_tail(&list, skb);
+		cb->tx_completion(ar, transfer_context, transfer_id);
 	}
-
-	while ((skb = __skb_dequeue(&list)))
-		cb->tx_completion(ar, skb);
 }
 
 /* Called by lower (CE) layer when data is received from the Target. */
@@ -856,14 +844,12 @@
 	struct ath10k_pci_pipe *pipe_info =  &ar_pci->pipe_info[ce_state->id];
 	struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
 	struct sk_buff *skb;
-	struct sk_buff_head list;
 	void *transfer_context;
 	u32 ce_data;
 	unsigned int nbytes, max_nbytes;
 	unsigned int transfer_id;
 	unsigned int flags;
 
-	__skb_queue_head_init(&list);
 	while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
 					     &ce_data, &nbytes, &transfer_id,
 					     &flags) == 0) {
@@ -880,16 +866,7 @@
 		}
 
 		skb_put(skb, nbytes);
-		__skb_queue_tail(&list, skb);
-	}
-
-	while ((skb = __skb_dequeue(&list))) {
-		ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
-			   ce_state->id, skb->len);
-		ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
-				skb->data, skb->len);
-
-		cb->rx_completion(ar, skb);
+		cb->rx_completion(ar, skb, pipe_info->pipe_num);
 	}
 
 	ath10k_pci_rx_post_pipe(pipe_info);
@@ -964,12 +941,6 @@
 	return err;
 }
 
-static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
-				    size_t buf_len)
-{
-	return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
-}
-
 static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
 {
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -1020,8 +991,6 @@
 
 	spin_lock_bh(&ar->data_lock);
 
-	ar->stats.fw_crash_counter++;
-
 	crash_data = ath10k_debug_get_new_fw_crash_data(ar);
 
 	if (crash_data)
@@ -1160,38 +1129,15 @@
 						 &dl_is_polled);
 }
 
-static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
-{
-	u32 val;
-
-	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
-	val &= ~CORE_CTRL_PCIE_REG_31_MASK;
-
-	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
-}
-
-static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
-{
-	u32 val;
-
-	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
-	val |= CORE_CTRL_PCIE_REG_31_MASK;
-
-	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
-}
-
 static void ath10k_pci_irq_disable(struct ath10k *ar)
 {
-	ath10k_ce_disable_interrupts(ar);
-	ath10k_pci_disable_and_clear_legacy_irq(ar);
-	ath10k_pci_irq_msi_fw_mask(ar);
-}
-
-static void ath10k_pci_irq_sync(struct ath10k *ar)
-{
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	int i;
 
+	ath10k_ce_disable_interrupts(ar);
+	ath10k_pci_disable_and_clear_legacy_irq(ar);
+	/* FIXME: How to mask all MSI interrupts? */
+
 	for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
 		synchronize_irq(ar_pci->pdev->irq + i);
 }
@@ -1200,7 +1146,7 @@
 {
 	ath10k_ce_enable_interrupts(ar);
 	ath10k_pci_enable_legacy_irq(ar);
-	ath10k_pci_irq_msi_fw_unmask(ar);
+	/* FIXME: How to unmask all MSI interrupts? */
 }
 
 static int ath10k_pci_hif_start(struct ath10k *ar)
@@ -1213,74 +1159,64 @@
 	return 0;
 }
 
-static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
-{
-	struct ath10k *ar;
-	struct ath10k_ce_pipe *ce_pipe;
-	struct ath10k_ce_ring *ce_ring;
-	struct sk_buff *skb;
-	int i;
-
-	ar = pci_pipe->hif_ce_state;
-	ce_pipe = pci_pipe->ce_hdl;
-	ce_ring = ce_pipe->dest_ring;
-
-	if (!ce_ring)
-		return;
-
-	if (!pci_pipe->buf_sz)
-		return;
-
-	for (i = 0; i < ce_ring->nentries; i++) {
-		skb = ce_ring->per_transfer_context[i];
-		if (!skb)
-			continue;
-
-		ce_ring->per_transfer_context[i] = NULL;
-
-		dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
-				 skb->len + skb_tailroom(skb),
-				 DMA_FROM_DEVICE);
-		dev_kfree_skb_any(skb);
-	}
-}
-
-static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
+static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
 {
 	struct ath10k *ar;
 	struct ath10k_pci *ar_pci;
-	struct ath10k_ce_pipe *ce_pipe;
-	struct ath10k_ce_ring *ce_ring;
-	struct ce_desc *ce_desc;
-	struct sk_buff *skb;
-	unsigned int id;
-	int i;
+	struct ath10k_ce_pipe *ce_hdl;
+	u32 buf_sz;
+	struct sk_buff *netbuf;
+	u32 ce_data;
 
-	ar = pci_pipe->hif_ce_state;
+	buf_sz = pipe_info->buf_sz;
+
+	/* Unused Copy Engine */
+	if (buf_sz == 0)
+		return;
+
+	ar = pipe_info->hif_ce_state;
 	ar_pci = ath10k_pci_priv(ar);
-	ce_pipe = pci_pipe->ce_hdl;
-	ce_ring = ce_pipe->src_ring;
+	ce_hdl = pipe_info->ce_hdl;
 
-	if (!ce_ring)
+	while (ath10k_ce_revoke_recv_next(ce_hdl, (void **)&netbuf,
+					  &ce_data) == 0) {
+		dma_unmap_single(ar->dev, ATH10K_SKB_CB(netbuf)->paddr,
+				 netbuf->len + skb_tailroom(netbuf),
+				 DMA_FROM_DEVICE);
+		dev_kfree_skb_any(netbuf);
+	}
+}
+
+static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
+{
+	struct ath10k *ar;
+	struct ath10k_pci *ar_pci;
+	struct ath10k_ce_pipe *ce_hdl;
+	struct sk_buff *netbuf;
+	u32 ce_data;
+	unsigned int nbytes;
+	unsigned int id;
+	u32 buf_sz;
+
+	buf_sz = pipe_info->buf_sz;
+
+	/* Unused Copy Engine */
+	if (buf_sz == 0)
 		return;
 
-	if (!pci_pipe->buf_sz)
-		return;
+	ar = pipe_info->hif_ce_state;
+	ar_pci = ath10k_pci_priv(ar);
+	ce_hdl = pipe_info->ce_hdl;
 
-	ce_desc = ce_ring->shadow_base;
-	if (WARN_ON(!ce_desc))
-		return;
-
-	for (i = 0; i < ce_ring->nentries; i++) {
-		skb = ce_ring->per_transfer_context[i];
-		if (!skb)
+	while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf,
+					  &ce_data, &nbytes, &id) == 0) {
+		/* no need to call tx completion for NULL pointers */
+		if (!netbuf)
 			continue;
 
-		ce_ring->per_transfer_context[i] = NULL;
-		id = MS(__le16_to_cpu(ce_desc[i].flags),
-			CE_DESC_FLAGS_META_DATA);
-
-		ar_pci->msg_callbacks_current.tx_completion(ar, skb);
+		ar_pci->msg_callbacks_current.tx_completion(ar,
+							    netbuf,
+							    id);
 	}
 }
 
@@ -1338,7 +1274,6 @@
 	ath10k_pci_warm_reset(ar);
 
 	ath10k_pci_irq_disable(ar);
-	ath10k_pci_irq_sync(ar);
 	ath10k_pci_flush(ar);
 }
 
@@ -1459,9 +1394,6 @@
 					  &nbytes, &transfer_id, &flags))
 		return;
 
-	if (WARN_ON_ONCE(!xfer))
-		return;
-
 	if (!xfer->wait_for_resp) {
 		ath10k_warn(ar, "unexpected: BMI data received; ignoring\n");
 		return;
@@ -1645,40 +1577,23 @@
 	return 0;
 }
 
-static int ath10k_pci_alloc_pipes(struct ath10k *ar)
+static int ath10k_pci_alloc_ce(struct ath10k *ar)
 {
-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-	struct ath10k_pci_pipe *pipe;
 	int i, ret;
 
 	for (i = 0; i < CE_COUNT; i++) {
-		pipe = &ar_pci->pipe_info[i];
-		pipe->ce_hdl = &ar_pci->ce_states[i];
-		pipe->pipe_num = i;
-		pipe->hif_ce_state = ar;
-
-		ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i],
-					   ath10k_pci_ce_send_done,
-					   ath10k_pci_ce_recv_data);
+		ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]);
 		if (ret) {
 			ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n",
 				   i, ret);
 			return ret;
 		}
-
-		/* Last CE is Diagnostic Window */
-		if (i == CE_COUNT - 1) {
-			ar_pci->ce_diag = pipe->ce_hdl;
-			continue;
-		}
-
-		pipe->buf_sz = (size_t)(host_ce_config_wlan[i].src_sz_max);
 	}
 
 	return 0;
 }
 
-static void ath10k_pci_free_pipes(struct ath10k *ar)
+static void ath10k_pci_free_ce(struct ath10k *ar)
 {
 	int i;
 
@@ -1686,17 +1601,39 @@
 		ath10k_ce_free_pipe(ar, i);
 }
 
-static int ath10k_pci_init_pipes(struct ath10k *ar)
+static int ath10k_pci_ce_init(struct ath10k *ar)
 {
-	int i, ret;
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+	struct ath10k_pci_pipe *pipe_info;
+	const struct ce_attr *attr;
+	int pipe_num, ret;
 
-	for (i = 0; i < CE_COUNT; i++) {
-		ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]);
+	for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
+		pipe_info = &ar_pci->pipe_info[pipe_num];
+		pipe_info->ce_hdl = &ar_pci->ce_states[pipe_num];
+		pipe_info->pipe_num = pipe_num;
+		pipe_info->hif_ce_state = ar;
+		attr = &host_ce_config_wlan[pipe_num];
+
+		ret = ath10k_ce_init_pipe(ar, pipe_num, attr,
+					  ath10k_pci_ce_send_done,
+					  ath10k_pci_ce_recv_data);
 		if (ret) {
 			ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n",
-				   i, ret);
+				   pipe_num, ret);
 			return ret;
 		}
+
+		if (pipe_num == CE_COUNT - 1) {
+			/*
+			 * Reserve the ultimate CE for
+			 * diagnostic Window support
+			 */
+			ar_pci->ce_diag = pipe_info->ce_hdl;
+			continue;
+		}
+
+		pipe_info->buf_sz = (size_t)(attr->src_sz_max);
 	}
 
 	return 0;
@@ -1737,167 +1674,93 @@
 	msleep(10);
 }
 
-static void ath10k_pci_warm_reset_cpu(struct ath10k *ar)
+static int ath10k_pci_warm_reset(struct ath10k *ar)
 {
 	u32 val;
 
+	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
+
+	/* debug */
+	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+				PCIE_INTR_CAUSE_ADDRESS);
+	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n",
+		   val);
+
+	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+				CPU_INTR_ADDRESS);
+	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
+		   val);
+
+	/* disable pending irqs */
+	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+			   PCIE_INTR_ENABLE_ADDRESS, 0);
+
+	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+			   PCIE_INTR_CLR_ADDRESS, ~0);
+
+	msleep(100);
+
+	/* clear fw indicator */
 	ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0);
 
-	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-				SOC_RESET_CONTROL_ADDRESS);
-	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-			   val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
-}
-
-static void ath10k_pci_warm_reset_ce(struct ath10k *ar)
-{
-	u32 val;
-
-	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-				SOC_RESET_CONTROL_ADDRESS);
-
-	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-			   val | SOC_RESET_CONTROL_CE_RST_MASK);
-	msleep(10);
-	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-			   val & ~SOC_RESET_CONTROL_CE_RST_MASK);
-}
-
-static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar)
-{
-	u32 val;
-
+	/* clear target LF timer interrupts */
 	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
 				SOC_LF_TIMER_CONTROL0_ADDRESS);
 	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
 			   SOC_LF_TIMER_CONTROL0_ADDRESS,
 			   val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
-}
 
-static int ath10k_pci_warm_reset(struct ath10k *ar)
-{
-	int ret;
+	/* reset CE */
+	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+				SOC_RESET_CONTROL_ADDRESS);
+	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
+			   val | SOC_RESET_CONTROL_CE_RST_MASK);
+	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+				SOC_RESET_CONTROL_ADDRESS);
+	msleep(10);
 
-	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
+	/* unreset CE */
+	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
+			   val & ~SOC_RESET_CONTROL_CE_RST_MASK);
+	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+				SOC_RESET_CONTROL_ADDRESS);
+	msleep(10);
 
-	spin_lock_bh(&ar->data_lock);
-	ar->stats.fw_warm_reset_counter++;
-	spin_unlock_bh(&ar->data_lock);
-
-	ath10k_pci_irq_disable(ar);
-
-	/* Make sure the target CPU is not doing anything dangerous, e.g. if it
-	 * were to access copy engine while host performs copy engine reset
-	 * then it is possible for the device to confuse pci-e controller to
-	 * the point of bringing host system to a complete stop (i.e. hang).
-	 */
 	ath10k_pci_warm_reset_si0(ar);
-	ath10k_pci_warm_reset_cpu(ar);
-	ath10k_pci_init_pipes(ar);
-	ath10k_pci_wait_for_target_init(ar);
 
-	ath10k_pci_warm_reset_clear_lf(ar);
-	ath10k_pci_warm_reset_ce(ar);
-	ath10k_pci_warm_reset_cpu(ar);
-	ath10k_pci_init_pipes(ar);
+	/* debug */
+	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+				PCIE_INTR_CAUSE_ADDRESS);
+	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n",
+		   val);
 
-	ret = ath10k_pci_wait_for_target_init(ar);
-	if (ret) {
-		ath10k_warn(ar, "failed to wait for target init: %d\n", ret);
-		return ret;
-	}
+	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+				CPU_INTR_ADDRESS);
+	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
+		   val);
+
+	/* CPU warm reset */
+	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+				SOC_RESET_CONTROL_ADDRESS);
+	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
+			   val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
+
+	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+				SOC_RESET_CONTROL_ADDRESS);
+	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target reset state: 0x%08x\n",
+		   val);
+
+	msleep(100);
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n");
 
 	return 0;
 }
 
-static int ath10k_pci_chip_reset(struct ath10k *ar)
-{
-	int i, ret;
-	u32 val;
-
-	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset\n");
-
-	/* Some hardware revisions (e.g. CUS223v2) has issues with cold reset.
-	 * It is thus preferred to use warm reset which is safer but may not be
-	 * able to recover the device from all possible fail scenarios.
-	 *
-	 * Warm reset doesn't always work on first try so attempt it a few
-	 * times before giving up.
-	 */
-	for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) {
-		ret = ath10k_pci_warm_reset(ar);
-		if (ret) {
-			ath10k_warn(ar, "failed to warm reset attempt %d of %d: %d\n",
-				    i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS,
-				    ret);
-			continue;
-		}
-
-		/* FIXME: Sometimes copy engine doesn't recover after warm
-		 * reset. In most cases this needs cold reset. In some of these
-		 * cases the device is in such a state that a cold reset may
-		 * lock up the host.
-		 *
-		 * Reading any host interest register via copy engine is
-		 * sufficient to verify if device is capable of booting
-		 * firmware blob.
-		 */
-		ret = ath10k_pci_init_pipes(ar);
-		if (ret) {
-			ath10k_warn(ar, "failed to init copy engine: %d\n",
-				    ret);
-			continue;
-		}
-
-		ret = ath10k_pci_diag_read32(ar, QCA988X_HOST_INTEREST_ADDRESS,
-					     &val);
-		if (ret) {
-			ath10k_warn(ar, "failed to poke copy engine: %d\n",
-				    ret);
-			continue;
-		}
-
-		ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (warm)\n");
-		return 0;
-	}
-
-	if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) {
-		ath10k_warn(ar, "refusing cold reset as requested\n");
-		return -EPERM;
-	}
-
-	ret = ath10k_pci_cold_reset(ar);
-	if (ret) {
-		ath10k_warn(ar, "failed to cold reset: %d\n", ret);
-		return ret;
-	}
-
-	ret = ath10k_pci_wait_for_target_init(ar);
-	if (ret) {
-		ath10k_warn(ar, "failed to wait for target after cold reset: %d\n",
-			    ret);
-		return ret;
-	}
-
-	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (cold)\n");
-
-	return 0;
-}
-
-static int ath10k_pci_hif_power_up(struct ath10k *ar)
+static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset)
 {
 	int ret;
 
-	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n");
-
-	ret = ath10k_pci_wake(ar);
-	if (ret) {
-		ath10k_err(ar, "failed to wake up target: %d\n", ret);
-		return ret;
-	}
-
 	/*
 	 * Bring the target up cleanly.
 	 *
@@ -1908,16 +1771,26 @@
 	 * is in an unexpected state. We try to catch that here in order to
 	 * reset the Target and retry the probe.
 	 */
-	ret = ath10k_pci_chip_reset(ar);
+	if (cold_reset)
+		ret = ath10k_pci_cold_reset(ar);
+	else
+		ret = ath10k_pci_warm_reset(ar);
+
 	if (ret) {
-		ath10k_err(ar, "failed to reset chip: %d\n", ret);
-		goto err_sleep;
+		ath10k_err(ar, "failed to reset target: %d\n", ret);
+		goto err;
 	}
 
-	ret = ath10k_pci_init_pipes(ar);
+	ret = ath10k_pci_ce_init(ar);
 	if (ret) {
 		ath10k_err(ar, "failed to initialize CE: %d\n", ret);
-		goto err_sleep;
+		goto err;
+	}
+
+	ret = ath10k_pci_wait_for_target_init(ar);
+	if (ret) {
+		ath10k_err(ar, "failed to wait for target to init: %d\n", ret);
+		goto err_ce;
 	}
 
 	ret = ath10k_pci_init_config(ar);
@@ -1936,21 +1809,73 @@
 
 err_ce:
 	ath10k_pci_ce_deinit(ar);
-
-err_sleep:
-	ath10k_pci_sleep(ar);
+	ath10k_pci_warm_reset(ar);
+err:
 	return ret;
 }
 
+static int ath10k_pci_hif_power_up_warm(struct ath10k *ar)
+{
+	int i, ret;
+
+	/*
+	 * Sometime warm reset succeeds after retries.
+	 *
+	 * FIXME: It might be possible to tune ath10k_pci_warm_reset() to work
+	 * at first try.
+	 */
+	for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) {
+		ret = __ath10k_pci_hif_power_up(ar, false);
+		if (ret == 0)
+			break;
+
+		ath10k_warn(ar, "failed to warm reset (attempt %d out of %d): %d\n",
+			    i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, ret);
+	}
+
+	return ret;
+}
+
+static int ath10k_pci_hif_power_up(struct ath10k *ar)
+{
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n");
+
+	/*
+	 * Hardware CUS232 version 2 has some issues with cold reset and the
+	 * preferred (and safer) way to perform a device reset is through a
+	 * warm reset.
+	 *
+	 * Warm reset doesn't always work though so fall back to cold reset may
+	 * be necessary.
+	 */
+	ret = ath10k_pci_hif_power_up_warm(ar);
+	if (ret) {
+		ath10k_warn(ar, "failed to power up target using warm reset: %d\n",
+			    ret);
+
+		if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY)
+			return ret;
+
+		ath10k_warn(ar, "trying cold reset\n");
+
+		ret = __ath10k_pci_hif_power_up(ar, true);
+		if (ret) {
+			ath10k_err(ar, "failed to power up target using cold reset too (%d)\n",
+				   ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static void ath10k_pci_hif_power_down(struct ath10k *ar)
 {
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n");
 
-	/* Currently hif_power_up performs effectively a reset and hif_stop
-	 * resets the chip as well so there's no point in resetting here.
-	 */
-
-	ath10k_pci_sleep(ar);
+	ath10k_pci_warm_reset(ar);
 }
 
 #ifdef CONFIG_PM
@@ -2004,8 +1929,6 @@
 
 static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
 	.tx_sg			= ath10k_pci_hif_tx_sg,
-	.diag_read		= ath10k_pci_hif_diag_read,
-	.diag_write		= ath10k_pci_diag_write_mem,
 	.exchange_bmi_msg	= ath10k_pci_hif_exchange_bmi_msg,
 	.start			= ath10k_pci_hif_start,
 	.stop			= ath10k_pci_hif_stop,
@@ -2016,8 +1939,6 @@
 	.get_free_queue_number	= ath10k_pci_hif_get_free_queue_number,
 	.power_up		= ath10k_pci_hif_power_up,
 	.power_down		= ath10k_pci_hif_power_down,
-	.read32			= ath10k_pci_read32,
-	.write32		= ath10k_pci_write32,
 #ifdef CONFIG_PM
 	.suspend		= ath10k_pci_hif_suspend,
 	.resume			= ath10k_pci_hif_resume,
@@ -2337,14 +2258,14 @@
 
 		if (ar_pci->num_msi_intrs == 0)
 			/* Fix potential race by repeating CORE_BASE writes */
-			ath10k_pci_enable_legacy_irq(ar);
+			ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+					   PCIE_INTR_ENABLE_ADDRESS,
+					   PCIE_INTR_FIRMWARE_MASK |
+					   PCIE_INTR_CE_MASK_ALL);
 
 		mdelay(10);
 	} while (time_before(jiffies, timeout));
 
-	ath10k_pci_disable_and_clear_legacy_irq(ar);
-	ath10k_pci_irq_msi_fw_mask(ar);
-
 	if (val == 0xffffffff) {
 		ath10k_err(ar, "failed to read device register, device is gone\n");
 		return -EIO;
@@ -2374,12 +2295,6 @@
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
 
-	spin_lock_bh(&ar->data_lock);
-
-	ar->stats.fw_cold_reset_counter++;
-
-	spin_unlock_bh(&ar->data_lock);
-
 	/* Put Target, including PCIe, into RESET. */
 	val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);
 	val |= 1;
@@ -2493,7 +2408,6 @@
 	u32 chip_id;
 
 	ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev,
-				ATH10K_BUS_PCI,
 				&ath10k_pci_hif_ops);
 	if (!ar) {
 		dev_err(&pdev->dev, "failed to allocate core\n");
@@ -2529,7 +2443,7 @@
 		goto err_sleep;
 	}
 
-	ret = ath10k_pci_alloc_pipes(ar);
+	ret = ath10k_pci_alloc_ce(ar);
 	if (ret) {
 		ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",
 			   ret);
@@ -2537,12 +2451,25 @@
 	}
 
 	ath10k_pci_ce_deinit(ar);
-	ath10k_pci_irq_disable(ar);
+
+	ret = ath10k_ce_disable_interrupts(ar);
+	if (ret) {
+		ath10k_err(ar, "failed to disable copy engine interrupts: %d\n",
+			   ret);
+		goto err_free_ce;
+	}
+
+	/* Workaround: There's no known way to mask all possible interrupts via
+	 * device CSR. The only way to make sure device doesn't assert
+	 * interrupts is to reset it. Interrupts are then disabled on host
+	 * after handlers are registered.
+	 */
+	ath10k_pci_warm_reset(ar);
 
 	ret = ath10k_pci_init_irq(ar);
 	if (ret) {
 		ath10k_err(ar, "failed to init irqs: %d\n", ret);
-		goto err_free_pipes;
+		goto err_free_ce;
 	}
 
 	ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n",
@@ -2555,7 +2482,8 @@
 		goto err_deinit_irq;
 	}
 
-	ath10k_pci_sleep(ar);
+	/* This shouldn't race as the device has been reset above. */
+	ath10k_pci_irq_disable(ar);
 
 	ret = ath10k_core_register(ar, chip_id);
 	if (ret) {
@@ -2572,8 +2500,8 @@
 err_deinit_irq:
 	ath10k_pci_deinit_irq(ar);
 
-err_free_pipes:
-	ath10k_pci_free_pipes(ar);
+err_free_ce:
+	ath10k_pci_free_ce(ar);
 
 err_sleep:
 	ath10k_pci_sleep(ar);
@@ -2607,7 +2535,8 @@
 	ath10k_pci_kill_tasklet(ar);
 	ath10k_pci_deinit_irq(ar);
 	ath10k_pci_ce_deinit(ar);
-	ath10k_pci_free_pipes(ar);
+	ath10k_pci_free_ce(ar);
+	ath10k_pci_sleep(ar);
 	ath10k_pci_release(ar);
 	ath10k_core_destroy(ar);
 }
@@ -2644,7 +2573,5 @@
 MODULE_AUTHOR("Qualcomm Atheros");
 MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
 MODULE_LICENSE("Dual BSD/GPL");
-MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE);
-MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE);
-MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE);
+MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_3_FILE);
 MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index 127c8df..f45b90f 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -56,14 +56,14 @@
 }
 
 int ath10k_spectral_process_fft(struct ath10k *ar,
-				const struct wmi_phyerr *phyerr,
-				const struct phyerr_fft_report *fftr,
+				struct wmi_single_phyerr_rx_event *event,
+				struct phyerr_fft_report *fftr,
 				size_t bin_len, u64 tsf)
 {
 	struct fft_sample_ath10k *fft_sample;
 	u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
 	u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
-	u32 reg0, reg1;
+	u32 reg0, reg1, nf_list1, nf_list2;
 	u8 chain_idx, *bins;
 	int dc_pos;
 
@@ -82,7 +82,7 @@
 	/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
 	 * but the results/plots suggest that its actually 22/44/88 MHz.
 	 */
-	switch (phyerr->chan_width_mhz) {
+	switch (event->hdr.chan_width_mhz) {
 	case 20:
 		fft_sample->chan_width_mhz = 22;
 		break;
@@ -101,7 +101,7 @@
 		fft_sample->chan_width_mhz = 88;
 		break;
 	default:
-		fft_sample->chan_width_mhz = phyerr->chan_width_mhz;
+		fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
 	}
 
 	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
@@ -110,22 +110,36 @@
 	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
 	fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
 	fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
-	fft_sample->rssi = phyerr->rssi_combined;
+	fft_sample->rssi = event->hdr.rssi_combined;
 
 	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
 	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
 	fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
 	fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
 
-	freq1 = __le16_to_cpu(phyerr->freq1);
-	freq2 = __le16_to_cpu(phyerr->freq2);
+	freq1 = __le16_to_cpu(event->hdr.freq1);
+	freq2 = __le16_to_cpu(event->hdr.freq2);
 	fft_sample->freq1 = __cpu_to_be16(freq1);
 	fft_sample->freq2 = __cpu_to_be16(freq2);
 
+	nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
+	nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
 	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
 
-	fft_sample->noise = __cpu_to_be16(
-			__le16_to_cpu(phyerr->nf_chains[chain_idx]));
+	switch (chain_idx) {
+	case 0:
+		fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
+		break;
+	case 1:
+		fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
+		break;
+	case 2:
+		fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
+		break;
+	case 3:
+		fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
+		break;
+	}
 
 	bins = (u8 *)fftr;
 	bins += sizeof(*fftr);
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
index 918a1d3..ee20232 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.h
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -47,8 +47,8 @@
 #ifdef CPTCFG_ATH10K_DEBUGFS
 
 int ath10k_spectral_process_fft(struct ath10k *ar,
-				const struct wmi_phyerr *phyerr,
-				const struct phyerr_fft_report *fftr,
+				struct wmi_single_phyerr_rx_event *event,
+				struct phyerr_fft_report *fftr,
 				size_t bin_len, u64 tsf);
 int ath10k_spectral_start(struct ath10k *ar);
 int ath10k_spectral_vif_stop(struct ath10k_vif *arvif);
@@ -59,8 +59,8 @@
 
 static inline int
 ath10k_spectral_process_fft(struct ath10k *ar,
-			    const struct wmi_phyerr *phyerr,
-			    const struct phyerr_fft_report *fftr,
+			    struct wmi_single_phyerr_rx_event *event,
+			    struct phyerr_fft_report *fftr,
 			    size_t bin_len, u64 tsf)
 {
 	return 0;
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h
index b3bba04..31fe5cd 100644
--- a/drivers/net/wireless/ath/ath10k/trace.h
+++ b/drivers/net/wireless/ath/ath10k/trace.h
@@ -20,15 +20,6 @@
 #include <linux/tracepoint.h>
 #include "core.h"
 
-#if !defined(_TRACE_H_)
-static inline u32 ath10k_frm_hdr_len(const void *buf)
-{
-	const struct ieee80211_hdr *hdr = buf;
-
-	return ieee80211_hdrlen(hdr->frame_control);
-}
-#endif
-
 #define _TRACE_H_
 
 /* create empty functions when tracing is disabled */
@@ -147,8 +138,7 @@
 );
 
 TRACE_EVENT(ath10k_wmi_cmd,
-	TP_PROTO(struct ath10k *ar, int id, const void *buf, size_t buf_len,
-		 int ret),
+	TP_PROTO(struct ath10k *ar, int id, void *buf, size_t buf_len, int ret),
 
 	TP_ARGS(ar, id, buf, buf_len, ret),
 
@@ -181,7 +171,7 @@
 );
 
 TRACE_EVENT(ath10k_wmi_event,
-	TP_PROTO(struct ath10k *ar, int id, const void *buf, size_t buf_len),
+	TP_PROTO(struct ath10k *ar, int id, void *buf, size_t buf_len),
 
 	TP_ARGS(ar, id, buf, buf_len),
 
@@ -211,7 +201,7 @@
 );
 
 TRACE_EVENT(ath10k_htt_stats,
-	TP_PROTO(struct ath10k *ar, const void *buf, size_t buf_len),
+	TP_PROTO(struct ath10k *ar, void *buf, size_t buf_len),
 
 	TP_ARGS(ar, buf, buf_len),
 
@@ -238,7 +228,7 @@
 );
 
 TRACE_EVENT(ath10k_wmi_dbglog,
-	TP_PROTO(struct ath10k *ar, const void *buf, size_t buf_len),
+	TP_PROTO(struct ath10k *ar, void *buf, size_t buf_len),
 
 	TP_ARGS(ar, buf, buf_len),
 
@@ -264,195 +254,6 @@
 	)
 );
 
-TRACE_EVENT(ath10k_htt_pktlog,
-	    TP_PROTO(struct ath10k *ar, const void *buf, u16 buf_len),
-
-	TP_ARGS(ar, buf, buf_len),
-
-	TP_STRUCT__entry(
-		__string(device, dev_name(ar->dev))
-		__string(driver, dev_driver_string(ar->dev))
-		__field(u16, buf_len)
-		__dynamic_array(u8, pktlog, buf_len)
-	),
-
-	TP_fast_assign(
-		__assign_str(device, dev_name(ar->dev));
-		__assign_str(driver, dev_driver_string(ar->dev));
-		__entry->buf_len = buf_len;
-		memcpy(__get_dynamic_array(pktlog), buf, buf_len);
-	),
-
-	TP_printk(
-		"%s %s size %hu",
-		__get_str(driver),
-		__get_str(device),
-		__entry->buf_len
-	 )
-);
-
-TRACE_EVENT(ath10k_htt_tx,
-	    TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len,
-		     u8 vdev_id, u8 tid),
-
-	TP_ARGS(ar, msdu_id, msdu_len, vdev_id, tid),
-
-	TP_STRUCT__entry(
-		__string(device, dev_name(ar->dev))
-		__string(driver, dev_driver_string(ar->dev))
-		__field(u16, msdu_id)
-		__field(u16, msdu_len)
-		__field(u8, vdev_id)
-		__field(u8, tid)
-	),
-
-	TP_fast_assign(
-		__assign_str(device, dev_name(ar->dev));
-		__assign_str(driver, dev_driver_string(ar->dev));
-		__entry->msdu_id = msdu_id;
-		__entry->msdu_len = msdu_len;
-		__entry->vdev_id = vdev_id;
-		__entry->tid = tid;
-	),
-
-	TP_printk(
-		"%s %s msdu_id %d msdu_len %d vdev_id %d tid %d",
-		__get_str(driver),
-		__get_str(device),
-		__entry->msdu_id,
-		__entry->msdu_len,
-		__entry->vdev_id,
-		__entry->tid
-	 )
-);
-
-TRACE_EVENT(ath10k_txrx_tx_unref,
-	    TP_PROTO(struct ath10k *ar, u16 msdu_id),
-
-	TP_ARGS(ar, msdu_id),
-
-	TP_STRUCT__entry(
-		__string(device, dev_name(ar->dev))
-		__string(driver, dev_driver_string(ar->dev))
-		__field(u16, msdu_id)
-	),
-
-	TP_fast_assign(
-		__assign_str(device, dev_name(ar->dev));
-		__assign_str(driver, dev_driver_string(ar->dev));
-		__entry->msdu_id = msdu_id;
-	),
-
-	TP_printk(
-		"%s %s msdu_id %d",
-		__get_str(driver),
-		__get_str(device),
-		__entry->msdu_id
-	 )
-);
-
-DECLARE_EVENT_CLASS(ath10k_hdr_event,
-		    TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-
-	TP_ARGS(ar, data, len),
-
-	TP_STRUCT__entry(
-		__string(device, dev_name(ar->dev))
-		__string(driver, dev_driver_string(ar->dev))
-		__field(size_t, len)
-		__dynamic_array(u8, data, ath10k_frm_hdr_len(data))
-	),
-
-	TP_fast_assign(
-		__assign_str(device, dev_name(ar->dev));
-		__assign_str(driver, dev_driver_string(ar->dev));
-		__entry->len = ath10k_frm_hdr_len(data);
-		memcpy(__get_dynamic_array(data), data, __entry->len);
-	),
-
-	TP_printk(
-		"%s %s len %zu\n",
-		__get_str(driver),
-		__get_str(device),
-		__entry->len
-	)
-);
-
-DECLARE_EVENT_CLASS(ath10k_payload_event,
-		    TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-
-	TP_ARGS(ar, data, len),
-
-	TP_STRUCT__entry(
-		__string(device, dev_name(ar->dev))
-		__string(driver, dev_driver_string(ar->dev))
-		__field(size_t, len)
-		__dynamic_array(u8, payload, (len - ath10k_frm_hdr_len(data)))
-	),
-
-	TP_fast_assign(
-		__assign_str(device, dev_name(ar->dev));
-		__assign_str(driver, dev_driver_string(ar->dev));
-		__entry->len = len - ath10k_frm_hdr_len(data);
-		memcpy(__get_dynamic_array(payload),
-		       data + ath10k_frm_hdr_len(data), __entry->len);
-	),
-
-	TP_printk(
-		"%s %s len %zu\n",
-		__get_str(driver),
-		__get_str(device),
-		__entry->len
-	)
-);
-
-DEFINE_EVENT(ath10k_hdr_event, ath10k_tx_hdr,
-	     TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-	     TP_ARGS(ar, data, len)
-);
-
-DEFINE_EVENT(ath10k_payload_event, ath10k_tx_payload,
-	     TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-	     TP_ARGS(ar, data, len)
-);
-
-DEFINE_EVENT(ath10k_hdr_event, ath10k_rx_hdr,
-	     TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-	     TP_ARGS(ar, data, len)
-);
-
-DEFINE_EVENT(ath10k_payload_event, ath10k_rx_payload,
-	     TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-	     TP_ARGS(ar, data, len)
-);
-
-TRACE_EVENT(ath10k_htt_rx_desc,
-	    TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-
-	TP_ARGS(ar, data, len),
-
-	TP_STRUCT__entry(
-		__string(device, dev_name(ar->dev))
-		__string(driver, dev_driver_string(ar->dev))
-		__field(u16, len)
-		__dynamic_array(u8, rxdesc, len)
-	),
-
-	TP_fast_assign(
-		__assign_str(device, dev_name(ar->dev));
-		__assign_str(driver, dev_driver_string(ar->dev));
-		__entry->len = len;
-		memcpy(__get_dynamic_array(rxdesc), data, len);
-	),
-
-	TP_printk(
-		"%s %s rxdesc len %d",
-		__get_str(driver),
-		__get_str(device),
-		__entry->len
-	 )
-);
-
 #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/
 
 /* we don't want to use include/trace/events */
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 2f774c6..7c16b8b 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -84,7 +84,6 @@
 
 	info = IEEE80211_SKB_CB(msdu);
 	memset(&info->status, 0, sizeof(info->status));
-	trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
 
 	if (tx_done->discard) {
 		ieee80211_free_txskb(htt->ar->hw, msdu);
@@ -149,8 +148,7 @@
 						       ATH10K_MAX_NUM_PEER_IDS);
 			spin_unlock_bh(&ar->data_lock);
 
-			(mapped == expect_mapped ||
-			 test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags));
+			mapped == expect_mapped;
 		}), 3*HZ);
 
 	if (ret <= 0)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index a769d15..fd39c22 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -609,40 +609,6 @@
 	.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
 };
 
-static void
-ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
-			   const struct wmi_channel_arg *arg)
-{
-	u32 flags = 0;
-
-	memset(ch, 0, sizeof(*ch));
-
-	if (arg->passive)
-		flags |= WMI_CHAN_FLAG_PASSIVE;
-	if (arg->allow_ibss)
-		flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
-	if (arg->allow_ht)
-		flags |= WMI_CHAN_FLAG_ALLOW_HT;
-	if (arg->allow_vht)
-		flags |= WMI_CHAN_FLAG_ALLOW_VHT;
-	if (arg->ht40plus)
-		flags |= WMI_CHAN_FLAG_HT40_PLUS;
-	if (arg->chan_radar)
-		flags |= WMI_CHAN_FLAG_DFS;
-
-	ch->mhz = __cpu_to_le32(arg->freq);
-	ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
-	ch->band_center_freq2 = 0;
-	ch->min_power = arg->min_power;
-	ch->max_power = arg->max_power;
-	ch->reg_power = arg->max_reg_power;
-	ch->antenna_max = arg->max_antenna_gain;
-
-	/* mode & flags share storage */
-	ch->mode = arg->mode;
-	ch->flags |= __cpu_to_le32(flags);
-}
-
 int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
 {
 	int ret;
@@ -781,10 +747,6 @@
 		ath10k_wmi_tx_beacons_nowait(ar);
 
 		ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
-
-		if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
-			ret = -ESHUTDOWN;
-
 		(ret != -EAGAIN);
 	}), 3*HZ);
 
@@ -839,8 +801,6 @@
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
 		   wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE,
 		   fc & IEEE80211_FCTL_STYPE);
-	trace_ath10k_tx_hdr(ar, skb->data, skb->len);
-	trace_ath10k_tx_payload(ar, skb->data, skb->len);
 
 	/* Send the management frame buffer to the target */
 	ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid);
@@ -1110,46 +1070,13 @@
 	return rate_idx;
 }
 
-/* If keys are configured, HW decrypts all frames
- * with protected bit set. Mark such frames as decrypted.
- */
-static void ath10k_wmi_handle_wep_reauth(struct ath10k *ar,
-					 struct sk_buff *skb,
-					 struct ieee80211_rx_status *status)
-{
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	unsigned int hdrlen;
-	bool peer_key;
-	u8 *addr, keyidx;
-
-	if (!ieee80211_is_auth(hdr->frame_control) ||
-	    !ieee80211_has_protected(hdr->frame_control))
-		return;
-
-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-	if (skb->len < (hdrlen + IEEE80211_WEP_IV_LEN))
-		return;
-
-	keyidx = skb->data[hdrlen + (IEEE80211_WEP_IV_LEN - 1)] >> WEP_KEYID_SHIFT;
-	addr = ieee80211_get_SA(hdr);
-
-	spin_lock_bh(&ar->data_lock);
-	peer_key = ath10k_mac_is_peer_wep_key_set(ar, addr, keyidx);
-	spin_unlock_bh(&ar->data_lock);
-
-	if (peer_key) {
-		ath10k_dbg(ar, ATH10K_DBG_MAC,
-			   "mac wep key present for peer %pM\n", addr);
-		status->flag |= RX_FLAG_DECRYPTED;
-	}
-}
-
 static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_mgmt_rx_event_v1 *ev_v1;
 	struct wmi_mgmt_rx_event_v2 *ev_v2;
 	struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+	struct ieee80211_channel *ch;
 	struct ieee80211_hdr *hdr;
 	u32 rx_status;
 	u32 channel;
@@ -1197,33 +1124,29 @@
 		return 0;
 	}
 
-	if (rx_status & WMI_RX_STATUS_ERR_CRC) {
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
+	if (rx_status & WMI_RX_STATUS_ERR_CRC)
+		status->flag |= RX_FLAG_FAILED_FCS_CRC;
 	if (rx_status & WMI_RX_STATUS_ERR_MIC)
 		status->flag |= RX_FLAG_MMIC_ERROR;
 
-	/* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to
+	/* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to
 	 * MODE_11B. This means phy_mode is not a reliable source for the band
-	 * of mgmt rx.
-	 */
-	if (channel >= 1 && channel <= 14) {
-		status->band = IEEE80211_BAND_2GHZ;
-	} else if (channel >= 36 && channel <= 165) {
-		status->band = IEEE80211_BAND_5GHZ;
-	} else {
-		/* Shouldn't happen unless list of advertised channels to
-		 * mac80211 has been changed.
-		 */
-		WARN_ON_ONCE(1);
-		dev_kfree_skb(skb);
-		return 0;
-	}
+	 * of mgmt rx. */
 
-	if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ)
-		ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
+	ch = ar->scan_channel;
+	if (!ch)
+		ch = ar->rx_channel;
+
+	if (ch) {
+		status->band = ch->band;
+
+		if (phy_mode == MODE_11B &&
+		    status->band == IEEE80211_BAND_5GHZ)
+			ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
+	} else {
+		ath10k_warn(ar, "using (unreliable) phy_mode to extract band for mgmt rx\n");
+		status->band = phy_mode_to_band(phy_mode);
+	}
 
 	status->freq = ieee80211_channel_to_frequency(channel, status->band);
 	status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
@@ -1234,8 +1157,6 @@
 	hdr = (struct ieee80211_hdr *)skb->data;
 	fc = le16_to_cpu(hdr->frame_control);
 
-	ath10k_wmi_handle_wep_reauth(ar, skb, status);
-
 	/* FW delivers WEP Shared Auth frame with Protected Bit set and
 	 * encrypted payload. However in case of PMF it delivers decrypted
 	 * frames with Protected Bit set. */
@@ -1371,196 +1292,14 @@
 	return 0;
 }
 
-static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
-				       struct ath10k_fw_stats_pdev *dst)
-{
-	const struct wal_dbg_tx_stats *tx = &src->wal.tx;
-	const struct wal_dbg_rx_stats *rx = &src->wal.rx;
-
-	dst->ch_noise_floor = __le32_to_cpu(src->chan_nf);
-	dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count);
-	dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count);
-	dst->rx_clear_count = __le32_to_cpu(src->rx_clear_count);
-	dst->cycle_count = __le32_to_cpu(src->cycle_count);
-	dst->phy_err_count = __le32_to_cpu(src->phy_err_count);
-	dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr);
-
-	dst->comp_queued = __le32_to_cpu(tx->comp_queued);
-	dst->comp_delivered = __le32_to_cpu(tx->comp_delivered);
-	dst->msdu_enqued = __le32_to_cpu(tx->msdu_enqued);
-	dst->mpdu_enqued = __le32_to_cpu(tx->mpdu_enqued);
-	dst->wmm_drop = __le32_to_cpu(tx->wmm_drop);
-	dst->local_enqued = __le32_to_cpu(tx->local_enqued);
-	dst->local_freed = __le32_to_cpu(tx->local_freed);
-	dst->hw_queued = __le32_to_cpu(tx->hw_queued);
-	dst->hw_reaped = __le32_to_cpu(tx->hw_reaped);
-	dst->underrun = __le32_to_cpu(tx->underrun);
-	dst->tx_abort = __le32_to_cpu(tx->tx_abort);
-	dst->mpdus_requed = __le32_to_cpu(tx->mpdus_requed);
-	dst->tx_ko = __le32_to_cpu(tx->tx_ko);
-	dst->data_rc = __le32_to_cpu(tx->data_rc);
-	dst->self_triggers = __le32_to_cpu(tx->self_triggers);
-	dst->sw_retry_failure = __le32_to_cpu(tx->sw_retry_failure);
-	dst->illgl_rate_phy_err = __le32_to_cpu(tx->illgl_rate_phy_err);
-	dst->pdev_cont_xretry = __le32_to_cpu(tx->pdev_cont_xretry);
-	dst->pdev_tx_timeout = __le32_to_cpu(tx->pdev_tx_timeout);
-	dst->pdev_resets = __le32_to_cpu(tx->pdev_resets);
-	dst->phy_underrun = __le32_to_cpu(tx->phy_underrun);
-	dst->txop_ovf = __le32_to_cpu(tx->txop_ovf);
-
-	dst->mid_ppdu_route_change = __le32_to_cpu(rx->mid_ppdu_route_change);
-	dst->status_rcvd = __le32_to_cpu(rx->status_rcvd);
-	dst->r0_frags = __le32_to_cpu(rx->r0_frags);
-	dst->r1_frags = __le32_to_cpu(rx->r1_frags);
-	dst->r2_frags = __le32_to_cpu(rx->r2_frags);
-	dst->r3_frags = __le32_to_cpu(rx->r3_frags);
-	dst->htt_msdus = __le32_to_cpu(rx->htt_msdus);
-	dst->htt_mpdus = __le32_to_cpu(rx->htt_mpdus);
-	dst->loc_msdus = __le32_to_cpu(rx->loc_msdus);
-	dst->loc_mpdus = __le32_to_cpu(rx->loc_mpdus);
-	dst->oversize_amsdu = __le32_to_cpu(rx->oversize_amsdu);
-	dst->phy_errs = __le32_to_cpu(rx->phy_errs);
-	dst->phy_err_drop = __le32_to_cpu(rx->phy_err_drop);
-	dst->mpdu_errs = __le32_to_cpu(rx->mpdu_errs);
-}
-
-static void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
-				       struct ath10k_fw_stats_peer *dst)
-{
-	ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
-	dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
-	dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
-}
-
-static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar,
-					 struct sk_buff *skb,
-					 struct ath10k_fw_stats *stats)
-{
-	const struct wmi_stats_event *ev = (void *)skb->data;
-	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
-	int i;
-
-	if (!skb_pull(skb, sizeof(*ev)))
-		return -EPROTO;
-
-	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
-	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
-	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-
-	for (i = 0; i < num_pdev_stats; i++) {
-		const struct wmi_pdev_stats *src;
-		struct ath10k_fw_stats_pdev *dst;
-
-		src = (void *)skb->data;
-		if (!skb_pull(skb, sizeof(*src)))
-			return -EPROTO;
-
-		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-		if (!dst)
-			continue;
-
-		ath10k_wmi_pull_pdev_stats(src, dst);
-		list_add_tail(&dst->list, &stats->pdevs);
-	}
-
-	/* fw doesn't implement vdev stats */
-
-	for (i = 0; i < num_peer_stats; i++) {
-		const struct wmi_peer_stats *src;
-		struct ath10k_fw_stats_peer *dst;
-
-		src = (void *)skb->data;
-		if (!skb_pull(skb, sizeof(*src)))
-			return -EPROTO;
-
-		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-		if (!dst)
-			continue;
-
-		ath10k_wmi_pull_peer_stats(src, dst);
-		list_add_tail(&dst->list, &stats->peers);
-	}
-
-	return 0;
-}
-
-static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar,
-					struct sk_buff *skb,
-					struct ath10k_fw_stats *stats)
-{
-	const struct wmi_stats_event *ev = (void *)skb->data;
-	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
-	int i;
-
-	if (!skb_pull(skb, sizeof(*ev)))
-		return -EPROTO;
-
-	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
-	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
-	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-
-	for (i = 0; i < num_pdev_stats; i++) {
-		const struct wmi_10x_pdev_stats *src;
-		struct ath10k_fw_stats_pdev *dst;
-
-		src = (void *)skb->data;
-		if (!skb_pull(skb, sizeof(*src)))
-			return -EPROTO;
-
-		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-		if (!dst)
-			continue;
-
-		ath10k_wmi_pull_pdev_stats(&src->old, dst);
-
-		dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
-		dst->rts_bad = __le32_to_cpu(src->rts_bad);
-		dst->rts_good = __le32_to_cpu(src->rts_good);
-		dst->fcs_bad = __le32_to_cpu(src->fcs_bad);
-		dst->no_beacons = __le32_to_cpu(src->no_beacons);
-		dst->mib_int_count = __le32_to_cpu(src->mib_int_count);
-
-		list_add_tail(&dst->list, &stats->pdevs);
-	}
-
-	/* fw doesn't implement vdev stats */
-
-	for (i = 0; i < num_peer_stats; i++) {
-		const struct wmi_10x_peer_stats *src;
-		struct ath10k_fw_stats_peer *dst;
-
-		src = (void *)skb->data;
-		if (!skb_pull(skb, sizeof(*src)))
-			return -EPROTO;
-
-		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-		if (!dst)
-			continue;
-
-		ath10k_wmi_pull_peer_stats(&src->old, dst);
-
-		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
-
-		list_add_tail(&dst->list, &stats->peers);
-	}
-
-	return 0;
-}
-
-int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
-			     struct ath10k_fw_stats *stats)
-{
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		return ath10k_wmi_10x_pull_fw_stats(ar, skb, stats);
-	else
-		return ath10k_wmi_main_pull_fw_stats(ar, skb, stats);
-}
-
 static void ath10k_wmi_event_update_stats(struct ath10k *ar,
 					  struct sk_buff *skb)
 {
+	struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data;
+
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
-	ath10k_debug_fw_stats_process(ar, skb);
+
+	ath10k_debug_read_target_stats(ar, ev);
 }
 
 static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar,
@@ -1837,7 +1576,6 @@
 	struct wmi_bcn_info *bcn_info;
 	struct ath10k_vif *arvif;
 	struct sk_buff *bcn;
-	dma_addr_t paddr;
 	int ret, vdev_id = 0;
 
 	int attempted_to_send_beacon = 0;
@@ -1909,36 +1647,27 @@
 				ath10k_warn(ar, "SWBA overrun on vdev %d\n",
 					    arvif->vdev_id);
 
-			ath10k_mac_vif_beacon_free(arvif);
+			dma_unmap_single(arvif->ar->dev,
+					 ATH10K_SKB_CB(arvif->beacon)->paddr,
+					 arvif->beacon->len, DMA_TO_DEVICE);
+			dev_kfree_skb_any(arvif->beacon);
+			arvif->beacon = NULL;
 		}
 
-		if (!arvif->beacon_buf) {
-			paddr = dma_map_single(arvif->ar->dev, bcn->data,
-					       bcn->len, DMA_TO_DEVICE);
-			ret = dma_mapping_error(arvif->ar->dev, paddr);
-			if (ret) {
-				ath10k_warn(ar, "failed to map beacon: %d\n",
-					    ret);
-				dev_kfree_skb_any(bcn);
-				goto skip;
-			}
-
-			ATH10K_SKB_CB(bcn)->paddr = paddr;
-		} else {
-			if (bcn->len > IEEE80211_MAX_FRAME_LEN) {
-				ath10k_warn(ar, "trimming beacon %d -> %d bytes!\n",
-					    bcn->len, IEEE80211_MAX_FRAME_LEN);
-				skb_trim(bcn, IEEE80211_MAX_FRAME_LEN);
-			}
-			memcpy(arvif->beacon_buf, bcn->data, bcn->len);
-			ATH10K_SKB_CB(bcn)->paddr = arvif->beacon_paddr;
+		ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev,
+							   bcn->data, bcn->len,
+							   DMA_TO_DEVICE);
+		ret = dma_mapping_error(arvif->ar->dev,
+					ATH10K_SKB_CB(bcn)->paddr);
+		if (ret) {
+			ath10k_warn(ar, "failed to map beacon: %d\n", ret);
+			dev_kfree_skb_any(bcn);
+			goto skip;
 		}
 
 		arvif->beacon = bcn;
 		arvif->beacon_sent = false;
 
-		trace_ath10k_tx_hdr(ar, bcn->data, bcn->len);
-		trace_ath10k_tx_payload(ar, bcn->data, bcn->len);
 		ret = ath10k_wmi_tx_beacon_nowait(arvif);
 		attempted_to_send_beacon = 1;
 		if (ret == 1) {
@@ -1967,8 +1696,8 @@
 }
 
 static void ath10k_dfs_radar_report(struct ath10k *ar,
-				    const struct wmi_phyerr *phyerr,
-				    const struct phyerr_radar_report *rr,
+				    struct wmi_single_phyerr_rx_event *event,
+				    struct phyerr_radar_report *rr,
 				    u64 tsf)
 {
 	u32 reg0, reg1, tsf32l;
@@ -2001,12 +1730,12 @@
 		return;
 
 	/* report event to DFS pattern detector */
-	tsf32l = __le32_to_cpu(phyerr->tsf_timestamp);
+	tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp);
 	tsf64 = tsf & (~0xFFFFFFFFULL);
 	tsf64 |= tsf32l;
 
 	width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR);
-	rssi = phyerr->rssi_combined;
+	rssi = event->hdr.rssi_combined;
 
 	/* hardware store this as 8 bit signed value,
 	 * set to zero if negative number
@@ -2045,8 +1774,8 @@
 }
 
 static int ath10k_dfs_fft_report(struct ath10k *ar,
-				 const struct wmi_phyerr *phyerr,
-				 const struct phyerr_fft_report *fftr,
+				 struct wmi_single_phyerr_rx_event *event,
+				 struct phyerr_fft_report *fftr,
 				 u64 tsf)
 {
 	u32 reg0, reg1;
@@ -2054,7 +1783,7 @@
 
 	reg0 = __le32_to_cpu(fftr->reg0);
 	reg1 = __le32_to_cpu(fftr->reg1);
-	rssi = phyerr->rssi_combined;
+	rssi = event->hdr.rssi_combined;
 
 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
 		   "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n",
@@ -2083,20 +1812,20 @@
 }
 
 static void ath10k_wmi_event_dfs(struct ath10k *ar,
-				 const struct wmi_phyerr *phyerr,
+				 struct wmi_single_phyerr_rx_event *event,
 				 u64 tsf)
 {
 	int buf_len, tlv_len, res, i = 0;
-	const struct phyerr_tlv *tlv;
-	const struct phyerr_radar_report *rr;
-	const struct phyerr_fft_report *fftr;
-	const u8 *tlv_buf;
+	struct phyerr_tlv *tlv;
+	struct phyerr_radar_report *rr;
+	struct phyerr_fft_report *fftr;
+	u8 *tlv_buf;
 
-	buf_len = __le32_to_cpu(phyerr->buf_len);
+	buf_len = __le32_to_cpu(event->hdr.buf_len);
 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
 		   "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
-		   phyerr->phy_err_code, phyerr->rssi_combined,
-		   __le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len);
+		   event->hdr.phy_err_code, event->hdr.rssi_combined,
+		   __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len);
 
 	/* Skip event if DFS disabled */
 	if (!config_enabled(CPTCFG_ATH10K_DFS_CERTIFIED))
@@ -2111,9 +1840,9 @@
 			return;
 		}
 
-		tlv = (struct phyerr_tlv *)&phyerr->buf[i];
+		tlv = (struct phyerr_tlv *)&event->bufp[i];
 		tlv_len = __le16_to_cpu(tlv->len);
-		tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
+		tlv_buf = &event->bufp[i + sizeof(*tlv)];
 		ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
 			   "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n",
 			   tlv_len, tlv->tag, tlv->sig);
@@ -2127,7 +1856,7 @@
 			}
 
 			rr = (struct phyerr_radar_report *)tlv_buf;
-			ath10k_dfs_radar_report(ar, phyerr, rr, tsf);
+			ath10k_dfs_radar_report(ar, event, rr, tsf);
 			break;
 		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
 			if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) {
@@ -2137,7 +1866,7 @@
 			}
 
 			fftr = (struct phyerr_fft_report *)tlv_buf;
-			res = ath10k_dfs_fft_report(ar, phyerr, fftr, tsf);
+			res = ath10k_dfs_fft_report(ar, event, fftr, tsf);
 			if (res)
 				return;
 			break;
@@ -2149,16 +1878,16 @@
 
 static void
 ath10k_wmi_event_spectral_scan(struct ath10k *ar,
-			       const struct wmi_phyerr *phyerr,
+			       struct wmi_single_phyerr_rx_event *event,
 			       u64 tsf)
 {
 	int buf_len, tlv_len, res, i = 0;
 	struct phyerr_tlv *tlv;
-	const void *tlv_buf;
-	const struct phyerr_fft_report *fftr;
+	u8 *tlv_buf;
+	struct phyerr_fft_report *fftr;
 	size_t fftr_len;
 
-	buf_len = __le32_to_cpu(phyerr->buf_len);
+	buf_len = __le32_to_cpu(event->hdr.buf_len);
 
 	while (i < buf_len) {
 		if (i + sizeof(*tlv) > buf_len) {
@@ -2167,9 +1896,9 @@
 			return;
 		}
 
-		tlv = (struct phyerr_tlv *)&phyerr->buf[i];
+		tlv = (struct phyerr_tlv *)&event->bufp[i];
 		tlv_len = __le16_to_cpu(tlv->len);
-		tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
+		tlv_buf = &event->bufp[i + sizeof(*tlv)];
 
 		if (i + sizeof(*tlv) + tlv_len > buf_len) {
 			ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n",
@@ -2186,8 +1915,8 @@
 			}
 
 			fftr_len = tlv_len - sizeof(*fftr);
-			fftr = tlv_buf;
-			res = ath10k_spectral_process_fft(ar, phyerr,
+			fftr = (struct phyerr_fft_report *)tlv_buf;
+			res = ath10k_spectral_process_fft(ar, event,
 							  fftr, fftr_len,
 							  tsf);
 			if (res < 0) {
@@ -2204,8 +1933,8 @@
 
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
 {
-	const struct wmi_phyerr_event *ev;
-	const struct wmi_phyerr *phyerr;
+	struct wmi_comb_phyerr_rx_event *comb_event;
+	struct wmi_single_phyerr_rx_event *event;
 	u32 count, i, buf_len, phy_err_code;
 	u64 tsf;
 	int left_len = skb->len;
@@ -2213,38 +1942,38 @@
 	ATH10K_DFS_STAT_INC(ar, phy_errors);
 
 	/* Check if combined event available */
-	if (left_len < sizeof(*ev)) {
+	if (left_len < sizeof(*comb_event)) {
 		ath10k_warn(ar, "wmi phyerr combined event wrong len\n");
 		return;
 	}
 
-	left_len -= sizeof(*ev);
+	left_len -= sizeof(*comb_event);
 
 	/* Check number of included events */
-	ev = (const struct wmi_phyerr_event *)skb->data;
-	count = __le32_to_cpu(ev->num_phyerrs);
+	comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data;
+	count = __le32_to_cpu(comb_event->hdr.num_phyerr_events);
 
-	tsf = __le32_to_cpu(ev->tsf_u32);
+	tsf = __le32_to_cpu(comb_event->hdr.tsf_u32);
 	tsf <<= 32;
-	tsf |= __le32_to_cpu(ev->tsf_l32);
+	tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi event phyerr count %d tsf64 0x%llX\n",
 		   count, tsf);
 
-	phyerr = ev->phyerrs;
+	event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp;
 	for (i = 0; i < count; i++) {
 		/* Check if we can read event header */
-		if (left_len < sizeof(*phyerr)) {
+		if (left_len < sizeof(*event)) {
 			ath10k_warn(ar, "single event (%d) wrong head len\n",
 				    i);
 			return;
 		}
 
-		left_len -= sizeof(*phyerr);
+		left_len -= sizeof(*event);
 
-		buf_len = __le32_to_cpu(phyerr->buf_len);
-		phy_err_code = phyerr->phy_err_code;
+		buf_len = __le32_to_cpu(event->hdr.buf_len);
+		phy_err_code = event->hdr.phy_err_code;
 
 		if (left_len < buf_len) {
 			ath10k_warn(ar, "single event (%d) wrong buf len\n", i);
@@ -2255,20 +1984,20 @@
 
 		switch (phy_err_code) {
 		case PHY_ERROR_RADAR:
-			ath10k_wmi_event_dfs(ar, phyerr, tsf);
+			ath10k_wmi_event_dfs(ar, event, tsf);
 			break;
 		case PHY_ERROR_SPECTRAL_SCAN:
-			ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
+			ath10k_wmi_event_spectral_scan(ar, event, tsf);
 			break;
 		case PHY_ERROR_FALSE_RADAR_EXT:
-			ath10k_wmi_event_dfs(ar, phyerr, tsf);
-			ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
+			ath10k_wmi_event_dfs(ar, event, tsf);
+			ath10k_wmi_event_spectral_scan(ar, event, tsf);
 			break;
 		default:
 			break;
 		}
 
-		phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len;
+		event += sizeof(*event) + buf_len;
 	}
 }
 
@@ -2314,7 +2043,7 @@
 	/* the last byte is always reserved for the null character */
 	buf[i] = '\0';
 
-	ath10k_dbg(ar, ATH10K_DBG_WMI_PRINT, "wmi print '%s'\n", buf);
+	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf);
 }
 
 static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb)
@@ -2449,117 +2178,30 @@
 	return 0;
 }
 
-static int ath10k_wmi_main_pull_svc_rdy_ev(struct sk_buff *skb,
-					   struct wmi_svc_rdy_ev_arg *arg)
+static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
+					      struct sk_buff *skb)
 {
-	struct wmi_service_ready_event *ev;
-	size_t i, n;
+	struct wmi_service_ready_event *ev = (void *)skb->data;
+	DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
 
-	if (skb->len < sizeof(*ev))
-		return -EPROTO;
-
-	ev = (void *)skb->data;
-	skb_pull(skb, sizeof(*ev));
-	arg->min_tx_power = ev->hw_min_tx_power;
-	arg->max_tx_power = ev->hw_max_tx_power;
-	arg->ht_cap = ev->ht_cap_info;
-	arg->vht_cap = ev->vht_cap_info;
-	arg->sw_ver0 = ev->sw_version;
-	arg->sw_ver1 = ev->sw_version_1;
-	arg->phy_capab = ev->phy_capability;
-	arg->num_rf_chains = ev->num_rf_chains;
-	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
-	arg->num_mem_reqs = ev->num_mem_reqs;
-	arg->service_map = ev->wmi_service_bitmap;
-	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
-
-	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
-		  ARRAY_SIZE(arg->mem_reqs));
-	for (i = 0; i < n; i++)
-		arg->mem_reqs[i] = &ev->mem_reqs[i];
-
-	if (skb->len <
-	    __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
-		return -EPROTO;
-
-	return 0;
-}
-
-static int ath10k_wmi_10x_pull_svc_rdy_ev(struct sk_buff *skb,
-					  struct wmi_svc_rdy_ev_arg *arg)
-{
-	struct wmi_10x_service_ready_event *ev;
-	int i, n;
-
-	if (skb->len < sizeof(*ev))
-		return -EPROTO;
-
-	ev = (void *)skb->data;
-	skb_pull(skb, sizeof(*ev));
-	arg->min_tx_power = ev->hw_min_tx_power;
-	arg->max_tx_power = ev->hw_max_tx_power;
-	arg->ht_cap = ev->ht_cap_info;
-	arg->vht_cap = ev->vht_cap_info;
-	arg->sw_ver0 = ev->sw_version;
-	arg->phy_capab = ev->phy_capability;
-	arg->num_rf_chains = ev->num_rf_chains;
-	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
-	arg->num_mem_reqs = ev->num_mem_reqs;
-	arg->service_map = ev->wmi_service_bitmap;
-	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
-
-	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
-		  ARRAY_SIZE(arg->mem_reqs));
-	for (i = 0; i < n; i++)
-		arg->mem_reqs[i] = &ev->mem_reqs[i];
-
-	if (skb->len <
-	    __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
-		return -EPROTO;
-
-	return 0;
-}
-
-static void ath10k_wmi_event_service_ready(struct ath10k *ar,
-					   struct sk_buff *skb)
-{
-	struct wmi_svc_rdy_ev_arg arg = {};
-	u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
-	int ret;
-
-	memset(&ar->wmi.svc_map, 0, sizeof(ar->wmi.svc_map));
-
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-		ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg);
-		wmi_10x_svc_map(arg.service_map, ar->wmi.svc_map,
-				arg.service_map_len);
-	} else {
-		ret = ath10k_wmi_main_pull_svc_rdy_ev(skb, &arg);
-		wmi_main_svc_map(arg.service_map, ar->wmi.svc_map,
-				 arg.service_map_len);
-	}
-
-	if (ret) {
-		ath10k_warn(ar, "failed to parse service ready: %d\n", ret);
+	if (skb->len < sizeof(*ev)) {
+		ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
+			    skb->len, sizeof(*ev));
 		return;
 	}
 
-	ar->hw_min_tx_power = __le32_to_cpu(arg.min_tx_power);
-	ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
-	ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
-	ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
+	ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
+	ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
+	ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
+	ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
 	ar->fw_version_major =
-		(__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
-	ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
+		(__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
+	ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
 	ar->fw_version_release =
-		(__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16;
-	ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff);
-	ar->phy_capability = __le32_to_cpu(arg.phy_capab);
-	ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
-	ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd);
-
-	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
-			arg.service_map, arg.service_map_len);
+		(__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16;
+	ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff);
+	ar->phy_capability = __le32_to_cpu(ev->phy_capability);
+	ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
 
 	/* only manually set fw features when not using FW IE format */
 	if (ar->fw_api == 1 && ar->fw_version_build > 636)
@@ -2571,8 +2213,13 @@
 		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
 	}
 
-	ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
-	ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
+	ar->ath_common.regulatory.current_rd =
+		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
+
+	wmi_main_svc_map(ev->wmi_service_bitmap, svc_bmap);
+	ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
+	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
+			ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap));
 
 	if (strlen(ar->hw->wiphy->fw_version) == 0) {
 		snprintf(ar->hw->wiphy->fw_version,
@@ -2584,18 +2231,93 @@
 			 ar->fw_version_build);
 	}
 
-	num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs);
-	if (num_mem_reqs > WMI_MAX_MEM_REQS) {
+	/* FIXME: it probably should be better to support this */
+	if (__le32_to_cpu(ev->num_mem_reqs) > 0) {
+		ath10k_warn(ar, "target requested %d memory chunks; ignoring\n",
+			    __le32_to_cpu(ev->num_mem_reqs));
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_WMI,
+		   "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
+		   __le32_to_cpu(ev->sw_version),
+		   __le32_to_cpu(ev->sw_version_1),
+		   __le32_to_cpu(ev->abi_version),
+		   __le32_to_cpu(ev->phy_capability),
+		   __le32_to_cpu(ev->ht_cap_info),
+		   __le32_to_cpu(ev->vht_cap_info),
+		   __le32_to_cpu(ev->vht_supp_mcs),
+		   __le32_to_cpu(ev->sys_cap_info),
+		   __le32_to_cpu(ev->num_mem_reqs),
+		   __le32_to_cpu(ev->num_rf_chains));
+
+	complete(&ar->wmi.service_ready);
+}
+
+static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
+						  struct sk_buff *skb)
+{
+	u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
+	int ret;
+	struct wmi_service_ready_event_10x *ev = (void *)skb->data;
+	DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
+
+	if (skb->len < sizeof(*ev)) {
+		ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
+			    skb->len, sizeof(*ev));
+		return;
+	}
+
+	ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
+	ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
+	ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
+	ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
+	ar->fw_version_major =
+		(__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
+	ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
+	ar->phy_capability = __le32_to_cpu(ev->phy_capability);
+	ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
+
+	if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
+		ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
+			    ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
+		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
+	}
+
+	ar->ath_common.regulatory.current_rd =
+		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
+
+	wmi_10x_svc_map(ev->wmi_service_bitmap, svc_bmap);
+	ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
+	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
+			ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap));
+
+	if (strlen(ar->hw->wiphy->fw_version) == 0) {
+		snprintf(ar->hw->wiphy->fw_version,
+			 sizeof(ar->hw->wiphy->fw_version),
+			 "%u.%u",
+			 ar->fw_version_major,
+			 ar->fw_version_minor);
+	}
+
+	num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs);
+
+	if (num_mem_reqs > ATH10K_MAX_MEM_REQS) {
 		ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n",
 			    num_mem_reqs);
 		return;
 	}
 
+	if (!num_mem_reqs)
+		goto exit;
+
+	ath10k_dbg(ar, ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n",
+		   num_mem_reqs);
+
 	for (i = 0; i < num_mem_reqs; ++i) {
-		req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
-		num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
-		unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size);
-		num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info);
+		req_id = __le32_to_cpu(ev->mem_reqs[i].req_id);
+		num_units = __le32_to_cpu(ev->mem_reqs[i].num_units);
+		unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size);
+		num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info);
 
 		if (num_unit_info & NUM_UNITS_IS_NUM_PEERS)
 			/* number of units to allocate is number of
@@ -2609,7 +2331,7 @@
 		ath10k_dbg(ar, ATH10K_DBG_WMI,
 			   "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n",
 			   req_id,
-			   __le32_to_cpu(arg.mem_reqs[i]->num_units),
+			   __le32_to_cpu(ev->mem_reqs[i].num_units),
 			   num_unit_info,
 			   unit_size,
 			   num_units);
@@ -2620,23 +2342,23 @@
 			return;
 	}
 
+exit:
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
-		   "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
-		   __le32_to_cpu(arg.min_tx_power),
-		   __le32_to_cpu(arg.max_tx_power),
-		   __le32_to_cpu(arg.ht_cap),
-		   __le32_to_cpu(arg.vht_cap),
-		   __le32_to_cpu(arg.sw_ver0),
-		   __le32_to_cpu(arg.sw_ver1),
-		   __le32_to_cpu(arg.phy_capab),
-		   __le32_to_cpu(arg.num_rf_chains),
-		   __le32_to_cpu(arg.eeprom_rd),
-		   __le32_to_cpu(arg.num_mem_reqs));
+		   "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
+		   __le32_to_cpu(ev->sw_version),
+		   __le32_to_cpu(ev->abi_version),
+		   __le32_to_cpu(ev->phy_capability),
+		   __le32_to_cpu(ev->ht_cap_info),
+		   __le32_to_cpu(ev->vht_cap_info),
+		   __le32_to_cpu(ev->vht_supp_mcs),
+		   __le32_to_cpu(ev->sys_cap_info),
+		   __le32_to_cpu(ev->num_mem_reqs),
+		   __le32_to_cpu(ev->num_rf_chains));
 
 	complete(&ar->wmi.service_ready);
 }
 
-static int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
+static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data;
 
@@ -2759,10 +2481,10 @@
 		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
 		break;
 	case WMI_SERVICE_READY_EVENTID:
-		ath10k_wmi_event_service_ready(ar, skb);
+		ath10k_wmi_service_ready_event_rx(ar, skb);
 		break;
 	case WMI_READY_EVENTID:
-		ath10k_wmi_event_ready(ar, skb);
+		ath10k_wmi_ready_event_rx(ar, skb);
 		break;
 	default:
 		ath10k_warn(ar, "Unknown eventid: %d\n", id);
@@ -2879,10 +2601,10 @@
 		ath10k_wmi_event_vdev_resume_req(ar, skb);
 		break;
 	case WMI_10X_SERVICE_READY_EVENTID:
-		ath10k_wmi_event_service_ready(ar, skb);
+		ath10k_wmi_10x_service_ready_event_rx(ar, skb);
 		break;
 	case WMI_10X_READY_EVENTID:
-		ath10k_wmi_event_ready(ar, skb);
+		ath10k_wmi_ready_event_rx(ar, skb);
 		break;
 	case WMI_10X_PDEV_UTF_EVENTID:
 		/* ignore utf events */
@@ -2990,10 +2712,10 @@
 		ath10k_wmi_event_vdev_resume_req(ar, skb);
 		break;
 	case WMI_10_2_SERVICE_READY_EVENTID:
-		ath10k_wmi_event_service_ready(ar, skb);
+		ath10k_wmi_10x_service_ready_event_rx(ar, skb);
 		break;
 	case WMI_10_2_READY_EVENTID:
-		ath10k_wmi_event_ready(ar, skb);
+		ath10k_wmi_ready_event_rx(ar, skb);
 		break;
 	case WMI_10_2_RTT_KEEPALIVE_EVENTID:
 	case WMI_10_2_GPIO_INPUT_EVENTID:
@@ -3025,6 +2747,45 @@
 	}
 }
 
+/* WMI Initialization functions */
+int ath10k_wmi_attach(struct ath10k *ar)
+{
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
+			ar->wmi.cmd = &wmi_10_2_cmd_map;
+		else
+			ar->wmi.cmd = &wmi_10x_cmd_map;
+
+		ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
+		ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
+	} else {
+		ar->wmi.cmd = &wmi_cmd_map;
+		ar->wmi.vdev_param = &wmi_vdev_param_map;
+		ar->wmi.pdev_param = &wmi_pdev_param_map;
+	}
+
+	init_completion(&ar->wmi.service_ready);
+	init_completion(&ar->wmi.unified_ready);
+	init_waitqueue_head(&ar->wmi.tx_credits_wq);
+
+	return 0;
+}
+
+void ath10k_wmi_detach(struct ath10k *ar)
+{
+	int i;
+
+	/* free the host memory chunks requested by firmware */
+	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+		dma_free_coherent(ar->dev,
+				  ar->wmi.mem_chunks[i].len,
+				  ar->wmi.mem_chunks[i].vaddr,
+				  ar->wmi.mem_chunks[i].paddr);
+	}
+
+	ar->wmi.num_mem_chunks = 0;
+}
+
 int ath10k_wmi_connect(struct ath10k *ar)
 {
 	int status;
@@ -3119,6 +2880,42 @@
 							 ctl2g, ctl5g);
 }
 
+int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
+				const struct wmi_channel_arg *arg)
+{
+	struct wmi_set_channel_cmd *cmd;
+	struct sk_buff *skb;
+	u32 ch_flags = 0;
+
+	if (arg->passive)
+		return -EINVAL;
+
+	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	if (arg->chan_radar)
+		ch_flags |= WMI_CHAN_FLAG_DFS;
+
+	cmd = (struct wmi_set_channel_cmd *)skb->data;
+	cmd->chan.mhz               = __cpu_to_le32(arg->freq);
+	cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq);
+	cmd->chan.mode              = arg->mode;
+	cmd->chan.flags		   |= __cpu_to_le32(ch_flags);
+	cmd->chan.min_power         = arg->min_power;
+	cmd->chan.max_power         = arg->max_power;
+	cmd->chan.reg_power         = arg->max_reg_power;
+	cmd->chan.reg_classid       = arg->reg_class_id;
+	cmd->chan.antenna_max       = arg->max_antenna_gain;
+
+	ath10k_dbg(ar, ATH10K_DBG_WMI,
+		   "wmi set channel mode %d freq %d\n",
+		   arg->mode, arg->freq);
+
+	return ath10k_wmi_cmd_send(ar, skb,
+				   ar->wmi.cmd->pdev_set_channel_cmdid);
+}
+
 int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
 {
 	struct wmi_pdev_suspend_cmd *cmd;
@@ -3169,37 +2966,16 @@
 	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid);
 }
 
-static void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar,
-					   struct wmi_host_mem_chunks *chunks)
-{
-	struct host_memory_chunk *chunk;
-	int i;
-
-	chunks->count = __cpu_to_le32(ar->wmi.num_mem_chunks);
-
-	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
-		chunk = &chunks->items[i];
-		chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
-		chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
-		chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
-
-		ath10k_dbg(ar, ATH10K_DBG_WMI,
-			   "wmi chunk %d len %d requested, addr 0x%llx\n",
-			   i,
-			   ar->wmi.mem_chunks[i].len,
-			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
-	}
-}
-
 static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
 {
 	struct wmi_init_cmd *cmd;
 	struct sk_buff *buf;
 	struct wmi_resource_config config = {};
 	u32 len, val;
+	int i;
 
 	config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS);
-	config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS);
+	config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS);
 	config.num_offload_peers = __cpu_to_le32(TARGET_NUM_OFFLOAD_PEERS);
 
 	config.num_offload_reorder_bufs =
@@ -3260,8 +3036,32 @@
 
 	cmd = (struct wmi_init_cmd *)buf->data;
 
+	if (ar->wmi.num_mem_chunks == 0) {
+		cmd->num_host_mem_chunks = 0;
+		goto out;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
+		   ar->wmi.num_mem_chunks);
+
+	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
+
+	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+		cmd->host_mem_chunks[i].ptr =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+		cmd->host_mem_chunks[i].size =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].len);
+		cmd->host_mem_chunks[i].req_id =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+		ath10k_dbg(ar, ATH10K_DBG_WMI,
+			   "wmi chunk %d len %d requested, addr 0x%llx\n",
+			   i,
+			   ar->wmi.mem_chunks[i].len,
+			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
+	}
+out:
 	memcpy(&cmd->resource_config, &config, sizeof(config));
-	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n");
 	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
@@ -3273,6 +3073,7 @@
 	struct sk_buff *buf;
 	struct wmi_resource_config_10x config = {};
 	u32 len, val;
+	int i;
 
 	config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
 	config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
@@ -3329,8 +3130,32 @@
 
 	cmd = (struct wmi_init_cmd_10x *)buf->data;
 
+	if (ar->wmi.num_mem_chunks == 0) {
+		cmd->num_host_mem_chunks = 0;
+		goto out;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
+		   ar->wmi.num_mem_chunks);
+
+	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
+
+	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+		cmd->host_mem_chunks[i].ptr =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+		cmd->host_mem_chunks[i].size =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].len);
+		cmd->host_mem_chunks[i].req_id =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+		ath10k_dbg(ar, ATH10K_DBG_WMI,
+			   "wmi chunk %d len %d requested, addr 0x%llx\n",
+			   i,
+			   ar->wmi.mem_chunks[i].len,
+			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
+	}
+out:
 	memcpy(&cmd->resource_config, &config, sizeof(config));
-	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n");
 	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
@@ -3342,6 +3167,7 @@
 	struct sk_buff *buf;
 	struct wmi_resource_config_10x config = {};
 	u32 len, val;
+	int i;
 
 	config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
 	config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
@@ -3395,8 +3221,32 @@
 
 	cmd = (struct wmi_init_cmd_10_2 *)buf->data;
 
+	if (ar->wmi.num_mem_chunks == 0) {
+		cmd->num_host_mem_chunks = 0;
+		goto out;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
+		   ar->wmi.num_mem_chunks);
+
+	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
+
+	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+		cmd->host_mem_chunks[i].ptr =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+		cmd->host_mem_chunks[i].size =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].len);
+		cmd->host_mem_chunks[i].req_id =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+		ath10k_dbg(ar, ATH10K_DBG_WMI,
+			   "wmi chunk %d len %d requested, addr 0x%llx\n",
+			   i,
+			   ar->wmi.mem_chunks[i].len,
+			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
+	}
+out:
 	memcpy(&cmd->resource_config.common, &config, sizeof(config));
-	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n");
 	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
@@ -3418,50 +3268,52 @@
 	return ret;
 }
 
-static int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
+static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar,
+					  const struct wmi_start_scan_arg *arg)
 {
-	if (arg->ie_len && !arg->ie)
-		return -EINVAL;
-	if (arg->n_channels && !arg->channels)
-		return -EINVAL;
-	if (arg->n_ssids && !arg->ssids)
-		return -EINVAL;
-	if (arg->n_bssids && !arg->bssids)
-		return -EINVAL;
+	int len;
 
-	if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
-		return -EINVAL;
-	if (arg->n_channels > ARRAY_SIZE(arg->channels))
-		return -EINVAL;
-	if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
-		return -EINVAL;
-	if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
-		return -EINVAL;
-
-	return 0;
-}
-
-static size_t
-ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg)
-{
-	int len = 0;
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+		len = sizeof(struct wmi_start_scan_cmd_10x);
+	else
+		len = sizeof(struct wmi_start_scan_cmd);
 
 	if (arg->ie_len) {
+		if (!arg->ie)
+			return -EINVAL;
+		if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
+			return -EINVAL;
+
 		len += sizeof(struct wmi_ie_data);
 		len += roundup(arg->ie_len, 4);
 	}
 
 	if (arg->n_channels) {
+		if (!arg->channels)
+			return -EINVAL;
+		if (arg->n_channels > ARRAY_SIZE(arg->channels))
+			return -EINVAL;
+
 		len += sizeof(struct wmi_chan_list);
 		len += sizeof(__le32) * arg->n_channels;
 	}
 
 	if (arg->n_ssids) {
+		if (!arg->ssids)
+			return -EINVAL;
+		if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
+			return -EINVAL;
+
 		len += sizeof(struct wmi_ssid_list);
 		len += sizeof(struct wmi_ssid) * arg->n_ssids;
 	}
 
 	if (arg->n_bssids) {
+		if (!arg->bssids)
+			return -EINVAL;
+		if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
+			return -EINVAL;
+
 		len += sizeof(struct wmi_bssid_list);
 		len += sizeof(struct wmi_mac_addr) * arg->n_bssids;
 	}
@@ -3469,12 +3321,28 @@
 	return len;
 }
 
-static void
-ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
-				 const struct wmi_start_scan_arg *arg)
+int ath10k_wmi_start_scan(struct ath10k *ar,
+			  const struct wmi_start_scan_arg *arg)
 {
+	struct wmi_start_scan_cmd *cmd;
+	struct sk_buff *skb;
+	struct wmi_ie_data *ie;
+	struct wmi_chan_list *channels;
+	struct wmi_ssid_list *ssids;
+	struct wmi_bssid_list *bssids;
 	u32 scan_id;
 	u32 scan_req_id;
+	int off;
+	int len = 0;
+	int i;
+
+	len = ath10k_wmi_start_scan_calc_len(ar, arg);
+	if (len < 0)
+		return len; /* len contains error code here */
+
+	skb = ath10k_wmi_alloc_skb(ar, len);
+	if (!skb)
+		return -ENOMEM;
 
 	scan_id  = WMI_HOST_SCAN_REQ_ID_PREFIX;
 	scan_id |= arg->scan_id;
@@ -3482,36 +3350,35 @@
 	scan_req_id  = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
 	scan_req_id |= arg->scan_req_id;
 
-	cmn->scan_id            = __cpu_to_le32(scan_id);
-	cmn->scan_req_id        = __cpu_to_le32(scan_req_id);
-	cmn->vdev_id            = __cpu_to_le32(arg->vdev_id);
-	cmn->scan_priority      = __cpu_to_le32(arg->scan_priority);
-	cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
-	cmn->dwell_time_active  = __cpu_to_le32(arg->dwell_time_active);
-	cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
-	cmn->min_rest_time      = __cpu_to_le32(arg->min_rest_time);
-	cmn->max_rest_time      = __cpu_to_le32(arg->max_rest_time);
-	cmn->repeat_probe_time  = __cpu_to_le32(arg->repeat_probe_time);
-	cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
-	cmn->idle_time          = __cpu_to_le32(arg->idle_time);
-	cmn->max_scan_time      = __cpu_to_le32(arg->max_scan_time);
-	cmn->probe_delay        = __cpu_to_le32(arg->probe_delay);
-	cmn->scan_ctrl_flags    = __cpu_to_le32(arg->scan_ctrl_flags);
-}
+	cmd = (struct wmi_start_scan_cmd *)skb->data;
+	cmd->scan_id            = __cpu_to_le32(scan_id);
+	cmd->scan_req_id        = __cpu_to_le32(scan_req_id);
+	cmd->vdev_id            = __cpu_to_le32(arg->vdev_id);
+	cmd->scan_priority      = __cpu_to_le32(arg->scan_priority);
+	cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
+	cmd->dwell_time_active  = __cpu_to_le32(arg->dwell_time_active);
+	cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
+	cmd->min_rest_time      = __cpu_to_le32(arg->min_rest_time);
+	cmd->max_rest_time      = __cpu_to_le32(arg->max_rest_time);
+	cmd->repeat_probe_time  = __cpu_to_le32(arg->repeat_probe_time);
+	cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
+	cmd->idle_time          = __cpu_to_le32(arg->idle_time);
+	cmd->max_scan_time      = __cpu_to_le32(arg->max_scan_time);
+	cmd->probe_delay        = __cpu_to_le32(arg->probe_delay);
+	cmd->scan_ctrl_flags    = __cpu_to_le32(arg->scan_ctrl_flags);
 
-static void
-ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs,
-			       const struct wmi_start_scan_arg *arg)
-{
-	struct wmi_ie_data *ie;
-	struct wmi_chan_list *channels;
-	struct wmi_ssid_list *ssids;
-	struct wmi_bssid_list *bssids;
-	void *ptr = tlvs->tlvs;
-	int i;
+	/* TLV list starts after fields included in the struct */
+	/* There's just one filed that differes the two start_scan
+	 * structures - burst_duration, which we are not using btw,
+	   no point to make the split here, just shift the buffer to fit with
+	   given FW */
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+		off = sizeof(struct wmi_start_scan_cmd_10x);
+	else
+		off = sizeof(struct wmi_start_scan_cmd);
 
 	if (arg->n_channels) {
-		channels = ptr;
+		channels = (void *)skb->data + off;
 		channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG);
 		channels->num_chan = __cpu_to_le32(arg->n_channels);
 
@@ -3519,12 +3386,12 @@
 			channels->channel_list[i].freq =
 				__cpu_to_le16(arg->channels[i]);
 
-		ptr += sizeof(*channels);
-		ptr += sizeof(__le32) * arg->n_channels;
+		off += sizeof(*channels);
+		off += sizeof(__le32) * arg->n_channels;
 	}
 
 	if (arg->n_ssids) {
-		ssids = ptr;
+		ssids = (void *)skb->data + off;
 		ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG);
 		ssids->num_ssids = __cpu_to_le32(arg->n_ssids);
 
@@ -3536,12 +3403,12 @@
 			       arg->ssids[i].len);
 		}
 
-		ptr += sizeof(*ssids);
-		ptr += sizeof(struct wmi_ssid) * arg->n_ssids;
+		off += sizeof(*ssids);
+		off += sizeof(struct wmi_ssid) * arg->n_ssids;
 	}
 
 	if (arg->n_bssids) {
-		bssids = ptr;
+		bssids = (void *)skb->data + off;
 		bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG);
 		bssids->num_bssid = __cpu_to_le32(arg->n_bssids);
 
@@ -3550,57 +3417,23 @@
 			       arg->bssids[i].bssid,
 			       ETH_ALEN);
 
-		ptr += sizeof(*bssids);
-		ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids;
+		off += sizeof(*bssids);
+		off += sizeof(struct wmi_mac_addr) * arg->n_bssids;
 	}
 
 	if (arg->ie_len) {
-		ie = ptr;
+		ie = (void *)skb->data + off;
 		ie->tag = __cpu_to_le32(WMI_IE_TAG);
 		ie->ie_len = __cpu_to_le32(arg->ie_len);
 		memcpy(ie->ie_data, arg->ie, arg->ie_len);
 
-		ptr += sizeof(*ie);
-		ptr += roundup(arg->ie_len, 4);
+		off += sizeof(*ie);
+		off += roundup(arg->ie_len, 4);
 	}
-}
 
-int ath10k_wmi_start_scan(struct ath10k *ar,
-			  const struct wmi_start_scan_arg *arg)
-{
-	struct sk_buff *skb;
-	size_t len;
-	int ret;
-
-	ret = ath10k_wmi_start_scan_verify(arg);
-	if (ret)
-		return ret;
-
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		len = sizeof(struct wmi_10x_start_scan_cmd) +
-		      ath10k_wmi_start_scan_tlvs_len(arg);
-	else
-		len = sizeof(struct wmi_start_scan_cmd) +
-		      ath10k_wmi_start_scan_tlvs_len(arg);
-
-	skb = ath10k_wmi_alloc_skb(ar, len);
-	if (!skb)
-		return -ENOMEM;
-
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-		struct wmi_10x_start_scan_cmd *cmd;
-
-		cmd = (struct wmi_10x_start_scan_cmd *)skb->data;
-		ath10k_wmi_put_start_scan_common(&cmd->common, arg);
-		ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
-	} else {
-		struct wmi_start_scan_cmd *cmd;
-
-		cmd = (struct wmi_start_scan_cmd *)skb->data;
-		cmd->burst_duration_ms = __cpu_to_le32(0);
-
-		ath10k_wmi_put_start_scan_common(&cmd->common, arg);
-		ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
+	if (off != skb->len) {
+		dev_kfree_skb(skb);
+		return -EINVAL;
 	}
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n");
@@ -3719,6 +3552,7 @@
 	struct sk_buff *skb;
 	const char *cmdname;
 	u32 flags = 0;
+	u32 ch_flags = 0;
 
 	if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid &&
 	    cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid)
@@ -3745,6 +3579,8 @@
 		flags |= WMI_VDEV_START_HIDDEN_SSID;
 	if (arg->pmf_enabled)
 		flags |= WMI_VDEV_START_PMF_ENABLED;
+	if (arg->channel.chan_radar)
+		ch_flags |= WMI_CHAN_FLAG_DFS;
 
 	cmd = (struct wmi_vdev_start_request_cmd *)skb->data;
 	cmd->vdev_id         = __cpu_to_le32(arg->vdev_id);
@@ -3762,7 +3598,18 @@
 		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
 	}
 
-	ath10k_wmi_put_wmi_channel(&cmd->chan, &arg->channel);
+	cmd->chan.mhz = __cpu_to_le32(arg->channel.freq);
+
+	cmd->chan.band_center_freq1 =
+		__cpu_to_le32(arg->channel.band_center_freq1);
+
+	cmd->chan.mode = arg->channel.mode;
+	cmd->chan.flags |= __cpu_to_le32(ch_flags);
+	cmd->chan.min_power = arg->channel.min_power;
+	cmd->chan.max_power = arg->channel.max_power;
+	cmd->chan.reg_power = arg->channel.max_reg_power;
+	cmd->chan.reg_classid = arg->channel.reg_class_id;
+	cmd->chan.antenna_max = arg->channel.max_antenna_gain;
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n",
@@ -4143,10 +3990,35 @@
 	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
 
 	for (i = 0; i < arg->n_channels; i++) {
+		u32 flags = 0;
+
 		ch = &arg->channels[i];
 		ci = &cmd->chan_info[i];
 
-		ath10k_wmi_put_wmi_channel(ci, ch);
+		if (ch->passive)
+			flags |= WMI_CHAN_FLAG_PASSIVE;
+		if (ch->allow_ibss)
+			flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
+		if (ch->allow_ht)
+			flags |= WMI_CHAN_FLAG_ALLOW_HT;
+		if (ch->allow_vht)
+			flags |= WMI_CHAN_FLAG_ALLOW_VHT;
+		if (ch->ht40plus)
+			flags |= WMI_CHAN_FLAG_HT40_PLUS;
+		if (ch->chan_radar)
+			flags |= WMI_CHAN_FLAG_DFS;
+
+		ci->mhz               = __cpu_to_le32(ch->freq);
+		ci->band_center_freq1 = __cpu_to_le32(ch->freq);
+		ci->band_center_freq2 = 0;
+		ci->min_power         = ch->min_power;
+		ci->max_power         = ch->max_power;
+		ci->reg_power         = ch->max_reg_power;
+		ci->antenna_max       = ch->max_antenna_gain;
+
+		/* mode & flags share storage */
+		ci->mode              = ch->mode;
+		ci->flags            |= __cpu_to_le32(flags);
 	}
 
 	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
@@ -4258,9 +4130,9 @@
 
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
 		if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
-			ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg);
-		else
 			ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg);
+		else
+			ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg);
 	} else {
 		ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg);
 	}
@@ -4417,73 +4289,3 @@
 
 	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid);
 }
-
-int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_bitmap)
-{
-	struct wmi_pdev_pktlog_enable_cmd *cmd;
-	struct sk_buff *skb;
-
-	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-	if (!skb)
-		return -ENOMEM;
-
-	ev_bitmap &= ATH10K_PKTLOG_ANY;
-	ath10k_dbg(ar, ATH10K_DBG_WMI,
-		   "wmi enable pktlog filter:%x\n", ev_bitmap);
-
-	cmd = (struct wmi_pdev_pktlog_enable_cmd *)skb->data;
-	cmd->ev_bitmap = __cpu_to_le32(ev_bitmap);
-	return ath10k_wmi_cmd_send(ar, skb,
-				   ar->wmi.cmd->pdev_pktlog_enable_cmdid);
-}
-
-int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar)
-{
-	struct sk_buff *skb;
-
-	skb = ath10k_wmi_alloc_skb(ar, 0);
-	if (!skb)
-		return -ENOMEM;
-
-	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi disable pktlog\n");
-
-	return ath10k_wmi_cmd_send(ar, skb,
-				   ar->wmi.cmd->pdev_pktlog_disable_cmdid);
-}
-
-int ath10k_wmi_attach(struct ath10k *ar)
-{
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-		if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
-			ar->wmi.cmd = &wmi_10_2_cmd_map;
-		else
-			ar->wmi.cmd = &wmi_10x_cmd_map;
-
-		ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
-		ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
-	} else {
-		ar->wmi.cmd = &wmi_cmd_map;
-		ar->wmi.vdev_param = &wmi_vdev_param_map;
-		ar->wmi.pdev_param = &wmi_pdev_param_map;
-	}
-
-	init_completion(&ar->wmi.service_ready);
-	init_completion(&ar->wmi.unified_ready);
-
-	return 0;
-}
-
-void ath10k_wmi_detach(struct ath10k *ar)
-{
-	int i;
-
-	/* free the host memory chunks requested by firmware */
-	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
-		dma_free_coherent(ar->dev,
-				  ar->wmi.mem_chunks[i].len,
-				  ar->wmi.mem_chunks[i].vaddr,
-				  ar->wmi.mem_chunks[i].paddr);
-	}
-
-	ar->wmi.num_mem_chunks = 0;
-}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 09daa3e..048ba28 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -222,131 +222,128 @@
 #undef SVCSTR
 }
 
-#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
-	((svc_id) < (len) && \
-	 __le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
+#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \
+	(__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
 	 BIT((svc_id)%(sizeof(u32))))
 
-#define SVCMAP(x, y, len) \
+#define SVCMAP(x, y) \
 	do { \
-		if (WMI_SERVICE_IS_ENABLED((in), (x), (len))) \
+		if (WMI_SERVICE_IS_ENABLED((in), (x))) \
 			__set_bit(y, out); \
 	} while (0)
 
-static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
-				   size_t len)
+static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out)
 {
 	SVCMAP(WMI_10X_SERVICE_BEACON_OFFLOAD,
-	       WMI_SERVICE_BEACON_OFFLOAD, len);
+	       WMI_SERVICE_BEACON_OFFLOAD);
 	SVCMAP(WMI_10X_SERVICE_SCAN_OFFLOAD,
-	       WMI_SERVICE_SCAN_OFFLOAD, len);
+	       WMI_SERVICE_SCAN_OFFLOAD);
 	SVCMAP(WMI_10X_SERVICE_ROAM_OFFLOAD,
-	       WMI_SERVICE_ROAM_OFFLOAD, len);
+	       WMI_SERVICE_ROAM_OFFLOAD);
 	SVCMAP(WMI_10X_SERVICE_BCN_MISS_OFFLOAD,
-	       WMI_SERVICE_BCN_MISS_OFFLOAD, len);
+	       WMI_SERVICE_BCN_MISS_OFFLOAD);
 	SVCMAP(WMI_10X_SERVICE_STA_PWRSAVE,
-	       WMI_SERVICE_STA_PWRSAVE, len);
+	       WMI_SERVICE_STA_PWRSAVE);
 	SVCMAP(WMI_10X_SERVICE_STA_ADVANCED_PWRSAVE,
-	       WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
+	       WMI_SERVICE_STA_ADVANCED_PWRSAVE);
 	SVCMAP(WMI_10X_SERVICE_AP_UAPSD,
-	       WMI_SERVICE_AP_UAPSD, len);
+	       WMI_SERVICE_AP_UAPSD);
 	SVCMAP(WMI_10X_SERVICE_AP_DFS,
-	       WMI_SERVICE_AP_DFS, len);
+	       WMI_SERVICE_AP_DFS);
 	SVCMAP(WMI_10X_SERVICE_11AC,
-	       WMI_SERVICE_11AC, len);
+	       WMI_SERVICE_11AC);
 	SVCMAP(WMI_10X_SERVICE_BLOCKACK,
-	       WMI_SERVICE_BLOCKACK, len);
+	       WMI_SERVICE_BLOCKACK);
 	SVCMAP(WMI_10X_SERVICE_PHYERR,
-	       WMI_SERVICE_PHYERR, len);
+	       WMI_SERVICE_PHYERR);
 	SVCMAP(WMI_10X_SERVICE_BCN_FILTER,
-	       WMI_SERVICE_BCN_FILTER, len);
+	       WMI_SERVICE_BCN_FILTER);
 	SVCMAP(WMI_10X_SERVICE_RTT,
-	       WMI_SERVICE_RTT, len);
+	       WMI_SERVICE_RTT);
 	SVCMAP(WMI_10X_SERVICE_RATECTRL,
-	       WMI_SERVICE_RATECTRL, len);
+	       WMI_SERVICE_RATECTRL);
 	SVCMAP(WMI_10X_SERVICE_WOW,
-	       WMI_SERVICE_WOW, len);
+	       WMI_SERVICE_WOW);
 	SVCMAP(WMI_10X_SERVICE_RATECTRL_CACHE,
-	       WMI_SERVICE_RATECTRL_CACHE, len);
+	       WMI_SERVICE_RATECTRL_CACHE);
 	SVCMAP(WMI_10X_SERVICE_IRAM_TIDS,
-	       WMI_SERVICE_IRAM_TIDS, len);
+	       WMI_SERVICE_IRAM_TIDS);
 	SVCMAP(WMI_10X_SERVICE_BURST,
-	       WMI_SERVICE_BURST, len);
+	       WMI_SERVICE_BURST);
 	SVCMAP(WMI_10X_SERVICE_SMART_ANTENNA_SW_SUPPORT,
-	       WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT, len);
+	       WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT);
 	SVCMAP(WMI_10X_SERVICE_FORCE_FW_HANG,
-	       WMI_SERVICE_FORCE_FW_HANG, len);
+	       WMI_SERVICE_FORCE_FW_HANG);
 	SVCMAP(WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
-	       WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT, len);
+	       WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT);
 }
 
-static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
-				    size_t len)
+static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out)
 {
 	SVCMAP(WMI_MAIN_SERVICE_BEACON_OFFLOAD,
-	       WMI_SERVICE_BEACON_OFFLOAD, len);
+	       WMI_SERVICE_BEACON_OFFLOAD);
 	SVCMAP(WMI_MAIN_SERVICE_SCAN_OFFLOAD,
-	       WMI_SERVICE_SCAN_OFFLOAD, len);
+	       WMI_SERVICE_SCAN_OFFLOAD);
 	SVCMAP(WMI_MAIN_SERVICE_ROAM_OFFLOAD,
-	       WMI_SERVICE_ROAM_OFFLOAD, len);
+	       WMI_SERVICE_ROAM_OFFLOAD);
 	SVCMAP(WMI_MAIN_SERVICE_BCN_MISS_OFFLOAD,
-	       WMI_SERVICE_BCN_MISS_OFFLOAD, len);
+	       WMI_SERVICE_BCN_MISS_OFFLOAD);
 	SVCMAP(WMI_MAIN_SERVICE_STA_PWRSAVE,
-	       WMI_SERVICE_STA_PWRSAVE, len);
+	       WMI_SERVICE_STA_PWRSAVE);
 	SVCMAP(WMI_MAIN_SERVICE_STA_ADVANCED_PWRSAVE,
-	       WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
+	       WMI_SERVICE_STA_ADVANCED_PWRSAVE);
 	SVCMAP(WMI_MAIN_SERVICE_AP_UAPSD,
-	       WMI_SERVICE_AP_UAPSD, len);
+	       WMI_SERVICE_AP_UAPSD);
 	SVCMAP(WMI_MAIN_SERVICE_AP_DFS,
-	       WMI_SERVICE_AP_DFS, len);
+	       WMI_SERVICE_AP_DFS);
 	SVCMAP(WMI_MAIN_SERVICE_11AC,
-	       WMI_SERVICE_11AC, len);
+	       WMI_SERVICE_11AC);
 	SVCMAP(WMI_MAIN_SERVICE_BLOCKACK,
-	       WMI_SERVICE_BLOCKACK, len);
+	       WMI_SERVICE_BLOCKACK);
 	SVCMAP(WMI_MAIN_SERVICE_PHYERR,
-	       WMI_SERVICE_PHYERR, len);
+	       WMI_SERVICE_PHYERR);
 	SVCMAP(WMI_MAIN_SERVICE_BCN_FILTER,
-	       WMI_SERVICE_BCN_FILTER, len);
+	       WMI_SERVICE_BCN_FILTER);
 	SVCMAP(WMI_MAIN_SERVICE_RTT,
-	       WMI_SERVICE_RTT, len);
+	       WMI_SERVICE_RTT);
 	SVCMAP(WMI_MAIN_SERVICE_RATECTRL,
-	       WMI_SERVICE_RATECTRL, len);
+	       WMI_SERVICE_RATECTRL);
 	SVCMAP(WMI_MAIN_SERVICE_WOW,
-	       WMI_SERVICE_WOW, len);
+	       WMI_SERVICE_WOW);
 	SVCMAP(WMI_MAIN_SERVICE_RATECTRL_CACHE,
-	       WMI_SERVICE_RATECTRL_CACHE, len);
+	       WMI_SERVICE_RATECTRL_CACHE);
 	SVCMAP(WMI_MAIN_SERVICE_IRAM_TIDS,
-	       WMI_SERVICE_IRAM_TIDS, len);
+	       WMI_SERVICE_IRAM_TIDS);
 	SVCMAP(WMI_MAIN_SERVICE_ARPNS_OFFLOAD,
-	       WMI_SERVICE_ARPNS_OFFLOAD, len);
+	       WMI_SERVICE_ARPNS_OFFLOAD);
 	SVCMAP(WMI_MAIN_SERVICE_NLO,
-	       WMI_SERVICE_NLO, len);
+	       WMI_SERVICE_NLO);
 	SVCMAP(WMI_MAIN_SERVICE_GTK_OFFLOAD,
-	       WMI_SERVICE_GTK_OFFLOAD, len);
+	       WMI_SERVICE_GTK_OFFLOAD);
 	SVCMAP(WMI_MAIN_SERVICE_SCAN_SCH,
-	       WMI_SERVICE_SCAN_SCH, len);
+	       WMI_SERVICE_SCAN_SCH);
 	SVCMAP(WMI_MAIN_SERVICE_CSA_OFFLOAD,
-	       WMI_SERVICE_CSA_OFFLOAD, len);
+	       WMI_SERVICE_CSA_OFFLOAD);
 	SVCMAP(WMI_MAIN_SERVICE_CHATTER,
-	       WMI_SERVICE_CHATTER, len);
+	       WMI_SERVICE_CHATTER);
 	SVCMAP(WMI_MAIN_SERVICE_COEX_FREQAVOID,
-	       WMI_SERVICE_COEX_FREQAVOID, len);
+	       WMI_SERVICE_COEX_FREQAVOID);
 	SVCMAP(WMI_MAIN_SERVICE_PACKET_POWER_SAVE,
-	       WMI_SERVICE_PACKET_POWER_SAVE, len);
+	       WMI_SERVICE_PACKET_POWER_SAVE);
 	SVCMAP(WMI_MAIN_SERVICE_FORCE_FW_HANG,
-	       WMI_SERVICE_FORCE_FW_HANG, len);
+	       WMI_SERVICE_FORCE_FW_HANG);
 	SVCMAP(WMI_MAIN_SERVICE_GPIO,
-	       WMI_SERVICE_GPIO, len);
+	       WMI_SERVICE_GPIO);
 	SVCMAP(WMI_MAIN_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
-	       WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM, len);
+	       WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM);
 	SVCMAP(WMI_MAIN_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
-	       WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG, len);
+	       WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG);
 	SVCMAP(WMI_MAIN_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
-	       WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG, len);
+	       WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG);
 	SVCMAP(WMI_MAIN_SERVICE_STA_KEEP_ALIVE,
-	       WMI_SERVICE_STA_KEEP_ALIVE, len);
+	       WMI_SERVICE_STA_KEEP_ALIVE);
 	SVCMAP(WMI_MAIN_SERVICE_TX_ENCAP,
-	       WMI_SERVICE_TX_ENCAP, len);
+	       WMI_SERVICE_TX_ENCAP);
 }
 
 #undef SVCMAP
@@ -1431,11 +1428,11 @@
 	 * where FW can access this memory directly (or) by DMA.
 	 */
 	__le32 num_mem_reqs;
-	struct wlan_host_mem_req mem_reqs[0];
+	struct wlan_host_mem_req mem_reqs[1];
 } __packed;
 
 /* This is the definition from 10.X firmware branch */
-struct wmi_10x_service_ready_event {
+struct wmi_service_ready_event_10x {
 	__le32 sw_version;
 	__le32 abi_version;
 
@@ -1470,7 +1467,7 @@
 	 */
 	__le32 num_mem_reqs;
 
-	struct wlan_host_mem_req mem_reqs[0];
+	struct wlan_host_mem_req mem_reqs[1];
 } __packed;
 
 #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
@@ -1886,26 +1883,38 @@
 	__le32 size;
 } __packed;
 
-struct wmi_host_mem_chunks {
-	__le32 count;
-	/* some fw revisions require at least 1 chunk regardless of count */
-	struct host_memory_chunk items[1];
-} __packed;
-
 struct wmi_init_cmd {
 	struct wmi_resource_config resource_config;
-	struct wmi_host_mem_chunks mem_chunks;
+	__le32 num_host_mem_chunks;
+
+	/*
+	 * variable number of host memory chunks.
+	 * This should be the last element in the structure
+	 */
+	struct host_memory_chunk host_mem_chunks[1];
 } __packed;
 
 /* _10x stucture is from 10.X FW API */
 struct wmi_init_cmd_10x {
 	struct wmi_resource_config_10x resource_config;
-	struct wmi_host_mem_chunks mem_chunks;
+	__le32 num_host_mem_chunks;
+
+	/*
+	 * variable number of host memory chunks.
+	 * This should be the last element in the structure
+	 */
+	struct host_memory_chunk host_mem_chunks[1];
 } __packed;
 
 struct wmi_init_cmd_10_2 {
 	struct wmi_resource_config_10_2 resource_config;
-	struct wmi_host_mem_chunks mem_chunks;
+	__le32 num_host_mem_chunks;
+
+	/*
+	 * variable number of host memory chunks.
+	 * This should be the last element in the structure
+	 */
+	struct host_memory_chunk host_mem_chunks[1];
 } __packed;
 
 struct wmi_chan_list_entry {
@@ -1955,11 +1964,6 @@
 #define WLAN_SCAN_PARAMS_MAX_BSSID   4
 #define WLAN_SCAN_PARAMS_MAX_IE_LEN  256
 
-/* Values lower than this may be refused by some firmware revisions with a scan
- * completion with a timedout reason.
- */
-#define WMI_SCAN_CHAN_MIN_TIME_MSEC 40
-
 /* Scan priority numbers must be sequential, starting with 0 */
 enum wmi_scan_priority {
 	WMI_SCAN_PRIORITY_VERY_LOW = 0,
@@ -1970,7 +1974,7 @@
 	WMI_SCAN_PRIORITY_COUNT   /* number of priorities supported */
 };
 
-struct wmi_start_scan_common {
+struct wmi_start_scan_cmd {
 	/* Scan ID */
 	__le32 scan_id;
 	/* Scan requestor ID */
@@ -2028,25 +2032,95 @@
 	__le32 probe_delay;
 	/* Scan control flags */
 	__le32 scan_ctrl_flags;
-} __packed;
 
-struct wmi_start_scan_tlvs {
-	/* TLV parameters. These includes channel list, ssid list, bssid list,
-	 * extra ies.
+	/* Burst duration time in msecs */
+	__le32 burst_duration;
+	/*
+	 * TLV (tag length value )  paramerters follow the scan_cmd structure.
+	 * TLV can contain channel list, bssid list, ssid list and
+	 * ie. the TLV tags are defined above;
 	 */
-	u8 tlvs[0];
-} __packed;
-
-struct wmi_start_scan_cmd {
-	struct wmi_start_scan_common common;
-	__le32 burst_duration_ms;
-	struct wmi_start_scan_tlvs tlvs;
 } __packed;
 
 /* This is the definition from 10.X firmware branch */
-struct wmi_10x_start_scan_cmd {
-	struct wmi_start_scan_common common;
-	struct wmi_start_scan_tlvs tlvs;
+struct wmi_start_scan_cmd_10x {
+	/* Scan ID */
+	__le32 scan_id;
+
+	/* Scan requestor ID */
+	__le32 scan_req_id;
+
+	/* VDEV id(interface) that is requesting scan */
+	__le32 vdev_id;
+
+	/* Scan Priority, input to scan scheduler */
+	__le32 scan_priority;
+
+	/* Scan events subscription */
+	__le32 notify_scan_events;
+
+	/* dwell time in msec on active channels */
+	__le32 dwell_time_active;
+
+	/* dwell time in msec on passive channels */
+	__le32 dwell_time_passive;
+
+	/*
+	 * min time in msec on the BSS channel,only valid if atleast one
+	 * VDEV is active
+	 */
+	__le32 min_rest_time;
+
+	/*
+	 * max rest time in msec on the BSS channel,only valid if at least
+	 * one VDEV is active
+	 */
+	/*
+	 * the scanner will rest on the bss channel at least min_rest_time
+	 * after min_rest_time the scanner will start checking for tx/rx
+	 * activity on all VDEVs. if there is no activity the scanner will
+	 * switch to off channel. if there is activity the scanner will let
+	 * the radio on the bss channel until max_rest_time expires.at
+	 * max_rest_time scanner will switch to off channel irrespective of
+	 * activity. activity is determined by the idle_time parameter.
+	 */
+	__le32 max_rest_time;
+
+	/*
+	 * time before sending next set of probe requests.
+	 * The scanner keeps repeating probe requests transmission with
+	 * period specified by repeat_probe_time.
+	 * The number of probe requests specified depends on the ssid_list
+	 * and bssid_list
+	 */
+	__le32 repeat_probe_time;
+
+	/* time in msec between 2 consequetive probe requests with in a set. */
+	__le32 probe_spacing_time;
+
+	/*
+	 * data inactivity time in msec on bss channel that will be used by
+	 * scanner for measuring the inactivity.
+	 */
+	__le32 idle_time;
+
+	/* maximum time in msec allowed for scan  */
+	__le32 max_scan_time;
+
+	/*
+	 * delay in msec before sending first probe request after switching
+	 * to a channel
+	 */
+	__le32 probe_delay;
+
+	/* Scan control flags */
+	__le32 scan_ctrl_flags;
+
+	/*
+	 * TLV (tag length value )  paramerters follow the scan_cmd structure.
+	 * TLV can contain channel list, bssid list, ssid list and
+	 * ie. the TLV tags are defined above;
+	 */
 } __packed;
 
 struct wmi_ssid_arg {
@@ -2232,25 +2306,94 @@
 #define PHY_ERROR_FALSE_RADAR_EXT		0x24
 #define PHY_ERROR_RADAR				0x05
 
-struct wmi_phyerr {
+struct wmi_single_phyerr_rx_hdr {
+	/* TSF timestamp */
 	__le32 tsf_timestamp;
+
+	/*
+	 * Current freq1, freq2
+	 *
+	 * [7:0]:    freq1[lo]
+	 * [15:8] :   freq1[hi]
+	 * [23:16]:   freq2[lo]
+	 * [31:24]:   freq2[hi]
+	 */
 	__le16 freq1;
 	__le16 freq2;
+
+	/*
+	 * Combined RSSI over all chains and channel width for this PHY error
+	 *
+	 * [7:0]: RSSI combined
+	 * [15:8]: Channel width (MHz)
+	 * [23:16]: PHY error code
+	 * [24:16]: reserved (future use)
+	 */
 	u8 rssi_combined;
 	u8 chan_width_mhz;
 	u8 phy_err_code;
 	u8 rsvd0;
-	__le32 rssi_chains[4];
-	__le16 nf_chains[4];
+
+	/*
+	 * RSSI on chain 0 through 3
+	 *
+	 * This is formatted the same as the PPDU_START RX descriptor
+	 * field:
+	 *
+	 * [7:0]:   pri20
+	 * [15:8]:  sec20
+	 * [23:16]: sec40
+	 * [31:24]: sec80
+	 */
+
+	__le32 rssi_chain0;
+	__le32 rssi_chain1;
+	__le32 rssi_chain2;
+	__le32 rssi_chain3;
+
+	/*
+	 * Last calibrated NF value for chain 0 through 3
+	 *
+	 * nf_list_1:
+	 *
+	 * + [15:0] - chain 0
+	 * + [31:16] - chain 1
+	 *
+	 * nf_list_2:
+	 *
+	 * + [15:0] - chain 2
+	 * + [31:16] - chain 3
+	 */
+	__le32 nf_list_1;
+	__le32 nf_list_2;
+
+	/* Length of the frame */
 	__le32 buf_len;
-	u8 buf[0];
 } __packed;
 
-struct wmi_phyerr_event {
-	__le32 num_phyerrs;
+struct wmi_single_phyerr_rx_event {
+	/* Phy error event header */
+	struct wmi_single_phyerr_rx_hdr hdr;
+	/* frame buffer */
+	u8 bufp[0];
+} __packed;
+
+struct wmi_comb_phyerr_rx_hdr {
+	/* Phy error phy error count */
+	__le32 num_phyerr_events;
 	__le32 tsf_l32;
 	__le32 tsf_u32;
-	struct wmi_phyerr phyerrs[0];
+} __packed;
+
+struct wmi_comb_phyerr_rx_event {
+	/* Phy error phy error count */
+	struct wmi_comb_phyerr_rx_hdr hdr;
+	/*
+	 * frame buffer - contains multiple payloads in the order:
+	 *                    header - payload, header - payload...
+	 *  (The header is of type: wmi_single_phyerr_rx_hdr)
+	 */
+	u8 bufp[0];
 } __packed;
 
 #define PHYERR_TLV_SIG				0xBB
@@ -2765,6 +2908,11 @@
 	WMI_TP_SCALE_SIZE   = 5,	/* max num of enum     */
 };
 
+struct wmi_set_channel_cmd {
+	/* channel (only frequency and mode info are used) */
+	struct wmi_channel chan;
+} __packed;
+
 struct wmi_pdev_chanlist_update_event {
 	/* number of channels */
 	__le32 num_chan;
@@ -2795,10 +2943,6 @@
 	struct wmi_channel chan;
 } __packed;
 
-struct wmi_pdev_pktlog_enable_cmd {
-	__le32 ev_bitmap;
-} __packed;
-
 /* Customize the DSCP (bit) to TID (0-7) mapping for QOS */
 #define WMI_DSCP_MAP_MAX    (64)
 struct wmi_pdev_set_dscp_tid_map_cmd {
@@ -3033,7 +3177,7 @@
  * PDEV statistics
  * TODO: add all PDEV stats here
  */
-struct wmi_pdev_stats {
+struct wmi_pdev_stats_old {
 	__le32 chan_nf;        /* Channel noise floor */
 	__le32 tx_frame_count; /* TX frame count */
 	__le32 rx_frame_count; /* RX frame count */
@@ -3044,8 +3188,15 @@
 	struct wal_dbg_stats wal; /* WAL dbg stats */
 } __packed;
 
-struct wmi_10x_pdev_stats {
-	struct wmi_pdev_stats old;
+struct wmi_pdev_stats_10x {
+	__le32 chan_nf;        /* Channel noise floor */
+	__le32 tx_frame_count; /* TX frame count */
+	__le32 rx_frame_count; /* RX frame count */
+	__le32 rx_clear_count; /* rx clear count */
+	__le32 cycle_count;    /* cycle count */
+	__le32 phy_err_count;  /* Phy error count */
+	__le32 chan_tx_pwr;    /* channel tx power */
+	struct wal_dbg_stats wal; /* WAL dbg stats */
 	__le32 ack_rx_bad;
 	__le32 rts_bad;
 	__le32 rts_good;
@@ -3066,14 +3217,16 @@
  * peer statistics.
  * TODO: add more stats
  */
-struct wmi_peer_stats {
+struct wmi_peer_stats_old {
 	struct wmi_mac_addr peer_macaddr;
 	__le32 peer_rssi;
 	__le32 peer_tx_rate;
 } __packed;
 
-struct wmi_10x_peer_stats {
-	struct wmi_peer_stats old;
+struct wmi_peer_stats_10x {
+	struct wmi_mac_addr peer_macaddr;
+	__le32 peer_rssi;
+	__le32 peer_tx_rate;
 	__le32 peer_rx_rate;
 } __packed;
 
@@ -4559,6 +4712,7 @@
 	__le32 config_valid;
 } __packed;
 
+#define ATH10K_RTS_MAX		2347
 #define ATH10K_FRAGMT_THRESHOLD_MIN	540
 #define ATH10K_FRAGMT_THRESHOLD_MAX	2346
 
@@ -4569,27 +4723,8 @@
 /* By default disable power save for IBSS */
 #define ATH10K_DEFAULT_ATIM 0
 
-#define WMI_MAX_MEM_REQS 16
-
-struct wmi_svc_rdy_ev_arg {
-	__le32 min_tx_power;
-	__le32 max_tx_power;
-	__le32 ht_cap;
-	__le32 vht_cap;
-	__le32 sw_ver0;
-	__le32 sw_ver1;
-	__le32 phy_capab;
-	__le32 num_rf_chains;
-	__le32 eeprom_rd;
-	__le32 num_mem_reqs;
-	const __le32 *service_map;
-	size_t service_map_len;
-	const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
-};
-
 struct ath10k;
 struct ath10k_vif;
-struct ath10k_fw_stats;
 
 int ath10k_wmi_attach(struct ath10k *ar);
 void ath10k_wmi_detach(struct ath10k *ar);
@@ -4601,6 +4736,8 @@
 struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
 int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
 
+int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
+				const struct wmi_channel_arg *);
 int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
 int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
 int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
@@ -4661,9 +4798,5 @@
 			     enum wmi_force_fw_hang_type type, u32 delay_ms);
 int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb);
 int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable);
-int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
-			     struct ath10k_fw_stats *stats);
-int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_list);
-int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar);
 
 #endif /* _WMI_H_ */
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index 85fe7d4..614737b 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -1,14 +1,13 @@
 config ATH5K
 	tristate "Atheros 5xxx wireless cards support"
 	depends on m
-	depends on (PCI || ATH25) && MAC80211
+	depends on PCI && MAC80211
 	select ATH_COMMON
 	select MAC80211_LEDS
-	select BPAUTO_LEDS_CLASS
-	select BPAUTO_NEW_LEDS
-	select BPAUTO_AVERAGE
-	select ATH5K_AHB if ATH25
-	select ATH5K_PCI if !ATH25
+	select BACKPORT_LEDS_CLASS
+	select BACKPORT_NEW_LEDS
+	select BACKPORT_AVERAGE
+	select ATH5K_PCI
 	---help---
 	  This module adds support for wireless adapters based on
 	  Atheros 5xxx chipset.
@@ -53,16 +52,9 @@
 
 	  If unsure, say N.
 
-config ATH5K_AHB
-	bool "Atheros 5xxx AHB bus support"
-	depends on ATH25
-	---help---
-	  This adds support for WiSoC type chipsets of the 5xxx Atheros
-	  family.
-
 config ATH5K_PCI
 	bool "Atheros 5xxx PCI bus support"
-	depends on (!ATH25 && PCI)
+	depends on PCI
 	---help---
 	  This adds support for PCI type chipsets of the 5xxx Atheros
 	  family.
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index 32a0f67..3c9c2ac 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -17,6 +17,5 @@
 ath5k-y				+= sysfs.o
 ath5k-y				+= mac80211-ops.o
 ath5k-$(CPTCFG_ATH5K_DEBUG)	+= debug.o
-ath5k-$(CPTCFG_ATH5K_AHB)	+= ahb.o
 ath5k-$(CPTCFG_ATH5K_PCI)	+= pci.o
 obj-$(CPTCFG_ATH5K)		+= ath5k.o
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
deleted file mode 100644
index 8f387cf..0000000
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/nl80211.h>
-#include <linux/platform_device.h>
-#include <linux/etherdevice.h>
-#include <linux/export.h>
-#include <ath25_platform.h>
-#include "ath5k.h"
-#include "debug.h"
-#include "base.h"
-#include "reg.h"
-
-/* return bus cachesize in 4B word units */
-static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
-{
-	*csz = L1_CACHE_BYTES >> 2;
-}
-
-static bool
-ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
-{
-	struct ath5k_hw *ah = common->priv;
-	struct platform_device *pdev = to_platform_device(ah->dev);
-	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
-	u16 *eeprom, *eeprom_end;
-
-	eeprom = (u16 *) bcfg->radio;
-	eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
-
-	eeprom += off;
-	if (eeprom > eeprom_end)
-		return false;
-
-	*data = *eeprom;
-	return true;
-}
-
-int ath5k_hw_read_srev(struct ath5k_hw *ah)
-{
-	struct platform_device *pdev = to_platform_device(ah->dev);
-	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
-	ah->ah_mac_srev = bcfg->devid;
-	return 0;
-}
-
-static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
-{
-	struct platform_device *pdev = to_platform_device(ah->dev);
-	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
-	u8 *cfg_mac;
-
-	if (to_platform_device(ah->dev)->id == 0)
-		cfg_mac = bcfg->config->wlan0_mac;
-	else
-		cfg_mac = bcfg->config->wlan1_mac;
-
-	memcpy(mac, cfg_mac, ETH_ALEN);
-	return 0;
-}
-
-static const struct ath_bus_ops ath_ahb_bus_ops = {
-	.ath_bus_type = ATH_AHB,
-	.read_cachesize = ath5k_ahb_read_cachesize,
-	.eeprom_read = ath5k_ahb_eeprom_read,
-	.eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
-};
-
-/*Initialization*/
-static int ath_ahb_probe(struct platform_device *pdev)
-{
-	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
-	struct ath5k_hw *ah;
-	struct ieee80211_hw *hw;
-	struct resource *res;
-	void __iomem *mem;
-	int irq;
-	int ret = 0;
-	u32 reg;
-
-	if (!dev_get_platdata(&pdev->dev)) {
-		dev_err(&pdev->dev, "no platform data specified\n");
-		ret = -EINVAL;
-		goto err_out;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no memory resource found\n");
-		ret = -ENXIO;
-		goto err_out;
-	}
-
-	mem = ioremap_nocache(res->start, resource_size(res));
-	if (mem == NULL) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_out;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no IRQ resource found\n");
-		ret = -ENXIO;
-		goto err_iounmap;
-	}
-
-	irq = res->start;
-
-	hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
-	if (hw == NULL) {
-		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
-		ret = -ENOMEM;
-		goto err_iounmap;
-	}
-
-	ah = hw->priv;
-	ah->hw = hw;
-	ah->dev = &pdev->dev;
-	ah->iobase = mem;
-	ah->irq = irq;
-	ah->devid = bcfg->devid;
-
-	if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
-		/* Enable WMAC AHB arbitration */
-		reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
-		reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
-		iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
-
-		/* Enable global WMAC swapping */
-		reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP);
-		reg |= AR5K_AR2315_BYTESWAP_WMAC;
-		iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
-	} else {
-		/* Enable WMAC DMA access (assuming 5312 or 231x*/
-		/* TODO: check other platforms */
-		reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
-		if (to_platform_device(ah->dev)->id == 0)
-			reg |= AR5K_AR5312_ENABLE_WLAN0;
-		else
-			reg |= AR5K_AR5312_ENABLE_WLAN1;
-		iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
-
-		/*
-		 * On a dual-band AR5312, the multiband radio is only
-		 * used as pass-through. Disable 2 GHz support in the
-		 * driver for it
-		 */
-		if (to_platform_device(ah->dev)->id == 0 &&
-		    (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
-		     (BD_WLAN1 | BD_WLAN0))
-			ah->ah_capabilities.cap_needs_2GHz_ovr = true;
-		else
-			ah->ah_capabilities.cap_needs_2GHz_ovr = false;
-	}
-
-	ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
-		ret = -ENODEV;
-		goto err_free_hw;
-	}
-
-	platform_set_drvdata(pdev, hw);
-
-	return 0;
-
- err_free_hw:
-	ieee80211_free_hw(hw);
- err_iounmap:
-        iounmap(mem);
- err_out:
-	return ret;
-}
-
-static int ath_ahb_remove(struct platform_device *pdev)
-{
-	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
-	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
-	struct ath5k_hw *ah;
-	u32 reg;
-
-	if (!hw)
-		return 0;
-
-	ah = hw->priv;
-
-	if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
-		/* Disable WMAC AHB arbitration */
-		reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
-		reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
-		iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
-	} else {
-		/*Stop DMA access */
-		reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
-		if (to_platform_device(ah->dev)->id == 0)
-			reg &= ~AR5K_AR5312_ENABLE_WLAN0;
-		else
-			reg &= ~AR5K_AR5312_ENABLE_WLAN1;
-		iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
-	}
-
-	ath5k_deinit_ah(ah);
-	iounmap(ah->iobase);
-	ieee80211_free_hw(hw);
-
-	return 0;
-}
-
-static struct platform_driver ath_ahb_driver = {
-	.probe      = ath_ahb_probe,
-	.remove     = ath_ahb_remove,
-	.driver		= {
-		.name	= "ar231x-wmac",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(ath_ahb_driver);
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index cc701f1..e43e883 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1647,32 +1647,6 @@
 	return &(ath5k_hw_common(ah)->regulatory);
 }
 
-#ifdef CPTCFG_ATH5K_AHB
-#define AR5K_AR2315_PCI_BASE	((void __iomem *)0xb0100000)
-
-static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
-{
-	/* On AR2315 and AR2317 the PCI clock domain registers
-	 * are outside of the WMAC register space */
-	if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
-	    (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
-		return AR5K_AR2315_PCI_BASE + reg;
-
-	return ah->iobase + reg;
-}
-
-static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
-{
-	return ioread32(ath5k_ahb_reg(ah, reg));
-}
-
-static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
-{
-	iowrite32(val, ath5k_ahb_reg(ah, reg));
-}
-
-#else
-
 static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
 {
 	return ioread32(ah->iobase + reg);
@@ -1683,8 +1657,6 @@
 	iowrite32(val, ah->iobase + reg);
 }
 
-#endif
-
 static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah)
 {
 	return ath5k_hw_common(ah)->bus_ops->ath_bus_type;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 65cc4b3..3f5fae0 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -99,15 +99,6 @@
 
 /* Known SREVs */
 static const struct ath5k_srev_name srev_names[] = {
-#ifdef CPTCFG_ATH5K_AHB
-	{ "5312",	AR5K_VERSION_MAC,	AR5K_SREV_AR5312_R2 },
-	{ "5312",	AR5K_VERSION_MAC,	AR5K_SREV_AR5312_R7 },
-	{ "2313",	AR5K_VERSION_MAC,	AR5K_SREV_AR2313_R8 },
-	{ "2315",	AR5K_VERSION_MAC,	AR5K_SREV_AR2315_R6 },
-	{ "2315",	AR5K_VERSION_MAC,	AR5K_SREV_AR2315_R7 },
-	{ "2317",	AR5K_VERSION_MAC,	AR5K_SREV_AR2317_R1 },
-	{ "2317",	AR5K_VERSION_MAC,	AR5K_SREV_AR2317_R2 },
-#else
 	{ "5210",	AR5K_VERSION_MAC,	AR5K_SREV_AR5210 },
 	{ "5311",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311 },
 	{ "5311A",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311A },
@@ -126,7 +117,6 @@
 	{ "5418",	AR5K_VERSION_MAC,	AR5K_SREV_AR5418 },
 	{ "2425",	AR5K_VERSION_MAC,	AR5K_SREV_AR2425 },
 	{ "2417",	AR5K_VERSION_MAC,	AR5K_SREV_AR2417 },
-#endif
 	{ "xxxxx",	AR5K_VERSION_MAC,	AR5K_SREV_UNKNOWN },
 	{ "5110",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5110 },
 	{ "5111",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5111 },
@@ -142,10 +132,6 @@
 	{ "5413",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5413 },
 	{ "5424",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5424 },
 	{ "5133",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5133 },
-#ifdef CPTCFG_ATH5K_AHB
-	{ "2316",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2316 },
-	{ "2317",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2317 },
-#endif
 	{ "xxxxx",	AR5K_VERSION_RAD,	AR5K_SREV_UNKNOWN },
 };
 
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 201d1de..0beb7e7 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -163,20 +163,14 @@
 {
 	int ret = 0;
 	struct ieee80211_hw *hw = ah->hw;
-#ifndef CPTCFG_ATH5K_AHB
 	struct pci_dev *pdev = ah->pdev;
-#endif
 	char name[ATH5K_LED_MAX_NAME_LEN + 1];
 	const struct pci_device_id *match;
 
 	if (!ah->pdev)
 		return 0;
 
-#ifdef CPTCFG_ATH5K_AHB
-	match = NULL;
-#else
 	match = pci_match_id(&ath5k_led_devices[0], pdev);
-#endif
 	if (match) {
 		__set_bit(ATH_STAT_LEDSOFT, ah->status);
 		ah->led_pin = ATH_PIN(match->driver_data);
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 19eab2a..ab2709a 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -547,9 +547,7 @@
 
 
 static void
-ath5k_sw_scan_start(struct ieee80211_hw *hw,
-		    struct ieee80211_vif *vif,
-		    const u8 *mac_addr)
+ath5k_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct ath5k_hw *ah = hw->priv;
 	if (!ah->assoc)
@@ -558,7 +556,7 @@
 
 
 static void
-ath5k_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+ath5k_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct ath5k_hw *ah = hw->priv;
 	ath5k_hw_set_ledstate(ah, ah->assoc ?
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index ddaad71..0583c69 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -225,7 +225,13 @@
 	} else {
 		switch (queue_type) {
 		case AR5K_TX_QUEUE_DATA:
-			queue = queue_info->tqi_subtype;
+			for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
+				ah->ah_txq[queue].tqi_type !=
+				AR5K_TX_QUEUE_INACTIVE; queue++) {
+
+				if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
+					return -EINVAL;
+			}
 			break;
 		case AR5K_TX_QUEUE_UAPSD:
 			queue = AR5K_TX_QUEUE_ID_UAPSD;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 03799d2..04d3c2e 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2976,11 +2976,11 @@
 static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
 static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
-			      struct station_del_parameters *params)
+			      const u8 *mac)
 {
 	struct ath6kl *ar = ath6kl_priv(dev);
 	struct ath6kl_vif *vif = netdev_priv(dev);
-	const u8 *addr = params->mac ? params->mac : bcast_addr;
+	const u8 *addr = mac ? mac : bcast_addr;
 
 	return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH,
 				      addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
index 4f82e86..05debf7 100644
--- a/drivers/net/wireless/ath/ath6kl/common.h
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -22,7 +22,7 @@
 
 #define ATH6KL_MAX_IE			256
 
-__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...);
+__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
 
 /*
  * Reflects the version of binary interface exposed by ATH6KL target
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index fc2b18a..f596535 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -37,64 +37,76 @@
 
 #define ATH6KL_FWLOG_VALID_MASK 0x1ffff
 
-void ath6kl_printk(const char *level, const char *fmt, ...)
+int ath6kl_printk(const char *level, const char *fmt, ...)
 {
 	struct va_format vaf;
 	va_list args;
+	int rtn;
 
 	va_start(args, fmt);
 
 	vaf.fmt = fmt;
 	vaf.va = &args;
 
-	printk("%sath6kl: %pV", level, &vaf);
+	rtn = printk("%sath6kl: %pV", level, &vaf);
 
 	va_end(args);
+
+	return rtn;
 }
 EXPORT_SYMBOL(ath6kl_printk);
 
-void ath6kl_info(const char *fmt, ...)
+int ath6kl_info(const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
+	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ath6kl_printk(KERN_INFO, "%pV", &vaf);
+	ret = ath6kl_printk(KERN_INFO, "%pV", &vaf);
 	trace_ath6kl_log_info(&vaf);
 	va_end(args);
+
+	return ret;
 }
 EXPORT_SYMBOL(ath6kl_info);
 
-void ath6kl_err(const char *fmt, ...)
+int ath6kl_err(const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
+	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ath6kl_printk(KERN_ERR, "%pV", &vaf);
+	ret = ath6kl_printk(KERN_ERR, "%pV", &vaf);
 	trace_ath6kl_log_err(&vaf);
 	va_end(args);
+
+	return ret;
 }
 EXPORT_SYMBOL(ath6kl_err);
 
-void ath6kl_warn(const char *fmt, ...)
+int ath6kl_warn(const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
+	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ath6kl_printk(KERN_WARNING, "%pV", &vaf);
+	ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf);
 	trace_ath6kl_log_warn(&vaf);
 	va_end(args);
+
+	return ret;
 }
 EXPORT_SYMBOL(ath6kl_warn);
 
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 5356e42..01debd4 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -50,10 +50,10 @@
 };
 
 extern unsigned int debug_mask;
-__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...);
-__printf(1, 2) void ath6kl_info(const char *fmt, ...);
-__printf(1, 2) void ath6kl_err(const char *fmt, ...);
-__printf(1, 2) void ath6kl_warn(const char *fmt, ...);
+__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
+__printf(1, 2) int ath6kl_info(const char *fmt, ...);
+__printf(1, 2) int ath6kl_err(const char *fmt, ...);
+__printf(1, 2) int ath6kl_warn(const char *fmt, ...);
 
 enum ath6kl_war {
 	ATH6KL_WAR_INVALID_RATE,
@@ -81,9 +81,10 @@
 void ath6kl_debug_cleanup(struct ath6kl *ar);
 
 #else
-static inline void ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
-			      const char *fmt, ...)
+static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
+			     const char *fmt, ...)
 {
+	return 0;
 }
 
 static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index a0b89b5..af439e7 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -1193,10 +1193,18 @@
 	return 0;
 }
 
+static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf)
+{
+	if (usb_get_intfdata(intf))
+		ath6kl_usb_remove(intf);
+	return 0;
+}
+
 #else
 
 #define ath6kl_usb_pm_suspend NULL
 #define ath6kl_usb_pm_resume NULL
+#define ath6kl_usb_pm_reset_resume NULL
 
 #endif
 
@@ -1214,6 +1222,7 @@
 	.probe = ath6kl_usb_probe,
 	.suspend = ath6kl_usb_pm_suspend,
 	.resume = ath6kl_usb_pm_resume,
+	.reset_resume = ath6kl_usb_pm_reset_resume,
 	.disconnect = ath6kl_usb_remove,
 	.id_table = ath6kl_usb_ids,
 	.supports_autosuspend = true,
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 9d490f2..1acecc2 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -5,8 +5,6 @@
 	tristate
 	depends on m
 	select ATH_COMMON
-	depends on DEBUG_FS
-	depends on RELAY
 config ATH9K_DFS_DEBUGFS
 	def_bool y
 	depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED
@@ -25,8 +23,8 @@
 	depends on MAC80211 && HAS_DMA
 	select ATH9K_HW
 	select MAC80211_LEDS
-	select BPAUTO_LEDS_CLASS
-	select BPAUTO_NEW_LEDS
+	select BACKPORT_LEDS_CLASS
+	select BACKPORT_NEW_LEDS
 	select ATH9K_COMMON
 	---help---
 	  This module adds support for wireless adapters based on
@@ -153,19 +151,14 @@
 	 for multi-channel concurrency. Enable this if P2P PowerSave support
 	 is required.
 
-config ATH9K_PCOEM
-	bool "Atheros ath9k support for PC OEM cards" if EXPERT
-	depends on ATH9K
-	default y
-
 config ATH9K_HTC
        tristate "Atheros HTC based wireless cards support"
        depends on m
        depends on USB && MAC80211
        select ATH9K_HW
        select MAC80211_LEDS
-       select BPAUTO_LEDS_CLASS
-       select BPAUTO_NEW_LEDS
+       select BACKPORT_LEDS_CLASS
+       select BACKPORT_NEW_LEDS
        select ATH9K_COMMON
        ---help---
 	 Support for Atheros HTC based cards.
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 18e21a8..ccee747 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -16,7 +16,8 @@
 ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o
 ath9k-$(CPTCFG_ATH9K_WOW) += wow.o
 
-ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o
+ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o \
+				 spectral.o
 
 ath9k-$(CPTCFG_ATH9K_STATION_STATISTICS) += debug_sta.o
 
@@ -31,6 +32,7 @@
 		ar5008_phy.o \
 		ar9002_calib.o \
 		ar9003_calib.o \
+		ar9003_rtt.o \
 		calib.o \
 		eeprom.o \
 		eeprom_def.o \
@@ -48,8 +50,6 @@
 ath9k_hw-$(CPTCFG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
 					   ar9003_mci.o
 
-ath9k_hw-$(CPTCFG_ATH9K_PCOEM) += ar9003_rtt.o
-
 ath9k_hw-$(CPTCFG_ATH9K_DYNACK) += dynack.o
 
 obj-$(CPTCFG_ATH9K_HW) += ath9k_hw.o
@@ -58,8 +58,7 @@
 ath9k_common-y:=	common.o \
 			common-init.o \
 			common-beacon.o \
-			common-debug.o \
-			common-spectral.o
+			common-debug.o
 
 ath9k_htc-y +=	htc_hst.o \
 		hif_usb.o \
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index e000c4c..4173838 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -175,6 +175,7 @@
 	.remove     = ath_ahb_remove,
 	.driver		= {
 		.name	= "ath9k",
+		.owner	= THIS_MODULE,
 	},
 	.id_table    = ath9k_platform_id_table,
 };
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 5829074..b72d0be 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -1190,7 +1190,7 @@
 static void ar5008_hw_set_radar_params(struct ath_hw *ah,
 				       struct ath_hw_radar_conf *conf)
 {
-	u32 radar_0 = 0, radar_1;
+	u32 radar_0 = 0, radar_1 = 0;
 
 	if (!conf) {
 		REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
@@ -1204,9 +1204,6 @@
 	radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
 	radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
 
-	radar_1 = REG_READ(ah, AR_PHY_RADAR_1);
-	radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH |
-		     AR_PHY_RADAR_1_RELPWR_THRESH);
 	radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
 	radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
 	radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
@@ -1228,7 +1225,7 @@
 	conf->fir_power = -33;
 	conf->radar_rssi = 20;
 	conf->pulse_height = 10;
-	conf->pulse_rssi = 15;
+	conf->pulse_rssi = 24;
 	conf->pulse_inband = 15;
 	conf->pulse_maxlen = 255;
 	conf->pulse_inband_step = 12;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 42190b6..cdc7400 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -657,29 +657,31 @@
 		ar9280_hw_olc_temp_compensation(ah);
 }
 
-static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
-			       u8 rxchainmask, bool longcal)
+static bool ar9002_hw_calibrate(struct ath_hw *ah,
+				struct ath9k_channel *chan,
+				u8 rxchainmask,
+				bool longcal)
 {
+	bool iscaldone = true;
 	struct ath9k_cal_list *currCal = ah->cal_list_curr;
-	bool nfcal, nfcal_pending = false, percal_pending;
-	int ret;
+	bool nfcal, nfcal_pending = false;
 
 	nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
 	if (ah->caldata)
 		nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
 
-	percal_pending = (currCal &&
-			  (currCal->calState == CAL_RUNNING ||
-			   currCal->calState == CAL_WAITING));
+	if (currCal && !nfcal &&
+	    (currCal->calState == CAL_RUNNING ||
+	     currCal->calState == CAL_WAITING)) {
+		iscaldone = ar9002_hw_per_calibration(ah, chan,
+						      rxchainmask, currCal);
+		if (iscaldone) {
+			ah->cal_list_curr = currCal = currCal->calNext;
 
-	if (percal_pending && !nfcal) {
-		if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal))
-			return 0;
-
-		ah->cal_list_curr = currCal = currCal->calNext;
-		if (currCal->calState == CAL_WAITING) {
-			ath9k_hw_reset_calibration(ah, currCal);
-			return 0;
+			if (currCal->calState == CAL_WAITING) {
+				iscaldone = false;
+				ath9k_hw_reset_calibration(ah, currCal);
+			}
 		}
 	}
 
@@ -696,9 +698,7 @@
 			 * NF is slow time-variant, so it is OK to use a
 			 * historical value.
 			 */
-			ret = ath9k_hw_loadnf(ah, ah->curchan);
-			if (ret < 0)
-				return ret;
+			ath9k_hw_loadnf(ah, ah->curchan);
 		}
 
 		if (longcal) {
@@ -709,7 +709,7 @@
 		}
 	}
 
-	return !percal_pending;
+	return iscaldone;
 }
 
 /* Carrier leakage Calibration fix */
@@ -856,8 +856,6 @@
 
 	/* Do PA Calibration */
 	ar9002_hw_pa_cal(ah, true);
-	ath9k_hw_loadnf(ah, chan);
-	ath9k_hw_start_nfcal(ah, true);
 
 	if (ah->caldata)
 		set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index f816909..2a93519 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -281,7 +281,7 @@
 
 	ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
 		| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-		| SM(i->txpower[0], AR_XmitPower0)
+		| SM(i->txpower, AR_XmitPower0)
 		| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
 		| (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
 		| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
@@ -307,9 +307,9 @@
 		| set11nRateFlags(i->rates, 3)
 		| SM(i->rtscts_rate, AR_RTSCTSRate);
 
-	ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower[1], AR_XmitPower1);
-	ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower[2], AR_XmitPower2);
-	ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower[3], AR_XmitPower3);
+	ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower, AR_XmitPower1);
+	ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower, AR_XmitPower2);
+	ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower, AR_XmitPower3);
 }
 
 static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index 757e0e0..5d71361 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -643,12 +643,9 @@
 	 * and fix otherwise.
 	 */
 	count = param->count;
-	if (param->endless) {
-		if (AR_SREV_9271(ah))
-			count = 0;
-		else
-			count = 0x80;
-	} else if (count & 0x80)
+	if (param->endless)
+		count = 0x80;
+	else if (count & 0x80)
 		count = 0x7f;
 
 	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 06ab71d..ac8301e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -121,12 +121,13 @@
 	return iscaldone;
 }
 
-static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
-			       u8 rxchainmask, bool longcal)
+static bool ar9003_hw_calibrate(struct ath_hw *ah,
+				struct ath9k_channel *chan,
+				u8 rxchainmask,
+				bool longcal)
 {
 	bool iscaldone = true;
 	struct ath9k_cal_list *currCal = ah->cal_list_curr;
-	int ret;
 
 	/*
 	 * For given calibration:
@@ -162,9 +163,7 @@
 		 * NF is slow time-variant, so it is OK to use a historical
 		 * value.
 		 */
-		ret = ath9k_hw_loadnf(ah, ah->curchan);
-		if (ret < 0)
-			return ret;
+		ath9k_hw_loadnf(ah, ah->curchan);
 
 		/* start NF calibration, without updating BB NF register */
 		ath9k_hw_start_nfcal(ah, false);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 278afac..ceafa9a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -4079,28 +4079,27 @@
 
 static void ar9003_hw_thermometer_apply(struct ath_hw *ah)
 {
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	int thermometer = ar9003_hw_get_thermometer(ah);
 	u8 therm_on = (thermometer < 0) ? 0 : 1;
 
 	REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4,
 		      AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
-	if (pCap->chip_chainmask & BIT(1))
+	if (ah->caps.tx_chainmask & BIT(1))
 		REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4,
 			      AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
-	if (pCap->chip_chainmask & BIT(2))
+	if (ah->caps.tx_chainmask & BIT(2))
 		REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
 			      AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
 
 	therm_on = (thermometer < 0) ? 0 : (thermometer == 0);
 	REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4,
 		      AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
-	if (pCap->chip_chainmask & BIT(1)) {
+	if (ah->caps.tx_chainmask & BIT(1)) {
 		therm_on = (thermometer < 0) ? 0 : (thermometer == 1);
 		REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4,
 			      AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
 	}
-	if (pCap->chip_chainmask & BIT(2)) {
+	if (ah->caps.tx_chainmask & BIT(2)) {
 		therm_on = (thermometer < 0) ? 0 : (thermometer == 2);
 		REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
 			      AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
@@ -4377,25 +4376,6 @@
 						 targetPowerArray, numPiers);
 }
 
-static void ar9003_hw_selfgen_tpc_txpower(struct ath_hw *ah,
-					  struct ath9k_channel *chan,
-					  u8 *pwr_array)
-{
-	u32 val;
-
-	/* target power values for self generated frames (ACK,RTS/CTS) */
-	if (IS_CHAN_2GHZ(chan)) {
-		val = SM(pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_ACK) |
-		      SM(pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_CTS) |
-		      SM(0x3f, AR_TPC_CHIRP) | SM(0x3f, AR_TPC_RPT);
-	} else {
-		val = SM(pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_ACK) |
-		      SM(pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_CTS) |
-		      SM(0x3f, AR_TPC_CHIRP) | SM(0x3f, AR_TPC_RPT);
-	}
-	REG_WRITE(ah, AR_TPC, val);
-}
-
 /* Set tx power registers to array of values passed in */
 static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 {
@@ -5331,7 +5311,6 @@
 	struct ar9300_modal_eep_header *modal_hdr;
 	u8 targetPowerValT2[ar9300RateSize];
 	u8 target_power_val_t2_eep[ar9300RateSize];
-	u8 targetPowerValT2_tpc[ar9300RateSize];
 	unsigned int i = 0, paprd_scale_factor = 0;
 	u8 pwr_idx, min_pwridx = 0;
 
@@ -5383,9 +5362,6 @@
 					   twiceAntennaReduction,
 					   powerLimit);
 
-	memcpy(targetPowerValT2_tpc, targetPowerValT2,
-	       sizeof(targetPowerValT2));
-
 	if (ar9003_is_paprd_enabled(ah)) {
 		for (i = 0; i < ar9300RateSize; i++) {
 			if ((ah->paprd_ratemask & (1 << i)) &&
@@ -5419,30 +5395,6 @@
 	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
 	ar9003_hw_calibration_apply(ah, chan->channel);
 	ar9003_paprd_set_txpower(ah, chan, targetPowerValT2);
-
-	ar9003_hw_selfgen_tpc_txpower(ah, chan, targetPowerValT2);
-
-	/* TPC initializations */
-	if (ah->tpc_enabled) {
-		u32 val;
-
-		ar9003_hw_init_rate_txpower(ah, targetPowerValT2_tpc, chan);
-
-		/* Enable TPC */
-		REG_WRITE(ah, AR_PHY_PWRTX_MAX,
-			  AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
-		/* Disable per chain power reduction */
-		val = REG_READ(ah, AR_PHY_POWER_TX_SUB);
-		if (AR_SREV_9340(ah))
-			REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
-				  val & 0xFFFFFFC0);
-		else
-			REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
-				  val & 0xFFFFF000);
-	} else {
-		/* Disable TPC */
-		REG_WRITE(ah, AR_PHY_PWRTX_MAX, 0);
-	}
 }
 
 static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 06ad217..ddef9ee 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -333,29 +333,12 @@
 			       qca953x_1p0_soc_preamble);
 		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
 			       qca953x_1p0_soc_postamble);
-
-		if (AR_SREV_9531_20(ah)) {
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-				       qca953x_2p0_common_wo_xlna_rx_gain_table);
-			INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
-				       qca953x_2p0_common_wo_xlna_rx_gain_bounds);
-		} else {
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-				       qca953x_1p0_common_wo_xlna_rx_gain_table);
-			INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
-				       qca953x_1p0_common_wo_xlna_rx_gain_bounds);
-		}
-
-		if (AR_SREV_9531_20(ah))
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       qca953x_2p0_modes_no_xpa_tx_gain_table);
-		else if (AR_SREV_9531_11(ah))
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       qca953x_1p1_modes_no_xpa_tx_gain_table);
-		else
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       qca953x_1p0_modes_no_xpa_tx_gain_table);
-
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+			       qca953x_1p0_common_wo_xlna_rx_gain_table);
+		INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
+			       qca953x_1p0_common_wo_xlna_rx_gain_bounds);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			       qca953x_1p0_modes_no_xpa_tx_gain_table);
 		INIT_INI_ARRAY(&ah->iniModesFastClock,
 			       qca953x_1p0_modes_fast_clock);
 	} else if (AR_SREV_9580(ah)) {
@@ -535,15 +518,9 @@
 	else if (AR_SREV_9550(ah))
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 			ar955x_1p0_modes_xpa_tx_gain_table);
-	else if (AR_SREV_9531_10(ah))
+	else if (AR_SREV_9531(ah))
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
-			       qca953x_1p0_modes_xpa_tx_gain_table);
-	else if (AR_SREV_9531_11(ah))
-		INIT_INI_ARRAY(&ah->iniModesTxGain,
-			       qca953x_1p1_modes_xpa_tx_gain_table);
-	else if (AR_SREV_9531_20(ah))
-		INIT_INI_ARRAY(&ah->iniModesTxGain,
-			       qca953x_2p0_modes_xpa_tx_gain_table);
+			qca953x_1p0_modes_xpa_tx_gain_table);
 	else if (AR_SREV_9580(ah))
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 			ar9580_1p0_lowest_ob_db_tx_gain_table);
@@ -585,10 +562,7 @@
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 			ar955x_1p0_modes_no_xpa_tx_gain_table);
 	else if (AR_SREV_9531(ah)) {
-		if (AR_SREV_9531_20(ah))
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       qca953x_2p0_modes_no_xpa_tx_gain_table);
-		else if (AR_SREV_9531_11(ah))
+		if (AR_SREV_9531_11(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       qca953x_1p1_modes_no_xpa_tx_gain_table);
 		else
@@ -696,6 +670,9 @@
 	if (AR_SREV_9485_11_OR_LATER(ah))
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 			ar9485Modes_green_ob_db_tx_gain_1_1);
+	else if (AR_SREV_9340(ah))
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			ar9340Modes_ub124_tx_gain_table_1p0);
 	else if (AR_SREV_9580(ah))
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 			ar9580_1p0_type5_tx_gain_table);
@@ -815,16 +792,11 @@
 			ar955x_1p0_common_wo_xlna_rx_gain_table);
 		INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
 			ar955x_1p0_common_wo_xlna_rx_gain_bounds);
-	} else if (AR_SREV_9531_10(ah) || AR_SREV_9531_11(ah)) {
+	} else if (AR_SREV_9531(ah)) {
 		INIT_INI_ARRAY(&ah->iniModesRxGain,
 			       qca953x_1p0_common_wo_xlna_rx_gain_table);
 		INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
 			       qca953x_1p0_common_wo_xlna_rx_gain_bounds);
-	} else if (AR_SREV_9531_20(ah)) {
-		INIT_INI_ARRAY(&ah->iniModesRxGain,
-			       qca953x_2p0_common_wo_xlna_rx_gain_table);
-		INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
-			       qca953x_2p0_common_wo_xlna_rx_gain_bounds);
 	} else if (AR_SREV_9580(ah))
 		INIT_INI_ARRAY(&ah->iniModesRxGain,
 			ar9580_1p0_wo_xlna_rx_gain_table);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index da84b70..057b165 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -101,7 +101,7 @@
 
 	ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
 		| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-		| SM(i->txpower[0], AR_XmitPower0)
+		| SM(i->txpower, AR_XmitPower0)
 		| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
 		| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
 		| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
@@ -152,9 +152,9 @@
 
 	ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
 
-	ACCESS_ONCE(ads->ctl20) = SM(i->txpower[1], AR_XmitPower1);
-	ACCESS_ONCE(ads->ctl21) = SM(i->txpower[2], AR_XmitPower2);
-	ACCESS_ONCE(ads->ctl22) = SM(i->txpower[3], AR_XmitPower3);
+	ACCESS_ONCE(ads->ctl20) = SM(i->txpower, AR_XmitPower1);
+	ACCESS_ONCE(ads->ctl21) = SM(i->txpower, AR_XmitPower2);
+	ACCESS_ONCE(ads->ctl22) = SM(i->txpower, AR_XmitPower3);
 }
 
 static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index d20a39e..fbe3059 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -18,21 +18,6 @@
 #include "hw.h"
 #include "ar9003_phy.h"
 
-#define AR9300_OFDM_RATES	8
-#define AR9300_HT_SS_RATES	8
-#define AR9300_HT_DS_RATES	8
-#define AR9300_HT_TS_RATES	8
-
-#define AR9300_11NA_OFDM_SHIFT		0
-#define AR9300_11NA_HT_SS_SHIFT		8
-#define AR9300_11NA_HT_DS_SHIFT		16
-#define AR9300_11NA_HT_TS_SHIFT		24
-
-#define AR9300_11NG_OFDM_SHIFT		4
-#define AR9300_11NG_HT_SS_SHIFT		12
-#define AR9300_11NG_HT_DS_SHIFT		20
-#define AR9300_11NG_HT_TS_SHIFT		28
-
 static const int firstep_table[] =
 /* level:  0   1   2   3   4   5   6   7   8  */
 	{ -4, -2,  0,  2,  4,  6,  8, 10, 12 }; /* lvl 0-8, default 2 */
@@ -55,71 +40,6 @@
 static const int m1ThreshExt_off = 127;
 static const int m2ThreshExt_off = 127;
 
-static const u8 ofdm2pwr[] = {
-	ALL_TARGET_LEGACY_6_24,
-	ALL_TARGET_LEGACY_6_24,
-	ALL_TARGET_LEGACY_6_24,
-	ALL_TARGET_LEGACY_6_24,
-	ALL_TARGET_LEGACY_6_24,
-	ALL_TARGET_LEGACY_36,
-	ALL_TARGET_LEGACY_48,
-	ALL_TARGET_LEGACY_54
-};
-
-static const u8 mcs2pwr_ht20[] = {
-	ALL_TARGET_HT20_0_8_16,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_4,
-	ALL_TARGET_HT20_5,
-	ALL_TARGET_HT20_6,
-	ALL_TARGET_HT20_7,
-	ALL_TARGET_HT20_0_8_16,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_12,
-	ALL_TARGET_HT20_13,
-	ALL_TARGET_HT20_14,
-	ALL_TARGET_HT20_15,
-	ALL_TARGET_HT20_0_8_16,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_1_3_9_11_17_19,
-	ALL_TARGET_HT20_20,
-	ALL_TARGET_HT20_21,
-	ALL_TARGET_HT20_22,
-	ALL_TARGET_HT20_23
-};
-
-static const u8 mcs2pwr_ht40[] = {
-	ALL_TARGET_HT40_0_8_16,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_4,
-	ALL_TARGET_HT40_5,
-	ALL_TARGET_HT40_6,
-	ALL_TARGET_HT40_7,
-	ALL_TARGET_HT40_0_8_16,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_12,
-	ALL_TARGET_HT40_13,
-	ALL_TARGET_HT40_14,
-	ALL_TARGET_HT40_15,
-	ALL_TARGET_HT40_0_8_16,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_1_3_9_11_17_19,
-	ALL_TARGET_HT40_20,
-	ALL_TARGET_HT40_21,
-	ALL_TARGET_HT40_22,
-	ALL_TARGET_HT40_23,
-};
-
 /**
  * ar9003_hw_set_channel - set channel on single-chip device
  * @ah: atheros hardware structure
@@ -744,19 +664,6 @@
 		ah->enabled_cals |= TX_CL_CAL;
 	else
 		ah->enabled_cals &= ~TX_CL_CAL;
-
-	if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
-		if (ah->is_clk_25mhz) {
-			REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
-			REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
-			REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae);
-		} else {
-			REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
-			REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
-			REG_WRITE(ah, AR_SLP32_INC, 0x0001e800);
-		}
-		udelay(100);
-	}
 }
 
 static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -1441,7 +1348,7 @@
 				       struct ath_hw_radar_conf *conf)
 {
 	unsigned int regWrites = 0;
-	u32 radar_0 = 0, radar_1;
+	u32 radar_0 = 0, radar_1 = 0;
 
 	if (!conf) {
 		REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
@@ -1455,9 +1362,6 @@
 	radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
 	radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
 
-	radar_1 = REG_READ(ah, AR_PHY_RADAR_1);
-	radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH |
-		     AR_PHY_RADAR_1_RELPWR_THRESH);
 	radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
 	radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
 	radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
@@ -1484,7 +1388,7 @@
 	conf->fir_power = -28;
 	conf->radar_rssi = 0;
 	conf->pulse_height = 10;
-	conf->pulse_rssi = 15;
+	conf->pulse_rssi = 24;
 	conf->pulse_inband = 8;
 	conf->pulse_maxlen = 255;
 	conf->pulse_inband_step = 12;
@@ -1879,100 +1783,6 @@
 		  ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_14],  0));
 }
 
-static void ar9003_hw_init_txpower_cck(struct ath_hw *ah, u8 *rate_array)
-{
-	ah->tx_power[0] = rate_array[ALL_TARGET_LEGACY_1L_5L];
-	ah->tx_power[1] = rate_array[ALL_TARGET_LEGACY_1L_5L];
-	ah->tx_power[2] = min(rate_array[ALL_TARGET_LEGACY_1L_5L],
-			      rate_array[ALL_TARGET_LEGACY_5S]);
-	ah->tx_power[3] = min(rate_array[ALL_TARGET_LEGACY_11L],
-			      rate_array[ALL_TARGET_LEGACY_11S]);
-}
-
-static void ar9003_hw_init_txpower_ofdm(struct ath_hw *ah, u8 *rate_array,
-					int offset)
-{
-	int i, j;
-
-	for (i = offset; i < offset + AR9300_OFDM_RATES; i++) {
-		/* OFDM rate to power table idx */
-		j = ofdm2pwr[i - offset];
-		ah->tx_power[i] = rate_array[j];
-	}
-}
-
-static void ar9003_hw_init_txpower_ht(struct ath_hw *ah, u8 *rate_array,
-				      int ss_offset, int ds_offset,
-				      int ts_offset, bool is_40)
-{
-	int i, j, mcs_idx = 0;
-	const u8 *mcs2pwr = (is_40) ? mcs2pwr_ht40 : mcs2pwr_ht20;
-
-	for (i = ss_offset; i < ss_offset + AR9300_HT_SS_RATES; i++) {
-		j = mcs2pwr[mcs_idx];
-		ah->tx_power[i] = rate_array[j];
-		mcs_idx++;
-	}
-
-	for (i = ds_offset; i < ds_offset + AR9300_HT_DS_RATES; i++) {
-		j = mcs2pwr[mcs_idx];
-		ah->tx_power[i] = rate_array[j];
-		mcs_idx++;
-	}
-
-	for (i = ts_offset; i < ts_offset + AR9300_HT_TS_RATES; i++) {
-		j = mcs2pwr[mcs_idx];
-		ah->tx_power[i] = rate_array[j];
-		mcs_idx++;
-	}
-}
-
-static void ar9003_hw_init_txpower_stbc(struct ath_hw *ah, int ss_offset,
-					int ds_offset, int ts_offset)
-{
-	memcpy(&ah->tx_power_stbc[ss_offset], &ah->tx_power[ss_offset],
-	       AR9300_HT_SS_RATES);
-	memcpy(&ah->tx_power_stbc[ds_offset], &ah->tx_power[ds_offset],
-	       AR9300_HT_DS_RATES);
-	memcpy(&ah->tx_power_stbc[ts_offset], &ah->tx_power[ts_offset],
-	       AR9300_HT_TS_RATES);
-}
-
-void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array,
-				 struct ath9k_channel *chan)
-{
-	if (IS_CHAN_5GHZ(chan)) {
-		ar9003_hw_init_txpower_ofdm(ah, rate_array,
-					    AR9300_11NA_OFDM_SHIFT);
-		if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) {
-			ar9003_hw_init_txpower_ht(ah, rate_array,
-						  AR9300_11NA_HT_SS_SHIFT,
-						  AR9300_11NA_HT_DS_SHIFT,
-						  AR9300_11NA_HT_TS_SHIFT,
-						  IS_CHAN_HT40(chan));
-			ar9003_hw_init_txpower_stbc(ah,
-						    AR9300_11NA_HT_SS_SHIFT,
-						    AR9300_11NA_HT_DS_SHIFT,
-						    AR9300_11NA_HT_TS_SHIFT);
-		}
-	} else {
-		ar9003_hw_init_txpower_cck(ah, rate_array);
-		ar9003_hw_init_txpower_ofdm(ah, rate_array,
-					    AR9300_11NG_OFDM_SHIFT);
-		if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) {
-			ar9003_hw_init_txpower_ht(ah, rate_array,
-						  AR9300_11NG_HT_SS_SHIFT,
-						  AR9300_11NG_HT_DS_SHIFT,
-						  AR9300_11NG_HT_TS_SHIFT,
-						  IS_CHAN_HT40(chan));
-			ar9003_hw_init_txpower_stbc(ah,
-						    AR9300_11NG_HT_SS_SHIFT,
-						    AR9300_11NG_HT_DS_SHIFT,
-						    AR9300_11NG_HT_TS_SHIFT);
-		}
-	}
-}
-
 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 {
 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
index 1efae69..a43b30d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
@@ -17,7 +17,6 @@
 #ifndef AR9003_RTT_H
 #define AR9003_RTT_H
 
-#ifdef CPTCFG_ATH9K_PCOEM
 void ar9003_hw_rtt_enable(struct ath_hw *ah);
 void ar9003_hw_rtt_disable(struct ath_hw *ah);
 void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask);
@@ -26,40 +25,5 @@
 void ar9003_hw_rtt_fill_hist(struct ath_hw *ah);
 void ar9003_hw_rtt_clear_hist(struct ath_hw *ah);
 bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan);
-#else
-static inline void ar9003_hw_rtt_enable(struct ath_hw *ah)
-{
-}
-
-static inline void ar9003_hw_rtt_disable(struct ath_hw *ah)
-{
-}
-
-static inline void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask)
-{
-}
-
-static inline bool ar9003_hw_rtt_force_restore(struct ath_hw *ah)
-{
-	return false;
-}
-
-static inline void ar9003_hw_rtt_load_hist(struct ath_hw *ah)
-{
-}
-
-static inline void ar9003_hw_rtt_fill_hist(struct ath_hw *ah)
-{
-}
-
-static inline void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
-{
-}
-
-static inline bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	return false;
-}
-#endif
 
 #endif
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
index 159cc6f..812a9d7 100644
--- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
@@ -20,8 +20,6 @@
 
 #define qca953x_1p0_mac_postamble ar9300_2p2_mac_postamble
 
-#define qca953x_1p0_soc_preamble ar955x_1p0_soc_preamble
-
 #define qca953x_1p0_soc_postamble ar9300_2p2_soc_postamble
 
 #define qca953x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2
@@ -30,10 +28,6 @@
 
 #define qca953x_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2
 
-#define qca953x_1p0_common_wo_xlna_rx_gain_bounds ar955x_1p0_common_wo_xlna_rx_gain_bounds
-
-#define qca953x_1p0_common_rx_gain_bounds ar955x_1p0_common_rx_gain_bounds
-
 static const u32 qca953x_1p0_mac_core[][2] = {
 	/* Addr      allmodes  */
 	{0x00000008, 0x00000000},
@@ -496,6 +490,35 @@
 	{0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000},
 };
 
+static const u32 qca953x_1p0_soc_preamble[][2] = {
+	/* Addr      allmodes  */
+	{0x00007000, 0x00000000},
+	{0x00007004, 0x00000000},
+	{0x00007008, 0x00000000},
+	{0x0000700c, 0x00000000},
+	{0x0000701c, 0x00000000},
+	{0x00007020, 0x00000000},
+	{0x00007024, 0x00000000},
+	{0x00007028, 0x00000000},
+	{0x0000702c, 0x00000000},
+	{0x00007030, 0x00000000},
+	{0x00007034, 0x00000002},
+	{0x00007038, 0x000004c2},
+	{0x00007048, 0x00000000},
+};
+
+static const u32 qca953x_1p0_common_rx_gain_bounds[][5] = {
+	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+	{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018},
+};
+
+static const u32 qca953x_1p0_common_wo_xlna_rx_gain_bounds[][5] = {
+	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+	{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+};
+
 static const u32 qca953x_1p0_modes_xpa_tx_gain_table[][2] = {
 	/* Addr      allmodes  */
 	{0x0000a2dc, 0xfffd5aaa},
@@ -692,73 +715,8 @@
 	{0x00016448, 0x6c927a70},
 };
 
-static const u32 qca953x_1p1_modes_xpa_tx_gain_table[][2] = {
-	/* Addr      allmodes  */
-	{0x0000a2dc, 0xfffb52aa},
-	{0x0000a2e0, 0xfffd64cc},
-	{0x0000a2e4, 0xfffe80f0},
-	{0x0000a2e8, 0xffffff00},
-	{0x0000a410, 0x000050d5},
-	{0x0000a500, 0x00000000},
-	{0x0000a504, 0x04000002},
-	{0x0000a508, 0x08000004},
-	{0x0000a50c, 0x0c000006},
-	{0x0000a510, 0x1000000a},
-	{0x0000a514, 0x1400000c},
-	{0x0000a518, 0x1800000e},
-	{0x0000a51c, 0x1c000048},
-	{0x0000a520, 0x2000004a},
-	{0x0000a524, 0x2400004c},
-	{0x0000a528, 0x2800004e},
-	{0x0000a52c, 0x2b00024a},
-	{0x0000a530, 0x2f00024c},
-	{0x0000a534, 0x3300024e},
-	{0x0000a538, 0x36000668},
-	{0x0000a53c, 0x38000669},
-	{0x0000a540, 0x3a000868},
-	{0x0000a544, 0x3d00086a},
-	{0x0000a548, 0x4000086c},
-	{0x0000a54c, 0x4200086e},
-	{0x0000a550, 0x43000a6e},
-	{0x0000a554, 0x43000a6e},
-	{0x0000a558, 0x43000a6e},
-	{0x0000a55c, 0x43000a6e},
-	{0x0000a560, 0x43000a6e},
-	{0x0000a564, 0x43000a6e},
-	{0x0000a568, 0x43000a6e},
-	{0x0000a56c, 0x43000a6e},
-	{0x0000a570, 0x43000a6e},
-	{0x0000a574, 0x43000a6e},
-	{0x0000a578, 0x43000a6e},
-	{0x0000a57c, 0x43000a6e},
-	{0x0000a600, 0x00000000},
-	{0x0000a604, 0x00000000},
-	{0x0000a608, 0x00000000},
-	{0x0000a60c, 0x03804000},
-	{0x0000a610, 0x03804e01},
-	{0x0000a614, 0x03804e01},
-	{0x0000a618, 0x03804e01},
-	{0x0000a61c, 0x04009002},
-	{0x0000a620, 0x04009002},
-	{0x0000a624, 0x04009002},
-	{0x0000a628, 0x04009002},
-	{0x0000a62c, 0x04009002},
-	{0x0000a630, 0x04009002},
-	{0x0000a634, 0x04009002},
-	{0x0000a638, 0x04009002},
-	{0x0000a63c, 0x04009002},
-	{0x0000b2dc, 0xfffb52aa},
-	{0x0000b2e0, 0xfffd64cc},
-	{0x0000b2e4, 0xfffe80f0},
-	{0x0000b2e8, 0xffffff00},
-	{0x00016044, 0x024922db},
-	{0x00016048, 0x6c927a70},
-	{0x00016444, 0x024922db},
-	{0x00016448, 0x6c927a70},
-};
-
 static const u32 qca953x_2p0_baseband_core[][2] = {
-	/* Addr      allmodes  */
+	/* Addr      allmodes */
 	{0x00009800, 0xafe68e30},
 	{0x00009804, 0xfd14e000},
 	{0x00009808, 0x9c0a9f6b},
@@ -956,400 +914,4 @@
 	{0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
 };
 
-static const u32 qca953x_2p0_common_wo_xlna_rx_gain_table[][2] = {
-	/* Addr      allmodes  */
-	{0x0000a000, 0x00010000},
-	{0x0000a004, 0x00030002},
-	{0x0000a008, 0x00050004},
-	{0x0000a00c, 0x00810080},
-	{0x0000a010, 0x00830082},
-	{0x0000a014, 0x01810180},
-	{0x0000a018, 0x01830182},
-	{0x0000a01c, 0x01850184},
-	{0x0000a020, 0x01890188},
-	{0x0000a024, 0x018b018a},
-	{0x0000a028, 0x018d018c},
-	{0x0000a02c, 0x03820190},
-	{0x0000a030, 0x03840383},
-	{0x0000a034, 0x03880385},
-	{0x0000a038, 0x038a0389},
-	{0x0000a03c, 0x038c038b},
-	{0x0000a040, 0x0390038d},
-	{0x0000a044, 0x03920391},
-	{0x0000a048, 0x03940393},
-	{0x0000a04c, 0x03960395},
-	{0x0000a050, 0x00000000},
-	{0x0000a054, 0x00000000},
-	{0x0000a058, 0x00000000},
-	{0x0000a05c, 0x00000000},
-	{0x0000a060, 0x00000000},
-	{0x0000a064, 0x00000000},
-	{0x0000a068, 0x00000000},
-	{0x0000a06c, 0x00000000},
-	{0x0000a070, 0x00000000},
-	{0x0000a074, 0x00000000},
-	{0x0000a078, 0x00000000},
-	{0x0000a07c, 0x00000000},
-	{0x0000a080, 0x29292929},
-	{0x0000a084, 0x29292929},
-	{0x0000a088, 0x29292929},
-	{0x0000a08c, 0x29292929},
-	{0x0000a090, 0x22292929},
-	{0x0000a094, 0x1d1d2222},
-	{0x0000a098, 0x0c111117},
-	{0x0000a09c, 0x00030303},
-	{0x0000a0a0, 0x00000000},
-	{0x0000a0a4, 0x00000000},
-	{0x0000a0a8, 0x00000000},
-	{0x0000a0ac, 0x00000000},
-	{0x0000a0b0, 0x00000000},
-	{0x0000a0b4, 0x00000000},
-	{0x0000a0b8, 0x00000000},
-	{0x0000a0bc, 0x00000000},
-	{0x0000a0c0, 0x001f0000},
-	{0x0000a0c4, 0x01000101},
-	{0x0000a0c8, 0x011e011f},
-	{0x0000a0cc, 0x011c011d},
-	{0x0000a0d0, 0x02030204},
-	{0x0000a0d4, 0x02010202},
-	{0x0000a0d8, 0x021f0200},
-	{0x0000a0dc, 0x0302021e},
-	{0x0000a0e0, 0x03000301},
-	{0x0000a0e4, 0x031e031f},
-	{0x0000a0e8, 0x0402031d},
-	{0x0000a0ec, 0x04000401},
-	{0x0000a0f0, 0x041e041f},
-	{0x0000a0f4, 0x0502041d},
-	{0x0000a0f8, 0x05000501},
-	{0x0000a0fc, 0x051e051f},
-	{0x0000a100, 0x06010602},
-	{0x0000a104, 0x061f0600},
-	{0x0000a108, 0x061d061e},
-	{0x0000a10c, 0x07020703},
-	{0x0000a110, 0x07000701},
-	{0x0000a114, 0x00000000},
-	{0x0000a118, 0x00000000},
-	{0x0000a11c, 0x00000000},
-	{0x0000a120, 0x00000000},
-	{0x0000a124, 0x00000000},
-	{0x0000a128, 0x00000000},
-	{0x0000a12c, 0x00000000},
-	{0x0000a130, 0x00000000},
-	{0x0000a134, 0x00000000},
-	{0x0000a138, 0x00000000},
-	{0x0000a13c, 0x00000000},
-	{0x0000a140, 0x001f0000},
-	{0x0000a144, 0x01000101},
-	{0x0000a148, 0x011e011f},
-	{0x0000a14c, 0x011c011d},
-	{0x0000a150, 0x02030204},
-	{0x0000a154, 0x02010202},
-	{0x0000a158, 0x021f0200},
-	{0x0000a15c, 0x0302021e},
-	{0x0000a160, 0x03000301},
-	{0x0000a164, 0x031e031f},
-	{0x0000a168, 0x0402031d},
-	{0x0000a16c, 0x04000401},
-	{0x0000a170, 0x041e041f},
-	{0x0000a174, 0x0502041d},
-	{0x0000a178, 0x05000501},
-	{0x0000a17c, 0x051e051f},
-	{0x0000a180, 0x06010602},
-	{0x0000a184, 0x061f0600},
-	{0x0000a188, 0x061d061e},
-	{0x0000a18c, 0x07020703},
-	{0x0000a190, 0x07000701},
-	{0x0000a194, 0x00000000},
-	{0x0000a198, 0x00000000},
-	{0x0000a19c, 0x00000000},
-	{0x0000a1a0, 0x00000000},
-	{0x0000a1a4, 0x00000000},
-	{0x0000a1a8, 0x00000000},
-	{0x0000a1ac, 0x00000000},
-	{0x0000a1b0, 0x00000000},
-	{0x0000a1b4, 0x00000000},
-	{0x0000a1b8, 0x00000000},
-	{0x0000a1bc, 0x00000000},
-	{0x0000a1c0, 0x00000000},
-	{0x0000a1c4, 0x00000000},
-	{0x0000a1c8, 0x00000000},
-	{0x0000a1cc, 0x00000000},
-	{0x0000a1d0, 0x00000000},
-	{0x0000a1d4, 0x00000000},
-	{0x0000a1d8, 0x00000000},
-	{0x0000a1dc, 0x00000000},
-	{0x0000a1e0, 0x00000000},
-	{0x0000a1e4, 0x00000000},
-	{0x0000a1e8, 0x00000000},
-	{0x0000a1ec, 0x00000000},
-	{0x0000a1f0, 0x00000396},
-	{0x0000a1f4, 0x00000396},
-	{0x0000a1f8, 0x00000396},
-	{0x0000a1fc, 0x00000196},
-	{0x0000b000, 0x00010000},
-	{0x0000b004, 0x00030002},
-	{0x0000b008, 0x00050004},
-	{0x0000b00c, 0x00810080},
-	{0x0000b010, 0x00830082},
-	{0x0000b014, 0x01810180},
-	{0x0000b018, 0x01830182},
-	{0x0000b01c, 0x01850184},
-	{0x0000b020, 0x02810280},
-	{0x0000b024, 0x02830282},
-	{0x0000b028, 0x02850284},
-	{0x0000b02c, 0x02890288},
-	{0x0000b030, 0x028b028a},
-	{0x0000b034, 0x0388028c},
-	{0x0000b038, 0x038a0389},
-	{0x0000b03c, 0x038c038b},
-	{0x0000b040, 0x0390038d},
-	{0x0000b044, 0x03920391},
-	{0x0000b048, 0x03940393},
-	{0x0000b04c, 0x03960395},
-	{0x0000b050, 0x00000000},
-	{0x0000b054, 0x00000000},
-	{0x0000b058, 0x00000000},
-	{0x0000b05c, 0x00000000},
-	{0x0000b060, 0x00000000},
-	{0x0000b064, 0x00000000},
-	{0x0000b068, 0x00000000},
-	{0x0000b06c, 0x00000000},
-	{0x0000b070, 0x00000000},
-	{0x0000b074, 0x00000000},
-	{0x0000b078, 0x00000000},
-	{0x0000b07c, 0x00000000},
-	{0x0000b080, 0x32323232},
-	{0x0000b084, 0x2f2f3232},
-	{0x0000b088, 0x23282a2d},
-	{0x0000b08c, 0x1c1e2123},
-	{0x0000b090, 0x14171919},
-	{0x0000b094, 0x0e0e1214},
-	{0x0000b098, 0x03050707},
-	{0x0000b09c, 0x00030303},
-	{0x0000b0a0, 0x00000000},
-	{0x0000b0a4, 0x00000000},
-	{0x0000b0a8, 0x00000000},
-	{0x0000b0ac, 0x00000000},
-	{0x0000b0b0, 0x00000000},
-	{0x0000b0b4, 0x00000000},
-	{0x0000b0b8, 0x00000000},
-	{0x0000b0bc, 0x00000000},
-	{0x0000b0c0, 0x003f0020},
-	{0x0000b0c4, 0x00400041},
-	{0x0000b0c8, 0x0140005f},
-	{0x0000b0cc, 0x0160015f},
-	{0x0000b0d0, 0x017e017f},
-	{0x0000b0d4, 0x02410242},
-	{0x0000b0d8, 0x025f0240},
-	{0x0000b0dc, 0x027f0260},
-	{0x0000b0e0, 0x0341027e},
-	{0x0000b0e4, 0x035f0340},
-	{0x0000b0e8, 0x037f0360},
-	{0x0000b0ec, 0x04400441},
-	{0x0000b0f0, 0x0460045f},
-	{0x0000b0f4, 0x0541047f},
-	{0x0000b0f8, 0x055f0540},
-	{0x0000b0fc, 0x057f0560},
-	{0x0000b100, 0x06400641},
-	{0x0000b104, 0x0660065f},
-	{0x0000b108, 0x067e067f},
-	{0x0000b10c, 0x07410742},
-	{0x0000b110, 0x075f0740},
-	{0x0000b114, 0x077f0760},
-	{0x0000b118, 0x07800781},
-	{0x0000b11c, 0x07a0079f},
-	{0x0000b120, 0x07c107bf},
-	{0x0000b124, 0x000007c0},
-	{0x0000b128, 0x00000000},
-	{0x0000b12c, 0x00000000},
-	{0x0000b130, 0x00000000},
-	{0x0000b134, 0x00000000},
-	{0x0000b138, 0x00000000},
-	{0x0000b13c, 0x00000000},
-	{0x0000b140, 0x003f0020},
-	{0x0000b144, 0x00400041},
-	{0x0000b148, 0x0140005f},
-	{0x0000b14c, 0x0160015f},
-	{0x0000b150, 0x017e017f},
-	{0x0000b154, 0x02410242},
-	{0x0000b158, 0x025f0240},
-	{0x0000b15c, 0x027f0260},
-	{0x0000b160, 0x0341027e},
-	{0x0000b164, 0x035f0340},
-	{0x0000b168, 0x037f0360},
-	{0x0000b16c, 0x04400441},
-	{0x0000b170, 0x0460045f},
-	{0x0000b174, 0x0541047f},
-	{0x0000b178, 0x055f0540},
-	{0x0000b17c, 0x057f0560},
-	{0x0000b180, 0x06400641},
-	{0x0000b184, 0x0660065f},
-	{0x0000b188, 0x067e067f},
-	{0x0000b18c, 0x07410742},
-	{0x0000b190, 0x075f0740},
-	{0x0000b194, 0x077f0760},
-	{0x0000b198, 0x07800781},
-	{0x0000b19c, 0x07a0079f},
-	{0x0000b1a0, 0x07c107bf},
-	{0x0000b1a4, 0x000007c0},
-	{0x0000b1a8, 0x00000000},
-	{0x0000b1ac, 0x00000000},
-	{0x0000b1b0, 0x00000000},
-	{0x0000b1b4, 0x00000000},
-	{0x0000b1b8, 0x00000000},
-	{0x0000b1bc, 0x00000000},
-	{0x0000b1c0, 0x00000000},
-	{0x0000b1c4, 0x00000000},
-	{0x0000b1c8, 0x00000000},
-	{0x0000b1cc, 0x00000000},
-	{0x0000b1d0, 0x00000000},
-	{0x0000b1d4, 0x00000000},
-	{0x0000b1d8, 0x00000000},
-	{0x0000b1dc, 0x00000000},
-	{0x0000b1e0, 0x00000000},
-	{0x0000b1e4, 0x00000000},
-	{0x0000b1e8, 0x00000000},
-	{0x0000b1ec, 0x00000000},
-	{0x0000b1f0, 0x00000396},
-	{0x0000b1f4, 0x00000396},
-	{0x0000b1f8, 0x00000396},
-	{0x0000b1fc, 0x00000196},
-};
-
-static const u32 qca953x_2p0_common_wo_xlna_rx_gain_bounds[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
-	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
-};
-
-static const u32 qca953x_2p0_modes_xpa_tx_gain_table[][2] = {
-	/* Addr      allmodes  */
-	{0x0000a2dc, 0xfffb52aa},
-	{0x0000a2e0, 0xfffd64cc},
-	{0x0000a2e4, 0xfffe80f0},
-	{0x0000a2e8, 0xffffff00},
-	{0x0000a410, 0x000050d5},
-	{0x0000a500, 0x00000000},
-	{0x0000a504, 0x04000002},
-	{0x0000a508, 0x08000004},
-	{0x0000a50c, 0x0c000006},
-	{0x0000a510, 0x1000000a},
-	{0x0000a514, 0x1400000c},
-	{0x0000a518, 0x1800000e},
-	{0x0000a51c, 0x1c000048},
-	{0x0000a520, 0x2000004a},
-	{0x0000a524, 0x2400004c},
-	{0x0000a528, 0x2800004e},
-	{0x0000a52c, 0x2b00024a},
-	{0x0000a530, 0x2f00024c},
-	{0x0000a534, 0x3300024e},
-	{0x0000a538, 0x36000668},
-	{0x0000a53c, 0x38000669},
-	{0x0000a540, 0x3a000868},
-	{0x0000a544, 0x3d00086a},
-	{0x0000a548, 0x4000086c},
-	{0x0000a54c, 0x4200086e},
-	{0x0000a550, 0x43000a6e},
-	{0x0000a554, 0x43000a6e},
-	{0x0000a558, 0x43000a6e},
-	{0x0000a55c, 0x43000a6e},
-	{0x0000a560, 0x43000a6e},
-	{0x0000a564, 0x43000a6e},
-	{0x0000a568, 0x43000a6e},
-	{0x0000a56c, 0x43000a6e},
-	{0x0000a570, 0x43000a6e},
-	{0x0000a574, 0x43000a6e},
-	{0x0000a578, 0x43000a6e},
-	{0x0000a57c, 0x43000a6e},
-	{0x0000a600, 0x00000000},
-	{0x0000a604, 0x00000000},
-	{0x0000a608, 0x00000000},
-	{0x0000a60c, 0x03804000},
-	{0x0000a610, 0x03804e01},
-	{0x0000a614, 0x03804e01},
-	{0x0000a618, 0x03804e01},
-	{0x0000a61c, 0x04009002},
-	{0x0000a620, 0x04009002},
-	{0x0000a624, 0x04009002},
-	{0x0000a628, 0x04009002},
-	{0x0000a62c, 0x04009002},
-	{0x0000a630, 0x04009002},
-	{0x0000a634, 0x04009002},
-	{0x0000a638, 0x04009002},
-	{0x0000a63c, 0x04009002},
-	{0x0000b2dc, 0xfffb52aa},
-	{0x0000b2e0, 0xfffd64cc},
-	{0x0000b2e4, 0xfffe80f0},
-	{0x0000b2e8, 0xffffff00},
-	{0x00016044, 0x024922db},
-	{0x00016048, 0x6c927a70},
-	{0x00016444, 0x024922db},
-	{0x00016448, 0x6c927a70},
-};
-
-static const u32 qca953x_2p0_modes_no_xpa_tx_gain_table[][2] = {
-	/* Addr      allmodes  */
-	{0x0000a2dc, 0xffd5f552},
-	{0x0000a2e0, 0xffe60664},
-	{0x0000a2e4, 0xfff80780},
-	{0x0000a2e8, 0xfffff800},
-	{0x0000a410, 0x000050de},
-	{0x0000a500, 0x00000061},
-	{0x0000a504, 0x04000063},
-	{0x0000a508, 0x08000065},
-	{0x0000a50c, 0x0c000261},
-	{0x0000a510, 0x10000263},
-	{0x0000a514, 0x14000265},
-	{0x0000a518, 0x18000482},
-	{0x0000a51c, 0x1b000484},
-	{0x0000a520, 0x1f000486},
-	{0x0000a524, 0x240008c2},
-	{0x0000a528, 0x28000cc1},
-	{0x0000a52c, 0x2d000ce3},
-	{0x0000a530, 0x31000ce5},
-	{0x0000a534, 0x350010e5},
-	{0x0000a538, 0x360012e5},
-	{0x0000a53c, 0x380014e5},
-	{0x0000a540, 0x3b0018e5},
-	{0x0000a544, 0x3d001d04},
-	{0x0000a548, 0x3e001d05},
-	{0x0000a54c, 0x40001d07},
-	{0x0000a550, 0x42001f27},
-	{0x0000a554, 0x43001f67},
-	{0x0000a558, 0x46001fe7},
-	{0x0000a55c, 0x47001f2b},
-	{0x0000a560, 0x49001f0d},
-	{0x0000a564, 0x4b001ed2},
-	{0x0000a568, 0x4c001ed4},
-	{0x0000a56c, 0x4e001f15},
-	{0x0000a570, 0x4f001ff6},
-	{0x0000a574, 0x4f001ff6},
-	{0x0000a578, 0x4f001ff6},
-	{0x0000a57c, 0x4f001ff6},
-	{0x0000a600, 0x00000000},
-	{0x0000a604, 0x00000000},
-	{0x0000a608, 0x00000000},
-	{0x0000a60c, 0x00804201},
-	{0x0000a610, 0x01008201},
-	{0x0000a614, 0x0180c402},
-	{0x0000a618, 0x0180c603},
-	{0x0000a61c, 0x0180c603},
-	{0x0000a620, 0x01c10603},
-	{0x0000a624, 0x01c10704},
-	{0x0000a628, 0x02c18b05},
-	{0x0000a62c, 0x02c14c07},
-	{0x0000a630, 0x01008704},
-	{0x0000a634, 0x01c10402},
-	{0x0000a638, 0x0301cc07},
-	{0x0000a63c, 0x0301cc07},
-	{0x0000b2dc, 0xffd5f552},
-	{0x0000b2e0, 0xffe60664},
-	{0x0000b2e4, 0xfff80780},
-	{0x0000b2e8, 0xfffff800},
-	{0x00016044, 0x049242db},
-	{0x00016048, 0x6c927a70},
-	{0x00016444, 0x049242db},
-	{0x00016448, 0x6c927a70},
-};
-
 #endif /* INITVALS_953X_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
index fd6a84c..74d8bc0 100644
--- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
@@ -507,7 +507,7 @@
 	{0x00009d04, 0x40206c10},
 	{0x00009d08, 0x009c4060},
 	{0x00009d0c, 0x9883800a},
-	{0x00009d10, 0x01884061},
+	{0x00009d10, 0x01834061},
 	{0x00009d14, 0x00c0040b},
 	{0x00009d18, 0x00000000},
 	{0x00009e08, 0x0038230c},
@@ -545,9 +545,9 @@
 	{0x0000a370, 0x00000000},
 	{0x0000a390, 0x00000001},
 	{0x0000a394, 0x00000444},
-	{0x0000a398, 0x001f0e0f},
-	{0x0000a39c, 0x0075393f},
-	{0x0000a3a0, 0xb79f6427},
+	{0x0000a398, 0x1f020503},
+	{0x0000a39c, 0x29180c03},
+	{0x0000a3a0, 0x9a8b6844},
 	{0x0000a3a4, 0x00000000},
 	{0x0000a3a8, 0xaaaaaaaa},
 	{0x0000a3ac, 0x3c466478},
diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
index 5d4629f..a5ca652 100644
--- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
@@ -24,149 +24,7 @@
 
 #define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble
 
-static const u32 ar9580_1p0_radio_core[][2] = {
-	/* Addr      allmodes  */
-	{0x00016000, 0x36db2db6},
-	{0x00016004, 0x6db6db40},
-	{0x00016008, 0x73f00000},
-	{0x0001600c, 0x00000000},
-	{0x00016040, 0x7f80fff8},
-	{0x0001604c, 0x76d005b5},
-	{0x00016050, 0x556cf031},
-	{0x00016054, 0x13449440},
-	{0x00016058, 0x0c51c92c},
-	{0x0001605c, 0x3db7fffc},
-	{0x00016060, 0xfffffffc},
-	{0x00016064, 0x000f0278},
-	{0x0001606c, 0x6db60000},
-	{0x00016080, 0x00000000},
-	{0x00016084, 0x0e48048c},
-	{0x00016088, 0x54214514},
-	{0x0001608c, 0x119f481e},
-	{0x00016090, 0x24926490},
-	{0x00016098, 0xd2888888},
-	{0x000160a0, 0x0a108ffe},
-	{0x000160a4, 0x812fc370},
-	{0x000160a8, 0x423c8000},
-	{0x000160b4, 0x92480080},
-	{0x000160c0, 0x00adb6d0},
-	{0x000160c4, 0x6db6db60},
-	{0x000160c8, 0x6db6db6c},
-	{0x000160cc, 0x01e6c000},
-	{0x00016100, 0x3fffbe01},
-	{0x00016104, 0xfff80000},
-	{0x00016108, 0x00080010},
-	{0x00016144, 0x02084080},
-	{0x00016148, 0x00000000},
-	{0x00016280, 0x058a0001},
-	{0x00016284, 0x3d840208},
-	{0x00016288, 0x05a20408},
-	{0x0001628c, 0x00038c07},
-	{0x00016290, 0x00000004},
-	{0x00016294, 0x458a214f},
-	{0x00016380, 0x00000000},
-	{0x00016384, 0x00000000},
-	{0x00016388, 0x00800700},
-	{0x0001638c, 0x00800700},
-	{0x00016390, 0x00800700},
-	{0x00016394, 0x00000000},
-	{0x00016398, 0x00000000},
-	{0x0001639c, 0x00000000},
-	{0x000163a0, 0x00000001},
-	{0x000163a4, 0x00000001},
-	{0x000163a8, 0x00000000},
-	{0x000163ac, 0x00000000},
-	{0x000163b0, 0x00000000},
-	{0x000163b4, 0x00000000},
-	{0x000163b8, 0x00000000},
-	{0x000163bc, 0x00000000},
-	{0x000163c0, 0x000000a0},
-	{0x000163c4, 0x000c0000},
-	{0x000163c8, 0x14021402},
-	{0x000163cc, 0x00001402},
-	{0x000163d0, 0x00000000},
-	{0x000163d4, 0x00000000},
-	{0x00016400, 0x36db2db6},
-	{0x00016404, 0x6db6db40},
-	{0x00016408, 0x73f00000},
-	{0x0001640c, 0x00000000},
-	{0x00016440, 0x7f80fff8},
-	{0x0001644c, 0x76d005b5},
-	{0x00016450, 0x556cf031},
-	{0x00016454, 0x13449440},
-	{0x00016458, 0x0c51c92c},
-	{0x0001645c, 0x3db7fffc},
-	{0x00016460, 0xfffffffc},
-	{0x00016464, 0x000f0278},
-	{0x0001646c, 0x6db60000},
-	{0x00016500, 0x3fffbe01},
-	{0x00016504, 0xfff80000},
-	{0x00016508, 0x00080010},
-	{0x00016544, 0x02084080},
-	{0x00016548, 0x00000000},
-	{0x00016780, 0x00000000},
-	{0x00016784, 0x00000000},
-	{0x00016788, 0x00800700},
-	{0x0001678c, 0x00800700},
-	{0x00016790, 0x00800700},
-	{0x00016794, 0x00000000},
-	{0x00016798, 0x00000000},
-	{0x0001679c, 0x00000000},
-	{0x000167a0, 0x00000001},
-	{0x000167a4, 0x00000001},
-	{0x000167a8, 0x00000000},
-	{0x000167ac, 0x00000000},
-	{0x000167b0, 0x00000000},
-	{0x000167b4, 0x00000000},
-	{0x000167b8, 0x00000000},
-	{0x000167bc, 0x00000000},
-	{0x000167c0, 0x000000a0},
-	{0x000167c4, 0x000c0000},
-	{0x000167c8, 0x14021402},
-	{0x000167cc, 0x00001402},
-	{0x000167d0, 0x00000000},
-	{0x000167d4, 0x00000000},
-	{0x00016800, 0x36db2db6},
-	{0x00016804, 0x6db6db40},
-	{0x00016808, 0x73f00000},
-	{0x0001680c, 0x00000000},
-	{0x00016840, 0x7f80fff8},
-	{0x0001684c, 0x76d005b5},
-	{0x00016850, 0x556cf031},
-	{0x00016854, 0x13449440},
-	{0x00016858, 0x0c51c92c},
-	{0x0001685c, 0x3db7fffc},
-	{0x00016860, 0xfffffffc},
-	{0x00016864, 0x000f0278},
-	{0x0001686c, 0x6db60000},
-	{0x00016900, 0x3fffbe01},
-	{0x00016904, 0xfff80000},
-	{0x00016908, 0x00080010},
-	{0x00016944, 0x02084080},
-	{0x00016948, 0x00000000},
-	{0x00016b80, 0x00000000},
-	{0x00016b84, 0x00000000},
-	{0x00016b88, 0x00800700},
-	{0x00016b8c, 0x00800700},
-	{0x00016b90, 0x00800700},
-	{0x00016b94, 0x00000000},
-	{0x00016b98, 0x00000000},
-	{0x00016b9c, 0x00000000},
-	{0x00016ba0, 0x00000001},
-	{0x00016ba4, 0x00000001},
-	{0x00016ba8, 0x00000000},
-	{0x00016bac, 0x00000000},
-	{0x00016bb0, 0x00000000},
-	{0x00016bb4, 0x00000000},
-	{0x00016bb8, 0x00000000},
-	{0x00016bbc, 0x00000000},
-	{0x00016bc0, 0x000000a0},
-	{0x00016bc4, 0x000c0000},
-	{0x00016bc8, 0x14021402},
-	{0x00016bcc, 0x00001402},
-	{0x00016bd0, 0x00000000},
-	{0x00016bd4, 0x00000000},
-};
+#define ar9580_1p0_radio_core ar9300_2p2_radio_core
 
 #define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble
 
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index e008569..4581876 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -28,6 +28,7 @@
 #include "debug.h"
 #include "mci.h"
 #include "dfs.h"
+#include "spectral.h"
 
 struct ath_node;
 struct ath_vif;
@@ -189,7 +190,6 @@
 	u8 rtscts_rate;
 	u8 retries : 7;
 	u8 baw_tracked : 1;
-	u8 tx_power;
 };
 
 struct ath_rxbuf {
@@ -345,9 +345,7 @@
 	u64 tsf_val;
 	u32 last_beacon;
 
-	int flush_timeout;
 	u16 txpower;
-	u16 cur_txpower;
 	bool offchannel;
 	bool stopped;
 	bool active;
@@ -364,7 +362,7 @@
 	ATH_CHANCTX_EVENT_BEACON_SENT,
 	ATH_CHANCTX_EVENT_TSF_TIMER,
 	ATH_CHANCTX_EVENT_BEACON_RECEIVED,
-	ATH_CHANCTX_EVENT_AUTHORIZED,
+	ATH_CHANCTX_EVENT_ASSOC,
 	ATH_CHANCTX_EVENT_SWITCH,
 	ATH_CHANCTX_EVENT_ASSIGN,
 	ATH_CHANCTX_EVENT_UNASSIGN,
@@ -382,12 +380,10 @@
 
 struct ath_chanctx_sched {
 	bool beacon_pending;
-	bool beacon_adjust;
 	bool offchannel_pending;
 	bool wait_switch;
 	bool force_noa_update;
 	bool extend_absence;
-	bool mgd_prepare_tx;
 	enum ath_chanctx_state state;
 	u8 beacon_miss;
 
@@ -472,7 +468,6 @@
 void ath_offchannel_next(struct ath_softc *sc);
 void ath_scan_complete(struct ath_softc *sc, bool abort);
 void ath_roc_complete(struct ath_softc *sc, bool abort);
-struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc);
 
 #else
 
@@ -545,6 +540,7 @@
 
 #endif /* CPTCFG_ATH9K_CHANNEL_CONTEXT */
 
+int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan);
 void ath_startrecv(struct ath_softc *sc);
 bool ath_stoprecv(struct ath_softc *sc);
 u32 ath_calcrxfilter(struct ath_softc *sc);
@@ -599,7 +595,7 @@
 	u16 seq_no;
 
 	/* BSS info */
-	u8 bssid[ETH_ALEN] __aligned(2);
+	u8 bssid[ETH_ALEN];
 	u16 aid;
 	bool assoc;
 
@@ -622,7 +618,6 @@
 	u32 noa_start;
 	u32 noa_duration;
 	bool periodic_noa;
-	bool oneshot_noa;
 };
 
 struct ath9k_vif_iter_data {
@@ -720,8 +715,7 @@
 void ath_update_survey_nf(struct ath_softc *sc, int channel);
 void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
 void ath_ps_full_sleep(unsigned long data);
-void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
-		   bool sw_pending, bool timeout_override);
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
 
 /**********/
 /* BTCOEX */
@@ -933,7 +927,6 @@
 #define ATH9K_PCI_AR9565_2ANT     0x0100
 #define ATH9K_PCI_NO_PLL_PWRSAVE  0x0200
 #define ATH9K_PCI_KILLER          0x0400
-#define ATH9K_PCI_LED_ACT_HI      0x0800
 
 /*
  * Default cache line size, in bytes.
@@ -982,7 +975,6 @@
 	struct ath_chanctx_sched sched;
 	struct ath_offchannel offchannel;
 	struct ath_chanctx *next_chan;
-	struct completion go_beacon;
 #endif
 
 	unsigned long driver_data;
@@ -990,6 +982,7 @@
 	u8 gtt_cnt;
 	u32 intrstatus;
 	u16 ps_flags; /* PS_* */
+	u16 curtxpow;
 	bool ps_enabled;
 	bool ps_idle;
 	short nbcnvifs;
@@ -1030,8 +1023,10 @@
 	struct dfs_pattern_detector *dfs_detector;
 	u64 dfs_prev_pulse_ts;
 	u32 wow_enabled;
-
-	struct ath_spec_scan_priv spec_priv;
+	/* relay(fs) channel for spectral scan */
+	struct rchan *rfs_chan_spec_scan;
+	enum spectral_mode spectral_mode;
+	struct ath_spec_scan spec_config;
 
 	struct ieee80211_vif *tx99_vif;
 	struct sk_buff *tx99_skb;
@@ -1074,7 +1069,7 @@
 int ath_cabq_update(struct ath_softc *);
 u8 ath9k_parse_mpdudensity(u8 mpdudensity);
 irqreturn_t ath_isr(int irq, void *dev);
-int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan);
+int ath_reset(struct ath_softc *sc);
 void ath_cancel_work(struct ath_softc *sc);
 void ath_restart_work(struct ath_softc *sc);
 int ath9k_init_device(u16 devid, struct ath_softc *sc,
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index cb366ad..ecb783b 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -78,7 +78,7 @@
 	struct ath_tx_info info;
 	struct ieee80211_supported_band *sband;
 	u8 chainmask = ah->txchainmask;
-	u8 i, rate = 0;
+	u8 rate = 0;
 
 	sband = &common->sbands[sc->cur_chandef.chan->band];
 	rate = sband->bitrates[rateidx].hw_value;
@@ -88,8 +88,7 @@
 	memset(&info, 0, sizeof(info));
 	info.pkt_len = skb->len + FCS_LEN;
 	info.type = ATH9K_PKT_TYPE_BEACON;
-	for (i = 0; i < 4; i++)
-		info.txpower[i] = MAX_RATE_POWER;
+	info.txpower = MAX_RATE_POWER;
 	info.keyix = ATH9K_TXKEYIX_INVALID;
 	info.keytype = ATH9K_KEY_TYPE_CLEAR;
 	info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK;
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index e200a6e..278365b 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -234,7 +234,7 @@
 	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 }
 
-int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 {
 	struct ath9k_nfcal_hist *h = NULL;
 	unsigned i, j;
@@ -301,7 +301,7 @@
 		ath_dbg(common, ANY,
 			"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
 			REG_READ(ah, AR_PHY_AGC_CONTROL));
-		return -ETIMEDOUT;
+		return;
 	}
 
 	/*
@@ -322,8 +322,6 @@
 		}
 	}
 	REGWRITE_BUFFER_FLUSH(ah);
-
-	return 0;
 }
 
 
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 87badf4..b8ed95e 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -109,7 +109,7 @@
 
 bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
 void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update);
-int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
 bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
 				  struct ath9k_channel *chan);
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 239e8a3..696152b 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -66,7 +66,7 @@
 	}
 
 	hchan = &sc->sc_ah->channels[pos];
-	r = ath_reset(sc, hchan);
+	r = ath_reset_internal(sc, hchan);
 	if (r)
 		return r;
 
@@ -92,8 +92,8 @@
 	} else {
 		/* perform spectral scan if requested. */
 		if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
-			sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN)
-			ath9k_cmn_spectral_scan_trigger(common, &sc->spec_priv);
+			sc->spectral_mode == SPECTRAL_CHANSCAN)
+			ath9k_spectral_scan_trigger(hw);
 	}
 
 	return 0;
@@ -117,7 +117,6 @@
 		cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
 		INIT_LIST_HEAD(&ctx->vifs);
 		ctx->txpower = ATH_TXPOWER_MAX;
-		ctx->flush_timeout = HZ / 5; /* 200ms */
 		for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
 			INIT_LIST_HEAD(&ctx->acq[j]);
 	}
@@ -146,36 +145,6 @@
 
 #ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT
 
-/*************/
-/* Utilities */
-/*************/
-
-struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc)
-{
-	struct ath_chanctx *ctx;
-	struct ath_vif *avp;
-	struct ieee80211_vif *vif;
-
-	spin_lock_bh(&sc->chan_lock);
-
-	ath_for_each_chanctx(sc, ctx) {
-		if (!ctx->active)
-			continue;
-
-		list_for_each_entry(avp, &ctx->vifs, list) {
-			vif = avp->vif;
-
-			if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO) {
-				spin_unlock_bh(&sc->chan_lock);
-				return ctx;
-			}
-		}
-	}
-
-	spin_unlock_bh(&sc->chan_lock);
-	return NULL;
-}
-
 /**********************************************************/
 /* Functions to handle the channel context state machine. */
 /**********************************************************/
@@ -202,7 +171,7 @@
 		case_rtn_string(ATH_CHANCTX_EVENT_BEACON_SENT);
 		case_rtn_string(ATH_CHANCTX_EVENT_TSF_TIMER);
 		case_rtn_string(ATH_CHANCTX_EVENT_BEACON_RECEIVED);
-		case_rtn_string(ATH_CHANCTX_EVENT_AUTHORIZED);
+		case_rtn_string(ATH_CHANCTX_EVENT_ASSOC);
 		case_rtn_string(ATH_CHANCTX_EVENT_SWITCH);
 		case_rtn_string(ATH_CHANCTX_EVENT_ASSIGN);
 		case_rtn_string(ATH_CHANCTX_EVENT_UNASSIGN);
@@ -229,7 +198,6 @@
 void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_chanctx *ictx;
 	struct ath_vif *avp;
 	bool active = false;
 	u8 n_active = 0;
@@ -237,28 +205,6 @@
 	if (!ctx)
 		return;
 
-	if (ctx == &sc->offchannel.chan) {
-		spin_lock_bh(&sc->chan_lock);
-
-		if (likely(sc->sched.channel_switch_time))
-			ctx->flush_timeout =
-				usecs_to_jiffies(sc->sched.channel_switch_time);
-		else
-			ctx->flush_timeout =
-				msecs_to_jiffies(10);
-
-		spin_unlock_bh(&sc->chan_lock);
-
-		/*
-		 * There is no need to iterate over the
-		 * active/assigned channel contexts if
-		 * the current context is offchannel.
-		 */
-		return;
-	}
-
-	ictx = ctx;
-
 	list_for_each_entry(avp, &ctx->vifs, list) {
 		struct ieee80211_vif *vif = avp->vif;
 
@@ -281,23 +227,12 @@
 		n_active++;
 	}
 
-	spin_lock_bh(&sc->chan_lock);
-
 	if (n_active <= 1) {
-		ictx->flush_timeout = HZ / 5;
 		clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags);
-		spin_unlock_bh(&sc->chan_lock);
 		return;
 	}
-
-	ictx->flush_timeout = usecs_to_jiffies(sc->sched.channel_switch_time);
-
-	if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) {
-		spin_unlock_bh(&sc->chan_lock);
+	if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
 		return;
-	}
-
-	spin_unlock_bh(&sc->chan_lock);
 
 	if (ath9k_is_chanctx_enabled()) {
 		ath_chanctx_event(sc, NULL,
@@ -366,111 +301,6 @@
 		"Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time));
 }
 
-static void ath_chanctx_handle_bmiss(struct ath_softc *sc,
-				     struct ath_chanctx *ctx,
-				     struct ath_vif *avp)
-{
-	/*
-	 * Clear the extend_absence flag if it had been
-	 * set during the previous beacon transmission,
-	 * since we need to revert to the normal NoA
-	 * schedule.
-	 */
-	if (ctx->active && sc->sched.extend_absence) {
-		avp->noa_duration = 0;
-		sc->sched.extend_absence = false;
-	}
-
-	/* If at least two consecutive beacons were missed on the STA
-	 * chanctx, stay on the STA channel for one extra beacon period,
-	 * to resync the timer properly.
-	 */
-	if (ctx->active && sc->sched.beacon_miss >= 2) {
-		avp->noa_duration = 0;
-		sc->sched.extend_absence = true;
-	}
-}
-
-static void ath_chanctx_offchannel_noa(struct ath_softc *sc,
-				       struct ath_chanctx *ctx,
-				       struct ath_vif *avp,
-				       u32 tsf_time)
-{
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
-	avp->noa_index++;
-	avp->offchannel_start = tsf_time;
-	avp->offchannel_duration = sc->sched.offchannel_duration;
-
-	ath_dbg(common, CHAN_CTX,
-		"offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
-		avp->offchannel_duration,
-		avp->offchannel_start,
-		avp->noa_index);
-
-	/*
-	 * When multiple contexts are active, the NoA
-	 * has to be recalculated and advertised after
-	 * an offchannel operation.
-	 */
-	if (ctx->active && avp->noa_duration)
-		avp->noa_duration = 0;
-}
-
-static void ath_chanctx_set_periodic_noa(struct ath_softc *sc,
-					 struct ath_vif *avp,
-					 struct ath_beacon_config *cur_conf,
-					 u32 tsf_time,
-					 u32 beacon_int)
-{
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
-	avp->noa_index++;
-	avp->noa_start = tsf_time;
-
-	if (sc->sched.extend_absence)
-		avp->noa_duration = (3 * beacon_int / 2) +
-			sc->sched.channel_switch_time;
-	else
-		avp->noa_duration =
-			TU_TO_USEC(cur_conf->beacon_interval) / 2 +
-			sc->sched.channel_switch_time;
-
-	if (test_bit(ATH_OP_SCANNING, &common->op_flags) ||
-	    sc->sched.extend_absence)
-		avp->periodic_noa = false;
-	else
-		avp->periodic_noa = true;
-
-	ath_dbg(common, CHAN_CTX,
-		"noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
-		avp->noa_duration,
-		avp->noa_start,
-		avp->noa_index,
-		avp->periodic_noa);
-}
-
-static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc,
-					struct ath_vif *avp,
-					u32 tsf_time,
-					u32 duration)
-{
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
-	avp->noa_index++;
-	avp->noa_start = tsf_time;
-	avp->periodic_noa = false;
-	avp->oneshot_noa = true;
-	avp->noa_duration = duration + sc->sched.channel_switch_time;
-
-	ath_dbg(common, CHAN_CTX,
-		"oneshot noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
-		avp->noa_duration,
-		avp->noa_start,
-		avp->noa_index,
-		avp->periodic_noa);
-}
-
 void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
 		       enum ath_chanctx_event ev)
 {
@@ -497,14 +327,6 @@
 		if (avp->offchannel_duration)
 			avp->offchannel_duration = 0;
 
-		if (avp->oneshot_noa) {
-			avp->noa_duration = 0;
-			avp->oneshot_noa = false;
-
-			ath_dbg(common, CHAN_CTX,
-				"Clearing oneshot NoA\n");
-		}
-
 		if (avp->chanctx != sc->cur_chan) {
 			ath_dbg(common, CHAN_CTX,
 				"Contexts differ, not preparing beacon\n");
@@ -534,24 +356,6 @@
 				"Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n");
 		}
 
-		if (sc->sched.mgd_prepare_tx)
-			sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
-
-		/*
-		 * When a context becomes inactive, for example,
-		 * disassociation of a station context, the NoA
-		 * attribute needs to be removed from subsequent
-		 * beacons.
-		 */
-		if (!ctx->active && avp->noa_duration &&
-		    sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) {
-			avp->noa_duration = 0;
-			avp->periodic_noa = false;
-
-			ath_dbg(common, CHAN_CTX,
-				"Clearing NoA schedule\n");
-		}
-
 		if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
 			break;
 
@@ -574,22 +378,45 @@
 		 * values and increment the index.
 		 */
 		if (sc->next_chan == &sc->offchannel.chan) {
-			ath_chanctx_offchannel_noa(sc, ctx, avp, tsf_time);
+			avp->noa_index++;
+			avp->offchannel_start = tsf_time;
+			avp->offchannel_duration = sc->sched.offchannel_duration;
+
+			ath_dbg(common, CHAN_CTX,
+				"offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
+				avp->offchannel_duration,
+				avp->offchannel_start,
+				avp->noa_index);
+
+			/*
+			 * When multiple contexts are active, the NoA
+			 * has to be recalculated and advertised after
+			 * an offchannel operation.
+			 */
+			if (ctx->active && avp->noa_duration)
+				avp->noa_duration = 0;
+
 			break;
 		}
 
-		ath_chanctx_handle_bmiss(sc, ctx, avp);
-
 		/*
-		 * If a mgd_prepare_tx() has been called by mac80211,
-		 * a one-shot NoA needs to be sent. This can happen
-		 * with one or more active channel contexts - in both
-		 * cases, a new NoA schedule has to be advertised.
+		 * Clear the extend_absence flag if it had been
+		 * set during the previous beacon transmission,
+		 * since we need to revert to the normal NoA
+		 * schedule.
 		 */
-		if (sc->sched.mgd_prepare_tx) {
-			ath_chanctx_set_oneshot_noa(sc, avp, tsf_time,
-						    jiffies_to_usecs(HZ / 5));
-			break;
+		if (ctx->active && sc->sched.extend_absence) {
+			avp->noa_duration = 0;
+			sc->sched.extend_absence = false;
+		}
+
+		/* If at least two consecutive beacons were missed on the STA
+		 * chanctx, stay on the STA channel for one extra beacon period,
+		 * to resync the timer properly.
+		 */
+		if (ctx->active && sc->sched.beacon_miss >= 2) {
+			avp->noa_duration = 0;
+			sc->sched.extend_absence = true;
 		}
 
 		/* Prevent wrap-around issues */
@@ -602,9 +429,31 @@
 		 * announcement.
 		 */
 		if (ctx->active &&
-		    (!avp->noa_duration || sc->sched.force_noa_update))
-			ath_chanctx_set_periodic_noa(sc, avp, cur_conf,
-						     tsf_time, beacon_int);
+		    (!avp->noa_duration || sc->sched.force_noa_update)) {
+			avp->noa_index++;
+			avp->noa_start = tsf_time;
+
+			if (sc->sched.extend_absence)
+				avp->noa_duration = (3 * beacon_int / 2) +
+					sc->sched.channel_switch_time;
+			else
+				avp->noa_duration =
+					TU_TO_USEC(cur_conf->beacon_interval) / 2 +
+					sc->sched.channel_switch_time;
+
+			if (test_bit(ATH_OP_SCANNING, &common->op_flags) ||
+			    sc->sched.extend_absence)
+				avp->periodic_noa = false;
+			else
+				avp->periodic_noa = true;
+
+			ath_dbg(common, CHAN_CTX,
+				"noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
+				avp->noa_duration,
+				avp->noa_start,
+				avp->noa_index,
+				avp->periodic_noa);
+		}
 
 		if (ctx->active && sc->sched.force_noa_update)
 			sc->sched.force_noa_update = false;
@@ -618,15 +467,6 @@
 		}
 
 		sc->sched.beacon_pending = false;
-
-		if (sc->sched.mgd_prepare_tx) {
-			sc->sched.mgd_prepare_tx = false;
-			complete(&sc->go_beacon);
-			ath_dbg(common, CHAN_CTX,
-				"Beacon sent, complete go_beacon\n");
-			break;
-		}
-
 		if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
 			break;
 
@@ -655,16 +495,10 @@
 		    sc->cur_chan == &sc->offchannel.chan)
 			break;
 
+		ath_chanctx_adjust_tbtt_delta(sc);
 		sc->sched.beacon_pending = false;
 		sc->sched.beacon_miss = 0;
 
-		if (sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
-		    !sc->sched.beacon_adjust ||
-		    !sc->cur_chan->tsf_val)
-			break;
-
-		ath_chanctx_adjust_tbtt_delta(sc);
-
 		/* TSF time might have been updated by the incoming beacon,
 		 * need update the channel switch timer to reflect the change.
 		 */
@@ -673,10 +507,10 @@
 			ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
 		tsf_time += ath9k_hw_gettsf32(ah);
 
-		sc->sched.beacon_adjust = false;
+
 		ath_chanctx_setup_timer(sc, tsf_time);
 		break;
-	case ATH_CHANCTX_EVENT_AUTHORIZED:
+	case ATH_CHANCTX_EVENT_ASSOC:
 		if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE ||
 		    avp->chanctx != sc->cur_chan)
 			break;
@@ -718,7 +552,6 @@
 
 		ath_chanctx_setup_timer(sc, tsf_time);
 		sc->sched.beacon_pending = true;
-		sc->sched.beacon_adjust = true;
 		break;
 	case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL:
 		if (sc->cur_chan == &sc->offchannel.chan ||
@@ -745,6 +578,22 @@
 		ieee80211_queue_work(sc->hw, &sc->chanctx_work);
 		break;
 	case ATH_CHANCTX_EVENT_ASSIGN:
+		/*
+		 * When adding a new channel context, check if a scan
+		 * is in progress and abort it since the addition of
+		 * a new channel context is usually followed by VIF
+		 * assignment, in which case we have to start multi-channel
+		 * operation.
+		 */
+		if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
+			ath_dbg(common, CHAN_CTX,
+				"Aborting HW scan to add new context\n");
+
+			spin_unlock_bh(&sc->chan_lock);
+			del_timer_sync(&sc->offchannel.timer);
+			ath_scan_complete(sc, true);
+			spin_lock_bh(&sc->chan_lock);
+		}
 		break;
 	case ATH_CHANCTX_EVENT_CHANGE:
 		break;
@@ -902,11 +751,6 @@
 		sc->offchannel.state = ATH_OFFCHANNEL_ROC_START;
 		ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan);
 	} else {
-		spin_lock_bh(&sc->chan_lock);
-		sc->sched.offchannel_pending = false;
-		sc->sched.wait_switch = false;
-		spin_unlock_bh(&sc->chan_lock);
-
 		ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
 				   NULL);
 		sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
@@ -926,7 +770,8 @@
 
 	sc->offchannel.roc_vif = NULL;
 	sc->offchannel.roc_chan = NULL;
-	ieee80211_remain_on_channel_expired(sc->hw);
+	if (!abort)
+		ieee80211_remain_on_channel_expired(sc->hw);
 	ath_offchannel_next(sc);
 	ath9k_ps_restore(sc);
 }
@@ -963,7 +808,7 @@
 	struct ieee80211_tx_info *info;
 	int band = sc->offchannel.chan.chandef.chan->band;
 
-	skb = ieee80211_probereq_get(sc->hw, vif->addr,
+	skb = ieee80211_probereq_get(sc->hw, vif,
 			ssid->ssid, ssid->ssid_len, req->ie_len);
 	if (!skb)
 		return;
@@ -1057,8 +902,9 @@
 		break;
 	case ATH_OFFCHANNEL_ROC_START:
 	case ATH_OFFCHANNEL_ROC_WAIT:
+		ctx = ath_chanctx_get_oper_chan(sc, false);
 		sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
-		ath_roc_complete(sc, false);
+		ath_chanctx_switch(sc, ctx, NULL);
 		break;
 	default:
 		break;
@@ -1188,6 +1034,7 @@
 		ieee80211_ready_on_channel(sc->hw);
 		break;
 	case ATH_OFFCHANNEL_ROC_DONE:
+		ath_roc_complete(sc, false);
 		break;
 	default:
 		break;
@@ -1235,11 +1082,10 @@
 		ath9k_chanctx_stop_queues(sc, sc->cur_chan);
 		queues_stopped = true;
 
-		__ath9k_flush(sc->hw, ~0, true, false, false);
+		__ath9k_flush(sc->hw, ~0, true);
 
 		if (ath_chanctx_send_ps_frame(sc, true))
-			__ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
-				      false, false, false);
+			__ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false);
 
 		send_ps = true;
 		spin_lock_bh(&sc->chan_lock);
@@ -1331,8 +1177,6 @@
 		    (unsigned long)sc);
 	setup_timer(&sc->sched.timer, ath_chanctx_timer,
 		    (unsigned long)sc);
-
-	init_completion(&sc->go_beacon);
 }
 
 void ath9k_deinit_channel_context(struct ath_softc *sc)
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index e8c6994..c6dd7f1 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -159,7 +159,7 @@
 		if (test_bit(keyix, common->keymap))
 			rxs->flag |= RX_FLAG_DECRYPTED;
 	}
-	if (ah->sw_mgmt_crypto_rx &&
+	if (ah->sw_mgmt_crypto &&
 	    (rxs->flag & RX_FLAG_DECRYPTED) &&
 	    ieee80211_is_mgmt(fc))
 		/* Use software decrypt for management frames. */
@@ -368,11 +368,11 @@
 {
 	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
 
-	if (reg->power_limit != new_txpow)
+	if (reg->power_limit != new_txpow) {
 		ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
-
-	/* read back in case value is clamped */
-	*txpower = reg->max_power_level;
+		/* read back in case value is clamped */
+		*txpower = reg->max_power_level;
+	}
 }
 EXPORT_SYMBOL(ath9k_cmn_update_txpow);
 
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 2b79a56..ffc454b 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -24,7 +24,6 @@
 #include "common-init.h"
 #include "common-beacon.h"
 #include "common-debug.h"
-#include "common-spectral.h"
 
 /* Common header for Atheros 802.11n base driver cores */
 
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 99ce0db..947be9a 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -401,14 +401,22 @@
 	.llseek = default_llseek,
 };
 
-static int read_file_dma(struct seq_file *file, void *data)
+static ssize_t read_file_dma(struct file *file, char __user *user_buf,
+			     size_t count, loff_t *ppos)
 {
-	struct ath_softc *sc = file->private;
+	struct ath_softc *sc = file->private_data;
 	struct ath_hw *ah = sc->sc_ah;
+	char *buf;
+	int retval;
+	unsigned int len = 0;
 	u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
 	int i, qcuOffset = 0, dcuOffset = 0;
 	u32 *qcuBase = &val[0], *dcuBase = &val[4];
 
+	buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	ath9k_ps_wakeup(sc);
 
 	REG_WRITE_D(ah, AR_MACMISC,
@@ -416,18 +424,21 @@
 		   (AR_MACMISC_MISC_OBS_BUS_1 <<
 		    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
 
-	seq_puts(file, "Raw DMA Debug values:\n");
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+			 "Raw DMA Debug values:\n");
 
 	for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
 		if (i % 4 == 0)
-			seq_puts(file, "\n");
+			len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n");
 
 		val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32)));
-		seq_printf(file, "%d: %08x ", i, val[i]);
+		len += scnprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ",
+				 i, val[i]);
 	}
 
-	seq_puts(file, "\n\n");
-	seq_puts(file, "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+	len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n\n");
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+			 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
 
 	for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
 		if (i == 8) {
@@ -440,47 +451,55 @@
 			dcuBase++;
 		}
 
-		seq_printf(file, "%2d          %2x      %1x     %2x           %2x\n",
-			   i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
-			   (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
-			   (val[2] & (0x7 << (i * 3))) >> (i * 3),
-			   (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+		len += scnprintf(buf + len, DMA_BUF_LEN - len,
+			 "%2d          %2x      %1x     %2x           %2x\n",
+			 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+			 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
+			 val[2] & (0x7 << (i * 3)) >> (i * 3),
+			 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
 	}
 
-	seq_puts(file, "\n");
+	len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n");
 
-	seq_printf(file, "qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
-		   (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
-	seq_printf(file, "qcu_complete state: %2x    dcu_complete state:     %2x\n",
-		   (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
-	seq_printf(file, "dcu_arb state:      %2x    dcu_fp state:           %2x\n",
-		   (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
-	seq_printf(file, "chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
-		   (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
-	seq_printf(file, "txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
-		   (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
-	seq_printf(file, "txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
-		   (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+		"qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
+		(val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+		"qcu_complete state: %2x    dcu_complete state:     %2x\n",
+		(val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+		"dcu_arb state:      %2x    dcu_fp state:           %2x\n",
+		(val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+		"chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
+		(val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+		"txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
+		(val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+		"txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
+		(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
 
-	seq_printf(file, "pcu observe: 0x%x\n", REG_READ_D(ah, AR_OBS_BUS_1));
-	seq_printf(file, "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
+	len += scnprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n",
+			 REG_READ_D(ah, AR_OBS_BUS_1));
+	len += scnprintf(buf + len, DMA_BUF_LEN - len,
+			 "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
 
 	ath9k_ps_restore(sc);
 
-	return 0;
-}
+	if (len > DMA_BUF_LEN)
+		len = DMA_BUF_LEN;
 
-static int open_file_dma(struct inode *inode, struct file *f)
-{
-	return single_open(f, read_file_dma, inode->i_private);
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+	return retval;
 }
 
 static const struct file_operations fops_dma = {
-	.open = open_file_dma,
-	.read = seq_read,
+	.read = read_file_dma,
+	.open = simple_open,
 	.owner = THIS_MODULE,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = default_llseek,
 };
 
 
@@ -537,14 +556,22 @@
 		sc->debug.stats.istats.gen_timer++;
 }
 
-static int read_file_interrupt(struct seq_file *file, void *data)
+static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
 {
-	struct ath_softc *sc = file->private;
+	struct ath_softc *sc = file->private_data;
+	unsigned int len = 0;
+	int rv;
+	int mxlen = 4000;
+	char *buf = kmalloc(mxlen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
 #define PR_IS(a, s)						\
 	do {							\
-		seq_printf(file, "%21s: %10u\n", a,		\
-			   sc->debug.stats.istats.s);		\
+		len += scnprintf(buf + len, mxlen - len,	\
+				 "%21s: %10u\n", a,		\
+				 sc->debug.stats.istats.s);	\
 	} while (0)
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
@@ -575,7 +602,8 @@
 	PR_IS("GENTIMER", gen_timer);
 	PR_IS("TOTAL", total);
 
-	seq_puts(file, "SYNC_CAUSE stats:\n");
+	len += scnprintf(buf + len, mxlen - len,
+			 "SYNC_CAUSE stats:\n");
 
 	PR_IS("Sync-All", sync_cause_all);
 	PR_IS("RTC-IRQ", sync_rtc_irq);
@@ -597,27 +625,35 @@
 	PR_IS("MAC-Asleep", mac_asleep);
 	PR_IS("MAC-Sleep-Access", mac_sleep_access);
 
-	return 0;
-}
+	if (len > mxlen)
+		len = mxlen;
 
-static int open_file_interrupt(struct inode *inode, struct file *f)
-{
-	return single_open(f, read_file_interrupt, inode->i_private);
+	rv = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+	return rv;
 }
 
 static const struct file_operations fops_interrupt = {
-	.read = seq_read,
-	.open = open_file_interrupt,
+	.read = read_file_interrupt,
+	.open = simple_open,
 	.owner = THIS_MODULE,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = default_llseek,
 };
 
-static int read_file_xmit(struct seq_file *file, void *data)
+static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
+			      size_t count, loff_t *ppos)
 {
-	struct ath_softc *sc = file->private;
+	struct ath_softc *sc = file->private_data;
+	char *buf;
+	unsigned int len = 0, size = 2048;
+	ssize_t retval = 0;
 
-	seq_printf(file, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len += sprintf(buf, "%30s %10s%10s%10s\n\n",
+		       "BE", "BK", "VI", "VO");
 
 	PR("MPDUs Queued:    ", queued);
 	PR("MPDUs Completed: ", completed);
@@ -642,162 +678,215 @@
 	PR("HW-tx-proc-desc: ", txprocdesc);
 	PR("TX-Failed:       ", txfailed);
 
-	return 0;
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
 }
 
-static void print_queue(struct ath_softc *sc, struct ath_txq *txq,
-			struct seq_file *file)
+static ssize_t print_queue(struct ath_softc *sc, struct ath_txq *txq,
+			   char *buf, ssize_t size)
 {
+	ssize_t len = 0;
+
 	ath_txq_lock(sc, txq);
 
-	seq_printf(file, "%s: %d ", "qnum", txq->axq_qnum);
-	seq_printf(file, "%s: %2d ", "qdepth", txq->axq_depth);
-	seq_printf(file, "%s: %2d ", "ampdu-depth", txq->axq_ampdu_depth);
-	seq_printf(file, "%s: %3d ", "pending", txq->pending_frames);
-	seq_printf(file, "%s: %d\n", "stopped", txq->stopped);
+	len += scnprintf(buf + len, size - len, "%s: %d ",
+			 "qnum", txq->axq_qnum);
+	len += scnprintf(buf + len, size - len, "%s: %2d ",
+			 "qdepth", txq->axq_depth);
+	len += scnprintf(buf + len, size - len, "%s: %2d ",
+			 "ampdu-depth", txq->axq_ampdu_depth);
+	len += scnprintf(buf + len, size - len, "%s: %3d ",
+			 "pending", txq->pending_frames);
+	len += scnprintf(buf + len, size - len, "%s: %d\n",
+			 "stopped", txq->stopped);
 
 	ath_txq_unlock(sc, txq);
+	return len;
 }
 
-static int read_file_queues(struct seq_file *file, void *data)
+static ssize_t read_file_queues(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
 {
-	struct ath_softc *sc = file->private;
+	struct ath_softc *sc = file->private_data;
 	struct ath_txq *txq;
+	char *buf;
+	unsigned int len = 0;
+	const unsigned int size = 1024;
+	ssize_t retval = 0;
 	int i;
 	static const char *qname[4] = {
 		"VO", "VI", "BE", "BK"
 	};
 
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 		txq = sc->tx.txq_map[i];
-		seq_printf(file, "(%s):  ", qname[i]);
-		print_queue(sc, txq, file);
+		len += scnprintf(buf + len, size - len, "(%s):  ", qname[i]);
+		len += print_queue(sc, txq, buf + len, size - len);
 	}
 
-	seq_puts(file, "(CAB): ");
-	print_queue(sc, sc->beacon.cabq, file);
+	len += scnprintf(buf + len, size - len, "(CAB): ");
+	len += print_queue(sc, sc->beacon.cabq, buf + len, size - len);
 
-	return 0;
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
 }
 
-static int read_file_misc(struct seq_file *file, void *data)
+static ssize_t read_file_misc(struct file *file, char __user *user_buf,
+			      size_t count, loff_t *ppos)
 {
-	struct ath_softc *sc = file->private;
+	struct ath_softc *sc = file->private_data;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath9k_vif_iter_data iter_data;
 	struct ath_chanctx *ctx;
+	char buf[512];
+	unsigned int len = 0;
+	ssize_t retval = 0;
 	unsigned int reg;
 	u32 rxfilter, i;
 
-	seq_printf(file, "BSSID: %pM\n", common->curbssid);
-	seq_printf(file, "BSSID-MASK: %pM\n", common->bssidmask);
-	seq_printf(file, "OPMODE: %s\n",
-		   ath_opmode_to_string(sc->sc_ah->opmode));
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "BSSID: %pM\n", common->curbssid);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "BSSID-MASK: %pM\n", common->bssidmask);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "OPMODE: %s\n",
+			 ath_opmode_to_string(sc->sc_ah->opmode));
 
 	ath9k_ps_wakeup(sc);
 	rxfilter = ath9k_hw_getrxfilter(sc->sc_ah);
 	ath9k_ps_restore(sc);
 
-	seq_printf(file, "RXFILTER: 0x%x", rxfilter);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "RXFILTER: 0x%x", rxfilter);
 
 	if (rxfilter & ATH9K_RX_FILTER_UCAST)
-		seq_puts(file, " UCAST");
+		len += scnprintf(buf + len, sizeof(buf) - len, " UCAST");
 	if (rxfilter & ATH9K_RX_FILTER_MCAST)
-		seq_puts(file, " MCAST");
+		len += scnprintf(buf + len, sizeof(buf) - len, " MCAST");
 	if (rxfilter & ATH9K_RX_FILTER_BCAST)
-		seq_puts(file, " BCAST");
+		len += scnprintf(buf + len, sizeof(buf) - len, " BCAST");
 	if (rxfilter & ATH9K_RX_FILTER_CONTROL)
-		seq_puts(file, " CONTROL");
+		len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL");
 	if (rxfilter & ATH9K_RX_FILTER_BEACON)
-		seq_puts(file, " BEACON");
+		len += scnprintf(buf + len, sizeof(buf) - len, " BEACON");
 	if (rxfilter & ATH9K_RX_FILTER_PROM)
-		seq_puts(file, " PROM");
+		len += scnprintf(buf + len, sizeof(buf) - len, " PROM");
 	if (rxfilter & ATH9K_RX_FILTER_PROBEREQ)
-		seq_puts(file, " PROBEREQ");
+		len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
 	if (rxfilter & ATH9K_RX_FILTER_PHYERR)
-		seq_puts(file, " PHYERR");
+		len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR");
 	if (rxfilter & ATH9K_RX_FILTER_MYBEACON)
-		seq_puts(file, " MYBEACON");
+		len += scnprintf(buf + len, sizeof(buf) - len, " MYBEACON");
 	if (rxfilter & ATH9K_RX_FILTER_COMP_BAR)
-		seq_puts(file, " COMP_BAR");
+		len += scnprintf(buf + len, sizeof(buf) - len, " COMP_BAR");
 	if (rxfilter & ATH9K_RX_FILTER_PSPOLL)
-		seq_puts(file, " PSPOLL");
+		len += scnprintf(buf + len, sizeof(buf) - len, " PSPOLL");
 	if (rxfilter & ATH9K_RX_FILTER_PHYRADAR)
-		seq_puts(file, " PHYRADAR");
+		len += scnprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
 	if (rxfilter & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
-		seq_puts(file, " MCAST_BCAST_ALL");
+		len += scnprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
 	if (rxfilter & ATH9K_RX_FILTER_CONTROL_WRAPPER)
-		seq_puts(file, " CONTROL_WRAPPER");
+		len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL_WRAPPER");
 
-	seq_puts(file, "\n");
+	len += scnprintf(buf + len, sizeof(buf) - len, "\n");
 
 	reg = sc->sc_ah->imask;
 
-	seq_printf(file, "INTERRUPT-MASK: 0x%x", reg);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "INTERRUPT-MASK: 0x%x", reg);
 
 	if (reg & ATH9K_INT_SWBA)
-		seq_puts(file, " SWBA");
+		len += scnprintf(buf + len, sizeof(buf) - len, " SWBA");
 	if (reg & ATH9K_INT_BMISS)
-		seq_puts(file, " BMISS");
+		len += scnprintf(buf + len, sizeof(buf) - len, " BMISS");
 	if (reg & ATH9K_INT_CST)
-		seq_puts(file, " CST");
+		len += scnprintf(buf + len, sizeof(buf) - len, " CST");
 	if (reg & ATH9K_INT_RX)
-		seq_puts(file, " RX");
+		len += scnprintf(buf + len, sizeof(buf) - len, " RX");
 	if (reg & ATH9K_INT_RXHP)
-		seq_puts(file, " RXHP");
+		len += scnprintf(buf + len, sizeof(buf) - len, " RXHP");
 	if (reg & ATH9K_INT_RXLP)
-		seq_puts(file, " RXLP");
+		len += scnprintf(buf + len, sizeof(buf) - len, " RXLP");
 	if (reg & ATH9K_INT_BB_WATCHDOG)
-		seq_puts(file, " BB_WATCHDOG");
+		len += scnprintf(buf + len, sizeof(buf) - len, " BB_WATCHDOG");
 
-	seq_puts(file, "\n");
+	len += scnprintf(buf + len, sizeof(buf) - len, "\n");
 
 	i = 0;
 	ath_for_each_chanctx(sc, ctx) {
-		if (list_empty(&ctx->vifs))
+		if (!ctx->assigned || list_empty(&ctx->vifs))
 			continue;
 		ath9k_calculate_iter_data(sc, ctx, &iter_data);
 
-		seq_printf(file,
-			   "VIFS: CTX %i(%i) AP: %i STA: %i MESH: %i WDS: %i",
-			   i++, (int)(ctx->assigned), iter_data.naps,
-			   iter_data.nstations,
-			   iter_data.nmeshes, iter_data.nwds);
-		seq_printf(file, " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
-			   iter_data.nadhocs, sc->cur_chan->nvifs,
-			   sc->nbcnvifs);
+		len += scnprintf(buf + len, sizeof(buf) - len,
+			"VIF-COUNTS: CTX %i AP: %i STA: %i MESH: %i WDS: %i",
+			i++, iter_data.naps, iter_data.nstations,
+			iter_data.nmeshes, iter_data.nwds);
+		len += scnprintf(buf + len, sizeof(buf) - len,
+			" ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
+			iter_data.nadhocs, sc->cur_chan->nvifs, sc->nbcnvifs);
 	}
 
-	return 0;
+	if (len > sizeof(buf))
+		len = sizeof(buf);
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	return retval;
 }
 
-static int read_file_reset(struct seq_file *file, void *data)
+static ssize_t read_file_reset(struct file *file, char __user *user_buf,
+			       size_t count, loff_t *ppos)
 {
-	struct ath_softc *sc = file->private;
-	static const char * const reset_cause[__RESET_TYPE_MAX] = {
-		[RESET_TYPE_BB_HANG] = "Baseband Hang",
-		[RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog",
-		[RESET_TYPE_FATAL_INT] = "Fatal HW Error",
-		[RESET_TYPE_TX_ERROR] = "TX HW error",
-		[RESET_TYPE_TX_GTT] = "Transmit timeout",
-		[RESET_TYPE_TX_HANG] = "TX Path Hang",
-		[RESET_TYPE_PLL_HANG] = "PLL RX Hang",
-		[RESET_TYPE_MAC_HANG] = "MAC Hang",
-		[RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
-		[RESET_TYPE_MCI] = "MCI Reset",
-		[RESET_TYPE_CALIBRATION] = "Calibration error",
-	};
-	int i;
+	struct ath_softc *sc = file->private_data;
+	char buf[512];
+	unsigned int len = 0;
 
-	for (i = 0; i < ARRAY_SIZE(reset_cause); i++) {
-		if (!reset_cause[i])
-		    continue;
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "Baseband Hang",
+			 sc->debug.stats.reset[RESET_TYPE_BB_HANG]);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "Baseband Watchdog",
+			 sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "Fatal HW Error",
+			 sc->debug.stats.reset[RESET_TYPE_FATAL_INT]);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "TX HW error",
+			 sc->debug.stats.reset[RESET_TYPE_TX_ERROR]);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "TX Path Hang",
+			 sc->debug.stats.reset[RESET_TYPE_TX_HANG]);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "PLL RX Hang",
+			 sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "MAC Hang",
+			 sc->debug.stats.reset[RESET_TYPE_MAC_HANG]);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "Stuck Beacon",
+			 sc->debug.stats.reset[RESET_TYPE_BEACON_STUCK]);
+	len += scnprintf(buf + len, sizeof(buf) - len,
+			 "%17s: %2d\n", "MCI Reset",
+			 sc->debug.stats.reset[RESET_TYPE_MCI]);
 
-		seq_printf(file, "%17s: %2d\n", reset_cause[i],
-			   sc->debug.stats.reset[i]);
-	}
+	if (len > sizeof(buf))
+		len = sizeof(buf);
 
-	return 0;
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
@@ -837,56 +926,32 @@
 		TX_STAT_INC(qnum, delim_underrun);
 }
 
-static int open_file_xmit(struct inode *inode, struct file *f)
-{
-	return single_open(f, read_file_xmit, inode->i_private);
-}
-
 static const struct file_operations fops_xmit = {
-	.read = seq_read,
-	.open = open_file_xmit,
+	.read = read_file_xmit,
+	.open = simple_open,
 	.owner = THIS_MODULE,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = default_llseek,
 };
 
-static int open_file_queues(struct inode *inode, struct file *f)
-{
-	return single_open(f, read_file_queues, inode->i_private);
-}
-
 static const struct file_operations fops_queues = {
-	.read = seq_read,
-	.open = open_file_queues,
+	.read = read_file_queues,
+	.open = simple_open,
 	.owner = THIS_MODULE,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = default_llseek,
 };
 
-static int open_file_misc(struct inode *inode, struct file *f)
-{
-	return single_open(f, read_file_misc, inode->i_private);
-}
-
 static const struct file_operations fops_misc = {
-	.read = seq_read,
-	.open = open_file_misc,
+	.read = read_file_misc,
+	.open = simple_open,
 	.owner = THIS_MODULE,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = default_llseek,
 };
 
-static int open_file_reset(struct inode *inode, struct file *f)
-{
-	return single_open(f, read_file_reset, inode->i_private);
-}
-
 static const struct file_operations fops_reset = {
-	.read = seq_read,
-	.open = open_file_reset,
+	.read = read_file_reset,
+	.open = simple_open,
 	.owner = THIS_MODULE,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = default_llseek,
 };
 
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
@@ -895,7 +960,7 @@
 }
 
 static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
-				size_t count, loff_t *ppos)
+                                size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
 	char buf[32];
@@ -906,7 +971,7 @@
 }
 
 static ssize_t write_file_regidx(struct file *file, const char __user *user_buf,
-				 size_t count, loff_t *ppos)
+			     size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
 	unsigned long regidx;
@@ -934,7 +999,7 @@
 };
 
 static ssize_t read_file_regval(struct file *file, char __user *user_buf,
-				size_t count, loff_t *ppos)
+			     size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
 	struct ath_hw *ah = sc->sc_ah;
@@ -950,7 +1015,7 @@
 }
 
 static ssize_t write_file_regval(struct file *file, const char __user *user_buf,
-				 size_t count, loff_t *ppos)
+			     size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
 	struct ath_hw *ah = sc->sc_ah;
@@ -1016,45 +1081,57 @@
 	.llseek = default_llseek,/* read accesses f_pos */
 };
 
-static int read_file_dump_nfcal(struct seq_file *file, void *data)
+static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
 {
-	struct ath_softc *sc = file->private;
+	struct ath_softc *sc = file->private_data;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath9k_nfcal_hist *h = sc->cur_chan->caldata.nfCalHist;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &common->hw->conf;
+	u32 len = 0, size = 1500;
 	u32 i, j;
+	ssize_t retval = 0;
+	char *buf;
 	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
 	u8 nread;
 
-	seq_printf(file, "Channel Noise Floor : %d\n", ah->noise);
-	seq_puts(file, "Chain | privNF | # Readings | NF Readings\n");
+	buf = kzalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	len += scnprintf(buf + len, size - len,
+			 "Channel Noise Floor : %d\n", ah->noise);
+	len += scnprintf(buf + len, size - len,
+			 "Chain | privNF | # Readings | NF Readings\n");
 	for (i = 0; i < NUM_NF_READINGS; i++) {
 		if (!(chainmask & (1 << i)) ||
 		    ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
 			continue;
 
 		nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount;
-		seq_printf(file, " %d\t %d\t %d\t\t", i, h[i].privNF, nread);
+		len += scnprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
+				 i, h[i].privNF, nread);
 		for (j = 0; j < nread; j++)
-			seq_printf(file, " %d", h[i].nfCalBuffer[j]);
-		seq_puts(file, "\n");
+			len += scnprintf(buf + len, size - len,
+					 " %d", h[i].nfCalBuffer[j]);
+		len += scnprintf(buf + len, size - len, "\n");
 	}
 
-	return 0;
-}
+	if (len > size)
+		len = size;
 
-static int open_file_dump_nfcal(struct inode *inode, struct file *f)
-{
-	return single_open(f, read_file_dump_nfcal, inode->i_private);
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
 }
 
 static const struct file_operations fops_dump_nfcal = {
-	.read = seq_read,
-	.open = open_file_dump_nfcal,
+	.read = read_file_dump_nfcal,
+	.open = simple_open,
 	.owner = THIS_MODULE,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = default_llseek,
 };
 
 #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
@@ -1238,7 +1315,7 @@
 
 void ath9k_deinit_debug(struct ath_softc *sc)
 {
-	ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
+	ath9k_spectral_deinit_debug(sc);
 }
 
 int ath9k_init_debug(struct ath_hw *ah)
@@ -1258,7 +1335,7 @@
 
 	ath9k_dfs_init_debug(sc);
 	ath9k_tx99_init_debug(sc);
-	ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);
+	ath9k_spectral_init_debug(sc);
 
 	debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
 			    &fops_dma);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 30340f1..82847c0 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -49,7 +49,6 @@
 	RESET_TYPE_MAC_HANG,
 	RESET_TYPE_BEACON_STUCK,
 	RESET_TYPE_MCI,
-	RESET_TYPE_CALIBRATION,
 	__RESET_TYPE_MAX
 };
 
@@ -196,11 +195,12 @@
 #define TXSTATS sc->debug.stats.txstats
 #define PR(str, elem)							\
 	do {								\
-		seq_printf(file, "%s%13u%11u%10u%10u\n", str,		\
-			   TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem,\
-			   TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem,\
-			   TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem,\
-			   TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
+		len += scnprintf(buf + len, size - len,			\
+				 "%s%13u%11u%10u%10u\n", str,		\
+				 TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem,\
+				 TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem,\
+				 TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem,\
+				 TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
 	} while(0)
 
 struct ath_rx_rate_stats {
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 303aa35..3516bbd 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -262,7 +262,7 @@
 {
 	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
 	struct ath_common *common = ath9k_hw_common(ah);
-	u16 *eepdata, temp, magic;
+	u16 *eepdata, temp, magic, magic2;
 	u32 sum = 0, el;
 	bool need_swap = false;
 	int i, addr, size;
@@ -272,16 +272,27 @@
 		return false;
 	}
 
-	if (swab16(magic) == AR5416_EEPROM_MAGIC &&
-	    !(ah->ah_flags & AH_NO_EEP_SWAP)) {
-		size = sizeof(struct ar5416_eeprom_def);
-		need_swap = true;
-		eepdata = (u16 *) (&ah->eeprom);
+	if (!ath9k_hw_use_flash(ah)) {
+		ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
 
-		for (addr = 0; addr < size / sizeof(u16); addr++) {
-			temp = swab16(*eepdata);
-			*eepdata = temp;
-			eepdata++;
+		if (magic != AR5416_EEPROM_MAGIC) {
+			magic2 = swab16(magic);
+
+			if (magic2 == AR5416_EEPROM_MAGIC) {
+				size = sizeof(struct ar5416_eeprom_def);
+				need_swap = true;
+				eepdata = (u16 *) (&ah->eeprom);
+
+				for (addr = 0; addr < size / sizeof(u16); addr++) {
+					temp = swab16(*eepdata);
+					*eepdata = temp;
+					eepdata++;
+				}
+			} else {
+				ath_err(common,
+					"Invalid EEPROM Magic. Endianness mismatch.\n");
+				return -EINVAL;
+			}
 		}
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 48ee417..3d9e8e4 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -25,12 +25,7 @@
 			       enum led_brightness brightness)
 {
 	struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
-	u32 val = (brightness == LED_OFF);
-
-	if (sc->sc_ah->config.led_active_high)
-		val = !val;
-
-	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
+	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
 }
 
 void ath_deinit_leds(struct ath_softc *sc)
@@ -87,7 +82,7 @@
 	ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 
 	/* LED off, active low */
-	ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
+	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
 }
 #endif
 
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index de6d475..e9278bc 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -481,7 +481,6 @@
 	unsigned long op_flags;
 
 	struct ath9k_hw_cal_data caldata;
-	struct ath_spec_scan_priv spec_priv;
 
 	spinlock_t beacon_lock;
 	struct ath_beacon_config cur_beacon_conf;
@@ -626,12 +625,8 @@
 #endif
 #ifdef CPTCFG_ATH9K_HTC_DEBUGFS
 int ath9k_htc_init_debug(struct ath_hw *ah);
-void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv);
 #else
 static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; };
-static inline void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv)
-{
-}
 #endif /* CPTCFG_ATH9K_HTC_DEBUGFS */
 
 #endif /* HTC_H */
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 8cef1ed..8b529e4 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -490,10 +490,6 @@
 	WARN_ON(i != ATH9K_HTC_SSTATS_LEN);
 }
 
-void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv)
-{
-	ath9k_cmn_spectral_deinit_debug(&priv->spec_priv);
-}
 
 int ath9k_htc_init_debug(struct ath_hw *ah)
 {
@@ -505,8 +501,6 @@
 	if (!priv->debug.debugfs_phy)
 		return -ENOMEM;
 
-	ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy);
-
 	debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy,
 			    priv, &fops_tgt_int_stats);
 	debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 33d9103..b153389 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -53,21 +53,6 @@
 };
 #endif
 
-static void ath9k_htc_op_ps_wakeup(struct ath_common *common)
-{
-	ath9k_htc_ps_wakeup((struct ath9k_htc_priv *) common->priv);
-}
-
-static void ath9k_htc_op_ps_restore(struct ath_common *common)
-{
-	ath9k_htc_ps_restore((struct ath9k_htc_priv *) common->priv);
-}
-
-static struct ath_ps_ops ath9k_htc_ps_ops = {
-	.wakeup = ath9k_htc_op_ps_wakeup,
-	.restore = ath9k_htc_op_ps_restore,
-};
-
 static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
 {
 	int time_left;
@@ -102,7 +87,6 @@
 
 	wiphy_rfkill_stop_polling(hw->wiphy);
 	ath9k_deinit_leds(priv);
-	ath9k_htc_deinit_debug(priv);
 	ieee80211_unregister_hw(hw);
 	ath9k_rx_cleanup(priv);
 	ath9k_tx_cleanup(priv);
@@ -465,14 +449,6 @@
 
 	common->last_rssi = ATH_RSSI_DUMMY_MARKER;
 	priv->ah->opmode = NL80211_IFTYPE_STATION;
-
-	priv->spec_priv.ah = priv->ah;
-	priv->spec_priv.spec_config.enabled = 0;
-	priv->spec_priv.spec_config.short_repeat = false;
-	priv->spec_priv.spec_config.count = 8;
-	priv->spec_priv.spec_config.endless = false;
-	priv->spec_priv.spec_config.period = 0x12;
-	priv->spec_priv.spec_config.fft_period = 0x02;
 }
 
 static int ath9k_init_priv(struct ath9k_htc_priv *priv,
@@ -502,7 +478,6 @@
 
 	common = ath9k_hw_common(ah);
 	common->ops = &ah->reg_ops;
-	common->ps_ops = &ath9k_htc_ps_ops;
 	common->bus_ops = &ath9k_usb_bus_ops;
 	common->ah = ah;
 	common->hw = priv->hw;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index ac9563e..c03b3fa 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -314,10 +314,6 @@
 	mod_timer(&priv->tx.cleanup_timer,
 		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
 
-	/* perform spectral scan if requested. */
-	if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
-		     priv->spec_priv.spectral_mode == SPECTRAL_CHANSCAN)
-		ath9k_cmn_spectral_scan_trigger(common, &priv->spec_priv);
 err:
 	ath9k_htc_ps_restore(priv);
 	return ret;
@@ -1447,7 +1443,7 @@
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
 				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-			if (priv->ah->sw_mgmt_crypto_tx &&
+			if (priv->ah->sw_mgmt_crypto &&
 			    key->cipher == WLAN_CIPHER_SUITE_CCMP)
 				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
 			ret = 0;
@@ -1691,9 +1687,7 @@
 	return ret;
 }
 
-static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    const u8 *mac_addr)
+static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -1707,8 +1701,7 @@
 	mutex_unlock(&priv->mutex);
 }
 
-static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif)
+static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_common *common = ath9k_hw_common(priv->ah);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index a0f58e2..f0484b1 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -946,7 +946,7 @@
 static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats,
 				 struct ath_htc_rx_status *rxstatus)
 {
-	rx_stats->rs_datalen	= be16_to_cpu(rxstatus->rs_datalen);
+	rx_stats->rs_datalen	= rxstatus->rs_datalen;
 	rx_stats->rs_status	= rxstatus->rs_status;
 	rx_stats->rs_phyerr	= rxstatus->rs_phyerr;
 	rx_stats->rs_rssi	= rxstatus->rs_rssi;
@@ -1012,20 +1012,6 @@
 	 * separately to avoid doing two lookups for a rate for each frame.
 	 */
 	hdr = (struct ieee80211_hdr *)skb->data;
-
-	/*
-	 * Process PHY errors and return so that the packet
-	 * can be dropped.
-	 */
-	if (rx_stats.rs_status & ATH9K_RXERR_PHY) {
-		/* TODO: Not using DFS processing now. */
-		if (ath_cmn_process_fft(&priv->spec_priv, hdr,
-				    &rx_stats, rx_status->mactime)) {
-			/* TODO: Code to collect spectral scan statistics */
-		}
-		goto rx_next;
-	}
-
 	if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats,
 			&decrypt_error, priv->rxfilter))
 		goto rx_next;
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index 6dd44d4..134862c 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -41,9 +41,10 @@
 	ath9k_hw_ops(ah)->set_desc_link(ds, link);
 }
 
-static inline int ath9k_hw_calibrate(struct ath_hw *ah,
-				     struct ath9k_channel *chan,
-				     u8 rxchainmask, bool longcal)
+static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
+				      struct ath9k_channel *chan,
+				      u8 rxchainmask,
+				      bool longcal)
 {
 	return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
 }
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 82c7afa..3e83eec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/time.h>
 #include <linux/bitops.h>
-#include <linux/etherdevice.h>
 #include <asm/unaligned.h>
 
 #include "hw.h"
@@ -447,16 +446,8 @@
 		common->macaddr[2 * i] = eeval >> 8;
 		common->macaddr[2 * i + 1] = eeval & 0xff;
 	}
-	if (!is_valid_ether_addr(common->macaddr)) {
-		ath_err(common,
-			"eeprom contains invalid mac address: %pM\n",
-			common->macaddr);
-
-		random_ether_addr(common->macaddr);
-		ath_err(common,
-			"random mac address will be used: %pM\n",
-			common->macaddr);
-	}
+	if (sum == 0 || sum == 0xffff * 3)
+		return -EADDRNOTAVAIL;
 
 	return 0;
 }
@@ -870,6 +861,19 @@
 	udelay(RTC_PLL_SETTLE_DELAY);
 
 	REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
+
+	if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
+		if (ah->is_clk_25mhz) {
+			REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
+			REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
+			REG_WRITE(ah,  AR_SLP32_INC, 0x0001e7ae);
+		} else {
+			REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
+			REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
+			REG_WRITE(ah,  AR_SLP32_INC, 0x0001e800);
+		}
+		udelay(100);
+	}
 }
 
 static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
@@ -1585,22 +1589,16 @@
 		 * frames when constructing CCMP AAD. */
 		REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
 			      0xc7ff);
-		if (AR_SREV_9271(ah) || AR_DEVID_7010(ah))
-			ah->sw_mgmt_crypto_tx = true;
-		else
-			ah->sw_mgmt_crypto_tx = false;
-		ah->sw_mgmt_crypto_rx = false;
+		ah->sw_mgmt_crypto = false;
 	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
 		/* Disable hardware crypto for management frames */
 		REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
 			    AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
 		REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
 			    AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
-		ah->sw_mgmt_crypto_tx = true;
-		ah->sw_mgmt_crypto_rx = true;
+		ah->sw_mgmt_crypto = true;
 	} else {
-		ah->sw_mgmt_crypto_tx = true;
-		ah->sw_mgmt_crypto_rx = true;
+		ah->sw_mgmt_crypto = true;
 	}
 }
 
@@ -1947,8 +1945,6 @@
 
 	REGWRITE_BUFFER_FLUSH(ah);
 
-	ath9k_hw_gen_timer_start_tsf2(ah);
-
 	ath9k_hw_init_desc(ah);
 
 	if (ath9k_hw_btcoex_is_enabled(ah))
@@ -1957,10 +1953,8 @@
 	if (ath9k_hw_mci_is_enabled(ah))
 		ar9003_mci_check_bt(ah);
 
-	if (AR_SREV_9300_20_OR_LATER(ah)) {
-		ath9k_hw_loadnf(ah, chan);
-		ath9k_hw_start_nfcal(ah, true);
-	}
+	ath9k_hw_loadnf(ah, chan);
+	ath9k_hw_start_nfcal(ah, true);
 
 	if (AR_SREV_9300_20_OR_LATER(ah))
 		ar9003_hw_bb_watchdog_config(ah);
@@ -2328,6 +2322,7 @@
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
+	unsigned int chip_chainmask;
 
 	u16 eeval;
 	u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
@@ -2347,40 +2342,31 @@
 	}
 
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
-
-	if (eeval & AR5416_OPFLAGS_11A) {
-		if (ah->disable_5ghz)
-			ath_warn(common, "disabling 5GHz band\n");
-		else
-			pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
-	}
-
-	if (eeval & AR5416_OPFLAGS_11G) {
-		if (ah->disable_2ghz)
-			ath_warn(common, "disabling 2GHz band\n");
-		else
-			pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
-	}
-
-	if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) {
-		ath_err(common, "both bands are disabled\n");
+	if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
+		ath_err(common,
+			"no band has been marked as supported in EEPROM\n");
 		return -EINVAL;
 	}
 
+	if (eeval & AR5416_OPFLAGS_11A)
+		pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
+
+	if (eeval & AR5416_OPFLAGS_11G)
+		pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
+
 	if (AR_SREV_9485(ah) ||
 	    AR_SREV_9285(ah) ||
 	    AR_SREV_9330(ah) ||
 	    AR_SREV_9565(ah))
-		pCap->chip_chainmask = 1;
+		chip_chainmask = 1;
+	else if (AR_SREV_9462(ah))
+		chip_chainmask = 3;
 	else if (!AR_SREV_9280_20_OR_LATER(ah))
-		pCap->chip_chainmask = 7;
-	else if (!AR_SREV_9300_20_OR_LATER(ah) ||
-		 AR_SREV_9340(ah) ||
-		 AR_SREV_9462(ah) ||
-		 AR_SREV_9531(ah))
-		pCap->chip_chainmask = 3;
+		chip_chainmask = 7;
+	else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
+		chip_chainmask = 3;
 	else
-		pCap->chip_chainmask = 7;
+		chip_chainmask = 7;
 
 	pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
 	/*
@@ -2398,8 +2384,8 @@
 		/* Use rx_chainmask from EEPROM. */
 		pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
 
-	pCap->tx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->tx_chainmask);
-	pCap->rx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->rx_chainmask);
+	pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
+	pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
 	ah->txchainmask = pCap->tx_chainmask;
 	ah->rxchainmask = pCap->rx_chainmask;
 
@@ -2913,16 +2899,6 @@
 }
 EXPORT_SYMBOL(ath9k_hw_gettsf32);
 
-void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah)
-{
-	struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
-
-	if (timer_table->tsf2_enabled) {
-		REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN);
-		REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE);
-	}
-}
-
 struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
 					  void (*trigger)(void *),
 					  void (*overflow)(void *),
@@ -2933,11 +2909,7 @@
 	struct ath_gen_timer *timer;
 
 	if ((timer_index < AR_FIRST_NDP_TIMER) ||
-	    (timer_index >= ATH_MAX_GEN_TIMER))
-		return NULL;
-
-	if ((timer_index > AR_FIRST_NDP_TIMER) &&
-	    !AR_SREV_9300_20_OR_LATER(ah))
+		(timer_index >= ATH_MAX_GEN_TIMER))
 		return NULL;
 
 	timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
@@ -2951,11 +2923,6 @@
 	timer->overflow = overflow;
 	timer->arg = arg;
 
-	if ((timer_index > AR_FIRST_NDP_TIMER) && !timer_table->tsf2_enabled) {
-		timer_table->tsf2_enabled = true;
-		ath9k_hw_gen_timer_start_tsf2(ah);
-	}
-
 	return timer;
 }
 EXPORT_SYMBOL(ath_gen_timer_alloc);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index fda6cb5..a578e51 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -217,8 +217,8 @@
 #define AH_WOW_BEACON_MISS		BIT(3)
 
 enum ath_hw_txq_subtype {
-	ATH_TXQ_AC_BK = 0,
-	ATH_TXQ_AC_BE = 1,
+	ATH_TXQ_AC_BE = 0,
+	ATH_TXQ_AC_BK = 1,
 	ATH_TXQ_AC_VI = 2,
 	ATH_TXQ_AC_VO = 3,
 };
@@ -244,20 +244,13 @@
 	ATH9K_HW_CAP_2GHZ			= BIT(11),
 	ATH9K_HW_CAP_5GHZ			= BIT(12),
 	ATH9K_HW_CAP_APM			= BIT(13),
-#ifdef CPTCFG_ATH9K_PCOEM
 	ATH9K_HW_CAP_RTT			= BIT(14),
 	ATH9K_HW_CAP_MCI			= BIT(15),
-	ATH9K_HW_WOW_DEVICE_CAPABLE		= BIT(16),
-	ATH9K_HW_CAP_BT_ANT_DIV			= BIT(17),
-#else
-	ATH9K_HW_CAP_RTT			= 0,
-	ATH9K_HW_CAP_MCI			= 0,
-	ATH9K_HW_WOW_DEVICE_CAPABLE		= 0,
-	ATH9K_HW_CAP_BT_ANT_DIV			= 0,
-#endif
-	ATH9K_HW_CAP_DFS			= BIT(18),
-	ATH9K_HW_CAP_PAPRD			= BIT(19),
-	ATH9K_HW_CAP_FCC_BAND_SWITCH		= BIT(20),
+	ATH9K_HW_CAP_DFS			= BIT(16),
+	ATH9K_HW_WOW_DEVICE_CAPABLE		= BIT(17),
+	ATH9K_HW_CAP_PAPRD			= BIT(18),
+	ATH9K_HW_CAP_FCC_BAND_SWITCH		= BIT(19),
+	ATH9K_HW_CAP_BT_ANT_DIV			= BIT(20),
 };
 
 /*
@@ -276,7 +269,6 @@
 	u16 rts_aggr_limit;
 	u8 tx_chainmask;
 	u8 rx_chainmask;
-	u8 chip_chainmask;
 	u8 max_txchains;
 	u8 max_rxchains;
 	u8 num_gpio_pins;
@@ -330,7 +322,6 @@
 	bool alt_mingainidx;
 	bool no_pll_pwrsave;
 	bool tx_gain_buffalo;
-	bool led_active_high;
 };
 
 enum ath9k_int {
@@ -526,7 +517,6 @@
 struct ath_gen_timer_table {
 	struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
 	u16 timer_mask;
-	bool tsf2_enabled;
 };
 
 struct ath_hw_antcomb_conf {
@@ -691,8 +681,10 @@
 				     bool power_off);
 	void (*rx_enable)(struct ath_hw *ah);
 	void (*set_desc_link)(void *ds, u32 link);
-	int (*calibrate)(struct ath_hw *ah, struct ath9k_channel *chan,
-			 u8 rxchainmask, bool longcal);
+	bool (*calibrate)(struct ath_hw *ah,
+			  struct ath9k_channel *chan,
+			  u8 rxchainmask,
+			  bool longcal);
 	bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked,
 			u32 *sync_cause_p);
 	void (*set_txdesc)(struct ath_hw *ah, void *ds,
@@ -734,7 +726,6 @@
 #define AH_USE_EEPROM   0x1
 #define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
 #define AH_FASTCC       0x4
-#define AH_NO_EEP_SWAP  0x8 /* Do not swap EEPROM data */
 
 struct ath_hw {
 	struct ath_ops reg_ops;
@@ -756,8 +747,7 @@
 	} eeprom;
 	const struct eeprom_ops *eep_ops;
 
-	bool sw_mgmt_crypto_tx;
-	bool sw_mgmt_crypto_rx;
+	bool sw_mgmt_crypto;
 	bool is_pciexpress;
 	bool aspm_enabled;
 	bool is_monitoring;
@@ -934,16 +924,10 @@
 	bool is_clk_25mhz;
 	int (*get_mac_revision)(void);
 	int (*external_reset)(void);
-	bool disable_2ghz;
-	bool disable_5ghz;
 
 	const struct firmware *eeprom_blob;
 
 	struct ath_dynack dynack;
-
-	bool tpc_enabled;
-	u8 tx_power[Ar5416RateSize];
-	u8 tx_power_stbc[Ar5416RateSize];
 };
 
 struct ath_bus_ops {
@@ -1043,7 +1027,6 @@
 			      struct ath_gen_timer *timer,
 			      u32 timer_next,
 			      u32 timer_period);
-void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah);
 void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
 
 void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
@@ -1084,8 +1067,6 @@
 bool ar9003_paprd_is_done(struct ath_hw *ah);
 bool ar9003_is_paprd_enabled(struct ath_hw *ah);
 void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
-void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array,
-				 struct ath9k_channel *chan);
 
 /* Hardware family op attach helpers */
 int ar5008_hw_attach_phy_ops(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 7764675..4df734e 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -104,21 +104,6 @@
 
 static void ath9k_deinit_softc(struct ath_softc *sc);
 
-static void ath9k_op_ps_wakeup(struct ath_common *common)
-{
-	ath9k_ps_wakeup((struct ath_softc *) common->priv);
-}
-
-static void ath9k_op_ps_restore(struct ath_common *common)
-{
-	ath9k_ps_restore((struct ath_softc *) common->priv);
-}
-
-static struct ath_ps_ops ath9k_ps_ops = {
-	.wakeup = ath9k_op_ps_wakeup,
-	.restore = ath9k_op_ps_restore,
-};
-
 /*
  * Read and write, they both share the same lock. We do this to serialize
  * reads and writes on Atheros 802.11n PCI devices only. This is required
@@ -203,20 +188,17 @@
 	ath_reg_notifier_apply(wiphy, request, reg);
 
 	/* Set tx power */
-	if (!ah->curchan)
-		return;
-
-	sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;
-	ath9k_ps_wakeup(sc);
-	ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
-	ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
-			       sc->cur_chan->txpower,
-			       &sc->cur_chan->cur_txpower);
-	/* synchronize DFS detector if regulatory domain changed */
-	if (sc->dfs_detector != NULL)
-		sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
-						 request->dfs_region);
-	ath9k_ps_restore(sc);
+	if (ah->curchan) {
+		sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;
+		ath9k_ps_wakeup(sc);
+		ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
+		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
+		/* synchronize DFS detector if regulatory domain changed */
+		if (sc->dfs_detector != NULL)
+			sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
+							 request->dfs_region);
+		ath9k_ps_restore(sc);
+	}
 }
 
 /*
@@ -382,13 +364,12 @@
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
 		sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
 
-	sc->spec_priv.ah = sc->sc_ah;
-	sc->spec_priv.spec_config.enabled = 0;
-	sc->spec_priv.spec_config.short_repeat = true;
-	sc->spec_priv.spec_config.count = 8;
-	sc->spec_priv.spec_config.endless = false;
-	sc->spec_priv.spec_config.period = 0xFF;
-	sc->spec_priv.spec_config.fft_period = 0xF;
+	sc->spec_config.enabled = 0;
+	sc->spec_config.short_repeat = true;
+	sc->spec_config.count = 8;
+	sc->spec_config.endless = false;
+	sc->spec_config.period = 0xFF;
+	sc->spec_config.fft_period = 0xF;
 }
 
 static void ath9k_init_pcoem_platform(struct ath_softc *sc)
@@ -397,9 +378,6 @@
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct ath_common *common = ath9k_hw_common(ah);
 
-	if (!IS_ENABLED(CPTCFG_ATH9K_PCOEM))
-		return;
-
 	if (common->bus_ops->ath_bus_type != ATH_PCI)
 		return;
 
@@ -457,9 +435,6 @@
 		ah->config.no_pll_pwrsave = true;
 		ath_info(common, "Disable PLL PowerSave\n");
 	}
-
-	if (sc->driver_data & ATH9K_PCI_LED_ACT_HI)
-		ah->config.led_active_high = true;
 }
 
 static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
@@ -548,14 +523,10 @@
 	ah->reg_ops.read = ath9k_ioread32;
 	ah->reg_ops.write = ath9k_iowrite32;
 	ah->reg_ops.rmw = ath9k_reg_rmw;
+	sc->sc_ah = ah;
 	pCap = &ah->caps;
 
 	common = ath9k_hw_common(ah);
-
-	/* Will be cleared in ath9k_start() */
-	set_bit(ATH_OP_INVALID, &common->op_flags);
-
-	sc->sc_ah = ah;
 	sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
 	sc->tx99_power = MAX_RATE_POWER + 1;
 	init_waitqueue_head(&sc->tx_wait);
@@ -573,15 +544,10 @@
 		ah->is_clk_25mhz = pdata->is_clk_25mhz;
 		ah->get_mac_revision = pdata->get_mac_revision;
 		ah->external_reset = pdata->external_reset;
-		ah->disable_2ghz = pdata->disable_2ghz;
-		ah->disable_5ghz = pdata->disable_5ghz;
-		if (!pdata->endian_check)
-			ah->ah_flags |= AH_NO_EEP_SWAP;
 	}
 
 	common->ops = &ah->reg_ops;
 	common->bus_ops = bus_ops;
-	common->ps_ops = &ath9k_ps_ops;
 	common->ah = ah;
 	common->hw = sc->hw;
 	common->priv = sc;
@@ -920,6 +886,9 @@
 	common = ath9k_hw_common(ah);
 	ath9k_set_hw_capab(sc, hw);
 
+	/* Will be cleared in ath9k_start() */
+	set_bit(ATH_OP_INVALID, &common->op_flags);
+
 	/* Initialize regulatory */
 	error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
 			      ath9k_reg_notifier);
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index b829263..2343f56 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -371,15 +371,9 @@
 
 	/* Perform calibration if necessary */
 	if (longcal || shortcal) {
-		int ret = ath9k_hw_calibrate(ah, ah->curchan, ah->rxchainmask,
-					     longcal);
-		if (ret < 0) {
-			common->ani.caldone = 0;
-			ath9k_queue_reset(sc, RESET_TYPE_CALIBRATION);
-			return;
-		}
-
-		common->ani.caldone = ret;
+		common->ani.caldone =
+			ath9k_hw_calibrate(ah, ah->curchan,
+					   ah->rxchainmask, longcal);
 	}
 
 	ath_dbg(common, ANI,
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 3e58bfa..275205a 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -311,7 +311,14 @@
 		q = ATH9K_NUM_TX_QUEUES - 3;
 		break;
 	case ATH9K_TX_QUEUE_DATA:
-		q = qinfo->tqi_subtype;
+		for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
+			if (ah->txq[q].tqi_type ==
+			    ATH9K_TX_QUEUE_INACTIVE)
+				break;
+		if (q == ATH9K_NUM_TX_QUEUES) {
+			ath_err(common, "No available TX queue\n");
+			return -1;
+		}
 		break;
 	default:
 		ath_err(common, "Invalid TX queue type: %u\n", type);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index e55fa11..aa69cea 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -704,7 +704,7 @@
 	enum ath9k_pkt_type type;
 	enum ath9k_key_type keytype;
 	u8 keyix;
-	u8 txpower[4];
+	u8 txpower;
 };
 
 struct ath_hw;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 38efe20..35bf3e7 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -54,8 +54,7 @@
 	}
 }
 
-static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq,
-				     bool sw_pending)
+static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
 {
 	bool pending = false;
 
@@ -66,9 +65,6 @@
 		goto out;
 	}
 
-	if (!sw_pending)
-		goto out;
-
 	if (txq->mac80211_qnum >= 0) {
 		struct list_head *list;
 
@@ -233,9 +229,8 @@
 
 	ath9k_calculate_summary_state(sc, sc->cur_chan);
 	ath_startrecv(sc);
-	ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
-			       sc->cur_chan->txpower,
-			       &sc->cur_chan->cur_txpower);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			       sc->cur_chan->txpower, &sc->curtxpow);
 	clear_bit(ATH_OP_HW_RESET, &common->op_flags);
 
 	if (!sc->cur_chan->offchannel && start) {
@@ -275,7 +270,7 @@
 	return true;
 }
 
-static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
+int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -286,7 +281,6 @@
 	__ath_cancel_work(sc);
 
 	tasklet_disable(&sc->intr_tq);
-	tasklet_disable(&sc->bcon_tasklet);
 	spin_lock_bh(&sc->sc_pcu_lock);
 
 	if (!sc->cur_chan->offchannel) {
@@ -332,7 +326,6 @@
 
 out:
 	spin_unlock_bh(&sc->sc_pcu_lock);
-	tasklet_enable(&sc->bcon_tasklet);
 	tasklet_enable(&sc->intr_tq);
 
 	return r;
@@ -546,10 +539,11 @@
 		sched = true;
 
 	/*
-	 * If a FATAL interrupt is received, we have to reset the chip
-	 * immediately.
+	 * If a FATAL or RXORN interrupt is received, we have to reset the
+	 * chip immediately.
 	 */
-	if (status & ATH9K_INT_FATAL)
+	if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
+	    !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
 		goto chip_reset;
 
 	if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
@@ -604,11 +598,7 @@
 #undef SCHED_INTR
 }
 
-/*
- * This function is called when a HW reset cannot be deferred
- * and has to be immediate.
- */
-int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan)
+int ath_reset(struct ath_softc *sc)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int r;
@@ -616,17 +606,12 @@
 	set_bit(ATH_OP_HW_RESET, &common->op_flags);
 
 	ath9k_ps_wakeup(sc);
-	r = ath_reset_internal(sc, hchan);
+	r = ath_reset_internal(sc, NULL);
 	ath9k_ps_restore(sc);
 
 	return r;
 }
 
-/*
- * When a HW reset can be deferred, it is added to the
- * hw_reset_work workqueue, but we set ATH_OP_HW_RESET before
- * queueing.
- */
 void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -641,9 +626,7 @@
 {
 	struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
 
-	ath9k_ps_wakeup(sc);
-	ath_reset_internal(sc, NULL);
-	ath9k_ps_restore(sc);
+	ath_reset(sc);
 }
 
 /**********************/
@@ -727,8 +710,7 @@
 	if (ah->led_pin >= 0) {
 		ath9k_hw_cfg_output(ah, ah->led_pin,
 				    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-		ath9k_hw_set_gpio(ah, ah->led_pin,
-				  (ah->config.led_active_high) ? 1 : 0);
+		ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 	}
 
 	/*
@@ -870,8 +852,7 @@
 	spin_lock_bh(&sc->sc_pcu_lock);
 
 	if (ah->led_pin >= 0) {
-		ath9k_hw_set_gpio(ah, ah->led_pin,
-				  (ah->config.led_active_high) ? 0 : 1);
+		ath9k_hw_set_gpio(ah, ah->led_pin, 1);
 		ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
 	}
 
@@ -887,9 +868,6 @@
 						    &sc->cur_chan->chandef);
 
 	ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
-
-	set_bit(ATH_OP_INVALID, &common->op_flags);
-
 	ath9k_hw_phy_disable(ah);
 
 	ath9k_hw_configpcipowersave(ah, true);
@@ -898,6 +876,7 @@
 
 	ath9k_ps_restore(sc);
 
+	set_bit(ATH_OP_INVALID, &common->op_flags);
 	sc->ps_idle = prev_idle;
 
 	mutex_unlock(&sc->mutex);
@@ -998,8 +977,9 @@
 	struct ath_vif *avp;
 
 	/*
-	 * The hardware will use primary station addr together with the
-	 * BSSID mask when matching addresses.
+	 * Pick the MAC address of the first interface as the new hardware
+	 * MAC address. The hardware will use it together with the BSSID mask
+	 * when matching addresses.
 	 */
 	memset(iter_data, 0, sizeof(*iter_data));
 	memset(&iter_data->mask, 0xff, ETH_ALEN);
@@ -1060,7 +1040,7 @@
 
 	eth_zero_addr(common->curbssid);
 	eth_broadcast_addr(common->bssidmask);
-	memcpy(common->macaddr, vif->addr, ETH_ALEN);
+	ether_addr_copy(common->macaddr, vif->addr);
 	common->curaid = 0;
 	ah->opmode = vif->type;
 	ah->imask &= ~ATH9K_INT_SWBA;
@@ -1101,7 +1081,7 @@
 	ath9k_calculate_iter_data(sc, ctx, &iter_data);
 
 	if (iter_data.has_hw_macaddr)
-		memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
+		ether_addr_copy(common->macaddr, iter_data.hw_macaddr);
 
 	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
 	ath_hw_setbssidmask(common);
@@ -1191,8 +1171,7 @@
 	for (i = 0; i < IEEE80211_NUM_ACS; i++)
 		vif->hw_queue[i] = i;
 
-	if (vif->type == NL80211_IFTYPE_AP ||
-	    vif->type == NL80211_IFTYPE_MESH_POINT)
+	if (vif->type == NL80211_IFTYPE_AP)
 		vif->cab_queue = hw->queues - 2;
 	else
 		vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
@@ -1229,8 +1208,6 @@
 		list_add_tail(&avp->list, &avp->chanctx->vifs);
 	}
 
-	ath9k_calculate_summary_state(sc, avp->chanctx);
-
 	ath9k_assign_hw_queues(hw, vif);
 
 	an->sc = sc;
@@ -1300,8 +1277,6 @@
 
 	ath_tx_node_cleanup(sc, &avp->mcast_node);
 
-	ath9k_calculate_summary_state(sc, avp->chanctx);
-
 	mutex_unlock(&sc->mutex);
 }
 
@@ -1348,6 +1323,78 @@
 	ath_dbg(common, PS, "PowerSave disabled\n");
 }
 
+void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	u32 rxfilter;
+
+	if (config_enabled(CPTCFG_ATH9K_TX99))
+		return;
+
+	if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
+		ath_err(common, "spectrum analyzer not implemented on this hardware\n");
+		return;
+	}
+
+	ath9k_ps_wakeup(sc);
+	rxfilter = ath9k_hw_getrxfilter(ah);
+	ath9k_hw_setrxfilter(ah, rxfilter |
+				 ATH9K_RX_FILTER_PHYRADAR |
+				 ATH9K_RX_FILTER_PHYERR);
+
+	/* TODO: usually this should not be neccesary, but for some reason
+	 * (or in some mode?) the trigger must be called after the
+	 * configuration, otherwise the register will have its values reset
+	 * (on my ar9220 to value 0x01002310)
+	 */
+	ath9k_spectral_scan_config(hw, sc->spectral_mode);
+	ath9k_hw_ops(ah)->spectral_scan_trigger(ah);
+	ath9k_ps_restore(sc);
+}
+
+int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
+			       enum spectral_mode spectral_mode)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
+		ath_err(common, "spectrum analyzer not implemented on this hardware\n");
+		return -1;
+	}
+
+	switch (spectral_mode) {
+	case SPECTRAL_DISABLED:
+		sc->spec_config.enabled = 0;
+		break;
+	case SPECTRAL_BACKGROUND:
+		/* send endless samples.
+		 * TODO: is this really useful for "background"?
+		 */
+		sc->spec_config.endless = 1;
+		sc->spec_config.enabled = 1;
+		break;
+	case SPECTRAL_CHANSCAN:
+	case SPECTRAL_MANUAL:
+		sc->spec_config.endless = 0;
+		sc->spec_config.enabled = 1;
+		break;
+	default:
+		return -1;
+	}
+
+	ath9k_ps_wakeup(sc);
+	ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config);
+	ath9k_ps_restore(sc);
+
+	sc->spectral_mode = spectral_mode;
+
+	return 0;
+}
+
 static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ath_softc *sc = hw->priv;
@@ -1408,9 +1455,8 @@
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
 		ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
 		sc->cur_chan->txpower = 2 * conf->power_level;
-		ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
-				       sc->cur_chan->txpower,
-				       &sc->cur_chan->cur_txpower);
+		ath9k_cmn_update_txpow(ah, sc->curtxpow,
+				       sc->cur_chan->txpower, &sc->curtxpow);
 	}
 
 	mutex_unlock(&sc->mutex);
@@ -1507,40 +1553,6 @@
 	return 0;
 }
 
-static int ath9k_sta_state(struct ieee80211_hw *hw,
-			   struct ieee80211_vif *vif,
-			   struct ieee80211_sta *sta,
-			   enum ieee80211_sta_state old_state,
-			   enum ieee80211_sta_state new_state)
-{
-	struct ath_softc *sc = hw->priv;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	int ret = 0;
-
-	if (old_state == IEEE80211_STA_AUTH &&
-	    new_state == IEEE80211_STA_ASSOC) {
-		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) {
-		ret = ath9k_sta_remove(hw, vif, sta);
-		ath_dbg(common, CONFIG,
-			"Remove station: %pM\n", sta->addr);
-	}
-
-	if (ath9k_is_chanctx_enabled()) {
-		if (vif->type == NL80211_IFTYPE_STATION) {
-			if (old_state == IEEE80211_STA_ASSOC &&
-			    new_state == IEEE80211_STA_AUTHORIZED)
-				ath_chanctx_event(sc, vif,
-						  ATH_CHANCTX_EVENT_AUTHORIZED);
-		}
-	}
-
-	return ret;
-}
-
 static void ath9k_sta_set_tx_filter(struct ath_hw *ah,
 				    struct ath_node *an,
 				    bool set)
@@ -1665,7 +1677,7 @@
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
 				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-			if (sc->sc_ah->sw_mgmt_crypto_tx &&
+			if (sc->sc_ah->sw_mgmt_crypto &&
 			    key->cipher == WLAN_CIPHER_SUITE_CCMP)
 				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
 			ret = 0;
@@ -1725,11 +1737,17 @@
 		ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
 			bss_conf->bssid, bss_conf->assoc);
 
-		memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN);
+		ether_addr_copy(avp->bssid, bss_conf->bssid);
 		avp->aid = bss_conf->aid;
 		avp->assoc = bss_conf->assoc;
 
 		ath9k_calculate_summary_state(sc, avp->chanctx);
+
+		if (ath9k_is_chanctx_enabled()) {
+			if (bss_conf->assoc)
+				ath_chanctx_event(sc, vif,
+						  ATH_CHANCTX_EVENT_ASSOC);
+		}
 	}
 
 	if (changed & BSS_CHANGED_IBSS) {
@@ -1825,7 +1843,6 @@
 			      u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ath_softc *sc = hw->priv;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	bool flush = false;
 	int ret = 0;
 
@@ -1837,12 +1854,6 @@
 	case IEEE80211_AMPDU_RX_STOP:
 		break;
 	case IEEE80211_AMPDU_TX_START:
-		if (ath9k_is_chanctx_enabled()) {
-			if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
-				ret = -EBUSY;
-				break;
-			}
-		}
 		ath9k_ps_wakeup(sc);
 		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
 		if (!ret)
@@ -1956,8 +1967,7 @@
 	mutex_unlock(&sc->mutex);
 }
 
-static bool ath9k_has_tx_pending(struct ath_softc *sc,
-				 bool sw_pending)
+static bool ath9k_has_tx_pending(struct ath_softc *sc)
 {
 	int i, npend = 0;
 
@@ -1965,8 +1975,7 @@
 		if (!ATH_TXQ_SETUP(sc, i))
 			continue;
 
-		npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i],
-						 sw_pending);
+		npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
 		if (npend)
 			break;
 	}
@@ -1978,38 +1987,18 @@
 			u32 queues, bool drop)
 {
 	struct ath_softc *sc = hw->priv;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
-	if (ath9k_is_chanctx_enabled()) {
-		if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
-			goto flush;
-
-		/*
-		 * If MCC is active, extend the flush timeout
-		 * and wait for the HW/SW queues to become
-		 * empty. This needs to be done outside the
-		 * sc->mutex lock to allow the channel scheduler
-		 * to switch channel contexts.
-		 *
-		 * The vif queues have been stopped in mac80211,
-		 * so there won't be any incoming frames.
-		 */
-		__ath9k_flush(hw, queues, drop, true, true);
-		return;
-	}
-flush:
 	mutex_lock(&sc->mutex);
-	__ath9k_flush(hw, queues, drop, true, false);
+	__ath9k_flush(hw, queues, drop);
 	mutex_unlock(&sc->mutex);
 }
 
-void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
-		   bool sw_pending, bool timeout_override)
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
-	int timeout;
+	int timeout = HZ / 5; /* 200 ms */
 	bool drain_txq;
 
 	cancel_delayed_work_sync(&sc->tx_complete_work);
@@ -2024,17 +2013,7 @@
 		return;
 	}
 
-	spin_lock_bh(&sc->chan_lock);
-	if (timeout_override)
-		timeout = HZ / 5;
-	else
-		timeout = sc->cur_chan->flush_timeout;
-	spin_unlock_bh(&sc->chan_lock);
-
-	ath_dbg(common, CHAN_CTX,
-		"Flush timeout: %d\n", jiffies_to_msecs(timeout));
-
-	if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending),
+	if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc),
 			       timeout) > 0)
 		drop = false;
 
@@ -2045,7 +2024,7 @@
 		spin_unlock_bh(&sc->sc_pcu_lock);
 
 		if (!drain_txq)
-			ath_reset(sc, NULL);
+			ath_reset(sc);
 
 		ath9k_ps_restore(sc);
 	}
@@ -2057,7 +2036,7 @@
 {
 	struct ath_softc *sc = hw->priv;
 
-	return ath9k_has_tx_pending(sc, true);
+	return ath9k_has_tx_pending(sc);
 }
 
 static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
@@ -2188,17 +2167,14 @@
 	return 0;
 }
 
-static void ath9k_sw_scan_start(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif,
-				const u8 *mac_addr)
+static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	set_bit(ATH_OP_SCANNING, &common->op_flags);
 }
 
-static void ath9k_sw_scan_complete(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif)
+static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -2207,28 +2183,6 @@
 
 #ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT
 
-static void ath9k_cancel_pending_offchannel(struct ath_softc *sc)
-{
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
-	if (sc->offchannel.roc_vif) {
-		ath_dbg(common, CHAN_CTX,
-			"%s: Aborting RoC\n", __func__);
-
-		del_timer_sync(&sc->offchannel.timer);
-		if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
-			ath_roc_complete(sc, true);
-	}
-
-	if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
-		ath_dbg(common, CHAN_CTX,
-			"%s: Aborting HW scan\n", __func__);
-
-		del_timer_sync(&sc->offchannel.timer);
-		ath_scan_complete(sc, true);
-	}
-}
-
 static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			 struct ieee80211_scan_request *hw_req)
 {
@@ -2359,6 +2313,7 @@
 			conf->def.chan->center_freq);
 
 		ath_chanctx_set_channel(sc, ctx, &conf->def);
+		ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ASSIGN);
 
 		mutex_unlock(&sc->mutex);
 		return 0;
@@ -2415,8 +2370,6 @@
 	struct ath_chanctx *ctx = ath_chanctx_get(conf);
 	int i;
 
-	ath9k_cancel_pending_offchannel(sc);
-
 	mutex_lock(&sc->mutex);
 
 	ath_dbg(common, CHAN_CTX,
@@ -2446,8 +2399,6 @@
 	struct ath_chanctx *ctx = ath_chanctx_get(conf);
 	int ac;
 
-	ath9k_cancel_pending_offchannel(sc);
-
 	mutex_lock(&sc->mutex);
 
 	ath_dbg(common, CHAN_CTX,
@@ -2471,11 +2422,7 @@
 	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_vif *avp = (struct ath_vif *) vif->drv_priv;
-	struct ath_beacon_config *cur_conf;
-	struct ath_chanctx *go_ctx;
-	unsigned long timeout;
 	bool changed = false;
-	u32 beacon_int;
 
 	if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
 		return;
@@ -2486,57 +2433,19 @@
 	mutex_lock(&sc->mutex);
 
 	spin_lock_bh(&sc->chan_lock);
-	if (sc->next_chan || (sc->cur_chan != avp->chanctx))
+	if (sc->next_chan || (sc->cur_chan != avp->chanctx)) {
+		sc->next_chan = avp->chanctx;
 		changed = true;
-	spin_unlock_bh(&sc->chan_lock);
-
-	if (!changed)
-		goto out;
-
-	ath9k_cancel_pending_offchannel(sc);
-
-	go_ctx = ath_is_go_chanctx_present(sc);
-
-	if (go_ctx) {
-		/*
-		 * Wait till the GO interface gets a chance
-		 * to send out an NoA.
-		 */
-		spin_lock_bh(&sc->chan_lock);
-		sc->sched.mgd_prepare_tx = true;
-		cur_conf = &go_ctx->beacon;
-		beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
-		spin_unlock_bh(&sc->chan_lock);
-
-		timeout = usecs_to_jiffies(beacon_int * 2);
-		init_completion(&sc->go_beacon);
-
-		mutex_unlock(&sc->mutex);
-
-		if (wait_for_completion_timeout(&sc->go_beacon,
-						timeout) == 0) {
-			ath_dbg(common, CHAN_CTX,
-				"Failed to send new NoA\n");
-
-			spin_lock_bh(&sc->chan_lock);
-			sc->sched.mgd_prepare_tx = false;
-			spin_unlock_bh(&sc->chan_lock);
-		}
-
-		mutex_lock(&sc->mutex);
 	}
-
 	ath_dbg(common, CHAN_CTX,
-		"%s: Set chanctx state to FORCE_ACTIVE for vif: %pM\n",
-		__func__, vif->addr);
-
-	spin_lock_bh(&sc->chan_lock);
-	sc->next_chan = avp->chanctx;
+		"%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n",
+		__func__, changed);
 	sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
 	spin_unlock_bh(&sc->chan_lock);
 
-	ath_chanctx_set_next(sc, true);
-out:
+	if (changed)
+		ath_chanctx_set_next(sc, true);
+
 	mutex_unlock(&sc->mutex);
 }
 
@@ -2559,24 +2468,6 @@
 
 #endif
 
-static int ath9k_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			     int *dbm)
-{
-	struct ath_softc *sc = hw->priv;
-	struct ath_vif *avp = (void *)vif->drv_priv;
-
-	mutex_lock(&sc->mutex);
-	if (avp->chanctx)
-		*dbm = avp->chanctx->cur_txpower;
-	else
-		*dbm = sc->cur_chan->cur_txpower;
-	mutex_unlock(&sc->mutex);
-
-	*dbm /= 2;
-
-	return 0;
-}
-
 struct ieee80211_ops ath9k_ops = {
 	.tx 		    = ath9k_tx,
 	.start 		    = ath9k_start,
@@ -2586,7 +2477,8 @@
 	.remove_interface   = ath9k_remove_interface,
 	.config 	    = ath9k_config,
 	.configure_filter   = ath9k_configure_filter,
-	.sta_state          = ath9k_sta_state,
+	.sta_add	    = ath9k_sta_add,
+	.sta_remove	    = ath9k_sta_remove,
 	.sta_notify         = ath9k_sta_notify,
 	.conf_tx 	    = ath9k_conf_tx,
 	.bss_info_changed   = ath9k_bss_info_changed,
@@ -2623,5 +2515,4 @@
 #endif
 	.sw_scan_start	    = ath9k_sw_scan_start,
 	.sw_scan_complete   = ath9k_sw_scan_complete,
-	.get_txpower        = ath9k_get_txpower,
 };
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 6bc24fb..c018dea 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -30,7 +30,6 @@
 	{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
 
-#ifdef CPTCFG_ATH9K_PCOEM
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x002A,
 			 PCI_VENDOR_ID_AZWAVE,
@@ -83,7 +82,6 @@
 			 PCI_VENDOR_ID_AZWAVE,
 			 0x2C37),
 	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
-#endif
 
 	{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
 	{ PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
@@ -104,7 +102,6 @@
 
 	{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E  AR9300 */
 
-#ifdef CPTCFG_ATH9K_PCOEM
 	/* PCI-E CUS198 */
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x0032,
@@ -297,12 +294,10 @@
 			 PCI_VENDOR_ID_ASUSTEK,
 			 0x850D),
 	  .driver_data = ATH9K_PCI_NO_PLL_PWRSAVE },
-#endif
 
 	{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E  AR9485 */
 	{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E  AR9580 */
 
-#ifdef CPTCFG_ATH9K_PCOEM
 	/* PCI-E CUS217 */
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x0034,
@@ -657,14 +652,11 @@
 			 0x0036,
 			 PCI_VENDOR_ID_DELL,
 			 0x020E),
-	  .driver_data = ATH9K_PCI_AR9565_2ANT |
-			 ATH9K_PCI_BT_ANT_DIV |
-			 ATH9K_PCI_LED_ACT_HI},
+	  .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
 
 	/* PCI-E AR9565 (WB335) */
 	{ PCI_VDEVICE(ATHEROS, 0x0036),
 	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
-#endif
 
 	{ 0 }
 };
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 04da61b..b231f21 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -870,7 +870,7 @@
 	 */
 	if (rx_stats->rs_status & ATH9K_RXERR_PHY) {
 		ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime);
-		if (ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime))
+		if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
 			RX_STAT_INC(rx_spectral);
 
 		return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 7743b38..2a938f4 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -892,21 +892,10 @@
 	(AR_SREV_9330((_ah)) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
 
-#ifdef CPTCFG_ATH9K_PCOEM
-#define AR_SREV_9462(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
 #define AR_SREV_9485(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
-#define AR_SREV_9565(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
-#else
-#define AR_SREV_9462(_ah) 0
-#define AR_SREV_9485(_ah) 0
-#define AR_SREV_9565(_ah) 0
-#endif
-
 #define AR_SREV_9485_11_OR_LATER(_ah) \
-	(AR_SREV_9485(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485) && \
 	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9485_11))
 #define AR_SREV_9485_OR_LATER(_ah) \
 	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485))
@@ -926,30 +915,34 @@
     (AR_SREV_9285_12_OR_LATER(_ah) && \
      ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
 
+#define AR_SREV_9462(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
 #define AR_SREV_9462_20(_ah) \
-	(AR_SREV_9462(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
 #define AR_SREV_9462_21(_ah) \
-	(AR_SREV_9462(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21))
 #define AR_SREV_9462_20_OR_LATER(_ah) \
-	(AR_SREV_9462(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
 	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
 #define AR_SREV_9462_21_OR_LATER(_ah) \
-	(AR_SREV_9462(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
 	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21))
 
+#define AR_SREV_9565(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
 #define AR_SREV_9565_10(_ah) \
-	(AR_SREV_9565(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10))
 #define AR_SREV_9565_101(_ah) \
-	(AR_SREV_9565(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101))
 #define AR_SREV_9565_11(_ah) \
-	(AR_SREV_9565(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11))
 #define AR_SREV_9565_11_OR_LATER(_ah) \
-	(AR_SREV_9565(_ah) && \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
 	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11))
 
 #define AR_SREV_9550(_ah) \
@@ -1605,7 +1598,6 @@
 
 #define AR_RESET_TSF        0x8020
 #define AR_RESET_TSF_ONCE   0x01000000
-#define AR_RESET_TSF2_ONCE  0x02000000
 
 #define AR_MAX_CFP_DUR      0x8038
 #define AR_CFP_VAL          0x0000FFFF
@@ -1724,8 +1716,6 @@
 #define AR_TPC_CTS_S           8
 #define AR_TPC_CHIRP           0x003f0000
 #define AR_TPC_CHIRP_S         16
-#define AR_TPC_RPT	       0x3f000000
-#define AR_TPC_RPT_S	       24
 
 #define AR_QUIET1          0x80fc
 #define AR_QUIET1_NEXT_QUIET_S         0
@@ -1969,8 +1959,6 @@
 #define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET		0x80000000
 #define AR_MAC_PCU_GEN_TIMER_TSF_SEL			0x83d8
 
-#define AR_DIRECT_CONNECT                              0x83a0
-#define AR_DC_AP_STA_EN                                0x00000001
 
 #define AR_AES_MUTE_MASK0       0x805c
 #define AR_AES_MUTE_MASK0_FC    0x0000FFFF
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c
similarity index 74%
rename from drivers/net/wireless/ath/ath9k/common-spectral.c
rename to drivers/net/wireless/ath/ath9k/spectral.c
index 5253136..fad0c14 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/spectral.c
@@ -24,24 +24,23 @@
 	return (s8) rssi_val;
 }
 
-static void ath_debug_send_fft_sample(struct ath_spec_scan_priv *spec_priv,
+static void ath_debug_send_fft_sample(struct ath_softc *sc,
 				      struct fft_sample_tlv *fft_sample_tlv)
 {
 	int length;
-	if (!spec_priv->rfs_chan_spec_scan)
+	if (!sc->rfs_chan_spec_scan)
 		return;
 
 	length = __be16_to_cpu(fft_sample_tlv->length) +
 		 sizeof(*fft_sample_tlv);
-	relay_write(spec_priv->rfs_chan_spec_scan, fft_sample_tlv, length);
+	relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
 }
 
 /* returns 1 if this was a spectral frame, even if not handled. */
-int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr,
+int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
 		    struct ath_rx_status *rs, u64 tsf)
 {
-	struct ath_hw *ah = spec_priv->ah;
-	struct ath_common *common = ath9k_hw_common(spec_priv->ah);
+	struct ath_hw *ah = sc->sc_ah;
 	u8 num_bins, *bins, *vdata = (u8 *)hdr;
 	struct fft_sample_ht20 fft_sample_20;
 	struct fft_sample_ht20_40 fft_sample_40;
@@ -68,7 +67,7 @@
 	if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
 		return 0;
 
-	chan_type = cfg80211_get_chandef_type(&common->hw->conf.chandef);
+	chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef);
 	if ((chan_type == NL80211_CHAN_HT40MINUS) ||
 	    (chan_type == NL80211_CHAN_HT40PLUS)) {
 		fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN;
@@ -200,11 +199,10 @@
 		tlv = (struct fft_sample_tlv *)&fft_sample_20;
 	}
 
-	ath_debug_send_fft_sample(spec_priv, tlv);
+	ath_debug_send_fft_sample(sc, tlv);
 
 	return 1;
 }
-EXPORT_SYMBOL(ath_cmn_process_fft);
 
 /*********************/
 /* spectral_scan_ctl */
@@ -213,11 +211,11 @@
 static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
 				       size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	char *mode = "";
 	unsigned int len;
 
-	switch (spec_priv->spectral_mode) {
+	switch (sc->spectral_mode) {
 	case SPECTRAL_DISABLED:
 		mode = "disable";
 		break;
@@ -235,84 +233,12 @@
 	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
 }
 
-void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
-				 struct ath_spec_scan_priv *spec_priv)
-{
-	struct ath_hw *ah = spec_priv->ah;
-	u32 rxfilter;
-
-	if (config_enabled(CPTCFG_ATH9K_TX99))
-		return;
-
-	if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
-		ath_err(common, "spectrum analyzer not implemented on this hardware\n");
-		return;
-	}
-
-	ath_ps_ops(common)->wakeup(common);
-	rxfilter = ath9k_hw_getrxfilter(ah);
-	ath9k_hw_setrxfilter(ah, rxfilter |
-				 ATH9K_RX_FILTER_PHYRADAR |
-				 ATH9K_RX_FILTER_PHYERR);
-
-	/* TODO: usually this should not be neccesary, but for some reason
-	 * (or in some mode?) the trigger must be called after the
-	 * configuration, otherwise the register will have its values reset
-	 * (on my ar9220 to value 0x01002310)
-	 */
-	ath9k_cmn_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode);
-	ath9k_hw_ops(ah)->spectral_scan_trigger(ah);
-	ath_ps_ops(common)->restore(common);
-}
-EXPORT_SYMBOL(ath9k_cmn_spectral_scan_trigger);
-
-int ath9k_cmn_spectral_scan_config(struct ath_common *common,
-			       struct ath_spec_scan_priv *spec_priv,
-			       enum spectral_mode spectral_mode)
-{
-	struct ath_hw *ah = spec_priv->ah;
-
-	if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
-		ath_err(common, "spectrum analyzer not implemented on this hardware\n");
-		return -1;
-	}
-
-	switch (spectral_mode) {
-	case SPECTRAL_DISABLED:
-		spec_priv->spec_config.enabled = 0;
-		break;
-	case SPECTRAL_BACKGROUND:
-		/* send endless samples.
-		 * TODO: is this really useful for "background"?
-		 */
-		spec_priv->spec_config.endless = 1;
-		spec_priv->spec_config.enabled = 1;
-		break;
-	case SPECTRAL_CHANSCAN:
-	case SPECTRAL_MANUAL:
-		spec_priv->spec_config.endless = 0;
-		spec_priv->spec_config.enabled = 1;
-		break;
-	default:
-		return -1;
-	}
-
-	ath_ps_ops(common)->wakeup(common);
-	ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config);
-	ath_ps_ops(common)->restore(common);
-
-	spec_priv->spectral_mode = spectral_mode;
-
-	return 0;
-}
-EXPORT_SYMBOL(ath9k_cmn_spectral_scan_config);
-
 static ssize_t write_file_spec_scan_ctl(struct file *file,
 					const char __user *user_buf,
 					size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
-	struct ath_common *common = ath9k_hw_common(spec_priv->ah);
+	struct ath_softc *sc = file->private_data;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	char buf[32];
 	ssize_t len;
 
@@ -326,18 +252,18 @@
 	buf[len] = '\0';
 
 	if (strncmp("trigger", buf, 7) == 0) {
-		ath9k_cmn_spectral_scan_trigger(common, spec_priv);
+		ath9k_spectral_scan_trigger(sc->hw);
 	} else if (strncmp("background", buf, 10) == 0) {
-		ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_BACKGROUND);
+		ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
 		ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
 	} else if (strncmp("chanscan", buf, 8) == 0) {
-		ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_CHANSCAN);
+		ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
 		ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
 	} else if (strncmp("manual", buf, 6) == 0) {
-		ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_MANUAL);
+		ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
 		ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
 	} else if (strncmp("disable", buf, 7) == 0) {
-		ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_DISABLED);
+		ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
 		ath_dbg(common, CONFIG, "spectral scan: disabled\n");
 	} else {
 		return -EINVAL;
@@ -362,11 +288,11 @@
 					       char __user *user_buf,
 					       size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	char buf[32];
 	unsigned int len;
 
-	len = sprintf(buf, "%d\n", spec_priv->spec_config.short_repeat);
+	len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -374,7 +300,7 @@
 						const char __user *user_buf,
 						size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	unsigned long val;
 	char buf[32];
 	ssize_t len;
@@ -390,7 +316,7 @@
 	if (val > 1)
 		return -EINVAL;
 
-	spec_priv->spec_config.short_repeat = val;
+	sc->spec_config.short_repeat = val;
 	return count;
 }
 
@@ -410,11 +336,11 @@
 					char __user *user_buf,
 					size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	char buf[32];
 	unsigned int len;
 
-	len = sprintf(buf, "%d\n", spec_priv->spec_config.count);
+	len = sprintf(buf, "%d\n", sc->spec_config.count);
 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -422,7 +348,7 @@
 					 const char __user *user_buf,
 					 size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	unsigned long val;
 	char buf[32];
 	ssize_t len;
@@ -438,7 +364,7 @@
 	if (val > 255)
 		return -EINVAL;
 
-	spec_priv->spec_config.count = val;
+	sc->spec_config.count = val;
 	return count;
 }
 
@@ -458,11 +384,11 @@
 					 char __user *user_buf,
 					 size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	char buf[32];
 	unsigned int len;
 
-	len = sprintf(buf, "%d\n", spec_priv->spec_config.period);
+	len = sprintf(buf, "%d\n", sc->spec_config.period);
 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -470,7 +396,7 @@
 					  const char __user *user_buf,
 					  size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	unsigned long val;
 	char buf[32];
 	ssize_t len;
@@ -486,7 +412,7 @@
 	if (val > 255)
 		return -EINVAL;
 
-	spec_priv->spec_config.period = val;
+	sc->spec_config.period = val;
 	return count;
 }
 
@@ -506,11 +432,11 @@
 					     char __user *user_buf,
 					     size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	char buf[32];
 	unsigned int len;
 
-	len = sprintf(buf, "%d\n", spec_priv->spec_config.fft_period);
+	len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -518,7 +444,7 @@
 					      const char __user *user_buf,
 					      size_t count, loff_t *ppos)
 {
-	struct ath_spec_scan_priv *spec_priv = file->private_data;
+	struct ath_softc *sc = file->private_data;
 	unsigned long val;
 	char buf[32];
 	ssize_t len;
@@ -534,7 +460,7 @@
 	if (val > 15)
 		return -EINVAL;
 
-	spec_priv->spec_config.fft_period = val;
+	sc->spec_config.fft_period = val;
 	return count;
 }
 
@@ -584,41 +510,38 @@
 /* Debug Init/Deinit */
 /*********************/
 
-void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
+void ath9k_spectral_deinit_debug(struct ath_softc *sc)
 {
-	if (config_enabled(CPTCFG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) {
-		relay_close(spec_priv->rfs_chan_spec_scan);
-		spec_priv->rfs_chan_spec_scan = NULL;
+	if (config_enabled(CPTCFG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
+		relay_close(sc->rfs_chan_spec_scan);
+		sc->rfs_chan_spec_scan = NULL;
 	}
 }
-EXPORT_SYMBOL(ath9k_cmn_spectral_deinit_debug);
 
-void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv,
-				   struct dentry *debugfs_phy)
+void ath9k_spectral_init_debug(struct ath_softc *sc)
 {
-	spec_priv->rfs_chan_spec_scan = relay_open("spectral_scan",
-					    debugfs_phy,
+	sc->rfs_chan_spec_scan = relay_open("spectral_scan",
+					    sc->debug.debugfs_phy,
 					    1024, 256, &rfs_spec_scan_cb,
 					    NULL);
 	debugfs_create_file("spectral_scan_ctl",
 			    S_IRUSR | S_IWUSR,
-			    debugfs_phy, spec_priv,
+			    sc->debug.debugfs_phy, sc,
 			    &fops_spec_scan_ctl);
 	debugfs_create_file("spectral_short_repeat",
 			    S_IRUSR | S_IWUSR,
-			    debugfs_phy, spec_priv,
+			    sc->debug.debugfs_phy, sc,
 			    &fops_spectral_short_repeat);
 	debugfs_create_file("spectral_count",
 			    S_IRUSR | S_IWUSR,
-			    debugfs_phy, spec_priv,
+			    sc->debug.debugfs_phy, sc,
 			    &fops_spectral_count);
 	debugfs_create_file("spectral_period",
 			    S_IRUSR | S_IWUSR,
-			    debugfs_phy, spec_priv,
+			    sc->debug.debugfs_phy, sc,
 			    &fops_spectral_period);
 	debugfs_create_file("spectral_fft_period",
 			    S_IRUSR | S_IWUSR,
-			    debugfs_phy, spec_priv,
+			    sc->debug.debugfs_phy, sc,
 			    &fops_spectral_fft_period);
 }
-EXPORT_SYMBOL(ath9k_cmn_spectral_init_debug);
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h
similarity index 84%
rename from drivers/net/wireless/ath/ath9k/common-spectral.h
rename to drivers/net/wireless/ath/ath9k/spectral.h
index 82d9dd2..0b9465e 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.h
+++ b/drivers/net/wireless/ath/ath9k/spectral.h
@@ -92,13 +92,6 @@
 	struct ath_radar_info radar_info;
 } __packed;
 
-struct ath_spec_scan_priv {
-	struct ath_hw *ah;
-	/* relay(fs) channel for spectral scan */
-	struct rchan *rfs_chan_spec_scan;
-	enum spectral_mode spectral_mode;
-	struct ath_spec_scan spec_config;
-};
 
 #define SPECTRAL_HT20_40_TOTAL_DATA_LEN	(sizeof(struct ath_ht20_40_fft_packet))
 
@@ -130,15 +123,23 @@
 	return bins[0] & 0x3f;
 }
 
-void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy);
-void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv);
+void ath9k_spectral_init_debug(struct ath_softc *sc);
+void ath9k_spectral_deinit_debug(struct ath_softc *sc);
 
-void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
-				 struct ath_spec_scan_priv *spec_priv);
-int ath9k_cmn_spectral_scan_config(struct ath_common *common,
-			       struct ath_spec_scan_priv *spec_priv,
+void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
+int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
 			       enum spectral_mode spectral_mode);
-int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr,
+
+#ifdef CPTCFG_ATH9K_DEBUGFS
+int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
 		    struct ath_rx_status *rs, u64 tsf);
+#else
+static inline int ath_process_fft(struct ath_softc *sc,
+				  struct ieee80211_hdr *hdr,
+				  struct ath_rx_status *rs, u64 tsf)
+{
+	return 0;
+}
+#endif /* CPTCFG_ATH9K_DEBUGFS */
 
 #endif /* SPECTRAL_H */
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
index ac4781f..40ab65e 100644
--- a/drivers/net/wireless/ath/ath9k/tx99.c
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
@@ -99,7 +99,7 @@
 
 static void ath9k_tx99_deinit(struct ath_softc *sc)
 {
-	ath_reset(sc, NULL);
+	ath_reset(sc);
 
 	ath9k_ps_wakeup(sc);
 	ath9k_tx99_stop(sc);
@@ -127,7 +127,7 @@
 	memset(&txctl, 0, sizeof(txctl));
 	txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
 
-	ath_reset(sc, NULL);
+	ath_reset(sc);
 
 	ath9k_ps_wakeup(sc);
 
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 6bf7bc7..f00fbc9 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1096,37 +1096,6 @@
 	}
 }
 
-static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
-			       u8 rateidx)
-{
-	u8 max_power;
-	struct ath_hw *ah = sc->sc_ah;
-
-	if (sc->tx99_state)
-		return MAX_RATE_POWER;
-
-	if (!AR_SREV_9300_20_OR_LATER(ah)) {
-		/* ar9002 is not sipported for the moment */
-		return MAX_RATE_POWER;
-	}
-
-	if (!bf->bf_state.bfs_paprd) {
-		struct sk_buff *skb = bf->bf_mpdu;
-		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-		struct ath_frame_info *fi = get_frame_info(skb);
-
-		if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
-			max_power = min(ah->tx_power_stbc[rateidx],
-					fi->tx_power);
-		else
-			max_power = min(ah->tx_power[rateidx], fi->tx_power);
-	} else {
-		max_power = ah->paprd_training_power;
-	}
-
-	return max_power;
-}
-
 static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
 			     struct ath_tx_info *info, int len, bool rts)
 {
@@ -1197,8 +1166,6 @@
 				 is_40, is_sgi, is_sp);
 			if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
 				info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
-
-			info->txpower[i] = ath_get_rate_txpower(sc, bf, rix);
 			continue;
 		}
 
@@ -1226,8 +1193,6 @@
 
 		info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
 			phy, rate->bitrate * 100, len, rix, is_sp);
-
-		info->txpower[i] = ath_get_rate_txpower(sc, bf, rix);
 	}
 
 	/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
@@ -1274,6 +1239,7 @@
 	memset(&info, 0, sizeof(info));
 	info.is_first = true;
 	info.is_last = true;
+	info.txpower = MAX_RATE_POWER;
 	info.qcu = txq->axq_qnum;
 
 	while (bf) {
@@ -2097,7 +2063,6 @@
 		fi->keyix = ATH9K_TXKEYIX_INVALID;
 	fi->keytype = keytype;
 	fi->framelen = framelen;
-	fi->tx_power = MAX_RATE_POWER;
 
 	if (!rate)
 		return;
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
index 2a510ba..a75b5c6 100644
--- a/drivers/net/wireless/ath/carl9170/Kconfig
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -20,8 +20,8 @@
 	bool "SoftLED Support"
 	depends on CARL9170
 	select MAC80211_LEDS
-	select BPAUTO_LEDS_CLASS
-	select BPAUTO_NEW_LEDS
+	select BACKPORT_LEDS_CLASS
+	select BACKPORT_NEW_LEDS
 	default y
 	help
 	  This option is necessary, if you want your device' LEDs to blink
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index dca6df1..b80b213 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -994,7 +994,7 @@
 			refsel0 = 0;
 			refsel1 = 1;
 		}
-		chansel = bitrev8(chansel);
+		chansel = byte_rev_table[chansel];
 	} else {
 		if (freq == 2484) {
 			chansel = 10 + (freq - 2274) / 5;
@@ -1002,7 +1002,7 @@
 		} else
 			chansel = 16 + (freq - 2272) / 5;
 		chansel *= 4;
-		chansel = bitrev8(chansel);
+		chansel = byte_rev_table[chansel];
 	}
 
 	d1 =	chansel;
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c
index 0e383ef..7a16686 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -86,7 +86,7 @@
 	FCC_PATTERN(1, 0, 5, 150, 230, 1, 23),
 	FCC_PATTERN(2, 6, 10, 200, 500, 1, 16),
 	FCC_PATTERN(3, 11, 20, 200, 500, 1, 12),
-	FCC_PATTERN(4, 50, 100, 1000, 2000, 1, 20),
+	FCC_PATTERN(4, 50, 100, 1000, 2000, 20, 1),
 	FCC_PATTERN(5, 0, 1, 333, 333, 1, 9),
 };
 
@@ -105,7 +105,7 @@
 	JP_PATTERN(4, 0, 5, 150, 230, 1, 23),
 	JP_PATTERN(5, 6, 10, 200, 500, 1, 16),
 	JP_PATTERN(6, 11, 20, 200, 500, 1, 12),
-	JP_PATTERN(7, 50, 100, 1000, 2000, 1, 20),
+	JP_PATTERN(7, 50, 100, 1000, 2000, 20, 1),
 	JP_PATTERN(5, 0, 1, 333, 333, 1, 9),
 };
 
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index 0cd964f..6253db8 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -515,7 +515,6 @@
 	if (!request)
 		return;
 
-	reg->region = request->dfs_region;
 	switch (request->initiator) {
 	case NL80211_REGDOM_SET_BY_CORE:
 		/*
@@ -780,19 +779,6 @@
 		return SD_NO_CTL;
 	}
 
-	if (ath_regd_get_eepromRD(reg) == CTRY_DEFAULT) {
-		switch (reg->region) {
-		case NL80211_DFS_FCC:
-			return CTL_FCC;
-		case NL80211_DFS_ETSI:
-			return CTL_ETSI;
-		case NL80211_DFS_JP:
-			return CTL_MKK;
-		default:
-			break;
-		}
-	}
-
 	switch (band) {
 	case IEEE80211_BAND_2GHZ:
 		return reg->regpair->reg_2ghz_ctl;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 7dd8873..b71d2b3 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -494,9 +494,7 @@
 	return ret;
 }
 
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
-				  struct ieee80211_vif *vif,
-				  const u8 *mac_addr)
+static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct wcn36xx *wcn = hw->priv;
 
@@ -504,8 +502,7 @@
 	wcn36xx_smd_start_scan(wcn);
 }
 
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif)
+static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct wcn36xx *wcn = hw->priv;
 
@@ -1078,6 +1075,7 @@
 	.remove     = wcn36xx_remove,
 	.driver         = {
 		.name   = "wcn36xx",
+		.owner  = THIS_MODULE,
 	},
 	.id_table    = wcn36xx_platform_id_table,
 };
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 38332a6..d9f4b30 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -792,13 +792,12 @@
 }
 
 static int wil_cfg80211_del_station(struct wiphy *wiphy,
-				    struct net_device *dev,
-				    struct station_del_parameters *params)
+				    struct net_device *dev, const u8 *mac)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 
 	mutex_lock(&wil->mutex);
-	wil6210_disconnect(wil, params->mac, params->reason_code, false);
+	wil6210_disconnect(wil, mac);
 	mutex_unlock(&wil->mutex);
 
 	return 0;
diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c
index 3249562..8d99021 100644
--- a/drivers/net/wireless/ath/wil6210/debug.c
+++ b/drivers/net/wireless/ath/wil6210/debug.c
@@ -32,23 +32,6 @@
 	va_end(args);
 }
 
-void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
-{
-	if (net_ratelimit()) {
-		struct net_device *ndev = wil_to_ndev(wil);
-		struct va_format vaf = {
-			.fmt = fmt,
-		};
-		va_list args;
-
-		va_start(args, fmt);
-		vaf.va = &args;
-		netdev_err(ndev, "%pV", &vaf);
-		trace_wil6210_log_err(&vaf);
-		va_end(args);
-	}
-}
-
 void wil_info(struct wil6210_priv *wil, const char *fmt, ...)
 {
 	struct net_device *ndev = wil_to_ndev(wil);
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 4e6e145..54a6ddc 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -573,10 +573,8 @@
 	if (!frame)
 		return -ENOMEM;
 
-	if (copy_from_user(frame, buf, len)) {
-		kfree(frame);
+	if (copy_from_user(frame, buf, len))
 		return -EIO;
-	}
 
 	params.buf = frame;
 	params.len = len;
@@ -616,10 +614,8 @@
 		return -ENOMEM;
 
 	rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
-	if (rc < 0) {
-		kfree(wmi);
+	if (rc < 0)
 		return rc;
-	}
 
 	cmd = &wmi[1];
 	cmdid = le16_to_cpu(wmi->id);
diff --git a/drivers/net/wireless/ath/wil6210/fw.c b/drivers/net/wireless/ath/wil6210/fw.c
index 93c5cc1..8c6f3b0 100644
--- a/drivers/net/wireless/ath/wil6210/fw.c
+++ b/drivers/net/wireless/ath/wil6210/fw.c
@@ -15,6 +15,7 @@
  */
 #include <linux/firmware.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/crc32.h>
 #include "wil6210.h"
 #include "fw.h"
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c
index d4acf93..44cb71f 100644
--- a/drivers/net/wireless/ath/wil6210/fw_inc.c
+++ b/drivers/net/wireless/ath/wil6210/fw_inc.c
@@ -446,7 +446,7 @@
 		if (size >= sizeof(*hdr)) {
 			wil_err_fw(wil, "Stop at offset %ld"
 				   " record type %d [%zd bytes]\n",
-				   (long)((const void *)hdr - data),
+				   (const void *)hdr - data,
 				   le16_to_cpu(hdr->type), hdr_sz);
 		}
 		return -EINVAL;
@@ -471,7 +471,7 @@
 	size_t sz;
 	const void *d;
 
-	rc = request_firmware(&fw, name, wil_to_dev(wil));
+	rc = request_firmware(&fw, name, wil_to_pcie_dev(wil));
 	if (rc) {
 		wil_err_fw(wil, "Failed to load firmware %s\n", name);
 		return rc;
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 0b6ac97..b7a0f6f 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -36,8 +36,7 @@
  */
 
 #define WIL6210_IRQ_DISABLE	(0xFFFFFFFFUL)
-#define WIL6210_IMC_RX		(BIT_DMA_EP_RX_ICR_RX_DONE | \
-				 BIT_DMA_EP_RX_ICR_RX_HTRSH)
+#define WIL6210_IMC_RX		BIT_DMA_EP_RX_ICR_RX_DONE
 #define WIL6210_IMC_TX		(BIT_DMA_EP_TX_ICR_TX_DONE | \
 				BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
 #define WIL6210_IMC_MISC	(ISR_MISC_FW_READY | \
@@ -172,7 +171,6 @@
 	u32 isr = wil_ioread32_and_clear(wil->csr +
 					 HOSTADDR(RGF_DMA_EP_RX_ICR) +
 					 offsetof(struct RGF_ICR, ICR));
-	bool need_unmask = true;
 
 	trace_wil6210_irq_rx(isr);
 	wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
@@ -184,24 +182,12 @@
 
 	wil6210_mask_irq_rx(wil);
 
-	/* RX_DONE and RX_HTRSH interrupts are the same if interrupt
-	 * moderation is not used. Interrupt moderation may cause RX
-	 * buffer overflow while RX_DONE is delayed. The required
-	 * action is always the same - should empty the accumulated
-	 * packets from the RX ring.
-	 */
-	if (isr & (BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH)) {
+	if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) {
 		wil_dbg_irq(wil, "RX done\n");
-
-		if (isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)
-			wil_err_ratelimited(wil, "Received \"Rx buffer is in risk "
-				"of overflow\" interrupt\n");
-
-		isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH);
+		isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE;
 		if (test_bit(wil_status_reset_done, &wil->status)) {
 			if (test_bit(wil_status_napi_en, &wil->status)) {
 				wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
-				need_unmask = false;
 				napi_schedule(&wil->napi_rx);
 			} else {
 				wil_err(wil, "Got Rx interrupt while "
@@ -218,10 +204,6 @@
 	/* Rx IRQ will be enabled when NAPI processing finished */
 
 	atomic_inc(&wil->isr_count_rx);
-
-	if (unlikely(need_unmask))
-		wil6210_unmask_irq_rx(wil);
-
 	return IRQ_HANDLED;
 }
 
@@ -231,7 +213,6 @@
 	u32 isr = wil_ioread32_and_clear(wil->csr +
 					 HOSTADDR(RGF_DMA_EP_TX_ICR) +
 					 offsetof(struct RGF_ICR, ICR));
-	bool need_unmask = true;
 
 	trace_wil6210_irq_tx(isr);
 	wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
@@ -250,7 +231,6 @@
 		isr &= ~(BIT(25) - 1UL);
 		if (test_bit(wil_status_reset_done, &wil->status)) {
 			wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
-			need_unmask = false;
 			napi_schedule(&wil->napi_tx);
 		} else {
 			wil_err(wil, "Got Tx interrupt while in reset\n");
@@ -263,10 +243,6 @@
 	/* Tx IRQ will be enabled when NAPI processing finished */
 
 	atomic_inc(&wil->isr_count_tx);
-
-	if (unlikely(need_unmask))
-		wil6210_unmask_irq_tx(wil);
-
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 8ff3fe3..6500caf 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -38,65 +38,6 @@
 module_param(itr_trsh, uint, S_IRUGO);
 MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs.");
 
-/* We allow allocation of more than 1 page buffers to support large packets.
- * It is suboptimal behavior performance wise in case MTU above page size.
- */
-unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - ETH_HLEN;
-static int mtu_max_set(const char *val, const struct kernel_param *kp)
-{
-	int ret;
-
-	/* sets mtu_max directly. no need to restore it in case of
-	 * illegal value since we assume this will fail insmod
-	 */
-	ret = param_set_uint(val, kp);
-	if (ret)
-		return ret;
-
-	if (mtu_max < 68 || mtu_max > IEEE80211_MAX_DATA_LEN_DMG)
-		ret = -EINVAL;
-
-	return ret;
-}
-
-static struct kernel_param_ops mtu_max_ops = {
-	.set = mtu_max_set,
-	.get = param_get_uint,
-};
-
-module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO);
-MODULE_PARM_DESC(mtu_max, " Max MTU value.");
-
-static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT;
-static uint tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT;
-
-static int ring_order_set(const char *val, const struct kernel_param *kp)
-{
-	int ret;
-	uint x;
-
-	ret = kstrtouint(val, 0, &x);
-	if (ret)
-		return ret;
-
-	if ((x < WIL_RING_SIZE_ORDER_MIN) || (x > WIL_RING_SIZE_ORDER_MAX))
-		return -EINVAL;
-
-	*((uint *)kp->arg) = x;
-
-	return 0;
-}
-
-static struct kernel_param_ops ring_order_ops = {
-	.set = ring_order_set,
-	.get = param_get_uint,
-};
-
-module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO);
-MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order");
-module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO);
-MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order");
-
 #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
 #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
 
@@ -133,8 +74,7 @@
 		__raw_writel(*s++, d++);
 }
 
-static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
-			       u16 reason_code, bool from_event)
+static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
 {
 	uint i;
 	struct net_device *ndev = wil_to_ndev(wil);
@@ -146,9 +86,7 @@
 
 	sta->data_port_open = false;
 	if (sta->status != wil_sta_unused) {
-		if (!from_event)
-			wmi_disconnect_sta(wil, sta->addr, reason_code);
-
+		wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING);
 		switch (wdev->iftype) {
 		case NL80211_IFTYPE_AP:
 		case NL80211_IFTYPE_P2P_GO:
@@ -180,8 +118,7 @@
 	memset(&sta->stats, 0, sizeof(sta->stats));
 }
 
-static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
-				u16 reason_code, bool from_event)
+static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
 {
 	int cid = -ENOENT;
 	struct net_device *ndev = wil_to_ndev(wil);
@@ -196,10 +133,10 @@
 	}
 
 	if (cid >= 0) /* disconnect 1 peer */
-		wil_disconnect_cid(wil, cid, reason_code, from_event);
+		wil_disconnect_cid(wil, cid);
 	else /* disconnect all */
 		for (cid = 0; cid < WIL6210_MAX_CID; cid++)
-			wil_disconnect_cid(wil, cid, reason_code, from_event);
+			wil_disconnect_cid(wil, cid);
 
 	/* link state */
 	switch (wdev->iftype) {
@@ -208,7 +145,8 @@
 		wil_link_off(wil);
 		if (test_bit(wil_status_fwconnected, &wil->status)) {
 			clear_bit(wil_status_fwconnected, &wil->status);
-			cfg80211_disconnected(ndev, reason_code,
+			cfg80211_disconnected(ndev,
+					      WLAN_STATUS_UNSPECIFIED_FAILURE,
 					      NULL, 0, GFP_KERNEL);
 		} else if (test_bit(wil_status_fwconnecting, &wil->status)) {
 			cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
@@ -228,7 +166,7 @@
 			struct wil6210_priv, disconnect_worker);
 
 	mutex_lock(&wil->mutex);
-	_wil6210_disconnect(wil, NULL, WLAN_REASON_UNSPECIFIED, false);
+	_wil6210_disconnect(wil, NULL);
 	mutex_unlock(&wil->mutex);
 }
 
@@ -250,7 +188,6 @@
 
 	clear_bit(wil_status_fwready, &wil->status);
 	wil_err(wil, "Scan timeout detected, start fw error recovery\n");
-	wil->recovery_state = fw_recovery_pending;
 	schedule_work(&wil->fw_error_worker);
 }
 
@@ -286,11 +223,6 @@
 
 	wil_dbg_misc(wil, "fw error worker\n");
 
-	if (!netif_running(wil_to_ndev(wil))) {
-		wil_info(wil, "No recovery - interface is down\n");
-		return;
-	}
-
 	/* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO
 	 * passed since last recovery attempt
 	 */
@@ -325,12 +257,9 @@
 		break;
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_P2P_GO:
-		wil_info(wil, "No recovery for AP-like interface\n");
 		/* recovery in these modes is done by upper layers */
 		break;
 	default:
-		wil_err(wil, "No recovery - unknown interface type %d\n",
-			wdev->iftype);
 		break;
 	}
 	mutex_unlock(&wil->mutex);
@@ -362,7 +291,7 @@
 
 	wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid);
 
-	rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
+	rc = wil_vring_init_tx(wil, ringid, WIL6210_TX_RING_SIZE, cid, 0);
 	wil->pending_connect_cid = -1;
 	if (rc == 0) {
 		wil->sta[cid].status = wil_sta_connected;
@@ -417,23 +346,12 @@
 	return 0;
 }
 
-/**
- * wil6210_disconnect - disconnect one connection
- * @wil: driver context
- * @bssid: peer to disconnect, NULL to disconnect all
- * @reason_code: Reason code for the Disassociation frame
- * @from_event: whether is invoked from FW event handler
- *
- * Disconnect and release associated resources. If invoked not from the
- * FW event handler, issue WMI command(s) to trigger MAC disconnect.
- */
-void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
-			u16 reason_code, bool from_event)
+void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
 {
 	wil_dbg_misc(wil, "%s()\n", __func__);
 
 	del_timer_sync(&wil->connect_timer);
-	_wil6210_disconnect(wil, bssid, reason_code, from_event);
+	_wil6210_disconnect(wil, bssid);
 }
 
 void wil_priv_deinit(struct wil6210_priv *wil)
@@ -445,7 +363,7 @@
 	cancel_work_sync(&wil->disconnect_worker);
 	cancel_work_sync(&wil->fw_error_worker);
 	mutex_lock(&wil->mutex);
-	wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
+	wil6210_disconnect(wil, NULL);
 	mutex_unlock(&wil->mutex);
 	wmi_event_flush(wil);
 	destroy_workqueue(wil->wmi_wq_conn);
@@ -477,7 +395,7 @@
 static int wil_target_reset(struct wil6210_priv *wil)
 {
 	int delay = 0;
-	u32 x;
+	u32 hw_state;
 	u32 rev_id;
 	bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
 
@@ -492,25 +410,9 @@
 	S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST);
 
 	wil_halt_cpu(wil);
-
-	/* Clear Fw Download notification */
-	C(RGF_USER_USAGE_6, BIT(0));
+	C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); /* 40 MHz */
 
 	if (is_sparrow) {
-		S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN);
-		/* XTAL stabilization should take about 3ms */
-		usleep_range(5000, 7000);
-		x = R(RGF_CAF_PLL_LOCK_STATUS);
-		if (!(x & BIT_CAF_OSC_DIG_XTAL_STABLE)) {
-			wil_err(wil, "Xtal stabilization timeout\n"
-				"RGF_CAF_PLL_LOCK_STATUS = 0x%08x\n", x);
-			return -ETIME;
-		}
-		/* switch 10k to XTAL*/
-		C(RGF_USER_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF);
-		/* 40 MHz */
-		C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL);
-
 		W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
 		W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
 	}
@@ -551,13 +453,13 @@
 	/* wait until device ready. typical time is 200..250 msec */
 	do {
 		msleep(RST_DELAY);
-		x = R(RGF_USER_HW_MACHINE_STATE);
+		hw_state = R(RGF_USER_HW_MACHINE_STATE);
 		if (delay++ > RST_COUNT) {
 			wil_err(wil, "Reset not completed, hw_state 0x%08x\n",
-				x);
+				hw_state);
 			return -ETIME;
 		}
-	} while (x != HW_MACHINE_BOOT_DONE);
+	} while (hw_state != HW_MACHINE_BOOT_DONE);
 
 	/* TODO: Erez check rev_id != 1 */
 	if (!is_sparrow && (rev_id != 1))
@@ -633,7 +535,7 @@
 	WARN_ON(test_bit(wil_status_napi_en, &wil->status));
 
 	cancel_work_sync(&wil->disconnect_worker);
-	wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
+	wil6210_disconnect(wil, NULL);
 
 	wil->status = 0; /* prevent NAPI from being scheduled */
 
@@ -738,7 +640,7 @@
 		return rc;
 
 	/* Rx VRING. After MAC and beacon */
-	rc = wil_rx_init(wil, 1 << rx_ring_order);
+	rc = wil_rx_init(wil);
 	if (rc)
 		return rc;
 
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index e81703c..2399651 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -41,7 +41,7 @@
 {
 	struct wil6210_priv *wil = ndev_to_wil(ndev);
 
-	if (new_mtu < 68 || new_mtu > mtu_max) {
+	if (new_mtu < 68 || new_mtu > (TX_BUF_LEN - ETH_HLEN)) {
 		wil_err(wil, "invalid MTU %d\n", new_mtu);
 		return -EINVAL;
 	}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index e3f8bdc..2936ef0 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -206,10 +206,12 @@
 			       u32 i, int headroom)
 {
 	struct device *dev = wil_to_dev(wil);
-	unsigned int sz = mtu_max + ETH_HLEN;
+	unsigned int sz = RX_BUF_LEN;
 	struct vring_rx_desc dd, *d = &dd;
 	volatile struct vring_rx_desc *_d = &vring->va[i].rx;
 	dma_addr_t pa;
+
+	/* TODO align */
 	struct sk_buff *skb = dev_alloc_skb(sz + headroom);
 
 	if (unlikely(!skb))
@@ -383,7 +385,7 @@
 	struct vring_rx_desc *d;
 	struct sk_buff *skb;
 	dma_addr_t pa;
-	unsigned int sz = mtu_max + ETH_HLEN;
+	unsigned int sz = RX_BUF_LEN;
 	u16 dmalen;
 	u8 ftype;
 	u8 ds_bits;
@@ -594,7 +596,7 @@
 	wil_rx_refill(wil, v->size);
 }
 
-int wil_rx_init(struct wil6210_priv *wil, u16 size)
+int wil_rx_init(struct wil6210_priv *wil)
 {
 	struct vring *vring = &wil->vring_rx;
 	int rc;
@@ -606,7 +608,7 @@
 		return -EINVAL;
 	}
 
-	vring->size = size;
+	vring->size = WIL6210_RX_RING_SIZE;
 	rc = wil_vring_alloc(wil, vring);
 	if (rc)
 		return rc;
@@ -644,8 +646,7 @@
 		.action = cpu_to_le32(WMI_VRING_CMD_ADD),
 		.vring_cfg = {
 			.tx_sw_ring = {
-				.max_mpdu_size =
-					cpu_to_le16(mtu_max + ETH_HLEN),
+				.max_mpdu_size = cpu_to_le16(TX_BUF_LEN),
 				.ring_size = cpu_to_le16(size),
 			},
 			.ringid = id,
@@ -926,9 +927,8 @@
 	wil_dbg_txrx(wil, "%s()\n", __func__);
 
 	if (avail < 1 + nr_frags) {
-		wil_err_ratelimited(wil,
-				    "Tx ring full. No space for %d fragments\n",
-				    1 + nr_frags);
+		wil_err(wil, "Tx ring full. No space for %d fragments\n",
+			1 + nr_frags);
 		return -ENOMEM;
 	}
 	_d = &vring->va[i].tx;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index 630aeb5..de04671 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -21,8 +21,8 @@
 #define BUF_HW_OWNED    (0)
 
 /* size of max. Tx/Rx buffers, as supported by FW */
-#define TXRX_BUF_LEN_DEFAULT (2242)
-
+#define RX_BUF_LEN      (2242)
+#define TX_BUF_LEN      (2242)
 /* how many bytes to reserve for rtap header? */
 #define WIL6210_RTAP_SIZE (128)
 
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index c6ec5b9..ce6488e 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -24,7 +24,6 @@
 #include "wil_platform.h"
 
 extern bool no_fw_recovery;
-extern unsigned int mtu_max;
 
 #define WIL_NAME "wil6210"
 #define WIL_FW_NAME "wil6210.fw"
@@ -49,11 +48,8 @@
 
 #define WIL6210_MEM_SIZE (2*1024*1024UL)
 
-#define WIL_RX_RING_SIZE_ORDER_DEFAULT	(9)
-#define WIL_TX_RING_SIZE_ORDER_DEFAULT	(9)
-/* limit ring size in range [32..32k] */
-#define WIL_RING_SIZE_ORDER_MIN	(5)
-#define WIL_RING_SIZE_ORDER_MAX	(15)
+#define WIL6210_RX_RING_SIZE	(128)
+#define WIL6210_TX_RING_SIZE	(512)
 #define WIL6210_MAX_TX_RINGS	(24) /* HW limit */
 #define WIL6210_MAX_CID		(8) /* HW limit */
 #define WIL6210_NAPI_BUDGET	(16) /* arbitrary */
@@ -121,15 +117,12 @@
 	#define BIT_USER_USER_ICR_SW_INT_2	BIT(18)
 #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0	(0x880c18)
 #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1	(0x880c2c)
-#define RGF_USER_SPARROW_M_4			(0x880c50) /* Sparrow */
-	#define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF	BIT(2)
 
 #define RGF_DMA_EP_TX_ICR		(0x881bb4) /* struct RGF_ICR */
 	#define BIT_DMA_EP_TX_ICR_TX_DONE	BIT(0)
 	#define BIT_DMA_EP_TX_ICR_TX_DONE_N(n)	BIT(n+1) /* n = [0..23] */
 #define RGF_DMA_EP_RX_ICR		(0x881bd0) /* struct RGF_ICR */
 	#define BIT_DMA_EP_RX_ICR_RX_DONE	BIT(0)
-	#define BIT_DMA_EP_RX_ICR_RX_HTRSH	BIT(1)
 #define RGF_DMA_EP_MISC_ICR		(0x881bec) /* struct RGF_ICR */
 	#define BIT_DMA_EP_MISC_ICR_RX_HTRSH	BIT(0)
 	#define BIT_DMA_EP_MISC_ICR_TX_NO_ACT	BIT(1)
@@ -159,10 +152,6 @@
 #define RGF_MAC_MTRL_COUNTER_0		(0x886aa8)
 
 #define RGF_CAF_ICR			(0x88946c) /* struct RGF_ICR */
-#define RGF_CAF_OSC_CONTROL		(0x88afa4)
-	#define BIT_CAF_OSC_XTAL_EN		BIT(0)
-#define RGF_CAF_PLL_LOCK_STATUS		(0x88afec)
-	#define BIT_CAF_OSC_DIG_XTAL_STABLE	BIT(0)
 
 /* popular locations */
 #define HOST_MBOX   HOSTADDR(RGF_USER_USER_SCRATCH_PAD)
@@ -472,14 +461,10 @@
 #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w))
 #define wil_to_ndev(i) (wil_to_wdev(i)->netdev)
 #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
+#define wil_to_pcie_dev(i) (&i->pdev->dev)
 
-__printf(2, 3)
 void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
-__printf(2, 3)
 void wil_err(struct wil6210_priv *wil, const char *fmt, ...);
-__printf(2, 3)
-void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...);
-__printf(2, 3)
 void wil_info(struct wil6210_priv *wil, const char *fmt, ...);
 #define wil_dbg(wil, fmt, arg...) do { \
 	netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \
@@ -590,10 +575,9 @@
 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
 int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
 int wmi_pcp_stop(struct wil6210_priv *wil);
-void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
-			u16 reason_code, bool from_event);
+void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid);
 
-int wil_rx_init(struct wil6210_priv *wil, u16 size);
+int wil_rx_init(struct wil6210_priv *wil);
 void wil_rx_fini(struct wil6210_priv *wil);
 
 /* TX API */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 63476c8..4311df9 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -478,15 +478,15 @@
 			       void *d, int len)
 {
 	struct wmi_disconnect_event *evt = d;
-	u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
 
-	wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
-		    evt->bssid, reason_code, evt->disconnect_reason);
+	wil_dbg_wmi(wil, "Disconnect %pM reason %d proto %d wmi\n",
+		    evt->bssid,
+		    evt->protocol_reason_status, evt->disconnect_reason);
 
 	wil->sinfo_gen++;
 
 	mutex_lock(&wil->mutex);
-	wil6210_disconnect(wil, evt->bssid, reason_code, true);
+	wil6210_disconnect(wil, evt->bssid);
 	mutex_unlock(&wil->mutex);
 }
 
@@ -1025,7 +1025,7 @@
 	struct wmi_cfg_rx_chain_cmd cmd = {
 		.action = WMI_RX_CHAIN_ADD,
 		.rx_sw_ring = {
-			.max_mpdu_size = cpu_to_le16(mtu_max + ETH_HLEN),
+			.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
 			.ring_mem_base = cpu_to_le64(vring->pa),
 			.ring_size = cpu_to_le16(vring->size),
 		},
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 809f01c..d726f6c 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -5110,9 +5110,7 @@
 	B43_WARN_ON(!vif || wl->vif != vif);
 }
 
-static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw,
-					  struct ieee80211_vif *vif,
-					  const u8 *mac_addr)
+static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
 	struct b43_wldev *dev;
@@ -5126,8 +5124,7 @@
 	mutex_unlock(&wl->mutex);
 }
 
-static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw,
-					     struct ieee80211_vif *vif)
+static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
 	struct b43_wldev *dev;
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 9e59f8b..94da49c 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -300,7 +300,9 @@
 
 void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
 {
-	b43_phy_write(dev, destreg, b43_phy_read(dev, srcreg));
+	assert_mac_suspended(dev);
+	dev->phy.ops->phy_write(dev, destreg,
+		dev->phy.ops->phy_read(dev, srcreg));
 }
 
 void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index a2f096f..0443fa7 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -12,7 +12,7 @@
 	select LEDS_CLASS if BCMA_DRIVER_GPIO
 	select BRCMUTIL
 	depends on FW_LOADER
-	select BPAUTO_CORDIC
+	select BACKPORT_CORDIC
 	---help---
 	  This module adds support for PCIe wireless adapters based on Broadcom
 	  IEEE802.11n SoftMAC chipsets. It also has WLAN led support, which will
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index d496643..3d168e8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -23,15 +23,15 @@
 
 obj-$(CPTCFG_BRCMFMAC) += brcmfmac.o
 brcmfmac-objs += \
-		cfg80211.o \
+		wl_cfg80211.o \
 		chip.o \
 		fwil.o \
 		fweh.o \
 		fwsignal.o \
 		p2p.o \
 		proto.o \
-		common.o \
-		core.o \
+		dhd_common.o \
+		dhd_linux.o \
 		firmware.o \
 		feature.o \
 		btcoex.o \
@@ -43,14 +43,14 @@
 		flowring.o \
 		msgbuf.o
 brcmfmac-$(CPTCFG_BRCMFMAC_SDIO) += \
-		sdio.o \
+		dhd_sdio.o \
 		bcmsdh.o
 brcmfmac-$(CPTCFG_BRCMFMAC_USB) += \
 		usb.o
 brcmfmac-$(CPTCFG_BRCMFMAC_PCIE) += \
 		pcie.o
 brcmfmac-$(CPTCFG_BRCMDBG) += \
-		debug.o
+		dhd_dbg.o
 brcmfmac-$(CPTCFG_BRCM_TRACING) += \
 		tracepoint.o
 brcmfmac-$(CONFIG_OF) += \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
index 8e0e91c..a159ff3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
@@ -25,10 +25,10 @@
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 
-#include "core.h"
-#include "bus.h"
+#include "dhd.h"
+#include "dhd_bus.h"
 #include "fwsignal.h"
-#include "debug.h"
+#include "dhd_dbg.h"
 #include "tracepoint.h"
 #include "proto.h"
 #include "bcdc.h"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 3c06e93..8dbd5db 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -41,9 +41,9 @@
 #include <chipcommon.h>
 #include <soc.h>
 #include "chip.h"
-#include "bus.h"
-#include "debug.h"
-#include "sdio.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "sdio_host.h"
 #include "of.h"
 
 #define SDIOH_API_ACCESS_RETRY_LIMIT	2
@@ -1064,16 +1064,6 @@
 	if (!sdiodev->pdata)
 		brcmf_of_probe(sdiodev);
 
-#ifdef CONFIG_PM_SLEEP
-	/* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
-	 * is true or when platform data OOB irq is true).
-	 */
-	if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
-	    ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
-	     (sdiodev->pdata->oob_irq_supported)))
-		bus_if->wowl_supported = true;
-#endif
-
 	atomic_set(&sdiodev->suspend, false);
 	init_waitqueue_head(&sdiodev->request_word_wait);
 	init_waitqueue_head(&sdiodev->request_buffer_wait);
@@ -1126,39 +1116,34 @@
 	brcmf_dbg(SDIO, "Exit\n");
 }
 
-void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
-{
-	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-
-	brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
-	sdiodev->wowl_enabled = enabled;
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int brcmf_ops_sdio_suspend(struct device *dev)
 {
+	mmc_pm_flag_t sdio_flags;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-	mmc_pm_flag_t sdio_flags;
+	int ret = 0;
 
 	brcmf_dbg(SDIO, "Enter\n");
 
+	sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
+	if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
+		brcmf_err("Host can't keep power while suspended\n");
+		return -EINVAL;
+	}
+
 	atomic_set(&sdiodev->suspend, true);
 
-	if (sdiodev->wowl_enabled) {
-		sdio_flags = MMC_PM_KEEP_POWER;
-		if (sdiodev->pdata->oob_irq_supported)
-			enable_irq_wake(sdiodev->pdata->oob_irq_nr);
-		else
-			sdio_flags = MMC_PM_WAKE_SDIO_IRQ;
-		if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
-			brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
+	ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
+	if (ret) {
+		brcmf_err("Failed to set pm_flags\n");
+		atomic_set(&sdiodev->suspend, false);
+		return ret;
 	}
 
 	brcmf_sdio_wd_timer(sdiodev->bus, 0);
 
-	return 0;
+	return ret;
 }
 
 static int brcmf_ops_sdio_resume(struct device *dev)
@@ -1167,8 +1152,6 @@
 	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 
 	brcmf_dbg(SDIO, "Enter\n");
-	if (sdiodev->pdata->oob_irq_supported)
-		disable_irq_wake(sdiodev->pdata->oob_irq_nr);
 	brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
 	atomic_set(&sdiodev->suspend, false);
 	return 0;
@@ -1221,6 +1204,7 @@
 	.remove		= brcmf_sdio_pd_remove,
 	.driver		= {
 		.name	= BRCMFMAC_SDIO_PDATA_NAME,
+		.owner	= THIS_MODULE,
 	}
 };
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
index 0445163..a29ac49 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
@@ -20,13 +20,13 @@
 #include <brcmu_wifi.h>
 #include <brcmu_utils.h>
 #include <defs.h>
-#include "core.h"
-#include "debug.h"
+#include <dhd.h>
+#include <dhd_dbg.h>
 #include "fwil.h"
 #include "fwil_types.h"
 #include "btcoex.h"
 #include "p2p.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
 
 /* T1 start SCO/eSCO priority suppression */
 #define BRCMF_BTCOEX_OPPR_WIN_TIME   2000
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
index ddae0b5..95efde8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
@@ -25,7 +25,7 @@
 #include <brcm_hw_ids.h>
 #include <brcmu_utils.h>
 #include <chipcommon.h>
-#include "debug.h"
+#include "dhd_dbg.h"
 #include "chip.h"
 
 /* SOC Interconnect types (aka chip types) */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.c b/drivers/net/wireless/brcm80211/brcmfmac/common.c
deleted file mode 100644
index ed8356d..0000000
--- a/drivers/net/wireless/brcm80211/brcmfmac/common.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/netdevice.h>
-#include <brcmu_wifi.h>
-#include <brcmu_utils.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
-#include "fwil.h"
-#include "fwil_types.h"
-#include "tracepoint.h"
-
-#define BRCMF_DEFAULT_BCN_TIMEOUT	3
-#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME	40
-#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME	40
-
-/* boost value for RSSI_DELTA in preferred join selection */
-#define BRCMF_JOIN_PREF_RSSI_BOOST	8
-
-int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
-{
-	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
-	u8 buf[BRCMF_DCMD_SMLEN];
-	struct brcmf_join_pref_params join_pref_params[2];
-	char *ptr;
-	s32 err;
-
-	/* retreive mac address */
-	err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
-				       sizeof(ifp->mac_addr));
-	if (err < 0) {
-		brcmf_err("Retreiving cur_etheraddr failed, %d\n",
-			  err);
-		goto done;
-	}
-	memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
-
-	/* query for 'ver' to get version info from firmware */
-	memset(buf, 0, sizeof(buf));
-	strcpy(buf, "ver");
-	err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
-	if (err < 0) {
-		brcmf_err("Retreiving version information failed, %d\n",
-			  err);
-		goto done;
-	}
-	ptr = (char *)buf;
-	strsep(&ptr, "\n");
-
-	/* Print fw version info */
-	brcmf_err("Firmware version = %s\n", buf);
-
-	/* locate firmware version number for ethtool */
-	ptr = strrchr(buf, ' ') + 1;
-	strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
-
-	/* set mpc */
-	err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
-	if (err) {
-		brcmf_err("failed setting mpc\n");
-		goto done;
-	}
-
-	/*
-	 * Setup timeout if Beacons are lost and roam is off to report
-	 * link down
-	 */
-	err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
-				      BRCMF_DEFAULT_BCN_TIMEOUT);
-	if (err) {
-		brcmf_err("bcn_timeout error (%d)\n", err);
-		goto done;
-	}
-
-	/* Enable/Disable build-in roaming to allowed ext supplicant to take
-	 * of romaing
-	 */
-	err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
-	if (err) {
-		brcmf_err("roam_off error (%d)\n", err);
-		goto done;
-	}
-
-	/* Setup join_pref to select target by RSSI(with boost on 5GHz) */
-	join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
-	join_pref_params[0].len = 2;
-	join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
-	join_pref_params[0].band = WLC_BAND_5G;
-	join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
-	join_pref_params[1].len = 2;
-	join_pref_params[1].rssi_gain = 0;
-	join_pref_params[1].band = 0;
-	err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
-				       sizeof(join_pref_params));
-	if (err)
-		brcmf_err("Set join_pref error (%d)\n", err);
-
-	/* Setup event_msgs, enable E_IF */
-	err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
-				       BRCMF_EVENTING_MASK_LEN);
-	if (err) {
-		brcmf_err("Get event_msgs error (%d)\n", err);
-		goto done;
-	}
-	setbit(eventmask, BRCMF_E_IF);
-	err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
-				       BRCMF_EVENTING_MASK_LEN);
-	if (err) {
-		brcmf_err("Set event_msgs error (%d)\n", err);
-		goto done;
-	}
-
-	/* Setup default scan channel time */
-	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
-				    BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
-	if (err) {
-		brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
-			  err);
-		goto done;
-	}
-
-	/* Setup default scan unassoc time */
-	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
-				    BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
-	if (err) {
-		brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
-			  err);
-		goto done;
-	}
-
-	/* do bus specific preinit here */
-	err = brcmf_bus_preinit(ifp->drvr->bus_if);
-done:
-	return err;
-}
-
-#if defined(CPTCFG_BRCM_TRACING) || defined(CPTCFG_BRCMDBG)
-void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
-{
-	struct va_format vaf = {
-		.fmt = fmt,
-	};
-	va_list args;
-
-	va_start(args, fmt);
-	vaf.va = &args;
-	if (brcmf_msg_level & level)
-		pr_debug("%s %pV", func, &vaf);
-	trace_brcmf_dbg(level, func, &vaf);
-	va_end(args);
-}
-#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
index 77656c7..c6d65b8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
@@ -19,7 +19,7 @@
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 
-#include "core.h"
+#include "dhd.h"
 #include "commonring.h"
 
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
similarity index 96%
rename from drivers/net/wireless/brcm80211/brcmfmac/core.h
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 23f74b1..5e4317d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -18,8 +18,8 @@
  * Common types *
  */
 
-#ifndef BRCMFMAC_CORE_H
-#define BRCMFMAC_CORE_H
+#ifndef _BRCMF_H_
+#define _BRCMF_H_
 
 #include "fweh.h"
 
@@ -83,6 +83,7 @@
 	/* Internal brcmf items */
 	uint hdrlen;		/* Total BRCMF header length (proto + bus) */
 	uint rxsz;		/* Rx buffer size bus module should use */
+	u8 wme_dp;		/* wme discard priority */
 
 	/* Dongle media info */
 	char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN];
@@ -175,8 +176,7 @@
 int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
 struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
 			      char *name, u8 *mac_addr);
-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx);
-int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
+void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
 void brcmf_txflowblock_if(struct brcmf_if *ifp,
 			  enum brcmf_netif_stop_reason reason, bool state);
 void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
@@ -186,4 +186,4 @@
 /* Sets dongle media info (drv_version, mac address). */
 int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
 
-#endif /* BRCMFMAC_CORE_H */
+#endif				/* _BRCMF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
similarity index 98%
rename from drivers/net/wireless/brcm80211/brcmfmac/bus.h
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index ba6eb69..027ff83 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -14,10 +14,10 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef BRCMFMAC_BUS_H
-#define BRCMFMAC_BUS_H
+#ifndef _BRCMF_BUS_H_
+#define _BRCMF_BUS_H_
 
-#include "debug.h"
+#include "dhd_dbg.h"
 
 /* IDs of the 6 default common rings of msgbuf protocol */
 #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT	0
@@ -227,7 +227,8 @@
 void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
 
 int brcmf_bus_start(struct device *dev);
-s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len);
+s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data,
+				u32 len);
 void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
 
 #ifdef CPTCFG_BRCMFMAC_SDIO
@@ -240,4 +241,4 @@
 void brcmf_usb_register(void);
 #endif
 
-#endif /* BRCMFMAC_BUS_H */
+#endif				/* _BRCMF_BUS_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
new file mode 100644
index 0000000..67503e2
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "tracepoint.h"
+
+#define PKTFILTER_BUF_SIZE		128
+#define BRCMF_DEFAULT_BCN_TIMEOUT	3
+#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME	40
+#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME	40
+#define BRCMF_DEFAULT_PACKET_FILTER	"100 0 0 0 0x01 0x00"
+
+/* boost value for RSSI_DELTA in preferred join selection */
+#define BRCMF_JOIN_PREF_RSSI_BOOST	8
+
+
+bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
+		      struct sk_buff *pkt, int prec)
+{
+	struct sk_buff *p;
+	int eprec = -1;		/* precedence to evict from */
+	bool discard_oldest;
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+
+	/* Fast case, precedence queue is not full and we are also not
+	 * exceeding total queue length
+	 */
+	if (!pktq_pfull(q, prec) && !pktq_full(q)) {
+		brcmu_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 = brcmu_pktq_peek_tail(q, &eprec);
+		if (eprec > prec)
+			return false;
+	}
+
+	/* Evict if needed */
+	if (eprec >= 0) {
+		/* Detect queueing to unconfigured precedence */
+		discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec);
+		if (eprec == prec && !discard_oldest)
+			return false;	/* refuse newer (incoming) packet */
+		/* Evict packet according to discard policy */
+		p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
+			brcmu_pktq_pdeq_tail(q, eprec);
+		if (p == NULL)
+			brcmf_err("brcmu_pktq_penq() failed, oldest %d\n",
+				  discard_oldest);
+
+		brcmu_pkt_buf_free_skb(p);
+	}
+
+	/* Enqueue */
+	p = brcmu_pktq_penq(q, prec, pkt);
+	if (p == NULL)
+		brcmf_err("brcmu_pktq_penq() failed\n");
+
+	return p != NULL;
+}
+
+/* Convert user's input in hex pattern to byte-size mask */
+static int brcmf_c_pattern_atoh(char *src, char *dst)
+{
+	int i;
+	if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
+		brcmf_err("Mask invalid format. Needs to start with 0x\n");
+		return -EINVAL;
+	}
+	src = src + 2;		/* Skip past 0x */
+	if (strlen(src) % 2 != 0) {
+		brcmf_err("Mask invalid format. Length must be even.\n");
+		return -EINVAL;
+	}
+	for (i = 0; *src != '\0'; i++) {
+		unsigned long res;
+		char num[3];
+		strncpy(num, src, 2);
+		num[2] = '\0';
+		if (kstrtoul(num, 16, &res))
+			return -EINVAL;
+		dst[i] = (u8)res;
+		src += 2;
+	}
+	return i;
+}
+
+static void
+brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable,
+				 int master_mode)
+{
+	unsigned long res;
+	char *argv;
+	char *arg_save = NULL, *arg_org = NULL;
+	s32 err;
+	struct brcmf_pkt_filter_enable_le enable_parm;
+
+	arg_save = kstrdup(arg, GFP_ATOMIC);
+	if (!arg_save)
+		goto fail;
+
+	arg_org = arg_save;
+
+	argv = strsep(&arg_save, " ");
+
+	if (argv == NULL) {
+		brcmf_err("No args provided\n");
+		goto fail;
+	}
+
+	/* Parse packet filter id. */
+	enable_parm.id = 0;
+	if (!kstrtoul(argv, 0, &res))
+		enable_parm.id = cpu_to_le32((u32)res);
+
+	/* Enable/disable the specified filter. */
+	enable_parm.enable = cpu_to_le32(enable);
+
+	err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm,
+				       sizeof(enable_parm));
+	if (err)
+		brcmf_err("Set pkt_filter_enable error (%d)\n", err);
+
+	/* Control the master mode */
+	err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode);
+	if (err)
+		brcmf_err("Set pkt_filter_mode error (%d)\n", err);
+
+fail:
+	kfree(arg_org);
+}
+
+static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg)
+{
+	struct brcmf_pkt_filter_le *pkt_filter;
+	unsigned long res;
+	int buf_len;
+	s32 err;
+	u32 mask_size;
+	u32 pattern_size;
+	char *argv[8], *buf = NULL;
+	int i = 0;
+	char *arg_save = NULL, *arg_org = NULL;
+
+	arg_save = kstrdup(arg, GFP_ATOMIC);
+	if (!arg_save)
+		goto fail;
+
+	arg_org = arg_save;
+
+	buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC);
+	if (!buf)
+		goto fail;
+
+	argv[i] = strsep(&arg_save, " ");
+	while (argv[i]) {
+		i++;
+		if (i >= 8) {
+			brcmf_err("Too many parameters\n");
+			goto fail;
+		}
+		argv[i] = strsep(&arg_save, " ");
+	}
+
+	if (i != 6) {
+		brcmf_err("Not enough args provided %d\n", i);
+		goto fail;
+	}
+
+	pkt_filter = (struct brcmf_pkt_filter_le *)buf;
+
+	/* Parse packet filter id. */
+	pkt_filter->id = 0;
+	if (!kstrtoul(argv[0], 0, &res))
+		pkt_filter->id = cpu_to_le32((u32)res);
+
+	/* Parse filter polarity. */
+	pkt_filter->negate_match = 0;
+	if (!kstrtoul(argv[1], 0, &res))
+		pkt_filter->negate_match = cpu_to_le32((u32)res);
+
+	/* Parse filter type. */
+	pkt_filter->type = 0;
+	if (!kstrtoul(argv[2], 0, &res))
+		pkt_filter->type = cpu_to_le32((u32)res);
+
+	/* Parse pattern filter offset. */
+	pkt_filter->u.pattern.offset = 0;
+	if (!kstrtoul(argv[3], 0, &res))
+		pkt_filter->u.pattern.offset = cpu_to_le32((u32)res);
+
+	/* Parse pattern filter mask. */
+	mask_size = brcmf_c_pattern_atoh(argv[4],
+			(char *)pkt_filter->u.pattern.mask_and_pattern);
+
+	/* Parse pattern filter pattern. */
+	pattern_size = brcmf_c_pattern_atoh(argv[5],
+		(char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]);
+
+	if (mask_size != pattern_size) {
+		brcmf_err("Mask and pattern not the same size\n");
+		goto fail;
+	}
+
+	pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
+	buf_len = offsetof(struct brcmf_pkt_filter_le,
+			   u.pattern.mask_and_pattern);
+	buf_len += mask_size + pattern_size;
+
+	err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
+				       buf_len);
+	if (err)
+		brcmf_err("Set pkt_filter_add error (%d)\n", err);
+
+fail:
+	kfree(arg_org);
+
+	kfree(buf);
+}
+
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
+{
+	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+	u8 buf[BRCMF_DCMD_SMLEN];
+	struct brcmf_join_pref_params join_pref_params[2];
+	char *ptr;
+	s32 err;
+
+	/* retreive mac address */
+	err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
+				       sizeof(ifp->mac_addr));
+	if (err < 0) {
+		brcmf_err("Retreiving cur_etheraddr failed, %d\n",
+			  err);
+		goto done;
+	}
+	memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
+
+	/* query for 'ver' to get version info from firmware */
+	memset(buf, 0, sizeof(buf));
+	strcpy(buf, "ver");
+	err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
+	if (err < 0) {
+		brcmf_err("Retreiving version information failed, %d\n",
+			  err);
+		goto done;
+	}
+	ptr = (char *)buf;
+	strsep(&ptr, "\n");
+
+	/* Print fw version info */
+	brcmf_err("Firmware version = %s\n", buf);
+
+	/* locate firmware version number for ethtool */
+	ptr = strrchr(buf, ' ') + 1;
+	strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
+
+	/* set mpc */
+	err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
+	if (err) {
+		brcmf_err("failed setting mpc\n");
+		goto done;
+	}
+
+	/*
+	 * Setup timeout if Beacons are lost and roam is off to report
+	 * link down
+	 */
+	err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
+				      BRCMF_DEFAULT_BCN_TIMEOUT);
+	if (err) {
+		brcmf_err("bcn_timeout error (%d)\n", err);
+		goto done;
+	}
+
+	/* Enable/Disable build-in roaming to allowed ext supplicant to take
+	 * of romaing
+	 */
+	err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
+	if (err) {
+		brcmf_err("roam_off error (%d)\n", err);
+		goto done;
+	}
+
+	/* Setup join_pref to select target by RSSI(with boost on 5GHz) */
+	join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
+	join_pref_params[0].len = 2;
+	join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
+	join_pref_params[0].band = WLC_BAND_5G;
+	join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
+	join_pref_params[1].len = 2;
+	join_pref_params[1].rssi_gain = 0;
+	join_pref_params[1].band = 0;
+	err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
+				       sizeof(join_pref_params));
+	if (err)
+		brcmf_err("Set join_pref error (%d)\n", err);
+
+	/* Setup event_msgs, enable E_IF */
+	err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
+				       BRCMF_EVENTING_MASK_LEN);
+	if (err) {
+		brcmf_err("Get event_msgs error (%d)\n", err);
+		goto done;
+	}
+	setbit(eventmask, BRCMF_E_IF);
+	err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
+				       BRCMF_EVENTING_MASK_LEN);
+	if (err) {
+		brcmf_err("Set event_msgs error (%d)\n", err);
+		goto done;
+	}
+
+	/* Setup default scan channel time */
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+				    BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
+	if (err) {
+		brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
+			  err);
+		goto done;
+	}
+
+	/* Setup default scan unassoc time */
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+				    BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
+	if (err) {
+		brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
+			  err);
+		goto done;
+	}
+
+	/* Setup packet filter */
+	brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
+	brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
+					 0, true);
+
+	/* do bus specific preinit here */
+	err = brcmf_bus_preinit(ifp->drvr->bus_if);
+done:
+	return err;
+}
+
+#ifdef CPTCFG_BRCM_TRACING
+void __brcmf_err(const char *func, const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	pr_err("%s: %pV", func, &vaf);
+	trace_brcmf_err(func, &vaf);
+	va_end(args);
+}
+#endif
+#if defined(CPTCFG_BRCM_TRACING) || defined(CPTCFG_BRCMDBG)
+void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	if (brcmf_msg_level & level)
+		pr_debug("%s %pV", func, &vaf);
+	trace_brcmf_dbg(level, func, &vaf);
+	va_end(args);
+}
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
similarity index 97%
rename from drivers/net/wireless/brcm80211/brcmfmac/debug.c
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index 9b473d5..be9f4f8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -19,9 +19,9 @@
 
 #include <brcmu_wifi.h>
 #include <brcmu_utils.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
 
 static struct dentry *root_folder;
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
similarity index 97%
rename from drivers/net/wireless/brcm80211/brcmfmac/debug.h
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index a1a9bf4..b811d59 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -14,8 +14,8 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef BRCMFMAC_DEBUG_H
-#define BRCMFMAC_DEBUG_H
+#ifndef _BRCMF_DBG_H_
+#define _BRCMF_DBG_H_
 
 /* message levels */
 #define BRCMF_TRACE_VAL		0x00000002
@@ -133,4 +133,4 @@
 }
 #endif
 
-#endif /* BRCMFMAC_DEBUG_H */
+#endif				/* _BRCMF_DBG_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
similarity index 96%
rename from drivers/net/wireless/brcm80211/brcmfmac/core.c
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index f8785da..c1a16b1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -22,12 +22,12 @@
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
 #include "fwil_types.h"
 #include "p2p.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
 #include "fwil.h"
 #include "fwsignal.h"
 #include "feature.h"
@@ -836,7 +836,7 @@
 	return ifp;
 }
 
-static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
+void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
 {
 	struct brcmf_if *ifp;
 
@@ -869,38 +869,6 @@
 	}
 }
 
-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx)
-{
-	if (drvr->iflist[bssidx]) {
-		brcmf_fws_del_interface(drvr->iflist[bssidx]);
-		brcmf_del_if(drvr, bssidx);
-	}
-}
-
-int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
-{
-	int ifidx;
-	int bsscfgidx;
-	bool available;
-	int highest;
-
-	available = false;
-	bsscfgidx = 2;
-	highest = 2;
-	for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) {
-		if (drvr->iflist[ifidx]) {
-			if (drvr->iflist[ifidx]->bssidx == bsscfgidx)
-				bsscfgidx = highest + 1;
-			else if (drvr->iflist[ifidx]->bssidx > highest)
-				highest = drvr->iflist[ifidx]->bssidx;
-		} else {
-			available = true;
-		}
-	}
-
-	return available ? bsscfgidx : -ENOMEM;
-}
-
 int brcmf_attach(struct device *dev)
 {
 	struct brcmf_pub *drvr = NULL;
@@ -1065,7 +1033,10 @@
 
 	/* make sure primary interface removed last */
 	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
-		brcmf_remove_interface(drvr, i);
+		if (drvr->iflist[i]) {
+			brcmf_fws_del_interface(drvr->iflist[i]);
+			brcmf_del_if(drvr, i);
+		}
 
 	brcmf_cfg80211_detach(drvr->config);
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
similarity index 98%
rename from drivers/net/wireless/brcm80211/brcmfmac/sdio.c
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 0b0d51a..f55f625 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -40,7 +40,7 @@
 #include <brcmu_utils.h>
 #include <brcm_hw_ids.h>
 #include <soc.h>
-#include "sdio.h"
+#include "sdio_host.h"
 #include "chip.h"
 #include "firmware.h"
 
@@ -96,8 +96,8 @@
 #endif				/* DEBUG */
 #include <chipcommon.h>
 
-#include "bus.h"
-#include "debug.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
 #include "tracepoint.h"
 
 #define TXQLEN		2048	/* bulk tx queue length */
@@ -670,6 +670,7 @@
 				  struct brcmf_sdio_dev *sdiodev)
 {
 	int i;
+	uint fw_len, nv_len;
 	char end;
 
 	for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
@@ -683,25 +684,25 @@
 		return -ENODEV;
 	}
 
+	fw_len = sizeof(sdiodev->fw_name) - 1;
+	nv_len = sizeof(sdiodev->nvram_name) - 1;
 	/* check if firmware path is provided by module parameter */
 	if (brcmf_firmware_path[0] != '\0') {
-		strlcpy(sdiodev->fw_name, brcmf_firmware_path,
-			sizeof(sdiodev->fw_name));
-		strlcpy(sdiodev->nvram_name, brcmf_firmware_path,
-			sizeof(sdiodev->nvram_name));
+		strncpy(sdiodev->fw_name, brcmf_firmware_path, fw_len);
+		strncpy(sdiodev->nvram_name, brcmf_firmware_path, nv_len);
+		fw_len -= strlen(sdiodev->fw_name);
+		nv_len -= strlen(sdiodev->nvram_name);
 
 		end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
 		if (end != '/') {
-			strlcat(sdiodev->fw_name, "/",
-				sizeof(sdiodev->fw_name));
-			strlcat(sdiodev->nvram_name, "/",
-				sizeof(sdiodev->nvram_name));
+			strncat(sdiodev->fw_name, "/", fw_len);
+			strncat(sdiodev->nvram_name, "/", nv_len);
+			fw_len--;
+			nv_len--;
 		}
 	}
-	strlcat(sdiodev->fw_name, brcmf_fwname_data[i].bin,
-		sizeof(sdiodev->fw_name));
-	strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv,
-		sizeof(sdiodev->nvram_name));
+	strncat(sdiodev->fw_name, brcmf_fwname_data[i].bin, fw_len);
+	strncat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, nv_len);
 
 	return 0;
 }
@@ -2762,48 +2763,6 @@
 	return &bus->txq;
 }
 
-static bool brcmf_sdio_prec_enq(struct pktq *q, struct sk_buff *pkt, int prec)
-{
-	struct sk_buff *p;
-	int eprec = -1;		/* precedence to evict from */
-
-	/* Fast case, precedence queue is not full and we are also not
-	 * exceeding total queue length
-	 */
-	if (!pktq_pfull(q, prec) && !pktq_full(q)) {
-		brcmu_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 = brcmu_pktq_peek_tail(q, &eprec);
-		if (eprec > prec)
-			return false;
-	}
-
-	/* Evict if needed */
-	if (eprec >= 0) {
-		/* Detect queueing to unconfigured precedence */
-		if (eprec == prec)
-			return false;	/* refuse newer (incoming) packet */
-		/* Evict packet according to discard policy */
-		p = brcmu_pktq_pdeq_tail(q, eprec);
-		if (p == NULL)
-			brcmf_err("brcmu_pktq_pdeq_tail() failed\n");
-		brcmu_pkt_buf_free_skb(p);
-	}
-
-	/* Enqueue */
-	p = brcmu_pktq_penq(q, prec, pkt);
-	if (p == NULL)
-		brcmf_err("brcmu_pktq_penq() failed\n");
-
-	return p != NULL;
-}
-
 static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
 {
 	int ret = -EBADE;
@@ -2829,7 +2788,7 @@
 	spin_lock_bh(&bus->txq_lock);
 	/* reset bus_flags in packet cb */
 	*(u16 *)(pkt->cb) = 0;
-	if (!brcmf_sdio_prec_enq(&bus->txq, pkt, prec)) {
+	if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
 		skb_pull(pkt, bus->tx_hdrlen);
 		brcmf_err("out of bus->txq !!!\n");
 		ret = -ENOSR;
@@ -2839,7 +2798,7 @@
 
 	if (pktq_len(&bus->txq) >= TXHI) {
 		bus->txoff = true;
-		brcmf_txflowblock(dev, true);
+		brcmf_txflowblock(bus->sdiodev->dev, true);
 	}
 	spin_unlock_bh(&bus->txq_lock);
 
@@ -3990,7 +3949,6 @@
 	.txctl = brcmf_sdio_bus_txctl,
 	.rxctl = brcmf_sdio_bus_rxctl,
 	.gettxq = brcmf_sdio_bus_gettxq,
-	.wowl_config = brcmf_sdio_wowl_config
 };
 
 static void brcmf_sdio_firmware_callback(struct device *dev,
@@ -4117,7 +4075,7 @@
 
 	/* platform specific configuration:
 	 *   alignments must be at least 4 bytes for ADMA
-	 */
+         */
 	bus->head_align = ALIGNMENT;
 	bus->sgentry_align = ALIGNMENT;
 	if (sdiodev->pdata) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
index defb7a4..aed53ac 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
@@ -17,13 +17,18 @@
 #include <linux/netdevice.h>
 
 #include <brcm_hw_ids.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
 #include "fwil.h"
 #include "feature.h"
 
 /*
+ * firmware error code received if iovar is unsupported.
+ */
+#define EBRCMF_FEAT_UNSUPPORTED		23
+
+/*
  * expand feature list to array of feature strings.
  */
 #define BRCMF_FEAT_DEF(_f) \
@@ -97,28 +102,6 @@
 	}
 }
 
-/**
- * brcmf_feat_iovar_int_set() - determine feature through iovar set.
- *
- * @ifp: interface to query.
- * @id: feature id.
- * @name: iovar name.
- */
-static void brcmf_feat_iovar_int_set(struct brcmf_if *ifp,
-				     enum brcmf_feat_id id, char *name, u32 val)
-{
-	int err;
-
-	err = brcmf_fil_iovar_int_set(ifp, name, val);
-	if (err == 0) {
-		brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
-		ifp->drvr->feat_flags |= BIT(id);
-	} else {
-		brcmf_dbg(TRACE, "%s feature check failed: %d\n",
-			  brcmf_feat_names[id], err);
-	}
-}
-
 void brcmf_feat_attach(struct brcmf_pub *drvr)
 {
 	struct brcmf_if *ifp = drvr->iflist[0];
@@ -126,7 +109,6 @@
 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
 	if (drvr->bus_if->wowl_supported)
 		brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
-	brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
 
 	/* set chip related quirks */
 	switch (drvr->bus_if->chip) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
index f5832e0..b9a796d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
@@ -22,7 +22,6 @@
  * MCHAN: multi-channel for concurrent P2P.
  */
 #define BRCMF_FEAT_LIST \
-	BRCMF_FEAT_DEF(MBSS) \
 	BRCMF_FEAT_DEF(MCHAN) \
 	BRCMF_FEAT_DEF(WOWL)
 /*
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
index 1ff787d..8ea9f28 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -20,7 +20,7 @@
 #include <linux/firmware.h>
 #include <linux/module.h>
 
-#include "debug.h"
+#include "dhd_dbg.h"
 #include "firmware.h"
 
 char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
@@ -262,7 +262,8 @@
 
 fail:
 	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
-	release_firmware(fwctx->code);
+	if (fwctx->code)
+		release_firmware(fwctx->code);
 	device_release_driver(fwctx->dev);
 	kfree(fwctx);
 }
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
index 44f3a84..1faa929 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
@@ -19,9 +19,9 @@
 #include <linux/etherdevice.h>
 #include <brcmu_utils.h>
 
-#include "core.h"
-#include "debug.h"
-#include "bus.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
 #include "proto.h"
 #include "flowring.h"
 #include "msgbuf.h"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
index ec62492..44fc85f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -18,8 +18,8 @@
 #include "brcmu_wifi.h"
 #include "brcmu_utils.h"
 
-#include "core.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
 #include "tracepoint.h"
 #include "fwsignal.h"
 #include "fweh.h"
@@ -221,8 +221,10 @@
 
 	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
 
-	if (ifp && ifevent->action == BRCMF_E_IF_DEL)
-		brcmf_remove_interface(drvr, ifevent->bssidx);
+	if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
+		brcmf_fws_del_interface(ifp);
+		brcmf_del_if(drvr, ifevent->bssidx);
+	}
 }
 
 /**
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
index 03f2c40..ded328f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
@@ -22,9 +22,9 @@
 #include <linux/netdevice.h>
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
 #include "tracepoint.h"
 #include "fwil.h"
 #include "proto.h"
@@ -32,76 +32,6 @@
 
 #define MAX_HEX_DUMP_LEN	64
 
-#ifdef DEBUG
-static const char * const brcmf_fil_errstr[] = {
-	"BCME_OK",
-	"BCME_ERROR",
-	"BCME_BADARG",
-	"BCME_BADOPTION",
-	"BCME_NOTUP",
-	"BCME_NOTDOWN",
-	"BCME_NOTAP",
-	"BCME_NOTSTA",
-	"BCME_BADKEYIDX",
-	"BCME_RADIOOFF",
-	"BCME_NOTBANDLOCKED",
-	"BCME_NOCLK",
-	"BCME_BADRATESET",
-	"BCME_BADBAND",
-	"BCME_BUFTOOSHORT",
-	"BCME_BUFTOOLONG",
-	"BCME_BUSY",
-	"BCME_NOTASSOCIATED",
-	"BCME_BADSSIDLEN",
-	"BCME_OUTOFRANGECHAN",
-	"BCME_BADCHAN",
-	"BCME_BADADDR",
-	"BCME_NORESOURCE",
-	"BCME_UNSUPPORTED",
-	"BCME_BADLEN",
-	"BCME_NOTREADY",
-	"BCME_EPERM",
-	"BCME_NOMEM",
-	"BCME_ASSOCIATED",
-	"BCME_RANGE",
-	"BCME_NOTFOUND",
-	"BCME_WME_NOT_ENABLED",
-	"BCME_TSPEC_NOTFOUND",
-	"BCME_ACM_NOTSUPPORTED",
-	"BCME_NOT_WME_ASSOCIATION",
-	"BCME_SDIO_ERROR",
-	"BCME_DONGLE_DOWN",
-	"BCME_VERSION",
-	"BCME_TXFAIL",
-	"BCME_RXFAIL",
-	"BCME_NODEVICE",
-	"BCME_NMODE_DISABLED",
-	"BCME_NONRESIDENT",
-	"BCME_SCANREJECT",
-	"BCME_USAGE_ERROR",
-	"BCME_IOCTL_ERROR",
-	"BCME_SERIAL_PORT_ERR",
-	"BCME_DISABLED",
-	"BCME_DECERR",
-	"BCME_ENCERR",
-	"BCME_MICERR",
-	"BCME_REPLAY",
-	"BCME_IE_NOTFOUND",
-};
-
-static const char *brcmf_fil_get_errstr(u32 err)
-{
-	if (err >= ARRAY_SIZE(brcmf_fil_errstr))
-		return "(unknown)";
-
-	return brcmf_fil_errstr[err];
-}
-#else
-static const char *brcmf_fil_get_errstr(u32 err)
-{
-	return "";
-}
-#endif /* DEBUG */
 
 static s32
 brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
@@ -122,11 +52,11 @@
 		err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
 
 	if (err >= 0)
-		return 0;
+		err = 0;
+	else
+		brcmf_dbg(FIL, "Failed err=%d\n", err);
 
-	brcmf_dbg(FIL, "Failed: %s (%d)\n",
-		  brcmf_fil_get_errstr((u32)(-err)), err);
-	return -EBADE;
+	return err;
 }
 
 s32
@@ -136,7 +66,7 @@
 
 	mutex_lock(&ifp->drvr->proto_block);
 
-	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
+	brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
@@ -154,7 +84,7 @@
 	mutex_lock(&ifp->drvr->proto_block);
 	err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
 
-	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
+	brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
@@ -171,7 +101,7 @@
 	__le32 data_le = cpu_to_le32(data);
 
 	mutex_lock(&ifp->drvr->proto_block);
-	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, data);
+	brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, data);
 	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
 	mutex_unlock(&ifp->drvr->proto_block);
 
@@ -188,7 +118,7 @@
 	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
 	mutex_unlock(&ifp->drvr->proto_block);
 	*data = le32_to_cpu(data_le);
-	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, *data);
+	brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, *data);
 
 	return err;
 }
@@ -224,7 +154,7 @@
 
 	mutex_lock(&drvr->proto_block);
 
-	brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
+	brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
@@ -264,7 +194,7 @@
 		brcmf_err("Creating iovar failed\n");
 	}
 
-	brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
+	brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
@@ -347,8 +277,7 @@
 
 	mutex_lock(&drvr->proto_block);
 
-	brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx,
-		  ifp->bssidx, name, len);
+	brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
@@ -387,8 +316,7 @@
 		err = -EPERM;
 		brcmf_err("Creating bsscfg failed\n");
 	}
-	brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx,
-		  ifp->bssidx, name, len);
+	brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
 	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
 			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
index 50891c0..5ff5cd0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
@@ -55,63 +55,59 @@
 
 /* WOWL bits */
 /* Wakeup on Magic packet: */
-#define BRCMF_WOWL_MAGIC		(1 << 0)
+#define WL_WOWL_MAGIC			(1 << 0)
 /* Wakeup on Netpattern */
-#define BRCMF_WOWL_NET			(1 << 1)
+#define WL_WOWL_NET			(1 << 1)
 /* Wakeup on loss-of-link due to Disassoc/Deauth: */
-#define BRCMF_WOWL_DIS			(1 << 2)
+#define WL_WOWL_DIS			(1 << 2)
 /* Wakeup on retrograde TSF: */
-#define BRCMF_WOWL_RETR			(1 << 3)
+#define WL_WOWL_RETR			(1 << 3)
 /* Wakeup on loss of beacon: */
-#define BRCMF_WOWL_BCN			(1 << 4)
+#define WL_WOWL_BCN			(1 << 4)
 /* Wakeup after test: */
-#define BRCMF_WOWL_TST			(1 << 5)
+#define WL_WOWL_TST			(1 << 5)
 /* Wakeup after PTK refresh: */
-#define BRCMF_WOWL_M1			(1 << 6)
+#define WL_WOWL_M1			(1 << 6)
 /* Wakeup after receipt of EAP-Identity Req: */
-#define BRCMF_WOWL_EAPID		(1 << 7)
+#define WL_WOWL_EAPID			(1 << 7)
 /* Wakeind via PME(0) or GPIO(1): */
-#define BRCMF_WOWL_PME_GPIO		(1 << 8)
+#define WL_WOWL_PME_GPIO		(1 << 8)
 /* need tkip phase 1 key to be updated by the driver: */
-#define BRCMF_WOWL_NEEDTKIP1		(1 << 9)
+#define WL_WOWL_NEEDTKIP1		(1 << 9)
 /* enable wakeup if GTK fails: */
-#define BRCMF_WOWL_GTK_FAILURE		(1 << 10)
+#define WL_WOWL_GTK_FAILURE		(1 << 10)
 /* support extended magic packets: */
-#define BRCMF_WOWL_EXTMAGPAT		(1 << 11)
+#define WL_WOWL_EXTMAGPAT		(1 << 11)
 /* support ARP/NS/keepalive offloading: */
-#define BRCMF_WOWL_ARPOFFLOAD		(1 << 12)
+#define WL_WOWL_ARPOFFLOAD		(1 << 12)
 /* read protocol version for EAPOL frames: */
-#define BRCMF_WOWL_WPA2			(1 << 13)
+#define WL_WOWL_WPA2			(1 << 13)
 /* If the bit is set, use key rotaton: */
-#define BRCMF_WOWL_KEYROT		(1 << 14)
+#define WL_WOWL_KEYROT			(1 << 14)
 /* If the bit is set, frm received was bcast frame: */
-#define BRCMF_WOWL_BCAST		(1 << 15)
+#define WL_WOWL_BCAST			(1 << 15)
 /* If the bit is set, scan offload is enabled: */
-#define BRCMF_WOWL_SCANOL		(1 << 16)
+#define WL_WOWL_SCANOL			(1 << 16)
 /* Wakeup on tcpkeep alive timeout: */
-#define BRCMF_WOWL_TCPKEEP_TIME		(1 << 17)
+#define WL_WOWL_TCPKEEP_TIME		(1 << 17)
 /* Wakeup on mDNS Conflict Resolution: */
-#define BRCMF_WOWL_MDNS_CONFLICT	(1 << 18)
+#define WL_WOWL_MDNS_CONFLICT		(1 << 18)
 /* Wakeup on mDNS Service Connect: */
-#define BRCMF_WOWL_MDNS_SERVICE		(1 << 19)
+#define WL_WOWL_MDNS_SERVICE		(1 << 19)
 /* tcp keepalive got data: */
-#define BRCMF_WOWL_TCPKEEP_DATA		(1 << 20)
+#define WL_WOWL_TCPKEEP_DATA		(1 << 20)
 /* Firmware died in wowl mode: */
-#define BRCMF_WOWL_FW_HALT		(1 << 21)
+#define WL_WOWL_FW_HALT			(1 << 21)
 /* Enable detection of radio button changes: */
-#define BRCMF_WOWL_ENAB_HWRADIO		(1 << 22)
+#define WL_WOWL_ENAB_HWRADIO		(1 << 22)
 /* Offloads detected MIC failure(s): */
-#define BRCMF_WOWL_MIC_FAIL		(1 << 23)
+#define WL_WOWL_MIC_FAIL		(1 << 23)
 /* Wakeup in Unassociated state (Net/Magic Pattern): */
-#define BRCMF_WOWL_UNASSOC		(1 << 24)
+#define WL_WOWL_UNASSOC			(1 << 24)
 /* Wakeup if received matched secured pattern: */
-#define BRCMF_WOWL_SECURE		(1 << 25)
+#define WL_WOWL_SECURE			(1 << 25)
 /* Link Down indication in WoWL mode: */
-#define BRCMF_WOWL_LINKDOWN		(1 << 31)
-
-#define BRCMF_WOWL_MAXPATTERNS		8
-#define BRCMF_WOWL_MAXPATTERNSIZE	128
-
+#define WL_WOWL_LINKDOWN		(1 << 31)
 
 /* join preference types for join_pref iovar */
 enum brcmf_join_pref_types {
@@ -128,12 +124,6 @@
 	BRCMF_FIL_P2P_IF_DEV,
 };
 
-enum brcmf_wowl_pattern_type {
-	BRCMF_WOWL_PATTERN_TYPE_BITMAP = 0,
-	BRCMF_WOWL_PATTERN_TYPE_ARP,
-	BRCMF_WOWL_PATTERN_TYPE_NA
-};
-
 struct brcmf_fil_p2p_if_le {
 	u8 addr[ETH_ALEN];
 	__le16 type;
@@ -494,35 +484,4 @@
 	__be32	rate;
 };
 
-/**
- * struct brcmf_fil_wowl_pattern_le - wowl pattern configuration struct.
- *
- * @cmd: "add", "del" or "clr".
- * @masksize: Size of the mask in #of bytes
- * @offset: Pattern byte offset in packet
- * @patternoffset: Offset of start of pattern. Starting from field masksize.
- * @patternsize: Size of the pattern itself in #of bytes
- * @id: id
- * @reasonsize: Size of the wakeup reason code
- * @type: Type of pattern (enum brcmf_wowl_pattern_type)
- */
-struct brcmf_fil_wowl_pattern_le {
-	u8	cmd[4];
-	__le32	masksize;
-	__le32	offset;
-	__le32	patternoffset;
-	__le32	patternsize;
-	__le32	id;
-	__le32	reasonsize;
-	__le32	type;
-	/* u8 mask[] - Mask follows the structure above */
-	/* u8 pattern[] - Pattern follows the mask is at 'patternoffset' */
-};
-
-struct brcmf_mbss_ssid_le {
-	__le32	bsscfgidx;
-	__le32	SSID_len;
-	unsigned char SSID[32];
-};
-
 #endif /* FWIL_TYPES_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index f0dda0e..183f08d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -26,15 +26,15 @@
 
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
-#include "core.h"
-#include "debug.h"
-#include "bus.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
 #include "fwil.h"
 #include "fwil_types.h"
 #include "fweh.h"
 #include "fwsignal.h"
 #include "p2p.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
 #include "proto.h"
 
 /**
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
index 456944a..11cc051 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
@@ -24,13 +24,13 @@
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 
-#include "core.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
 #include "proto.h"
 #include "msgbuf.h"
 #include "commonring.h"
 #include "flowring.h"
-#include "bus.h"
+#include "dhd_bus.h"
 #include "tracepoint.h"
 
 
@@ -518,7 +518,8 @@
 		memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
 				       len : msgbuf->ioctl_resp_ret_len);
 	}
-	brcmu_pkt_buf_free_skb(skb);
+	if (skb)
+		brcmu_pkt_buf_free_skb(skb);
 
 	return msgbuf->ioctl_resp_status;
 }
@@ -1080,17 +1081,8 @@
 {
 	struct brcmf_if *ifp;
 
-	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
-	 * events this is easy because it contains the bssidx which maps
-	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
-	 * bssidx 1 is used for p2p0 and no data can be received or
-	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
-	 */
-	if (ifidx)
-		(ifidx)++;
 	ifp = msgbuf->drvr->iflist[ifidx];
 	if (!ifp || !ifp->ndev) {
-		brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
 		brcmu_pkt_buf_free_skb(skb);
 		return;
 	}
@@ -1363,7 +1355,6 @@
 	}
 	INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker);
 	count = BITS_TO_LONGS(if_msgbuf->nrof_flowrings);
-	count = count * sizeof(unsigned long);
 	msgbuf->flow_map = kzalloc(count, GFP_KERNEL);
 	if (!msgbuf->flow_map)
 		goto fail;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/of.c b/drivers/net/wireless/brcm80211/brcmfmac/of.c
index c824570..f05f527 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/of.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/of.c
@@ -21,8 +21,8 @@
 #include <linux/mmc/sdio_func.h>
 
 #include <defs.h>
-#include "debug.h"
-#include "sdio.h"
+#include "dhd_dbg.h"
+#include "sdio_host.h"
 
 void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
 {
@@ -40,8 +40,8 @@
 		return;
 
 	irq = irq_of_parse_and_map(np, 0);
-	if (!irq) {
-		brcmf_err("interrupt could not be mapped\n");
+	if (irq < 0) {
+		brcmf_err("interrupt could not be mapped: err=%d\n", irq);
 		devm_kfree(dev, sdiodev->pdata);
 		return;
 	}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index effb48e..d54c58a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -21,12 +21,12 @@
 #include <brcmu_wifi.h>
 #include <brcmu_utils.h>
 #include <defs.h>
-#include "core.h"
-#include "debug.h"
+#include <dhd.h>
+#include <dhd_dbg.h>
 #include "fwil.h"
 #include "fwil_types.h"
 #include "p2p.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
 
 /* parameters used for p2p escan */
 #define P2PAPI_SCAN_NPROBES 1
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
index 905991f..8c0632e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
@@ -19,10 +19,10 @@
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
+#include <linux/unaligned/access_ok.h>
 #include <linux/interrupt.h>
 #include <linux/bcma/bcma.h>
 #include <linux/sched.h>
-#include <asm/unaligned.h>
 
 #include <soc.h>
 #include <chipcommon.h>
@@ -30,8 +30,8 @@
 #include <brcmu_wifi.h>
 #include <brcm_hw_ids.h>
 
-#include "debug.h"
-#include "bus.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
 #include "commonring.h"
 #include "msgbuf.h"
 #include "pcie.h"
@@ -798,14 +798,12 @@
 	brcmf_dbg(PCIE, "Enter\n");
 	/* is it a v1 or v2 implementation */
 	devinfo->irq_requested = false;
-	pci_enable_msi(pdev);
 	if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
 		if (request_threaded_irq(pdev->irq,
 					 brcmf_pcie_quick_check_isr_v1,
 					 brcmf_pcie_isr_thread_v1,
 					 IRQF_SHARED, "brcmf_pcie_intr",
 					 devinfo)) {
-			pci_disable_msi(pdev);
 			brcmf_err("Failed to request IRQ %d\n", pdev->irq);
 			return -EIO;
 		}
@@ -815,7 +813,6 @@
 					 brcmf_pcie_isr_thread_v2,
 					 IRQF_SHARED, "brcmf_pcie_intr",
 					 devinfo)) {
-			pci_disable_msi(pdev);
 			brcmf_err("Failed to request IRQ %d\n", pdev->irq);
 			return -EIO;
 		}
@@ -842,7 +839,6 @@
 		return;
 	devinfo->irq_requested = false;
 	free_irq(pdev->irq, devinfo);
-	pci_disable_msi(pdev);
 
 	msleep(50);
 	count = 0;
@@ -1861,8 +1857,6 @@
 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
-	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
-	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
 	{ /* end: all zeroes */ }
 };
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c
index 26b68c3..62b9407 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/proto.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.c
@@ -20,9 +20,9 @@
 #include <linux/netdevice.h>
 
 #include <brcmu_wifi.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
 #include "proto.h"
 #include "bcdc.h"
 #include "msgbuf.h"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
similarity index 98%
rename from drivers/net/wireless/brcm80211/brcmfmac/sdio.h
rename to drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 8eb4262..f2d06ca 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -14,8 +14,8 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef	BRCMFMAC_SDIO_H
-#define	BRCMFMAC_SDIO_H
+#ifndef	_BRCM_SDH_H_
+#define	_BRCM_SDH_H_
 
 #include <linux/skbuff.h>
 #include <linux/firmware.h>
@@ -186,7 +186,6 @@
 	struct sg_table sgtable;
 	char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
 	char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
-	bool wowl_enabled;
 };
 
 /* sdio core registers */
@@ -335,6 +334,5 @@
 void brcmf_sdio_isr(struct brcmf_sdio *bus);
 
 void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick);
-void brcmf_sdio_wowl_config(struct device *dev, bool enabled);
 
-#endif /* BRCMFMAC_SDIO_H */
+#endif				/* _BRCM_SDH_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
index a10f35c..b505db4 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
@@ -19,19 +19,4 @@
 #ifndef __CHECKER__
 #define CREATE_TRACE_POINTS
 #include "tracepoint.h"
-
-void __brcmf_err(const char *func, const char *fmt, ...)
-{
-	struct va_format vaf = {
-		.fmt = fmt,
-	};
-	va_list args;
-
-	va_start(args, fmt);
-	vaf.va = &args;
-	pr_err("%s: %pV", func, &vaf);
-	trace_brcmf_err(func, &vaf);
-	va_end(args);
-}
-
 #endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index a662707..99b03a1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -23,11 +23,12 @@
 #include <brcmu_utils.h>
 #include <brcm_hw_ids.h>
 #include <brcmu_wifi.h>
-#include "bus.h"
-#include "debug.h"
-#include "firmware.h"
-#include "usb.h"
+#include <dhd_bus.h>
+#include <dhd_dbg.h>
 
+#include "firmware.h"
+#include "usb_rdl.h"
+#include "usb.h"
 
 #define IOCTL_RESP_TIMEOUT		2000
 
@@ -48,71 +49,6 @@
 #define BRCMF_USB_43242_FW_NAME		"brcm/brcmfmac43242a.bin"
 #define BRCMF_USB_43569_FW_NAME		"brcm/brcmfmac43569.bin"
 
-#define TRX_MAGIC		0x30524448	/* "HDR0" */
-#define TRX_MAX_OFFSET		3		/* Max number of file offsets */
-#define TRX_UNCOMP_IMAGE	0x20		/* Trx holds uncompressed img */
-#define TRX_RDL_CHUNK		1500		/* size of each dl transfer */
-#define TRX_OFFSETS_DLFWLEN_IDX	0
-
-/* Control messages: bRequest values */
-#define DL_GETSTATE	0	/* returns the rdl_state_t struct */
-#define DL_CHECK_CRC	1	/* currently unused */
-#define DL_GO		2	/* execute downloaded image */
-#define DL_START	3	/* initialize dl state */
-#define DL_REBOOT	4	/* reboot the device in 2 seconds */
-#define DL_GETVER	5	/* returns the bootrom_id_t struct */
-#define DL_GO_PROTECTED	6	/* execute the downloaded code and set reset
-				 * event to occur in 2 seconds.  It is the
-				 * responsibility of the downloaded code to
-				 * clear this event
-				 */
-#define DL_EXEC		7	/* jump to a supplied address */
-#define DL_RESETCFG	8	/* To support single enum on dongle
-				 * - Not used by bootloader
-				 */
-#define DL_DEFER_RESP_OK 9	/* Potentially defer the response to setup
-				 * if resp unavailable
-				 */
-
-/* states */
-#define DL_WAITING	0	/* waiting to rx first pkt */
-#define DL_READY	1	/* hdr was good, waiting for more of the
-				 * compressed image
-				 */
-#define DL_BAD_HDR	2	/* hdr was corrupted */
-#define DL_BAD_CRC	3	/* compressed image was corrupted */
-#define DL_RUNNABLE	4	/* download was successful,waiting for go cmd */
-#define DL_START_FAIL	5	/* failed to initialize correctly */
-#define DL_NVRAM_TOOBIG	6	/* host specified nvram data exceeds DL_NVRAM
-				 * value
-				 */
-#define DL_IMAGE_TOOBIG	7	/* firmware image too big */
-
-
-struct trx_header_le {
-	__le32 magic;		/* "HDR0" */
-	__le32 len;		/* Length of file including header */
-	__le32 crc32;		/* CRC from flag_version to end of file */
-	__le32 flag_version;	/* 0:15 flags, 16:31 version */
-	__le32 offsets[TRX_MAX_OFFSET];	/* Offsets of partitions from start of
-					 * header
-					 */
-};
-
-struct rdl_state_le {
-	__le32 state;
-	__le32 bytes;
-};
-
-struct bootrom_id_le {
-	__le32 chip;		/* Chip id */
-	__le32 chiprev;		/* Chip rev */
-	__le32 ramsize;		/* Size of  RAM */
-	__le32 remapbase;	/* Current remap base address */
-	__le32 boardtype;	/* Type of board */
-	__le32 boardrev;	/* Board revision */
-};
-
 struct brcmf_usb_image {
 	struct list_head list;
 	s8 *fwname;
@@ -157,8 +93,6 @@
 	u8 ifnum;
 
 	struct urb *bulk_urb; /* used for FW download */
-
-	bool wowl_enabled;
 };
 
 static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
@@ -666,16 +600,6 @@
 	return 0;
 }
 
-static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo)
-{
-	if (devinfo->ctl_urb)
-		usb_kill_urb(devinfo->ctl_urb);
-	if (devinfo->bulk_urb)
-		usb_kill_urb(devinfo->bulk_urb);
-	brcmf_usb_free_q(&devinfo->tx_postq, true);
-	brcmf_usb_free_q(&devinfo->rx_postq, true);
-}
-
 static void brcmf_usb_down(struct device *dev)
 {
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
@@ -689,7 +613,14 @@
 
 	brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
 
-	brcmf_cancel_all_urbs(devinfo);
+	if (devinfo->ctl_urb)
+		usb_kill_urb(devinfo->ctl_urb);
+
+	if (devinfo->bulk_urb)
+		usb_kill_urb(devinfo->bulk_urb);
+	brcmf_usb_free_q(&devinfo->tx_postq, true);
+
+	brcmf_usb_free_q(&devinfo->rx_postq, true);
 }
 
 static void
@@ -738,12 +669,10 @@
 		goto finalize;
 	}
 
-	if (!brcmf_usb_ioctl_resp_wait(devinfo)) {
-		usb_kill_urb(devinfo->ctl_urb);
+	if (!brcmf_usb_ioctl_resp_wait(devinfo))
 		ret = -ETIMEDOUT;
-	} else {
+	else
 		memcpy(buffer, tmpbuf, buflen);
-	}
 
 finalize:
 	kfree(tmpbuf);
@@ -854,7 +783,7 @@
 
 	brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen);
 
-	bulkchunk = kmalloc(TRX_RDL_CHUNK, GFP_ATOMIC);
+	bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC);
 	if (bulkchunk == NULL) {
 		err = -ENOMEM;
 		goto fail;
@@ -881,10 +810,10 @@
 		/* Wait until the usb device reports it received all
 		 * the bytes we sent */
 		if ((rdlbytes == sent) && (rdlbytes != dllen)) {
-			if ((dllen-sent) < TRX_RDL_CHUNK)
+			if ((dllen-sent) < RDL_CHUNK)
 				sendlen = dllen-sent;
 			else
-				sendlen = TRX_RDL_CHUNK;
+				sendlen = RDL_CHUNK;
 
 			/* simply avoid having to send a ZLP by ensuring we
 			 * never have an even
@@ -1049,6 +978,21 @@
 	kfree(devinfo->rx_reqs);
 }
 
+#define TRX_MAGIC       0x30524448      /* "HDR0" */
+#define TRX_VERSION     1               /* Version 1 */
+#define TRX_MAX_LEN     0x3B0000        /* Max length */
+#define TRX_NO_HEADER   1               /* Do not write TRX header */
+#define TRX_MAX_OFFSET  3               /* Max number of individual files */
+#define TRX_UNCOMP_IMAGE        0x20    /* Trx contains uncompressed image */
+
+struct trx_header_le {
+	__le32 magic;		/* "HDR0" */
+	__le32 len;		/* Length of file including header */
+	__le32 crc32;		/* CRC from flag_version to end of file */
+	__le32 flag_version;	/* 0:15 flags, 16:31 version */
+	__le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of
+					 * header */
+};
 
 static int check_file(const u8 *headers)
 {
@@ -1150,24 +1094,11 @@
 	return NULL;
 }
 
-static void brcmf_usb_wowl_config(struct device *dev, bool enabled)
-{
-	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
-
-	brcmf_dbg(USB, "Configuring WOWL, enabled=%d\n", enabled);
-	devinfo->wowl_enabled = enabled;
-	if (enabled)
-		device_set_wakeup_enable(devinfo->dev, true);
-	else
-		device_set_wakeup_enable(devinfo->dev, false);
-}
-
 static struct brcmf_bus_ops brcmf_usb_bus_ops = {
 	.txdata = brcmf_usb_tx,
 	.stop = brcmf_usb_down,
 	.txctl = brcmf_usb_tx_ctlpkt,
 	.rxctl = brcmf_usb_rx_ctlpkt,
-	.wowl_config = brcmf_usb_wowl_config,
 };
 
 static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
@@ -1255,9 +1186,6 @@
 	bus->ops = &brcmf_usb_bus_ops;
 	bus->proto_type = BRCMF_PROTO_BCDC;
 	bus->always_use_fws_queue = true;
-#ifdef CONFIG_PM
-	bus->wowl_supported = true;
-#endif
 
 	if (!brcmf_usb_dlneeded(devinfo)) {
 		ret = brcmf_usb_bus_setup(devinfo);
@@ -1411,10 +1339,7 @@
 
 	brcmf_dbg(USB, "Enter\n");
 	devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP;
-	if (devinfo->wowl_enabled)
-		brcmf_cancel_all_urbs(devinfo);
-	else
-		brcmf_detach(&usb->dev);
+	brcmf_detach(&usb->dev);
 	return 0;
 }
 
@@ -1427,12 +1352,7 @@
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
 
 	brcmf_dbg(USB, "Enter\n");
-	if (!devinfo->wowl_enabled)
-		return brcmf_usb_bus_setup(devinfo);
-
-	devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP;
-	brcmf_usb_rx_fill_all(devinfo);
-	return 0;
+	return brcmf_usb_bus_setup(devinfo);
 }
 
 static int brcmf_usb_reset_resume(struct usb_interface *intf)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
new file mode 100644
index 0000000..0a35c51
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _USB_RDL_H
+#define _USB_RDL_H
+
+/* Control messages: bRequest values */
+#define DL_GETSTATE	0	/* returns the rdl_state_t struct */
+#define DL_CHECK_CRC	1	/* currently unused */
+#define DL_GO		2	/* execute downloaded image */
+#define DL_START	3	/* initialize dl state */
+#define DL_REBOOT	4	/* reboot the device in 2 seconds */
+#define DL_GETVER	5	/* returns the bootrom_id_t struct */
+#define DL_GO_PROTECTED	6	/* execute the downloaded code and set reset
+				 * event to occur in 2 seconds.  It is the
+				 * responsibility of the downloaded code to
+				 * clear this event
+				 */
+#define DL_EXEC		7	/* jump to a supplied address */
+#define DL_RESETCFG	8	/* To support single enum on dongle
+				 * - Not used by bootloader
+				 */
+#define DL_DEFER_RESP_OK 9	/* Potentially defer the response to setup
+				 * if resp unavailable
+				 */
+
+/* states */
+#define DL_WAITING	0	/* waiting to rx first pkt */
+#define DL_READY	1	/* hdr was good, waiting for more of the
+				 * compressed image */
+#define DL_BAD_HDR	2	/* hdr was corrupted */
+#define DL_BAD_CRC	3	/* compressed image was corrupted */
+#define DL_RUNNABLE	4	/* download was successful,waiting for go cmd */
+#define DL_START_FAIL	5	/* failed to initialize correctly */
+#define DL_NVRAM_TOOBIG	6	/* host specified nvram data exceeds DL_NVRAM
+				 * value */
+#define DL_IMAGE_TOOBIG	7	/* download image too big (exceeds DATA_START
+				 *  for rdl) */
+
+struct rdl_state_le {
+	__le32 state;
+	__le32 bytes;
+};
+
+struct bootrom_id_le {
+	__le32 chip;	/* Chip id */
+	__le32 chiprev;	/* Chip rev */
+	__le32 ramsize;	/* Size of  RAM */
+	__le32 remapbase;	/* Current remap base address */
+	__le32 boardtype;	/* Type of board */
+	__le32 boardrev;	/* Board revision */
+};
+
+#define RDL_CHUNK	1500  /* size of each dl transfer */
+
+#define TRX_OFFSETS_DLFWLEN_IDX	0
+#define TRX_OFFSETS_JUMPTO_IDX	1
+#define TRX_OFFSETS_NVM_LEN_IDX	2
+
+#define TRX_OFFSETS_DLBASE_IDX  0
+
+#endif  /* _USB_RDL_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
index 50cdf70..5960d82 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
@@ -20,10 +20,10 @@
 
 #include <brcmu_wifi.h>
 #include "fwil_types.h"
-#include "core.h"
+#include "dhd.h"
 #include "p2p.h"
-#include "debug.h"
-#include "cfg80211.h"
+#include "dhd_dbg.h"
+#include "wl_cfg80211.h"
 #include "vendor.h"
 #include "fwil.h"
 
@@ -31,8 +31,8 @@
 						 struct wireless_dev *wdev,
 						 const void *data, int len)
 {
-	struct brcmf_cfg80211_vif *vif;
-	struct brcmf_if *ifp;
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg);
 	const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
 	struct sk_buff *reply;
 	int ret, payload, ret_len;
@@ -42,9 +42,6 @@
 	brcmf_dbg(TRACE, "cmd %x set %d len %d\n", cmdhdr->cmd, cmdhdr->set,
 		  cmdhdr->len);
 
-	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
-	ifp = vif->ifp;
-
 	len -= sizeof(struct brcmf_vndr_dcmd_hdr);
 	ret_len = cmdhdr->len;
 	if (ret_len > 0 || len > 0) {
@@ -66,11 +63,11 @@
 	}
 
 	if (cmdhdr->set)
-		ret = brcmf_fil_cmd_data_set(ifp, cmdhdr->cmd, dcmd_buf,
-					     ret_len);
+		ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), cmdhdr->cmd,
+					     dcmd_buf, ret_len);
 	else
-		ret = brcmf_fil_cmd_data_get(ifp, cmdhdr->cmd, dcmd_buf,
-					     ret_len);
+		ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), cmdhdr->cmd,
+					     dcmd_buf, ret_len);
 	if (ret != 0)
 		goto exit;
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
similarity index 95%
rename from drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
rename to drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 3aecc5f..28fa25b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -26,18 +26,18 @@
 #include <brcmu_utils.h>
 #include <defs.h>
 #include <brcmu_wifi.h>
-#include "core.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
 #include "tracepoint.h"
 #include "fwil_types.h"
 #include "p2p.h"
 #include "btcoex.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
 #include "feature.h"
 #include "fwil.h"
 #include "proto.h"
 #include "vendor.h"
-#include "bus.h"
+#include "dhd_bus.h"
 
 #define BRCMF_SCAN_IE_LEN_MAX		2048
 #define BRCMF_PNO_VERSION		2
@@ -299,7 +299,6 @@
 	primary_offset = ch->center_freq1 - ch->chan->center_freq;
 	switch (ch->width) {
 	case NL80211_CHAN_WIDTH_20:
-	case NL80211_CHAN_WIDTH_20_NOHT:
 		ch_inf.bw = BRCMU_CHAN_BW_20;
 		WARN_ON(primary_offset != 0);
 		break;
@@ -324,10 +323,6 @@
 				ch_inf.sb = BRCMU_CHAN_SB_LU;
 		}
 		break;
-	case NL80211_CHAN_WIDTH_80P80:
-	case NL80211_CHAN_WIDTH_160:
-	case NL80211_CHAN_WIDTH_5:
-	case NL80211_CHAN_WIDTH_10:
 	default:
 		WARN_ON_ONCE(1);
 	}
@@ -338,7 +333,6 @@
 	case IEEE80211_BAND_5GHZ:
 		ch_inf.band = BRCMU_CHAN_BAND_5G;
 		break;
-	case IEEE80211_BAND_60GHZ:
 	default:
 		WARN_ON_ONCE(1);
 	}
@@ -520,95 +514,6 @@
 						ADDR_INDIRECT);
 }
 
-static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
-{
-	struct brcmf_mbss_ssid_le mbss_ssid_le;
-	int bsscfgidx;
-	int err;
-
-	memset(&mbss_ssid_le, 0, sizeof(mbss_ssid_le));
-	bsscfgidx = brcmf_get_next_free_bsscfgidx(ifp->drvr);
-	if (bsscfgidx < 0)
-		return bsscfgidx;
-
-	mbss_ssid_le.bsscfgidx = cpu_to_le32(bsscfgidx);
-	mbss_ssid_le.SSID_len = cpu_to_le32(5);
-	sprintf(mbss_ssid_le.SSID, "ssid%d" , bsscfgidx);
-
-	err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le,
-					sizeof(mbss_ssid_le));
-	if (err < 0)
-		brcmf_err("setting ssid failed %d\n", err);
-
-	return err;
-}
-
-/**
- * brcmf_ap_add_vif() - create a new AP virtual interface for multiple BSS
- *
- * @wiphy: wiphy device of new interface.
- * @name: name of the new interface.
- * @flags: not used.
- * @params: contains mac address for AP device.
- */
-static
-struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
-				      u32 *flags, struct vif_params *params)
-{
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
-	struct brcmf_cfg80211_vif *vif;
-	int err;
-
-	if (brcmf_cfg80211_vif_event_armed(cfg))
-		return ERR_PTR(-EBUSY);
-
-	brcmf_dbg(INFO, "Adding vif \"%s\"\n", name);
-
-	vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_AP, false);
-	if (IS_ERR(vif))
-		return (struct wireless_dev *)vif;
-
-	brcmf_cfg80211_arm_vif_event(cfg, vif);
-
-	err = brcmf_cfg80211_request_ap_if(ifp);
-	if (err) {
-		brcmf_cfg80211_arm_vif_event(cfg, NULL);
-		goto fail;
-	}
-
-	/* wait for firmware event */
-	err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_ADD,
-						    msecs_to_jiffies(1500));
-	brcmf_cfg80211_arm_vif_event(cfg, NULL);
-	if (!err) {
-		brcmf_err("timeout occurred\n");
-		err = -EIO;
-		goto fail;
-	}
-
-	/* interface created in firmware */
-	ifp = vif->ifp;
-	if (!ifp) {
-		brcmf_err("no if pointer provided\n");
-		err = -ENOENT;
-		goto fail;
-	}
-
-	strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1);
-	err = brcmf_net_attach(ifp, true);
-	if (err) {
-		brcmf_err("Registering netdevice failed\n");
-		goto fail;
-	}
-
-	return &ifp->vif->wdev;
-
-fail:
-	brcmf_free_vif(vif);
-	return ERR_PTR(err);
-}
-
 static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)
 {
 	enum nl80211_iftype iftype;
@@ -634,16 +539,12 @@
 	switch (type) {
 	case NL80211_IFTYPE_ADHOC:
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_AP_VLAN:
 	case NL80211_IFTYPE_WDS:
 	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_MESH_POINT:
 		return ERR_PTR(-EOPNOTSUPP);
-	case NL80211_IFTYPE_AP:
-		wdev = brcmf_ap_add_vif(wiphy, name, flags, params);
-		if (!IS_ERR(wdev))
-			brcmf_cfg80211_update_proto_addr_mode(wdev);
-		return wdev;
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_P2P_GO:
 	case NL80211_IFTYPE_P2P_DEVICE:
@@ -1908,7 +1809,6 @@
 		return -EIO;
 
 	clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
-	clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
 	cfg80211_disconnected(ndev, reason_code, NULL, 0, GFP_KERNEL);
 
 	memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
@@ -2879,44 +2779,6 @@
 	}
 }
 
-static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
-				     u8 *pattern, u32 patternsize, u8 *mask,
-				     u32 packet_offset)
-{
-	struct brcmf_fil_wowl_pattern_le *filter;
-	u32 masksize;
-	u32 patternoffset;
-	u8 *buf;
-	u32 bufsize;
-	s32 ret;
-
-	masksize = (patternsize + 7) / 8;
-	patternoffset = sizeof(*filter) - sizeof(filter->cmd) + masksize;
-
-	bufsize = sizeof(*filter) + patternsize + masksize;
-	buf = kzalloc(bufsize, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	filter = (struct brcmf_fil_wowl_pattern_le *)buf;
-
-	memcpy(filter->cmd, cmd, 4);
-	filter->masksize = cpu_to_le32(masksize);
-	filter->offset = cpu_to_le32(packet_offset);
-	filter->patternoffset = cpu_to_le32(patternoffset);
-	filter->patternsize = cpu_to_le32(patternsize);
-	filter->type = cpu_to_le32(BRCMF_WOWL_PATTERN_TYPE_BITMAP);
-
-	if ((mask) && (masksize))
-		memcpy(buf + sizeof(*filter), mask, masksize);
-	if ((pattern) && (patternsize))
-		memcpy(buf + sizeof(*filter) + masksize, pattern, patternsize);
-
-	ret = brcmf_fil_iovar_data_set(ifp, "wowl_pattern", buf, bufsize);
-
-	kfree(buf);
-	return ret;
-}
-
 static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
@@ -2926,11 +2788,10 @@
 	brcmf_dbg(TRACE, "Enter\n");
 
 	if (cfg->wowl_enabled) {
-		brcmf_configure_arp_offload(ifp, true);
 		brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
 				      cfg->pre_wowl_pmmode);
+		brcmf_fil_iovar_data_set(ifp, "wowl_pattern", "clr", 4);
 		brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
-		brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
 		cfg->wowl_enabled = false;
 	}
 	return 0;
@@ -2941,29 +2802,21 @@
 				 struct cfg80211_wowlan *wowl)
 {
 	u32 wowl_config;
-	u32 i;
 
 	brcmf_dbg(TRACE, "Suspend, wowl config.\n");
 
-	brcmf_configure_arp_offload(ifp, false);
 	brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->pre_wowl_pmmode);
 	brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX);
 
 	wowl_config = 0;
 	if (wowl->disconnect)
-		wowl_config = BRCMF_WOWL_DIS | BRCMF_WOWL_BCN | BRCMF_WOWL_RETR;
+		wowl_config |= WL_WOWL_DIS | WL_WOWL_BCN | WL_WOWL_RETR;
+		/* Note: if "wowl" target and not "wowlpf" then wowl_bcn_loss
+		 * should be configured. This paramater is not supported by
+		 * wowlpf.
+		 */
 	if (wowl->magic_pkt)
-		wowl_config |= BRCMF_WOWL_MAGIC;
-	if ((wowl->patterns) && (wowl->n_patterns)) {
-		wowl_config |= BRCMF_WOWL_NET;
-		for (i = 0; i < wowl->n_patterns; i++) {
-			brcmf_config_wowl_pattern(ifp, "add",
-				(u8 *)wowl->patterns[i].pattern,
-				wowl->patterns[i].pattern_len,
-				(u8 *)wowl->patterns[i].mask,
-				wowl->patterns[i].pkt_offset);
-		}
-	}
+		wowl_config |= WL_WOWL_MAGIC;
 	brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
 	brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
 	brcmf_bus_wowl_config(cfg->pub->bus_if, true);
@@ -3026,7 +2879,7 @@
 		     struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
 {
 	int i, j;
-	u32 pmkid_len;
+	int pmkid_len;
 
 	pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
 
@@ -3054,7 +2907,8 @@
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
 	s32 err = 0;
-	u32 pmkid_len, i;
+	int i;
+	int pmkid_len;
 
 	brcmf_dbg(TRACE, "Enter\n");
 	if (!check_vif_up(ifp->vif))
@@ -3093,7 +2947,7 @@
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct pmkid_list pmkid;
 	s32 err = 0;
-	u32 pmkid_len, i;
+	int i, pmkid_len;
 
 	brcmf_dbg(TRACE, "Enter\n");
 	if (!check_vif_up(ifp->vif))
@@ -3454,10 +3308,11 @@
 }
 
 static s32
-brcmf_configure_wpaie(struct brcmf_if *ifp,
+brcmf_configure_wpaie(struct net_device *ndev,
 		      const struct brcmf_vs_tlv *wpa_ie,
 		      bool is_rsn_ie)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	u32 auth = 0; /* d11 open authentication */
 	u16 count;
 	s32 err = 0;
@@ -3932,7 +3787,6 @@
 	enum nl80211_iftype dev_role;
 	struct brcmf_fil_bss_enable_le bss_enable;
 	u16 chanspec;
-	bool mbss;
 
 	brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
 		  settings->chandef.chan->hw_value,
@@ -3943,7 +3797,6 @@
 		  settings->inactivity_timeout);
 
 	dev_role = ifp->vif->wdev.iftype;
-	mbss = ifp->vif->mbss;
 
 	memset(&ssid_le, 0, sizeof(ssid_le));
 	if (settings->ssid == NULL || settings->ssid_len == 0) {
@@ -3963,10 +3816,8 @@
 		ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
 	}
 
-	if (!mbss) {
-		brcmf_set_mpc(ifp, 0);
-		brcmf_configure_arp_offload(ifp, false);
-	}
+	brcmf_set_mpc(ifp, 0);
+	brcmf_configure_arp_offload(ifp, false);
 
 	/* find the RSN_IE */
 	rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
@@ -3980,16 +3831,13 @@
 		brcmf_dbg(TRACE, "WPA(2) IE is found\n");
 		if (wpa_ie != NULL) {
 			/* WPA IE */
-			err = brcmf_configure_wpaie(ifp, wpa_ie, false);
+			err = brcmf_configure_wpaie(ndev, wpa_ie, false);
 			if (err < 0)
 				goto exit;
 		} else {
-			struct brcmf_vs_tlv *tmp_ie;
-
-			tmp_ie = (struct brcmf_vs_tlv *)rsn_ie;
-
 			/* RSN IE */
-			err = brcmf_configure_wpaie(ifp, tmp_ie, true);
+			err = brcmf_configure_wpaie(ndev,
+				(struct brcmf_vs_tlv *)rsn_ie, true);
 			if (err < 0)
 				goto exit;
 		}
@@ -4000,53 +3848,45 @@
 
 	brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
 
-	if (!mbss) {
-		chanspec = chandef_to_chanspec(&cfg->d11inf,
-					       &settings->chandef);
-		err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
+	chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
+	err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
+	if (err < 0) {
+		brcmf_err("Set Channel failed: chspec=%d, %d\n", chanspec, err);
+		goto exit;
+	}
+
+	if (settings->beacon_interval) {
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
+					    settings->beacon_interval);
 		if (err < 0) {
-			brcmf_err("Set Channel failed: chspec=%d, %d\n",
-				  chanspec, err);
-			goto exit;
-		}
-
-		if (settings->beacon_interval) {
-			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
-						    settings->beacon_interval);
-			if (err < 0) {
-				brcmf_err("Beacon Interval Set Error, %d\n",
-					  err);
-				goto exit;
-			}
-		}
-		if (settings->dtim_period) {
-			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
-						    settings->dtim_period);
-			if (err < 0) {
-				brcmf_err("DTIM Interval Set Error, %d\n", err);
-				goto exit;
-			}
-		}
-
-		if (dev_role == NL80211_IFTYPE_AP) {
-			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
-			if (err < 0) {
-				brcmf_err("BRCMF_C_DOWN error %d\n", err);
-				goto exit;
-			}
-			brcmf_fil_iovar_int_set(ifp, "apsta", 0);
-		}
-
-		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
-		if (err < 0) {
-			brcmf_err("SET INFRA error %d\n", err);
+			brcmf_err("Beacon Interval Set Error, %d\n", err);
 			goto exit;
 		}
 	}
-	if (dev_role == NL80211_IFTYPE_AP) {
-		if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))
-			brcmf_fil_iovar_int_set(ifp, "mbss", 1);
+	if (settings->dtim_period) {
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
+					    settings->dtim_period);
+		if (err < 0) {
+			brcmf_err("DTIM Interval Set Error, %d\n", err);
+			goto exit;
+		}
+	}
 
+	if (dev_role == NL80211_IFTYPE_AP) {
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+		if (err < 0) {
+			brcmf_err("BRCMF_C_DOWN error %d\n", err);
+			goto exit;
+		}
+		brcmf_fil_iovar_int_set(ifp, "apsta", 0);
+	}
+
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
+	if (err < 0) {
+		brcmf_err("SET INFRA error %d\n", err);
+		goto exit;
+	}
+	if (dev_role == NL80211_IFTYPE_AP) {
 		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
 		if (err < 0) {
 			brcmf_err("setting AP mode failed %d\n", err);
@@ -4091,7 +3931,7 @@
 	set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
 
 exit:
-	if ((err) && (!mbss)) {
+	if (err) {
 		brcmf_set_mpc(ifp, 1);
 		brcmf_configure_arp_offload(ifp, true);
 	}
@@ -4112,31 +3952,20 @@
 		/* first to make sure they get processed by fw. */
 		msleep(400);
 
-		if (ifp->vif->mbss) {
-			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
-			return err;
-		}
-
 		memset(&join_params, 0, sizeof(join_params));
 		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
 					     &join_params, sizeof(join_params));
 		if (err < 0)
 			brcmf_err("SET SSID error (%d)\n", err);
-		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
 		if (err < 0)
-			brcmf_err("BRCMF_C_DOWN error %d\n", err);
+			brcmf_err("BRCMF_C_UP error %d\n", err);
 		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
 		if (err < 0)
 			brcmf_err("setting AP mode failed %d\n", err);
 		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
 		if (err < 0)
 			brcmf_err("setting INFRA mode failed %d\n", err);
-		if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
-			brcmf_fil_iovar_int_set(ifp, "mbss", 0);
-		/* Bring device back up so it can be used again */
-		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
-		if (err < 0)
-			brcmf_err("BRCMF_C_UP error %d\n", err);
 	} else {
 		bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
 		bss_enable.enable = cpu_to_le32(0);
@@ -4169,24 +3998,24 @@
 
 static int
 brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
-			   struct station_del_parameters *params)
+			   const u8 *mac)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	struct brcmf_scb_val_le scbval;
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err;
 
-	if (!params->mac)
+	if (!mac)
 		return -EFAULT;
 
-	brcmf_dbg(TRACE, "Enter %pM\n", params->mac);
+	brcmf_dbg(TRACE, "Enter %pM\n", mac);
 
 	if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
 		ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
 	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
-	memcpy(&scbval.ea, params->mac, ETH_ALEN);
+	memcpy(&scbval.ea, mac, ETH_ALEN);
 	scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
 	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
 				     &scbval, sizeof(scbval));
@@ -4488,9 +4317,7 @@
 					   enum nl80211_iftype type,
 					   bool pm_block)
 {
-	struct brcmf_cfg80211_vif *vif_walk;
 	struct brcmf_cfg80211_vif *vif;
-	bool mbss;
 
 	brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n",
 		  sizeof(*vif));
@@ -4506,17 +4333,6 @@
 
 	brcmf_init_prof(&vif->profile);
 
-	if (type == NL80211_IFTYPE_AP) {
-		mbss = false;
-		list_for_each_entry(vif_walk, &cfg->vif_list, list) {
-			if (vif_walk->wdev.iftype == NL80211_IFTYPE_AP) {
-				mbss = true;
-				break;
-			}
-		}
-		vif->mbss = mbss;
-	}
-
 	list_add_tail(&vif->list, &cfg->vif_list);
 	return vif;
 }
@@ -4759,7 +4575,6 @@
 			       struct net_device *ndev,
 			       const struct brcmf_event_msg *e, void *data)
 {
-	struct brcmf_if *ifp = netdev_priv(ndev);
 	static int generation;
 	u32 event = e->event_code;
 	u32 reason = e->reason;
@@ -4770,8 +4585,6 @@
 	    ndev != cfg_to_ndev(cfg)) {
 		brcmf_dbg(CONN, "AP mode link down\n");
 		complete(&cfg->vif_disabled);
-		if (ifp->vif->mbss)
-			brcmf_remove_interface(ifp->drvr, ifp->bssidx);
 		return 0;
 	}
 
@@ -5563,28 +5376,7 @@
 	return 0;
 }
 
-static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = {
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_STATION) |
-			 BIT(NL80211_IFTYPE_ADHOC)
-	},
-	{
-		.max = 4,
-		.types = BIT(NL80211_IFTYPE_AP)
-	},
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
-			 BIT(NL80211_IFTYPE_P2P_GO)
-	},
-	{
-		.max = 1,
-		.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
-	}
-};
-
-static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = {
+static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
 	{
 		.max = 2,
 		.types = BIT(NL80211_IFTYPE_STATION) |
@@ -5605,8 +5397,8 @@
 	{
 		 .max_interfaces = BRCMF_IFACE_MAX_CNT,
 		 .num_different_channels = 1,
-		 .n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss),
-		 .limits = brcmf_iface_limits_sbss,
+		 .n_limits = ARRAY_SIZE(brcmf_iface_limits),
+		 .limits = brcmf_iface_limits
 	}
 };
 
@@ -5648,13 +5440,10 @@
 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
 }
 
+
 #ifdef CONFIG_PM
 static const struct wiphy_wowlan_support brcmf_wowlan_support = {
 	.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
-	.n_patterns = BRCMF_WOWL_MAXPATTERNS,
-	.pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE,
-	.pattern_min_len = 1,
-	.max_pkt_offset = 1500,
 };
 #endif
 
@@ -5682,10 +5471,6 @@
 	ifc_combo = brcmf_iface_combos[0];
 	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
 		ifc_combo.num_different_channels = 2;
-	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
-		ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss),
-		ifc_combo.limits = brcmf_iface_limits_mbss;
-	}
 	wiphy->iface_combinations = kmemdup(&ifc_combo,
 					    sizeof(ifc_combo),
 					    GFP_KERNEL);
@@ -5822,8 +5607,7 @@
 	return wdev->iftype;
 }
 
-bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,
-			     unsigned long state)
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state)
 {
 	struct brcmf_cfg80211_vif *vif;
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
similarity index 98%
rename from drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
rename to drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 9e98b8d..6abf94e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -14,8 +14,8 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef BRCMFMAC_CFG80211_H
-#define BRCMFMAC_CFG80211_H
+#ifndef _wl_cfg80211_h_
+#define _wl_cfg80211_h_
 
 /* for brcmu_d11inf */
 #include <brcmu_d11.h>
@@ -183,7 +183,6 @@
  * @pm_block: power-management blocked.
  * @list: linked list.
  * @mgmt_rx_reg: registered rx mgmt frame types.
- * @mbss: Multiple BSS type, set if not first AP (not relevant for P2P).
  */
 struct brcmf_cfg80211_vif {
 	struct brcmf_if *ifp;
@@ -195,7 +194,6 @@
 	struct vif_saved_ie saved_ie;
 	struct list_head list;
 	u16 mgmt_rx_reg;
-	bool mbss;
 };
 
 /* association inform */
@@ -482,8 +480,7 @@
 brcmf_parse_tlvs(const void *buf, int buflen, uint key);
 u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
 			struct ieee80211_channel *ch);
-bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,
-			     unsigned long state);
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state);
 void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
 				  struct brcmf_cfg80211_vif *vif);
 bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
@@ -496,4 +493,4 @@
 void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
 void brcmf_cfg80211_free_netdev(struct net_device *ndev);
 
-#endif /* BRCMFMAC_CFG80211_H */
+#endif				/* _wl_cfg80211_h_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
index d382d94..323c9de 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
@@ -30,7 +30,6 @@
 #include "main.h"
 #include "debug.h"
 #include "brcms_trace_events.h"
-#include "phy/phy_int.h"
 
 static struct dentry *root_folder;
 
@@ -72,161 +71,48 @@
 }
 
 static
-int brcms_debugfs_hardware_read(struct seq_file *s, void *data)
+ssize_t brcms_debugfs_hardware_read(struct file *f, char __user *data,
+					size_t count, loff_t *ppos)
 {
-	struct brcms_pub *drvr = s->private;
-	struct brcms_hardware *hw = drvr->wlc->hw;
-	struct bcma_device *core = hw->d11core;
-	struct bcma_bus *bus = core->bus;
-	char boardrev[10];
+	char buf[128];
+	int res;
+	struct brcms_pub *drvr = f->private_data;
 
-	seq_printf(s, "chipnum 0x%x\n"
-		   "chiprev 0x%x\n"
-		   "chippackage 0x%x\n"
-		   "corerev 0x%x\n"
-		   "boardid 0x%x\n"
-		   "boardvendor 0x%x\n"
-		   "boardrev %s\n"
-		   "boardflags 0x%x\n"
-		   "boardflags2 0x%x\n"
-		   "ucoderev 0x%x\n"
-		   "radiorev 0x%x\n"
-		   "phytype 0x%x\n"
-		   "phyrev 0x%x\n"
-		   "anarev 0x%x\n"
-		   "nvramrev %d\n",
-		   bus->chipinfo.id, bus->chipinfo.rev, bus->chipinfo.pkg,
-		   core->id.rev, bus->boardinfo.type, bus->boardinfo.vendor,
-		   brcmu_boardrev_str(hw->boardrev, boardrev),
-		   drvr->wlc->hw->boardflags, drvr->wlc->hw->boardflags2,
-		   drvr->wlc->ucode_rev, hw->band->radiorev,
-		   hw->band->phytype, hw->band->phyrev, hw->band->pi->ana_rev,
-		   hw->sromrev);
-	return 0;
+	/* only allow read from start */
+	if (*ppos > 0)
+		return 0;
+
+	res = scnprintf(buf, sizeof(buf),
+		"board vendor: %x\n"
+		"board type: %x\n"
+		"board revision: %x\n"
+		"board flags: %x\n"
+		"board flags2: %x\n"
+		"firmware revision: %x\n",
+		drvr->wlc->hw->d11core->bus->boardinfo.vendor,
+		drvr->wlc->hw->d11core->bus->boardinfo.type,
+		drvr->wlc->hw->boardrev,
+		drvr->wlc->hw->boardflags,
+		drvr->wlc->hw->boardflags2,
+		drvr->wlc->ucode_rev
+		);
+
+	return simple_read_from_buffer(data, count, ppos, buf, res);
 }
 
-static int brcms_debugfs_macstat_read(struct seq_file *s, void *data)
-{
-	struct brcms_pub *drvr = s->private;
-	struct brcms_info *wl = drvr->ieee_hw->priv;
-	struct macstat stats;
-	int i;
-
-	spin_lock_bh(&wl->lock);
-	stats = *(drvr->wlc->core->macstat_snapshot);
-	spin_unlock_bh(&wl->lock);
-
-	seq_printf(s, "txallfrm: %d\n", stats.txallfrm);
-	seq_printf(s, "txrtsfrm: %d\n", stats.txrtsfrm);
-	seq_printf(s, "txctsfrm: %d\n", stats.txctsfrm);
-	seq_printf(s, "txackfrm: %d\n", stats.txackfrm);
-	seq_printf(s, "txdnlfrm: %d\n", stats.txdnlfrm);
-	seq_printf(s, "txbcnfrm: %d\n", stats.txbcnfrm);
-	seq_printf(s, "txfunfl[8]:");
-	for (i = 0; i < ARRAY_SIZE(stats.txfunfl); i++)
-		seq_printf(s, " %d", stats.txfunfl[i]);
-	seq_printf(s, "\ntxtplunfl: %d\n", stats.txtplunfl);
-	seq_printf(s, "txphyerr: %d\n", stats.txphyerr);
-	seq_printf(s, "pktengrxducast: %d\n", stats.pktengrxducast);
-	seq_printf(s, "pktengrxdmcast: %d\n", stats.pktengrxdmcast);
-	seq_printf(s, "rxfrmtoolong: %d\n", stats.rxfrmtoolong);
-	seq_printf(s, "rxfrmtooshrt: %d\n", stats.rxfrmtooshrt);
-	seq_printf(s, "rxinvmachdr: %d\n", stats.rxinvmachdr);
-	seq_printf(s, "rxbadfcs: %d\n", stats.rxbadfcs);
-	seq_printf(s, "rxbadplcp: %d\n", stats.rxbadplcp);
-	seq_printf(s, "rxcrsglitch: %d\n", stats.rxcrsglitch);
-	seq_printf(s, "rxstrt: %d\n", stats.rxstrt);
-	seq_printf(s, "rxdfrmucastmbss: %d\n", stats.rxdfrmucastmbss);
-	seq_printf(s, "rxmfrmucastmbss: %d\n", stats.rxmfrmucastmbss);
-	seq_printf(s, "rxcfrmucast: %d\n", stats.rxcfrmucast);
-	seq_printf(s, "rxrtsucast: %d\n", stats.rxrtsucast);
-	seq_printf(s, "rxctsucast: %d\n", stats.rxctsucast);
-	seq_printf(s, "rxackucast: %d\n", stats.rxackucast);
-	seq_printf(s, "rxdfrmocast: %d\n", stats.rxdfrmocast);
-	seq_printf(s, "rxmfrmocast: %d\n", stats.rxmfrmocast);
-	seq_printf(s, "rxcfrmocast: %d\n", stats.rxcfrmocast);
-	seq_printf(s, "rxrtsocast: %d\n", stats.rxrtsocast);
-	seq_printf(s, "rxctsocast: %d\n", stats.rxctsocast);
-	seq_printf(s, "rxdfrmmcast: %d\n", stats.rxdfrmmcast);
-	seq_printf(s, "rxmfrmmcast: %d\n", stats.rxmfrmmcast);
-	seq_printf(s, "rxcfrmmcast: %d\n", stats.rxcfrmmcast);
-	seq_printf(s, "rxbeaconmbss: %d\n", stats.rxbeaconmbss);
-	seq_printf(s, "rxdfrmucastobss: %d\n", stats.rxdfrmucastobss);
-	seq_printf(s, "rxbeaconobss: %d\n", stats.rxbeaconobss);
-	seq_printf(s, "rxrsptmout: %d\n", stats.rxrsptmout);
-	seq_printf(s, "bcntxcancl: %d\n", stats.bcntxcancl);
-	seq_printf(s, "rxf0ovfl: %d\n", stats.rxf0ovfl);
-	seq_printf(s, "rxf1ovfl: %d\n", stats.rxf1ovfl);
-	seq_printf(s, "rxf2ovfl: %d\n", stats.rxf2ovfl);
-	seq_printf(s, "txsfovfl: %d\n", stats.txsfovfl);
-	seq_printf(s, "pmqovfl: %d\n", stats.pmqovfl);
-	seq_printf(s, "rxcgprqfrm: %d\n", stats.rxcgprqfrm);
-	seq_printf(s, "rxcgprsqovfl: %d\n", stats.rxcgprsqovfl);
-	seq_printf(s, "txcgprsfail: %d\n", stats.txcgprsfail);
-	seq_printf(s, "txcgprssuc: %d\n", stats.txcgprssuc);
-	seq_printf(s, "prs_timeout: %d\n", stats.prs_timeout);
-	seq_printf(s, "rxnack: %d\n", stats.rxnack);
-	seq_printf(s, "frmscons: %d\n", stats.frmscons);
-	seq_printf(s, "txnack: %d\n", stats.txnack);
-	seq_printf(s, "txglitch_nack: %d\n", stats.txglitch_nack);
-	seq_printf(s, "txburst: %d\n", stats.txburst);
-	seq_printf(s, "bphy_rxcrsglitch: %d\n", stats.bphy_rxcrsglitch);
-	seq_printf(s, "phywatchdog: %d\n", stats.phywatchdog);
-	seq_printf(s, "bphy_badplcp: %d\n", stats.bphy_badplcp);
-	return 0;
-}
-
-struct brcms_debugfs_entry {
-	int (*read)(struct seq_file *seq, void *data);
-	struct brcms_pub *drvr;
-};
-
-static int brcms_debugfs_entry_open(struct inode *inode, struct file *f)
-{
-	struct brcms_debugfs_entry *entry = inode->i_private;
-
-	return single_open(f, entry->read, entry->drvr);
-}
-
-static const struct file_operations brcms_debugfs_def_ops = {
+static const struct file_operations brcms_debugfs_hardware_ops = {
 	.owner = THIS_MODULE,
-	.open = brcms_debugfs_entry_open,
-	.release = single_release,
-	.read = seq_read,
-	.llseek = seq_lseek
+	.open = simple_open,
+	.read = brcms_debugfs_hardware_read
 };
 
-static int
-brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn,
-			int (*read_fn)(struct seq_file *seq, void *data))
-{
-	struct device *dev = &drvr->wlc->hw->d11core->dev;
-	struct dentry *dentry =  drvr->dbgfs_dir;
-	struct brcms_debugfs_entry *entry;
-
-	if (IS_ERR_OR_NULL(dentry))
-		return -ENOENT;
-
-	entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
-	if (!entry)
-		return -ENOMEM;
-
-	entry->read = read_fn;
-	entry->drvr = drvr;
-
-	dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
-				     &brcms_debugfs_def_ops);
-
-	return PTR_ERR_OR_ZERO(dentry);
-}
-
 void brcms_debugfs_create_files(struct brcms_pub *drvr)
 {
-	if (IS_ERR_OR_NULL(drvr->dbgfs_dir))
-		return;
+	struct dentry *dentry = drvr->dbgfs_dir;
 
-	brcms_debugfs_add_entry(drvr, "hardware", brcms_debugfs_hardware_read);
-	brcms_debugfs_add_entry(drvr, "macstat", brcms_debugfs_macstat_read);
+	if (!IS_ERR_OR_NULL(dentry))
+		debugfs_create_file("hardware", S_IRUGO, dentry,
+				    drvr, &brcms_debugfs_hardware_ops);
 }
 
 #define __brcms_fn(fn)						\
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index ac50a21..b6f5f95 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -764,9 +764,7 @@
 	return;
 }
 
-static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    const u8 *mac_addr)
+static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct brcms_info *wl = hw->priv;
 	spin_lock_bh(&wl->lock);
@@ -775,8 +773,7 @@
 	return;
 }
 
-static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif)
+static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct brcms_info *wl = hw->priv;
 	spin_lock_bh(&wl->lock);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index eb8584a..1b47482 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -316,7 +316,7 @@
 static const char * const fifo_names[] = {
 	"AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
 #else
-static const char fifo_names[6][1];
+static const char fifo_names[6][0];
 #endif
 
 #ifdef DEBUG
@@ -445,18 +445,18 @@
 	kfree(wlc->protection);
 	kfree(wlc->stf);
 	kfree(wlc->bandstate[0]);
-	if (wlc->corestate)
-		kfree(wlc->corestate->macstat_snapshot);
+	kfree(wlc->corestate->macstat_snapshot);
 	kfree(wlc->corestate);
-	if (wlc->hw)
-		kfree(wlc->hw->bandstate[0]);
+	kfree(wlc->hw->bandstate[0]);
 	kfree(wlc->hw);
 	if (wlc->beacon)
 		dev_kfree_skb_any(wlc->beacon);
 	if (wlc->probe_resp)
 		dev_kfree_skb_any(wlc->probe_resp);
 
+	/* free the wlc */
 	kfree(wlc);
+	wlc = NULL;
 }
 
 static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
@@ -1009,7 +1009,8 @@
 		if (txh)
 			trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
 					   sizeof(*txh));
-		brcmu_pkt_buf_free_skb(p);
+		if (p)
+			brcmu_pkt_buf_free_skb(p);
 	}
 
 	if (dma && queue < NFIFO) {
@@ -3080,7 +3081,7 @@
 static void brcms_c_statsupd(struct brcms_c_info *wlc)
 {
 	int i;
-	struct macstat *macstats;
+	struct macstat macstats;
 #ifdef DEBUG
 	u16 delta;
 	u16 rxf0ovfl;
@@ -3091,31 +3092,31 @@
 	if (!wlc->pub->up)
 		return;
 
-	macstats = wlc->core->macstat_snapshot;
-
 #ifdef DEBUG
 	/* save last rx fifo 0 overflow count */
-	rxf0ovfl = macstats->rxf0ovfl;
+	rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
 
 	/* save last tx fifo  underflow count */
 	for (i = 0; i < NFIFO; i++)
-		txfunfl[i] = macstats->txfunfl[i];
+		txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
 #endif				/* DEBUG */
 
 	/* Read mac stats from contiguous shared memory */
-	brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, macstats,
-				sizeof(*macstats), OBJADDR_SHM_SEL);
+	brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats,
+				sizeof(struct macstat), OBJADDR_SHM_SEL);
 
 #ifdef DEBUG
 	/* check for rx fifo 0 overflow */
-	delta = (u16)(macstats->rxf0ovfl - rxf0ovfl);
+	delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
 	if (delta)
 		brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n",
 			  wlc->pub->unit, delta);
 
 	/* check for tx fifo underflows */
 	for (i = 0; i < NFIFO; i++) {
-		delta = macstats->txfunfl[i] - txfunfl[i];
+		delta =
+		    (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
+			      txfunfl[i]);
 		if (delta)
 			brcms_err(wlc->hw->d11core,
 				  "wl%d: %u tx fifo %d underflows!\n",
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index 906e89d..0f7e1c7 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -261,21 +261,6 @@
 }
 EXPORT_SYMBOL(brcmu_pktq_mdeq);
 
-/* Produce a human-readable string for boardrev */
-char *brcmu_boardrev_str(u32 brev, char *buf)
-{
-	char c;
-
-	if (brev < 0x100) {
-		snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
-	} else {
-		c = (brev & 0xf000) == 0x1000 ? 'P' : 'A';
-		snprintf(buf, 8, "%c%03x", c, brev & 0xfff);
-	}
-	return buf;
-}
-EXPORT_SYMBOL(brcmu_boardrev_str);
-
 #if defined(DEBUG)
 /* pretty hex print a pkt buffer chain */
 void brcmu_prpkt(const char *msg, struct sk_buff *p0)
@@ -307,5 +292,4 @@
 	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data, size);
 }
 EXPORT_SYMBOL(brcmu_dbg_hex_dump);
-
 #endif				/* defined(DEBUG) */
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index 6996fcc..af26e0d 100644
--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
@@ -68,8 +68,6 @@
 #define BRCM_PCIE_43567_DEVICE_ID	0x43d3
 #define BRCM_PCIE_43570_DEVICE_ID	0x43d9
 #define BRCM_PCIE_43602_DEVICE_ID	0x43ba
-#define BRCM_PCIE_43602_2G_DEVICE_ID	0x43bb
-#define BRCM_PCIE_43602_5G_DEVICE_ID	0x43bc
 
 /* brcmsmac IDs */
 #define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index a043e29..8ba445b 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -218,6 +218,4 @@
 }
 #endif
 
-char *brcmu_boardrev_str(u32 brev, char *buf);
-
 #endif				/* _BRCMU_UTILS_H_ */
diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c
index f2e276f..b2fb6c6 100644
--- a/drivers/net/wireless/cw1200/scan.c
+++ b/drivers/net/wireless/cw1200/scan.c
@@ -78,7 +78,7 @@
 	if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
 		return -EINVAL;
 
-	frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
+	frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0,
 		req->ie_len);
 	if (!frame.skb)
 		return -ENOMEM;
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index d46df94..c2b7368 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -1363,7 +1363,7 @@
 	if (!priv->cmdlog)
 		return 0;
 	for (i = (priv->cmdlog_pos + 1) % priv->cmdlog_len;
-	     (i != priv->cmdlog_pos) && (len < PAGE_SIZE);
+	     (i != priv->cmdlog_pos) && (PAGE_SIZE - len);
 	     i = (i + 1) % priv->cmdlog_len) {
 		len +=
 		    snprintf(buf + len, PAGE_SIZE - len,
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index fe9e438..e1fccda 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -654,6 +654,10 @@
 	/* TPC Report - mandatory if spctrm mgmt required */
 	struct libipw_tpc_report tpc_report;
 
+	/* IBSS DFS - mandatory if spctrm mgmt required and IBSS
+	 * NOTE: This is variable length and so must be allocated dynamically */
+	struct libipw_ibss_dfs *ibss_dfs;
+
 	/* Channel Switch Announcement - optional if spctrm mgmt required */
 	struct libipw_csa csa;
 
@@ -966,6 +970,7 @@
 /* make sure to set stats->len */
 void libipw_rx_mgt(struct libipw_device *ieee, struct libipw_hdr_4addr *header,
 		   struct libipw_rx_stats *stats);
+void libipw_network_reset(struct libipw_network *network);
 
 /* libipw_geo.c */
 const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee);
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
index 1d1a28a..92a935f 100644
--- a/drivers/net/wireless/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -84,12 +84,25 @@
 	return 0;
 }
 
+void libipw_network_reset(struct libipw_network *network)
+{
+	if (!network)
+		return;
+
+	if (network->ibss_dfs) {
+		kfree(network->ibss_dfs);
+		network->ibss_dfs = NULL;
+	}
+}
+
 static inline void libipw_networks_free(struct libipw_device *ieee)
 {
 	int i;
 
-	for (i = 0; i < MAX_NETWORK_COUNT; i++)
+	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
+		kfree(ieee->networks[i]->ibss_dfs);
 		kfree(ieee->networks[i]);
+	}
 }
 
 void libipw_networks_age(struct libipw_device *ieee,
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index 3e4d83c..651a1ee 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -1298,6 +1298,13 @@
 			break;
 
 		case WLAN_EID_IBSS_DFS:
+			if (network->ibss_dfs)
+				break;
+			network->ibss_dfs = kmemdup(info_element->data,
+						    info_element->len,
+						    GFP_ATOMIC);
+			if (!network->ibss_dfs)
+				return 1;
 			network->flags |= NETWORK_HAS_IBSS_DFS;
 			break;
 
@@ -1328,7 +1335,9 @@
 static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_assoc_response
 				       *frame, struct libipw_rx_stats *stats)
 {
-	struct libipw_network network_resp = { };
+	struct libipw_network network_resp = {
+		.ibss_dfs = NULL,
+	};
 	struct libipw_network *network = &network_resp;
 	struct net_device *dev = ieee->dev;
 
@@ -1463,6 +1472,9 @@
 	int qos_active;
 	u8 old_param;
 
+	libipw_network_reset(dst);
+	dst->ibss_dfs = src->ibss_dfs;
+
 	/* We only update the statistics if they were created by receiving
 	 * the network information on the actual channel the network is on.
 	 *
@@ -1536,7 +1548,9 @@
 						    *stats)
 {
 	struct net_device *dev = ieee->dev;
-	struct libipw_network network = { };
+	struct libipw_network network = {
+		.ibss_dfs = NULL,
+	};
 	struct libipw_network *target;
 	struct libipw_network *oldest = NULL;
 #ifdef CPTCFG_LIBIPW_DEBUG
@@ -1604,6 +1618,7 @@
 			LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n",
 					  target->ssid_len, target->ssid,
 					  target->bssid);
+			libipw_network_reset(target);
 		} else {
 			/* Otherwise just pull from the free list */
 			target = list_entry(ieee->network_free_list.next,
@@ -1619,6 +1634,7 @@
 				  "BEACON" : "PROBE RESPONSE");
 #endif
 		memcpy(target, &network, sizeof(*target));
+		network.ibss_dfs = NULL;
 		list_add_tail(&target->list, &ieee->network_list);
 	} else {
 		LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n",
@@ -1627,6 +1643,7 @@
 				  is_beacon(beacon->header.frame_ctl) ?
 				  "BEACON" : "PROBE RESPONSE");
 		update_network(target, &network);
+		network.ibss_dfs = NULL;
 	}
 
 	spin_unlock_irqrestore(&ieee->lock, flags);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index cb90853..6c9cbb8 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -6063,7 +6063,7 @@
 }
 
 void
-il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+il4965_mac_channel_switch(struct ieee80211_hw *hw,
 			  struct ieee80211_channel_switch *ch_switch)
 {
 	struct il_priv *il = hw->priv;
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
index db04ecf..a96696e 100644
--- a/drivers/net/wireless/iwlegacy/4965.h
+++ b/drivers/net/wireless/iwlegacy/4965.h
@@ -187,9 +187,8 @@
 			    u8 buf_size);
 int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
-void
-il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			  struct ieee80211_channel_switch *ch_switch);
+void il4965_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch);
 
 void il4965_led_enable(struct il_priv *il);
 
diff --git a/drivers/net/wireless/iwlegacy/Kconfig b/drivers/net/wireless/iwlegacy/Kconfig
index cdc6baf..05d8fc7 100644
--- a/drivers/net/wireless/iwlegacy/Kconfig
+++ b/drivers/net/wireless/iwlegacy/Kconfig
@@ -2,9 +2,9 @@
 	tristate
 	depends on m
 	depends on FW_LOADER
-	select BPAUTO_NEW_LEDS
-	select BPAUTO_LEDS_CLASS
-	select BPAUTO_LEDS_TRIGGERS
+	select BACKPORT_NEW_LEDS
+	select BACKPORT_LEDS_CLASS
+	select BACKPORT_LEDS_TRIGGERS
 	select MAC80211_LEDS
 
 config IWL4965
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 63f153b..3721c07 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -46,7 +46,7 @@
 config IWLWIFI_LEDS
 	bool
 	depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
-	select BPAUTO_LEDS_TRIGGERS
+	select BACKPORT_LEDS_TRIGGERS
 	select MAC80211_LEDS
 	default y
 
@@ -62,7 +62,6 @@
 config IWLMVM
 	tristate "Intel Wireless WiFi MVM Firmware support"
 	depends on m
-	select BPAUTO_WANT_DEV_COREDUMP
 	help
 	  This is the driver that supports the MVM firmware which is
 	  currently only available for 7260 and 3160 devices.
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h
index 7a34e4d..751ae1d 100644
--- a/drivers/net/wireless/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
@@ -966,21 +966,21 @@
 
 
 /* WiFi queues mask */
-#define IWL_SCD_BK_MSK			BIT(0)
-#define IWL_SCD_BE_MSK			BIT(1)
-#define IWL_SCD_VI_MSK			BIT(2)
-#define IWL_SCD_VO_MSK			BIT(3)
-#define IWL_SCD_MGMT_MSK		BIT(3)
+#define IWL_SCD_BK_MSK			cpu_to_le32(BIT(0))
+#define IWL_SCD_BE_MSK			cpu_to_le32(BIT(1))
+#define IWL_SCD_VI_MSK			cpu_to_le32(BIT(2))
+#define IWL_SCD_VO_MSK			cpu_to_le32(BIT(3))
+#define IWL_SCD_MGMT_MSK		cpu_to_le32(BIT(3))
 
 /* PAN queues mask */
-#define IWL_PAN_SCD_BK_MSK		BIT(4)
-#define IWL_PAN_SCD_BE_MSK		BIT(5)
-#define IWL_PAN_SCD_VI_MSK		BIT(6)
-#define IWL_PAN_SCD_VO_MSK		BIT(7)
-#define IWL_PAN_SCD_MGMT_MSK		BIT(7)
-#define IWL_PAN_SCD_MULTICAST_MSK	BIT(8)
+#define IWL_PAN_SCD_BK_MSK		cpu_to_le32(BIT(4))
+#define IWL_PAN_SCD_BE_MSK		cpu_to_le32(BIT(5))
+#define IWL_PAN_SCD_VI_MSK		cpu_to_le32(BIT(6))
+#define IWL_PAN_SCD_VO_MSK		cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MGMT_MSK		cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MULTICAST_MSK	cpu_to_le32(BIT(8))
 
-#define IWL_AGG_TX_QUEUE_MSK		0xffc00
+#define IWL_AGG_TX_QUEUE_MSK		cpu_to_le32(0xffc00)
 
 #define IWL_DROP_ALL			BIT(1)
 
@@ -1005,17 +1005,12 @@
  *	1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable.
  *	2: Dump all FIFO
  */
-struct iwl_txfifo_flush_cmd_v3 {
+struct iwl_txfifo_flush_cmd {
 	__le32 queue_control;
 	__le16 flush_control;
 	__le16 reserved;
 } __packed;
 
-struct iwl_txfifo_flush_cmd_v2 {
-	__le16 queue_control;
-	__le16 flush_control;
-} __packed;
-
 /*
  * REPLY_WEP_KEY = 0x20
  */
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index 1d2223d..2191621 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -137,38 +137,37 @@
  */
 int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
 {
-	struct iwl_txfifo_flush_cmd_v3 flush_cmd_v3 = {
-		.flush_control = cpu_to_le16(IWL_DROP_ALL),
-	};
-	struct iwl_txfifo_flush_cmd_v2 flush_cmd_v2 = {
-		.flush_control = cpu_to_le16(IWL_DROP_ALL),
+	struct iwl_txfifo_flush_cmd flush_cmd;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_TXFIFO_FLUSH,
+		.len = { sizeof(struct iwl_txfifo_flush_cmd), },
+		.data = { &flush_cmd, },
 	};
 
-	u32 queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
-			    IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | IWL_SCD_MGMT_MSK;
+	memset(&flush_cmd, 0, sizeof(flush_cmd));
 
+	flush_cmd.queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
+				  IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
+				  IWL_SCD_MGMT_MSK;
 	if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
-		queue_control |= IWL_PAN_SCD_VO_MSK | IWL_PAN_SCD_VI_MSK |
-				 IWL_PAN_SCD_BE_MSK | IWL_PAN_SCD_BK_MSK |
-				 IWL_PAN_SCD_MGMT_MSK |
-				 IWL_PAN_SCD_MULTICAST_MSK;
+		flush_cmd.queue_control |= IWL_PAN_SCD_VO_MSK |
+					   IWL_PAN_SCD_VI_MSK |
+					   IWL_PAN_SCD_BE_MSK |
+					   IWL_PAN_SCD_BK_MSK |
+					   IWL_PAN_SCD_MGMT_MSK |
+					   IWL_PAN_SCD_MULTICAST_MSK;
 
 	if (priv->nvm_data->sku_cap_11n_enable)
-		queue_control |= IWL_AGG_TX_QUEUE_MSK;
+		flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK;
 
 	if (scd_q_msk)
-		queue_control = scd_q_msk;
+		flush_cmd.queue_control = cpu_to_le32(scd_q_msk);
 
-	IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", queue_control);
-	flush_cmd_v3.queue_control = cpu_to_le32(queue_control);
-	flush_cmd_v2.queue_control = cpu_to_le16((u16)queue_control);
+	IWL_DEBUG_INFO(priv, "queue control: 0x%x\n",
+		       flush_cmd.queue_control);
+	flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL);
 
-	if (IWL_UCODE_API(priv->fw->ucode_ver) > 2)
-		return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
-					    sizeof(flush_cmd_v3),
-					    &flush_cmd_v3);
-	return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
-				    sizeof(flush_cmd_v2), &flush_cmd_v2);
+	return iwl_dvm_send_cmd(priv, &cmd);
 }
 
 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
@@ -419,8 +418,8 @@
 
 static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
 {
-	return (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
-		BT_UART_MSG_FRAME3SCOESCO_POS;
+	return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >>
+			BT_UART_MSG_FRAME3SCOESCO_POS;
 }
 
 static void iwlagn_bt_traffic_change_work(struct work_struct *work)
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index dfa0626..d8ebc7e 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -941,7 +941,6 @@
 }
 
 static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
-				      struct ieee80211_vif *vif,
 				      struct ieee80211_channel_switch *ch_switch)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -1096,7 +1095,6 @@
 			     u32 queues, bool drop)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
-	u32 scd_queues;
 
 	mutex_lock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -1110,19 +1108,18 @@
 		goto done;
 	}
 
-	scd_queues = BIT(priv->cfg->base_params->num_of_queues) - 1;
-	scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) |
-			BIT(IWL_DEFAULT_CMD_QUEUE_NUM));
-
-	if (vif)
-		scd_queues &= ~BIT(vif->hw_queue[IEEE80211_AC_VO]);
-
-	IWL_DEBUG_TX_QUEUES(priv, "Flushing SCD queues: 0x%x\n", scd_queues);
-	if (iwlagn_txfifo_flush(priv, scd_queues)) {
-		IWL_ERR(priv, "flush request fail\n");
-		goto done;
+	/*
+	 * mac80211 will not push any more frames for transmit
+	 * until the flush is completed
+	 */
+	if (drop) {
+		IWL_DEBUG_MAC80211(priv, "send flush command\n");
+		if (iwlagn_txfifo_flush(priv, 0)) {
+			IWL_ERR(priv, "flush request fail\n");
+			goto done;
+		}
 	}
-	IWL_DEBUG_TX_QUEUES(priv, "wait transmit/flush all frames\n");
+	IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
 	iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff);
 done:
 	mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index e5be2d2..b04b885 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -73,12 +73,12 @@
 #define IWL3160_UCODE_API_MAX	10
 
 /* Oldest version we won't warn about */
-#define IWL7260_UCODE_API_OK	10
-#define IWL3160_UCODE_API_OK	10
+#define IWL7260_UCODE_API_OK	9
+#define IWL3160_UCODE_API_OK	9
 
 /* Lowest firmware API version supported */
-#define IWL7260_UCODE_API_MIN	9
-#define IWL3160_UCODE_API_MIN	9
+#define IWL7260_UCODE_API_MIN	8
+#define IWL3160_UCODE_API_MIN	8
 
 /* NVM versions */
 #define IWL7260_NVM_VERSION		0x0a1d
@@ -89,8 +89,6 @@
 #define IWL3165_TX_POWER_VERSION	0xffff /* meaningless */
 #define IWL7265_NVM_VERSION		0x0a1d
 #define IWL7265_TX_POWER_VERSION	0xffff /* meaningless */
-#define IWL7265D_NVM_VERSION		0x0c11
-#define IWL7265_TX_POWER_VERSION	0xffff /* meaningless */
 
 #define IWL7260_FW_PRE "iwlwifi-7260-"
 #define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
@@ -104,9 +102,6 @@
 #define IWL7265_FW_PRE "iwlwifi-7265-"
 #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
 
-#define IWL7265D_FW_PRE "iwlwifi-7265D-"
-#define IWL7265D_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
-
 #define NVM_HW_SECTION_NUM_FAMILY_7000		0
 
 static const struct iwl_base_params iwl7000_base_params = {
@@ -137,8 +132,8 @@
 	.base_params = &iwl7000_base_params,			\
 	.led_mode = IWL_LED_RF_STATE,				\
 	.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000,	\
-	.non_shared_ant = ANT_A,				\
-	.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
+	.non_shared_ant = ANT_A
+
 
 const struct iwl_cfg iwl7260_2ac_cfg = {
 	.name = "Intel(R) Dual Band Wireless AC 7260",
@@ -272,38 +267,7 @@
 	.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
 };
 
-const struct iwl_cfg iwl7265d_2ac_cfg = {
-	.name = "Intel(R) Dual Band Wireless AC 7265",
-	.fw_name_pre = IWL7265D_FW_PRE,
-	IWL_DEVICE_7000,
-	.ht_params = &iwl7265_ht_params,
-	.nvm_ver = IWL7265D_NVM_VERSION,
-	.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
-	.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
-};
-
-const struct iwl_cfg iwl7265d_2n_cfg = {
-	.name = "Intel(R) Dual Band Wireless N 7265",
-	.fw_name_pre = IWL7265D_FW_PRE,
-	IWL_DEVICE_7000,
-	.ht_params = &iwl7265_ht_params,
-	.nvm_ver = IWL7265D_NVM_VERSION,
-	.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
-	.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
-};
-
-const struct iwl_cfg iwl7265d_n_cfg = {
-	.name = "Intel(R) Wireless N 7265",
-	.fw_name_pre = IWL7265D_FW_PRE,
-	IWL_DEVICE_7000,
-	.ht_params = &iwl7265_ht_params,
-	.nvm_ver = IWL7265D_NVM_VERSION,
-	.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
-	.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
-};
-
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
 MODULE_FIRMWARE(IWL3165_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
 MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index bf0a95c..e435148 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -72,18 +72,17 @@
 #define IWL8000_UCODE_API_MAX	10
 
 /* Oldest version we won't warn about */
-#define IWL8000_UCODE_API_OK	10
+#define IWL8000_UCODE_API_OK	8
 
 /* Lowest firmware API version supported */
-#define IWL8000_UCODE_API_MIN	9
+#define IWL8000_UCODE_API_MIN	8
 
 /* NVM versions */
 #define IWL8000_NVM_VERSION		0x0a1d
 #define IWL8000_TX_POWER_VERSION	0xffff /* meaningless */
 
 #define IWL8000_FW_PRE "iwlwifi-8000"
-#define IWL8000_MODULE_FIRMWARE(api) \
-	IWL8000_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode"
 
 #define NVM_HW_SECTION_NUM_FAMILY_8000		10
 #define DEFAULT_NVM_FILE_FAMILY_8000		"iwl_nvm_8000.bin"
@@ -91,10 +90,6 @@
 /* Max SDIO RX aggregation size of the ADDBA request/response */
 #define MAX_RX_AGG_SIZE_8260_SDIO	28
 
-/* Max A-MPDU exponent for HT and VHT */
-#define MAX_HT_AMPDU_EXPONENT_8260_SDIO	IEEE80211_HT_MAX_AMPDU_32K
-#define MAX_VHT_AMPDU_EXPONENT_8260_SDIO	IEEE80211_VHT_MAX_AMPDU_32K
-
 static const struct iwl_base_params iwl8000_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
@@ -108,7 +103,6 @@
 };
 
 static const struct iwl_ht_params iwl8000_ht_params = {
-	.stbc = true,
 	.ldpc = true,
 	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
 };
@@ -123,7 +117,6 @@
 	.base_params = &iwl8000_base_params,			\
 	.led_mode = IWL_LED_RF_STATE,				\
 	.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000,	\
-	.d0i3 = true,						\
 	.non_shared_ant = ANT_A
 
 const struct iwl_cfg iwl8260_2n_cfg = {
@@ -142,7 +135,6 @@
 	.ht_params = &iwl8000_ht_params,
 	.nvm_ver = IWL8000_NVM_VERSION,
 	.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
-	.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
 };
 
 const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
@@ -155,23 +147,6 @@
 	.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
 	.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
 	.disable_dummy_notification = true,
-	.max_ht_ampdu_exponent  = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
-	.max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO,
-};
-
-const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
-	.name = "Intel(R) Dual Band Wireless-AC 4165",
-	.fw_name_pre = IWL8000_FW_PRE,
-	IWL_DEVICE_8000,
-	.ht_params = &iwl8000_ht_params,
-	.nvm_ver = IWL8000_NVM_VERSION,
-	.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
-	.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
-	.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
-	.bt_shared_single_ant = true,
-	.disable_dummy_notification = true,
-	.max_ht_ampdu_exponent  = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
-	.max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO,
 };
 
 MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index ab079ff..6926711 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -87,16 +87,6 @@
 	IWL_DEVICE_FAMILY_8000,
 };
 
-static inline bool iwl_has_secure_boot(u32 hw_rev,
-				       enum iwl_device_family family)
-{
-	/* return 1 only for family 8000 B0 */
-	if ((family == IWL_DEVICE_FAMILY_8000) && (hw_rev & 0xC))
-		return 1;
-
-	return 0;
-}
-
 /*
  * LED mode
  *    IWL_LED_DEFAULT:  use device default
@@ -256,11 +246,6 @@
  * @nvm_hw_section_num: the ID of the HW NVM section
  * @pwr_tx_backoffs: translation table between power limits and backoffs
  * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
- * @max_tx_agg_size: max TX aggregation size of the ADDBA request/response
- * @max_ht_ampdu_factor: the exponent of the max length of A-MPDU that the
- *	station can receive in HT
- * @max_vht_ampdu_exponent: the exponent of the max length of A-MPDU that the
- *	station can receive in VHT
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
@@ -300,9 +285,6 @@
 	const char *default_nvm_file;
 	unsigned int max_rx_agg_size;
 	bool disable_dummy_notification;
-	unsigned int max_tx_agg_size;
-	unsigned int max_ht_ampdu_exponent;
-	unsigned int max_vht_ampdu_exponent;
 };
 
 /*
@@ -364,14 +346,9 @@
 extern const struct iwl_cfg iwl7265_2ac_cfg;
 extern const struct iwl_cfg iwl7265_2n_cfg;
 extern const struct iwl_cfg iwl7265_n_cfg;
-extern const struct iwl_cfg iwl7265d_2ac_cfg;
-extern const struct iwl_cfg iwl7265d_2n_cfg;
-extern const struct iwl_cfg iwl7265d_n_cfg;
 extern const struct iwl_cfg iwl8260_2n_cfg;
 extern const struct iwl_cfg iwl8260_2ac_cfg;
 extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
-extern const struct iwl_cfg iwl4265_2ac_sdio_cfg;
-extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
 #endif /* CPTCFG_IWLMVM */
 
 #endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index aff63c3..3f6f015 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -129,8 +129,6 @@
 #define CSR_UCODE_DRV_GP1_CLR   (CSR_BASE+0x05c)
 #define CSR_UCODE_DRV_GP2       (CSR_BASE+0x060)
 
-#define CSR_MBOX_SET_REG	(CSR_BASE + 0x88)
-
 #define CSR_LED_REG             (CSR_BASE+0x094)
 #define CSR_DRAM_INT_TBL_REG	(CSR_BASE+0x0A0)
 #define CSR_MAC_SHADOW_REG_CTRL	(CSR_BASE+0x0A8) /* 6000 and up */
@@ -186,8 +184,6 @@
 #define CSR_HW_IF_CONFIG_REG_PREPARE		  (0x08000000) /* WAKE_ME */
 #define CSR_HW_IF_CONFIG_REG_PERSIST_MODE	  (0x40000000) /* PERSISTENCE */
 
-#define CSR_MBOX_SET_REG_OS_ALIVE		BIT(5)
-
 #define CSR_INT_PERIODIC_DIS			(0x00) /* disable periodic int*/
 #define CSR_INT_PERIODIC_ENA			(0xFF) /* 255*32 usec ~ 8 msec*/
 
@@ -309,24 +305,23 @@
 };
 
 
-#define CSR_HW_REV_TYPE_MSK		(0x000FFF0)
-#define CSR_HW_REV_TYPE_5300		(0x0000020)
-#define CSR_HW_REV_TYPE_5350		(0x0000030)
-#define CSR_HW_REV_TYPE_5100		(0x0000050)
-#define CSR_HW_REV_TYPE_5150		(0x0000040)
-#define CSR_HW_REV_TYPE_1000		(0x0000060)
-#define CSR_HW_REV_TYPE_6x00		(0x0000070)
-#define CSR_HW_REV_TYPE_6x50		(0x0000080)
-#define CSR_HW_REV_TYPE_6150		(0x0000084)
-#define CSR_HW_REV_TYPE_6x05		(0x00000B0)
-#define CSR_HW_REV_TYPE_6x30		CSR_HW_REV_TYPE_6x05
-#define CSR_HW_REV_TYPE_6x35		CSR_HW_REV_TYPE_6x05
-#define CSR_HW_REV_TYPE_2x30		(0x00000C0)
-#define CSR_HW_REV_TYPE_2x00		(0x0000100)
-#define CSR_HW_REV_TYPE_105		(0x0000110)
-#define CSR_HW_REV_TYPE_135		(0x0000120)
-#define CSR_HW_REV_TYPE_7265D		(0x0000210)
-#define CSR_HW_REV_TYPE_NONE		(0x00001F0)
+#define CSR_HW_REV_TYPE_MSK            (0x000FFF0)
+#define CSR_HW_REV_TYPE_5300           (0x0000020)
+#define CSR_HW_REV_TYPE_5350           (0x0000030)
+#define CSR_HW_REV_TYPE_5100           (0x0000050)
+#define CSR_HW_REV_TYPE_5150           (0x0000040)
+#define CSR_HW_REV_TYPE_1000           (0x0000060)
+#define CSR_HW_REV_TYPE_6x00           (0x0000070)
+#define CSR_HW_REV_TYPE_6x50           (0x0000080)
+#define CSR_HW_REV_TYPE_6150           (0x0000084)
+#define CSR_HW_REV_TYPE_6x05	       (0x00000B0)
+#define CSR_HW_REV_TYPE_6x30	       CSR_HW_REV_TYPE_6x05
+#define CSR_HW_REV_TYPE_6x35	       CSR_HW_REV_TYPE_6x05
+#define CSR_HW_REV_TYPE_2x30	       (0x00000C0)
+#define CSR_HW_REV_TYPE_2x00	       (0x0000100)
+#define CSR_HW_REV_TYPE_105	       (0x0000110)
+#define CSR_HW_REV_TYPE_135	       (0x0000120)
+#define CSR_HW_REV_TYPE_NONE           (0x00001F0)
 
 /* EEPROM REG */
 #define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 68b126b..2eb2346 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -143,7 +143,7 @@
 #define IWL_DL_INFO		0x00000001
 #define IWL_DL_MAC80211		0x00000002
 #define IWL_DL_HCMD		0x00000004
-#define IWL_DL_TDLS		0x00000008
+#define IWL_DL_STATE		0x00000008
 /* 0x000000F0 - 0x00000010 */
 #define IWL_DL_QUOTA		0x00000010
 #define IWL_DL_TE		0x00000020
@@ -180,7 +180,6 @@
 #define IWL_DL_TX_QUEUES	0x80000000
 
 #define IWL_DEBUG_INFO(p, f, a...)	IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_TDLS(p, f, a...)	IWL_DEBUG(p, IWL_DL_TDLS, f, ## a)
 #define IWL_DEBUG_MAC80211(p, f, a...)	IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
 #define IWL_DEBUG_EXTERNAL(p, f, a...)	IWL_DEBUG(p, IWL_DL_EXTERNAL, f, ## a)
 #define IWL_DEBUG_TEMP(p, f, a...)	IWL_DEBUG(p, IWL_DL_TEMP, f, ## a)
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 4322c55..5e8d279 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -78,6 +78,9 @@
 #include "iwl-config.h"
 #include "iwl-modparams.h"
 
+/* private includes */
+#include "iwl-fw-file.h"
+
 /******************************************************************************
  *
  * module boiler plate
@@ -184,11 +187,6 @@
 static void iwl_dealloc_ucode(struct iwl_drv *drv)
 {
 	int i;
-
-	kfree(drv->fw.dbg_dest_tlv);
-	for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++)
-		kfree(drv->fw.dbg_conf_tlv[i]);
-
 	for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
 		iwl_free_fw_img(drv, drv->fw.img + i);
 }
@@ -250,9 +248,6 @@
 	/*
 	 * Starting 8000B - FW name format has changed. This overwrites the
 	 * previous name and uses the new format.
-	 *
-	 * TODO:
-	 * Once there is only one supported step for 8000 family - delete this!
 	 */
 	if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
 		char rev_step[2] = {
@@ -263,13 +258,6 @@
 		if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP)
 			rev_step[0] = 0;
 
-		/*
-		 * If hw_rev wasn't set yet - default as B-step. If it IS A-step
-		 * we'll reload that FW later instead.
-		 */
-		if (drv->trans->hw_rev == 0)
-			rev_step[0] = 'B';
-
 		snprintf(drv->firmware_name, sizeof(drv->firmware_name),
 			 "%s%s-%s.ucode", name_pre, rev_step, tag);
 	}
@@ -313,11 +301,6 @@
 
 	u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
 	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-
-	/* FW debug data parsed for driver usage */
-	struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
-	struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
-	size_t dbg_conf_tlv_len[FW_DBG_MAX];
 };
 
 /*
@@ -591,8 +574,6 @@
 	char buildstr[25];
 	u32 build;
 	int num_of_cpus;
-	bool usniffer_images = false;
-	bool usniffer_req = false;
 
 	if (len < sizeof(*ucode)) {
 		IWL_ERR(drv, "uCode has invalid length: %zd\n", len);
@@ -826,16 +807,19 @@
 			iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
 					    tlv_len);
 			drv->fw.mvm_fw = true;
+			drv->fw.img[IWL_UCODE_REGULAR].is_secure = true;
 			break;
 		case IWL_UCODE_TLV_SECURE_SEC_INIT:
 			iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
 					    tlv_len);
 			drv->fw.mvm_fw = true;
+			drv->fw.img[IWL_UCODE_INIT].is_secure = true;
 			break;
 		case IWL_UCODE_TLV_SECURE_SEC_WOWLAN:
 			iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
 					    tlv_len);
 			drv->fw.mvm_fw = true;
+			drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true;
 			break;
 		case IWL_UCODE_TLV_NUM_OF_CPU:
 			if (tlv_len != sizeof(u32))
@@ -865,79 +849,12 @@
 			capa->n_scan_channels =
 				le32_to_cpup((__le32 *)tlv_data);
 			break;
-		case IWL_UCODE_TLV_FW_DBG_DEST: {
-			struct iwl_fw_dbg_dest_tlv *dest = (void *)tlv_data;
-
-			if (pieces->dbg_dest_tlv) {
-				IWL_ERR(drv,
-					"dbg destination ignored, already exists\n");
-				break;
-			}
-
-			pieces->dbg_dest_tlv = dest;
-			IWL_INFO(drv, "Found debug destination: %s\n",
-				 get_fw_dbg_mode_string(dest->monitor_mode));
-
-			drv->fw.dbg_dest_reg_num =
-				tlv_len - offsetof(struct iwl_fw_dbg_dest_tlv,
-						   reg_ops);
-			drv->fw.dbg_dest_reg_num /=
-				sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]);
-
-			break;
-			}
-		case IWL_UCODE_TLV_FW_DBG_CONF: {
-			struct iwl_fw_dbg_conf_tlv *conf = (void *)tlv_data;
-
-			if (!pieces->dbg_dest_tlv) {
-				IWL_ERR(drv,
-					"Ignore dbg config %d - no destination configured\n",
-					conf->id);
-				break;
-			}
-
-			if (conf->id >= ARRAY_SIZE(drv->fw.dbg_conf_tlv)) {
-				IWL_ERR(drv,
-					"Skip unknown configuration: %d\n",
-					conf->id);
-				break;
-			}
-
-			if (pieces->dbg_conf_tlv[conf->id]) {
-				IWL_ERR(drv,
-					"Ignore duplicate dbg config %d\n",
-					conf->id);
-				break;
-			}
-
-			if (conf->usniffer)
-				usniffer_req = true;
-
-			IWL_INFO(drv, "Found debug configuration: %d\n",
-				 conf->id);
-
-			pieces->dbg_conf_tlv[conf->id] = conf;
-			pieces->dbg_conf_tlv_len[conf->id] = tlv_len;
-			break;
-			}
-		case IWL_UCODE_TLV_SEC_RT_USNIFFER:
-			usniffer_images = true;
-			iwl_store_ucode_sec(pieces, tlv_data,
-					    IWL_UCODE_REGULAR_USNIFFER,
-					    tlv_len);
-			break;
 		default:
 			IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
 			break;
 		}
 	}
 
-	if (usniffer_req && !usniffer_images) {
-		IWL_ERR(drv,
-			"user selected to work with usniffer but usniffer image isn't available in ucode package\n");
-		return -EINVAL;
-	}
-
 	if (len) {
 		IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len);
 		iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len);
@@ -1075,14 +992,13 @@
 	struct iwl_ucode_header *ucode;
 	struct iwlwifi_opmode_table *op;
 	int err;
-	struct iwl_firmware_pieces *pieces;
+	struct iwl_firmware_pieces pieces;
 	const unsigned int api_max = drv->cfg->ucode_api_max;
 	unsigned int api_ok = drv->cfg->ucode_api_ok;
 	const unsigned int api_min = drv->cfg->ucode_api_min;
 	u32 api_ver;
 	int i;
 	bool load_module = false;
-	u32 hw_rev = drv->trans->hw_rev;
 
 	fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
 	fw->ucode_capa.standard_phy_calibration_size =
@@ -1092,9 +1008,7 @@
 	if (!api_ok)
 		api_ok = api_max;
 
-	pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
-	if (!pieces)
-		return;
+	memset(&pieces, 0, sizeof(pieces));
 
 	if (!ucode_raw) {
 		if (drv->fw_index <= api_ok)
@@ -1117,10 +1031,10 @@
 	ucode = (struct iwl_ucode_header *)ucode_raw->data;
 
 	if (ucode->ver)
-		err = iwl_parse_v1_v2_firmware(drv, ucode_raw, pieces);
+		err = iwl_parse_v1_v2_firmware(drv, ucode_raw, &pieces);
 	else
-		err = iwl_parse_tlv_firmware(drv, ucode_raw, pieces,
-					     &fw->ucode_capa);
+		err = iwl_parse_tlv_firmware(drv, ucode_raw, &pieces,
+					   &fw->ucode_capa);
 
 	if (err)
 		goto try_again;
@@ -1160,7 +1074,7 @@
 	 * In mvm uCode there is no difference between data and instructions
 	 * sections.
 	 */
-	if (!fw->mvm_fw && validate_sec_sizes(drv, pieces, drv->cfg))
+	if (!fw->mvm_fw && validate_sec_sizes(drv, &pieces, drv->cfg))
 		goto try_again;
 
 	/* Allocate ucode buffers for card's bus-master loading ... */
@@ -1169,33 +1083,9 @@
 	 * 1) unmodified from disk
 	 * 2) backup cache for save/restore during power-downs */
 	for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
-		if (iwl_alloc_ucode(drv, pieces, i))
+		if (iwl_alloc_ucode(drv, &pieces, i))
 			goto out_free_fw;
 
-	if (pieces->dbg_dest_tlv) {
-		drv->fw.dbg_dest_tlv =
-			kmemdup(pieces->dbg_dest_tlv,
-				sizeof(*pieces->dbg_dest_tlv) +
-				sizeof(pieces->dbg_dest_tlv->reg_ops[0]) *
-				drv->fw.dbg_dest_reg_num, GFP_KERNEL);
-
-		if (!drv->fw.dbg_dest_tlv)
-			goto out_free_fw;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) {
-		if (pieces->dbg_conf_tlv[i]) {
-			drv->fw.dbg_conf_tlv_len[i] =
-				pieces->dbg_conf_tlv_len[i];
-			drv->fw.dbg_conf_tlv[i] =
-				kmemdup(pieces->dbg_conf_tlv[i],
-					drv->fw.dbg_conf_tlv_len[i],
-					GFP_KERNEL);
-			if (!drv->fw.dbg_conf_tlv[i])
-				goto out_free_fw;
-		}
-	}
-
 	/* Now that we can no longer fail, copy information */
 
 	/*
@@ -1203,20 +1093,20 @@
 	 * for each event, which is of mode 1 (including timestamp) for all
 	 * new microcodes that include this information.
 	 */
-	fw->init_evtlog_ptr = pieces->init_evtlog_ptr;
-	if (pieces->init_evtlog_size)
-		fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12;
+	fw->init_evtlog_ptr = pieces.init_evtlog_ptr;
+	if (pieces.init_evtlog_size)
+		fw->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
 	else
 		fw->init_evtlog_size =
 			drv->cfg->base_params->max_event_log_size;
-	fw->init_errlog_ptr = pieces->init_errlog_ptr;
-	fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr;
-	if (pieces->inst_evtlog_size)
-		fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12;
+	fw->init_errlog_ptr = pieces.init_errlog_ptr;
+	fw->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
+	if (pieces.inst_evtlog_size)
+		fw->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
 	else
 		fw->inst_evtlog_size =
 			drv->cfg->base_params->max_event_log_size;
-	fw->inst_errlog_ptr = pieces->inst_errlog_ptr;
+	fw->inst_errlog_ptr = pieces.inst_errlog_ptr;
 
 	/*
 	 * figure out the offset of chain noise reset and gain commands
@@ -1275,55 +1165,10 @@
 				op->name, err);
 #endif
 	}
-
-	/*
-	 * We may have loaded the wrong FW file in 8000 HW family if it is an
-	 * A-step card, and if drv->trans->hw_rev wasn't properly read when
-	 * the FW file had been loaded. (This might happen in SDIO.) In such a
-	 * case - unload and reload the correct file.
-	 *
-	 * TODO:
-	 * Once there is only one supported step for 8000 family - delete this!
-	 */
-	if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
-	    CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP &&
-	    drv->trans->hw_rev != hw_rev) {
-		char firmware_name[32];
-
-		/* Free previous FW resources */
-		if (drv->op_mode)
-			_iwl_op_mode_stop(drv);
-		iwl_dealloc_ucode(drv);
-
-		/* Build name of correct-step FW */
-		snprintf(firmware_name, sizeof(firmware_name),
-			 strrchr(drv->firmware_name, '-'));
-		snprintf(drv->firmware_name, sizeof(drv->firmware_name),
-			 "%s%s", drv->cfg->fw_name_pre, firmware_name);
-
-		/* Clear data before loading correct FW */
-		list_del(&drv->list);
-
-		/* Request correct FW file this time */
-		IWL_DEBUG_INFO(drv, "attempting to load A-step FW %s\n",
-			       drv->firmware_name);
-		err = request_firmware(&ucode_raw, drv->firmware_name,
-				       drv->trans->dev);
-		if (err) {
-			IWL_ERR(drv, "Failed swapping FW!\n");
-			goto out_unbind;
-		}
-
-		/* Redo callback function - this time with right FW */
-		iwl_req_fw_callback(ucode_raw, context);
-	}
-
-	kfree(pieces);
 	return;
 
  try_again:
 	/* try next, if any */
-	kfree(pieces);
 	release_firmware(ucode_raw);
 	if (iwl_request_firmware(drv, false))
 		goto out_unbind;
@@ -1334,7 +1179,6 @@
 	iwl_dealloc_ucode(drv);
 	release_firmware(ucode_raw);
  out_unbind:
-	kfree(pieces);
 	complete(&drv->request_firmware_complete);
 	device_release_driver(drv->trans->dev);
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
index 41ff85d..74b796d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
@@ -764,7 +764,7 @@
 	if (iwlwifi_mod_params.amsdu_size_8K)
 		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
 
-	ht_info->ampdu_factor = cfg->max_ht_ampdu_exponent;
+	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
 
 	ht_info->mcs.rx_mask[0] = 0xFF;
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
index 20a8a64..e30a41d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
@@ -81,7 +81,6 @@
  * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
  * @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
  *	sections like this in a single file.
- * @IWL_FW_ERROR_DUMP_FH_REGS: range of FH registers
  */
 enum iwl_fw_error_dump_type {
 	IWL_FW_ERROR_DUMP_SRAM = 0,
@@ -91,8 +90,6 @@
 	IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
 	IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
 	IWL_FW_ERROR_DUMP_PRPH = 6,
-	IWL_FW_ERROR_DUMP_TXF = 7,
-	IWL_FW_ERROR_DUMP_FH_REGS = 8,
 
 	IWL_FW_ERROR_DUMP_MAX,
 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index f2a047f..401f7be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -131,9 +131,6 @@
 	IWL_UCODE_TLV_API_CHANGES_SET	= 29,
 	IWL_UCODE_TLV_ENABLED_CAPABILITIES	= 30,
 	IWL_UCODE_TLV_N_SCAN_CHANNELS		= 31,
-	IWL_UCODE_TLV_SEC_RT_USNIFFER	= 34,
-	IWL_UCODE_TLV_FW_DBG_DEST	= 38,
-	IWL_UCODE_TLV_FW_DBG_CONF	= 39,
 };
 
 struct iwl_ucode_tlv {
@@ -182,309 +179,4 @@
 	__le32 api_capa;
 } __packed;
 
-/**
- * enum iwl_ucode_tlv_flag - ucode API flags
- * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
- *	was a separate TLV but moved here to save space.
- * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
- *	treats good CRC threshold as a boolean
- * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
- * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
- * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
- * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: This uCode image supports uAPSD
- * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
- *	offload profile config command.
- * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
- *	(rather than two) IPv6 addresses
- * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
- *	from the probe request template.
- * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
- * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
- * @IWL_UCODE_TLV_FLAGS_P2P_PM: P2P client supports PM as a stand alone MAC
- * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
- *	P2P client interfaces simultaneously if they are in different bindings.
- * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_SCM: support power save on BSS station and
- *	P2P client interfaces simultaneously if they are in same bindings.
- * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD
- * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
- * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
- * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
- * @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.
- */
-enum iwl_ucode_tlv_flag {
-	IWL_UCODE_TLV_FLAGS_PAN			= BIT(0),
-	IWL_UCODE_TLV_FLAGS_NEWSCAN		= BIT(1),
-	IWL_UCODE_TLV_FLAGS_MFP			= BIT(2),
-	IWL_UCODE_TLV_FLAGS_P2P			= BIT(3),
-	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE		= BIT(4),
-	IWL_UCODE_TLV_FLAGS_SHORT_BL		= BIT(7),
-	IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS	= BIT(10),
-	IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID	= BIT(12),
-	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL	= BIT(15),
-	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE	= BIT(16),
-	IWL_UCODE_TLV_FLAGS_P2P_PM		= BIT(21),
-	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM	= BIT(22),
-	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM	= BIT(23),
-	IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT	= BIT(24),
-	IWL_UCODE_TLV_FLAGS_EBS_SUPPORT		= BIT(25),
-	IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD	= BIT(26),
-	IWL_UCODE_TLV_FLAGS_BCAST_FILTERING	= BIT(29),
-	IWL_UCODE_TLV_FLAGS_GO_UAPSD		= BIT(30),
-};
-
-/**
- * enum iwl_ucode_tlv_api - ucode api
- * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
- * @IWL_UCODE_TLV_CAPA_EXTENDED_BEACON: Support Extended beacon notification
- * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex
- * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
- * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit.
- * @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API.
- * @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif.
- * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time
- *	longer than the passive one, which is essential for fragmented scan.
- */
-enum iwl_ucode_tlv_api {
-	IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID	= BIT(0),
-	IWL_UCODE_TLV_CAPA_EXTENDED_BEACON	= BIT(1),
-	IWL_UCODE_TLV_API_BT_COEX_SPLIT         = BIT(3),
-	IWL_UCODE_TLV_API_CSA_FLOW		= BIT(4),
-	IWL_UCODE_TLV_API_DISABLE_STA_TX	= BIT(5),
-	IWL_UCODE_TLV_API_LMAC_SCAN		= BIT(6),
-	IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF	= BIT(7),
-	IWL_UCODE_TLV_API_FRAGMENTED_SCAN	= BIT(8),
-};
-
-/**
- * enum iwl_ucode_tlv_capa - ucode capabilities
- * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3
- * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory
- * @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan.
- * @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality
- * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
- *	tx power value into TPC Report action frame and Link Measurement Report
- *	action frame
- * @IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports updating current
- *	channel in DS parameter set element in probe requests.
- * @IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in
- *	probe requests.
- * @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests
- * @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),
- *	which also implies support for the scheduler configuration command
- * @IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching
- * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command
- */
-enum iwl_ucode_tlv_capa {
-	IWL_UCODE_TLV_CAPA_D0I3_SUPPORT			= BIT(0),
-	IWL_UCODE_TLV_CAPA_LAR_SUPPORT			= BIT(1),
-	IWL_UCODE_TLV_CAPA_UMAC_SCAN			= BIT(2),
-	IWL_UCODE_TLV_CAPA_TDLS_SUPPORT			= BIT(6),
-	IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT	= BIT(8),
-	IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT	= BIT(9),
-	IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT	= BIT(10),
-	IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT		= BIT(11),
-	IWL_UCODE_TLV_CAPA_DQA_SUPPORT			= BIT(12),
-	IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH		= BIT(13),
-	IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT		= BIT(18),
-};
-
-/* The default calibrate table size if not specified by firmware file */
-#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE	18
-#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE		19
-#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE			253
-
-/* The default max probe length if not specified by the firmware file */
-#define IWL_DEFAULT_MAX_PROBE_LENGTH	200
-
-/*
- * For 16.0 uCode and above, there is no differentiation between sections,
- * just an offset to the HW address.
- */
-#define IWL_UCODE_SECTION_MAX 12
-#define IWL_API_ARRAY_SIZE	1
-#define IWL_CAPABILITIES_ARRAY_SIZE	1
-#define CPU1_CPU2_SEPARATOR_SECTION	0xFFFFCCCC
-
-/* uCode version contains 4 values: Major/Minor/API/Serial */
-#define IWL_UCODE_MAJOR(ver)	(((ver) & 0xFF000000) >> 24)
-#define IWL_UCODE_MINOR(ver)	(((ver) & 0x00FF0000) >> 16)
-#define IWL_UCODE_API(ver)	(((ver) & 0x0000FF00) >> 8)
-#define IWL_UCODE_SERIAL(ver)	((ver) & 0x000000FF)
-
-/*
- * Calibration control struct.
- * Sent as part of the phy configuration command.
- * @flow_trigger: bitmap for which calibrations to perform according to
- *		flow triggers.
- * @event_trigger: bitmap for which calibrations to perform according to
- *		event triggers.
- */
-struct iwl_tlv_calib_ctrl {
-	__le32 flow_trigger;
-	__le32 event_trigger;
-} __packed;
-
-enum iwl_fw_phy_cfg {
-	FW_PHY_CFG_RADIO_TYPE_POS = 0,
-	FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS,
-	FW_PHY_CFG_RADIO_STEP_POS = 2,
-	FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS,
-	FW_PHY_CFG_RADIO_DASH_POS = 4,
-	FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS,
-	FW_PHY_CFG_TX_CHAIN_POS = 16,
-	FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
-	FW_PHY_CFG_RX_CHAIN_POS = 20,
-	FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
-};
-
-#define IWL_UCODE_MAX_CS		1
-
-/**
- * struct iwl_fw_cipher_scheme - a cipher scheme supported by FW.
- * @cipher: a cipher suite selector
- * @flags: cipher scheme flags (currently reserved for a future use)
- * @hdr_len: a size of MPDU security header
- * @pn_len: a size of PN
- * @pn_off: an offset of pn from the beginning of the security header
- * @key_idx_off: an offset of key index byte in the security header
- * @key_idx_mask: a bit mask of key_idx bits
- * @key_idx_shift: bit shift needed to get key_idx
- * @mic_len: mic length in bytes
- * @hw_cipher: a HW cipher index used in host commands
- */
-struct iwl_fw_cipher_scheme {
-	__le32 cipher;
-	u8 flags;
-	u8 hdr_len;
-	u8 pn_len;
-	u8 pn_off;
-	u8 key_idx_off;
-	u8 key_idx_mask;
-	u8 key_idx_shift;
-	u8 mic_len;
-	u8 hw_cipher;
-} __packed;
-
-enum iwl_fw_dbg_reg_operator {
-	CSR_ASSIGN,
-	CSR_SETBIT,
-	CSR_CLEARBIT,
-
-	PRPH_ASSIGN,
-	PRPH_SETBIT,
-	PRPH_CLEARBIT,
-};
-
-/**
- * struct iwl_fw_dbg_reg_op - an operation on a register
- *
- * @op: %enum iwl_fw_dbg_reg_operator
- * @addr: offset of the register
- * @val: value
- */
-struct iwl_fw_dbg_reg_op {
-	u8 op;
-	u8 reserved[3];
-	__le32 addr;
-	__le32 val;
-} __packed;
-
-/**
- * enum iwl_fw_dbg_monitor_mode - available monitor recording modes
- *
- * @SMEM_MODE: monitor stores the data in SMEM
- * @EXTERNAL_MODE: monitor stores the data in allocated DRAM
- * @MARBH_MODE: monitor stores the data in MARBH buffer
- */
-enum iwl_fw_dbg_monitor_mode {
-	SMEM_MODE = 0,
-	EXTERNAL_MODE = 1,
-	MARBH_MODE = 2,
-};
-
-/**
- * struct iwl_fw_dbg_dest_tlv - configures the destination of the debug data
- *
- * @version: version of the TLV - currently 0
- * @monitor_mode: %enum iwl_fw_dbg_monitor_mode
- * @base_reg: addr of the base addr register (PRPH)
- * @end_reg:  addr of the end addr register (PRPH)
- * @write_ptr_reg: the addr of the reg of the write pointer
- * @wrap_count: the addr of the reg of the wrap_count
- * @base_shift: shift right of the base addr reg
- * @end_shift: shift right of the end addr reg
- * @reg_ops: array of registers operations
- *
- * This parses IWL_UCODE_TLV_FW_DBG_DEST
- */
-struct iwl_fw_dbg_dest_tlv {
-	u8 version;
-	u8 monitor_mode;
-	u8 reserved[2];
-	__le32 base_reg;
-	__le32 end_reg;
-	__le32 write_ptr_reg;
-	__le32 wrap_count;
-	u8 base_shift;
-	u8 end_shift;
-	struct iwl_fw_dbg_reg_op reg_ops[0];
-} __packed;
-
-struct iwl_fw_dbg_conf_hcmd {
-	u8 id;
-	u8 reserved;
-	__le16 len;
-	u8 data[0];
-} __packed;
-
-/**
- * struct iwl_fw_dbg_trigger - a TLV that describes a debug configuration
- *
- * @enabled: is this trigger enabled
- * @reserved:
- * @len: length, in bytes, of the %trigger field
- * @trigger: pointer to a trigger struct
- */
-struct iwl_fw_dbg_trigger {
-	u8 enabled;
-	u8 reserved;
-	u8 len;
-	u8 trigger[0];
-} __packed;
-
-/**
- * enum iwl_fw_dbg_conf - configurations available
- *
- * @FW_DBG_CUSTOM: take this configuration from alive
- *	Note that the trigger is NO-OP for this configuration
- */
-enum iwl_fw_dbg_conf {
-	FW_DBG_CUSTOM = 0,
-
-	/* must be last */
-	FW_DBG_MAX,
-	FW_DBG_INVALID = 0xff,
-};
-
-/**
- * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration
- *
- * @id: %enum iwl_fw_dbg_conf
- * @usniffer: should the uSniffer image be used
- * @num_of_hcmds: how many HCMDs to send are present here
- * @hcmd: a variable length host command to be sent to apply the configuration.
- *	If there is more than one HCMD to send, they will appear one after the
- *	other and be sent in the order that they appear in.
- * This parses IWL_UCODE_TLV_FW_DBG_CONF
- */
-struct iwl_fw_dbg_conf_tlv {
-	u8 id;
-	u8 usniffer;
-	u8 reserved;
-	u8 num_of_hcmds;
-	struct iwl_fw_dbg_conf_hcmd hcmd;
-
-	/* struct iwl_fw_dbg_trigger sits after all variable length hcmds */
-} __packed;
-
 #endif  /* __iwl_fw_file_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index e6dc3b8..4f6e668 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -70,6 +70,110 @@
 #include "iwl-fw-file.h"
 
 /**
+ * enum iwl_ucode_tlv_flag - ucode API flags
+ * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
+ *	was a separate TLV but moved here to save space.
+ * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
+ *	treats good CRC threshold as a boolean
+ * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
+ * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
+ * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
+ * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: This uCode image supports uAPSD
+ * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
+ *	offload profile config command.
+ * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
+ *	(rather than two) IPv6 addresses
+ * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
+ *	from the probe request template.
+ * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
+ * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
+ * @IWL_UCODE_TLV_FLAGS_P2P_PM: P2P client supports PM as a stand alone MAC
+ * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
+ *	P2P client interfaces simultaneously if they are in different bindings.
+ * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_SCM: support power save on BSS station and
+ *	P2P client interfaces simultaneously if they are in same bindings.
+ * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD
+ * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
+ * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
+ * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
+ * @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.
+ */
+enum iwl_ucode_tlv_flag {
+	IWL_UCODE_TLV_FLAGS_PAN			= BIT(0),
+	IWL_UCODE_TLV_FLAGS_NEWSCAN		= BIT(1),
+	IWL_UCODE_TLV_FLAGS_MFP			= BIT(2),
+	IWL_UCODE_TLV_FLAGS_P2P			= BIT(3),
+	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE		= BIT(4),
+	IWL_UCODE_TLV_FLAGS_SHORT_BL		= BIT(7),
+	IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS	= BIT(10),
+	IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID	= BIT(12),
+	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL	= BIT(15),
+	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE	= BIT(16),
+	IWL_UCODE_TLV_FLAGS_P2P_PM		= BIT(21),
+	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM	= BIT(22),
+	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM	= BIT(23),
+	IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT	= BIT(24),
+	IWL_UCODE_TLV_FLAGS_EBS_SUPPORT		= BIT(25),
+	IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD	= BIT(26),
+	IWL_UCODE_TLV_FLAGS_BCAST_FILTERING	= BIT(29),
+	IWL_UCODE_TLV_FLAGS_GO_UAPSD		= BIT(30),
+};
+
+/**
+ * enum iwl_ucode_tlv_api - ucode api
+ * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
+ * @IWL_UCODE_TLV_CAPA_EXTENDED_BEACON: Support Extended beacon notification
+ * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex
+ * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
+ * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit.
+ * @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API.
+ * @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif.
+ * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time
+ *	longer than the passive one, which is essential for fragmented scan.
+ */
+enum iwl_ucode_tlv_api {
+	IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID	= BIT(0),
+	IWL_UCODE_TLV_CAPA_EXTENDED_BEACON	= BIT(1),
+	IWL_UCODE_TLV_API_BT_COEX_SPLIT         = BIT(3),
+	IWL_UCODE_TLV_API_CSA_FLOW		= BIT(4),
+	IWL_UCODE_TLV_API_DISABLE_STA_TX	= BIT(5),
+	IWL_UCODE_TLV_API_LMAC_SCAN		= BIT(6),
+	IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF	= BIT(7),
+	IWL_UCODE_TLV_API_FRAGMENTED_SCAN	= BIT(8),
+};
+
+/**
+ * enum iwl_ucode_tlv_capa - ucode capabilities
+ * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3
+ * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
+ *	tx power value into TPC Report action frame and Link Measurement Report
+ *	action frame
+ * @IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports adding DS params
+ *	element in probe requests.
+ * @IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in
+ *	probe requests.
+ * @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests
+ * @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),
+ *	which also implies support for the scheduler configuration command
+ */
+enum iwl_ucode_tlv_capa {
+	IWL_UCODE_TLV_CAPA_D0I3_SUPPORT			= BIT(0),
+	IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT	= BIT(8),
+	IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT	= BIT(9),
+	IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT	= BIT(10),
+	IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT		= BIT(11),
+	IWL_UCODE_TLV_CAPA_DQA_SUPPORT			= BIT(12),
+};
+
+/* The default calibrate table size if not specified by firmware file */
+#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE	18
+#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE		19
+#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE			253
+
+/* The default max probe length if not specified by the firmware file */
+#define IWL_DEFAULT_MAX_PROBE_LENGTH	200
+
+/**
  * enum iwl_ucode_type
  *
  * The type of ucode.
@@ -77,13 +181,11 @@
  * @IWL_UCODE_REGULAR: Normal runtime ucode
  * @IWL_UCODE_INIT: Initial ucode
  * @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
- * @IWL_UCODE_REGULAR_USNIFFER: Normal runtime ucode when using usniffer image
  */
 enum iwl_ucode_type {
 	IWL_UCODE_REGULAR,
 	IWL_UCODE_INIT,
 	IWL_UCODE_WOWLAN,
-	IWL_UCODE_REGULAR_USNIFFER,
 	IWL_UCODE_TYPE_MAX,
 };
 
@@ -98,6 +200,14 @@
 	IWL_UCODE_SECTION_DATA,
 	IWL_UCODE_SECTION_INST,
 };
+/*
+ * For 16.0 uCode and above, there is no differentiation between sections,
+ * just an offset to the HW address.
+ */
+#define IWL_UCODE_SECTION_MAX 12
+#define IWL_API_ARRAY_SIZE	1
+#define IWL_CAPABILITIES_ARRAY_SIZE	1
+#define CPU1_CPU2_SEPARATOR_SECTION	0xFFFFCCCC
 
 struct iwl_ucode_capabilities {
 	u32 max_probe_length;
@@ -117,6 +227,7 @@
 
 struct fw_img {
 	struct fw_desc sec[IWL_UCODE_SECTION_MAX];
+	bool is_secure;
 	bool is_dual_cpus;
 };
 
@@ -125,6 +236,66 @@
 	u32 size;
 };
 
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IWL_UCODE_MAJOR(ver)	(((ver) & 0xFF000000) >> 24)
+#define IWL_UCODE_MINOR(ver)	(((ver) & 0x00FF0000) >> 16)
+#define IWL_UCODE_API(ver)	(((ver) & 0x0000FF00) >> 8)
+#define IWL_UCODE_SERIAL(ver)	((ver) & 0x000000FF)
+
+/*
+ * Calibration control struct.
+ * Sent as part of the phy configuration command.
+ * @flow_trigger: bitmap for which calibrations to perform according to
+ *		flow triggers.
+ * @event_trigger: bitmap for which calibrations to perform according to
+ *		event triggers.
+ */
+struct iwl_tlv_calib_ctrl {
+	__le32 flow_trigger;
+	__le32 event_trigger;
+} __packed;
+
+enum iwl_fw_phy_cfg {
+	FW_PHY_CFG_RADIO_TYPE_POS = 0,
+	FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS,
+	FW_PHY_CFG_RADIO_STEP_POS = 2,
+	FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS,
+	FW_PHY_CFG_RADIO_DASH_POS = 4,
+	FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS,
+	FW_PHY_CFG_TX_CHAIN_POS = 16,
+	FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
+	FW_PHY_CFG_RX_CHAIN_POS = 20,
+	FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
+};
+
+#define IWL_UCODE_MAX_CS		1
+
+/**
+ * struct iwl_fw_cipher_scheme - a cipher scheme supported by FW.
+ * @cipher: a cipher suite selector
+ * @flags: cipher scheme flags (currently reserved for a future use)
+ * @hdr_len: a size of MPDU security header
+ * @pn_len: a size of PN
+ * @pn_off: an offset of pn from the beginning of the security header
+ * @key_idx_off: an offset of key index byte in the security header
+ * @key_idx_mask: a bit mask of key_idx bits
+ * @key_idx_shift: bit shift needed to get key_idx
+ * @mic_len: mic length in bytes
+ * @hw_cipher: a HW cipher index used in host commands
+ */
+struct iwl_fw_cipher_scheme {
+	__le32 cipher;
+	u8 flags;
+	u8 hdr_len;
+	u8 pn_len;
+	u8 pn_off;
+	u8 key_idx_off;
+	u8 key_idx_mask;
+	u8 key_idx_shift;
+	u8 mic_len;
+	u8 hw_cipher;
+} __packed;
+
 /**
  * struct iwl_fw_cscheme_list - a cipher scheme list
  * @size: a number of entries
@@ -151,11 +322,6 @@
  * @inst_errlog_ptr: error log offfset for runtime ucode.
  * @mvm_fw: indicates this is MVM firmware
  * @cipher_scheme: optional external cipher scheme.
- * @human_readable: human readable version
- * @dbg_dest_tlv: points to the destination TLV for debug
- * @dbg_conf_tlv: array of pointers to configuration TLVs for debug
- * @dbg_conf_tlv_len: lengths of the @dbg_conf_tlv entries
- * @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv
  */
 struct iwl_fw {
 	u32 ucode_ver;
@@ -180,68 +346,6 @@
 
 	struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
 	u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
-
-	struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
-	struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
-	size_t dbg_conf_tlv_len[FW_DBG_MAX];
-
-	u8 dbg_dest_reg_num;
 };
 
-static inline const char *get_fw_dbg_mode_string(int mode)
-{
-	switch (mode) {
-	case SMEM_MODE:
-		return "SMEM";
-	case EXTERNAL_MODE:
-		return "EXTERNAL_DRAM";
-	case MARBH_MODE:
-		return "MARBH";
-	default:
-		return "UNKNOWN";
-	}
-}
-
-static inline const struct iwl_fw_dbg_trigger *
-iwl_fw_dbg_conf_get_trigger(const struct iwl_fw *fw, u8 id)
-{
-	const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg_conf_tlv[id];
-	u8 *ptr;
-	int i;
-
-	if (!conf_tlv)
-		return NULL;
-
-	ptr = (void *)&conf_tlv->hcmd;
-	for (i = 0; i < conf_tlv->num_of_hcmds; i++) {
-		ptr += sizeof(conf_tlv->hcmd);
-		ptr += le16_to_cpu(conf_tlv->hcmd.len);
-	}
-
-	return (const struct iwl_fw_dbg_trigger *)ptr;
-}
-
-static inline bool
-iwl_fw_dbg_conf_enabled(const struct iwl_fw *fw, u8 id)
-{
-	const struct iwl_fw_dbg_trigger *trigger =
-		iwl_fw_dbg_conf_get_trigger(fw, id);
-
-	if (!trigger)
-		return false;
-
-	return trigger->enabled;
-}
-
-static inline bool
-iwl_fw_dbg_conf_usniffer(const struct iwl_fw *fw, u8 id)
-{
-	const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg_conf_tlv[id];
-
-	if (!conf_tlv)
-		return false;
-
-	return conf_tlv->usniffer;
-}
-
 #endif  /* __iwl_fw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 06e02fc..c302e74 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -325,8 +325,6 @@
 {
 	int num_rx_ants = num_of_ant(rx_chains);
 	int num_tx_ants = num_of_ant(tx_chains);
-	unsigned int max_ampdu_exponent = (cfg->max_vht_ampdu_exponent ?:
-					   IEEE80211_VHT_MAX_AMPDU_1024K);
 
 	vht_cap->vht_supported = true;
 
@@ -334,8 +332,7 @@
 		       IEEE80211_VHT_CAP_RXSTBC_1 |
 		       IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
 		       3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
-		       max_ampdu_exponent <<
-		       IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+		       7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
 
 	if (cfg->ht_params->ldpc)
 		vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC;
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index 17de6d4..b6d666e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -138,8 +138,7 @@
  * @nic_config: configure NIC, called before firmware is started.
  *	May sleep
  * @wimax_active: invoked when WiMax becomes active. May sleep
- * @enter_d0i3: configure the fw to enter d0i3. return 1 to indicate d0i3
- *	entrance is aborted (e.g. due to held reference). May sleep.
+ * @enter_d0i3: configure the fw to enter d0i3. May sleep.
  * @exit_d0i3: configure the fw to exit d0i3. May sleep.
  */
 struct iwl_op_mode_ops {
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 2df51ea..1560f45 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -322,7 +322,6 @@
 	LMPM_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ	= 0x00000002,
 };
 
-#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0	(0xA01E30)
 #define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR	(0x1E30)
 #define LMPM_SECURE_BOOT_CPU2_STATUS_ADDR	(0x1E34)
 enum secure_boot_status_reg {
@@ -334,7 +333,6 @@
 	LMPM_SECURE_BOOT_STATUS_SUCCESS			= 0x00000003,
 };
 
-#define FH_UCODE_LOAD_STATUS		(0x1AF0)
 #define CSR_UCODE_LOAD_STATUS_ADDR	(0x1E70)
 enum secure_load_status_reg {
 	LMPM_CPU_UCODE_LOADING_STARTED			= 0x00000001,
@@ -354,7 +352,7 @@
 #define LMPM_SECURE_CPU1_HDR_MEM_SPACE		(0x420000)
 #define LMPM_SECURE_CPU2_HDR_MEM_SPACE		(0x420400)
 
-#define LMPM_SECURE_TIME_OUT	(100) /* 10 micro */
+#define LMPM_SECURE_TIME_OUT	(100)
 
 /* Rx FIFO */
 #define RXF_SIZE_ADDR			(0xa00c88)
@@ -370,10 +368,4 @@
 #define MON_BUFF_WRPTR			(0xa03c44)
 #define MON_BUFF_CYCLE_CNT		(0xa03c48)
 
-/* FW chicken bits */
-#define LMPM_CHICK			0xA01FF8
-enum {
-	LMPM_CHICK_EXTENDED_ADDR_SPACE = BIT(0),
-};
-
 #endif				/* __iwl_prph_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 028408a..98b4c95 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -534,10 +534,10 @@
 			      u32 value);
 	void (*ref)(struct iwl_trans *trans);
 	void (*unref)(struct iwl_trans *trans);
-	void (*suspend)(struct iwl_trans *trans);
-	void (*resume)(struct iwl_trans *trans);
 
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
 	struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
+#endif
 };
 
 /**
@@ -563,7 +563,6 @@
  *	Set during transport allocation.
  * @hw_id_str: a string with info about HW ID. Set during transport allocation.
  * @pm_support: set to true in start_hw if link pm is supported
- * @ltr_enabled: set to true if the LTR is enabled
  * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
  *	The user should use iwl_trans_{alloc,free}_tx_cmd.
  * @dev_cmd_headroom: room needed for the transport's private use before the
@@ -574,9 +573,6 @@
  * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
  *	start of the 802.11 header in the @rx_mpdu_cmd
  * @dflt_pwr_limit: default power limit fetched from the platform (ACPI)
- * @dbg_dest_tlv: points to the destination TLV for debug
- * @dbg_conf_tlv: array of pointers to configuration TLVs for debug
- * @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv
  */
 struct iwl_trans {
 	const struct iwl_trans_ops *ops;
@@ -593,7 +589,6 @@
 	u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
 
 	bool pm_support;
-	bool ltr_enabled;
 
 	/* The following fields are internal only */
 	struct kmem_cache *dev_cmd_pool;
@@ -608,10 +603,6 @@
 
 	u64 dflt_pwr_limit;
 
-	const struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
-	const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
-	u8 dbg_dest_reg_num;
-
 	/* pointer to trans specific struct */
 	/*Ensure that this pointer will always be aligned to sizeof pointer */
 	char trans_specific[0] __aligned(sizeof(void *));
@@ -711,18 +702,7 @@
 		trans->ops->unref(trans);
 }
 
-static inline void iwl_trans_suspend(struct iwl_trans *trans)
-{
-	if (trans->ops->suspend)
-		trans->ops->suspend(trans);
-}
-
-static inline void iwl_trans_resume(struct iwl_trans *trans)
-{
-	if (trans->ops->resume)
-		trans->ops->resume(trans);
-}
-
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
 static inline struct iwl_trans_dump_data *
 iwl_trans_dump_data(struct iwl_trans *trans)
 {
@@ -730,6 +710,7 @@
 		return NULL;
 	return trans->ops->dump_data(trans);
 }
+#endif
 
 static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
 				     struct iwl_host_cmd *cmd)
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index a3bfda4..8df2021 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -72,6 +72,8 @@
 #include "mvm.h"
 #include "iwl-debug.h"
 
+#define BT_ANTENNA_COUPLING_THRESHOLD		(30)
+
 const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
 	[BT_KILL_MSK_DEFAULT] = 0xfffffc00,
 	[BT_KILL_MSK_NEVER] = 0xffffffff,
@@ -300,6 +302,11 @@
 	},
 };
 
+static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
+	cpu_to_le32(0x28412201),
+	cpu_to_le32(0x11118451),
+};
+
 struct corunning_block_luts {
 	u8 range;
 	__le32 lut20[BT_COEX_CORUN_LUT_SIZE];
@@ -598,7 +605,7 @@
 
 	bt_cmd->max_kill = cpu_to_le32(5);
 	bt_cmd->bt4_antenna_isolation_thr =
-		cpu_to_le32(IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS);
+				cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD);
 	bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15);
 	bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15);
 	bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
@@ -631,8 +638,8 @@
 
 	memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost,
 	       sizeof(iwl_bt_prio_boost));
-	bt_cmd->multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0);
-	bt_cmd->multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1);
+	memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut,
+	       sizeof(iwl_bt_mprio_lut));
 
 send_cmd:
 	memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
@@ -1137,22 +1144,6 @@
 	return lut_type != BT_COEX_LOOSE_LUT;
 }
 
-bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
-{
-	/* there is no other antenna, shared antenna is always available */
-	if (mvm->cfg->bt_shared_single_ant)
-		return true;
-
-	if (ant & mvm->cfg->non_shared_ant)
-		return true;
-
-	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
-		return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm);
-
-	return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
-		BT_HIGH_TRAFFIC;
-}
-
 bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
 {
 	/* there is no other antenna, shared antenna is always available */
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
index b3210cf..585c0ab 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
@@ -102,6 +102,8 @@
 
 #undef EVENT_PRIO_ANT
 
+#define BT_ANTENNA_COUPLING_THRESHOLD		(30)
+
 static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
 {
 	if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
@@ -288,6 +290,11 @@
 	},
 };
 
+static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
+	cpu_to_le32(0x28412201),
+	cpu_to_le32(0x11118451),
+};
+
 struct corunning_block_luts {
 	u8 range;
 	__le32 lut20[BT_COEX_CORUN_LUT_SIZE];
@@ -586,8 +593,7 @@
 	}
 
 	bt_cmd->max_kill = 5;
-	bt_cmd->bt4_antenna_isolation_thr =
-		IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS;
+	bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
 	bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
 	bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
 	bt_cmd->bt4_tx_rx_max_freq0 = 15;
@@ -612,9 +618,7 @@
 					    BT_VALID_ANT_ISOLATION_THRS |
 					    BT_VALID_TXTX_DELTA_FREQ_THRS |
 					    BT_VALID_TXRX_MAX_FREQ_0 |
-					    BT_VALID_SYNC_TO_SCO |
-					    BT_VALID_TTC |
-					    BT_VALID_RRC);
+					    BT_VALID_SYNC_TO_SCO);
 
 	if (IWL_MVM_BT_COEX_SYNC2SCO)
 		bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
@@ -630,12 +634,6 @@
 		bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
 	}
 
-	if (IWL_MVM_BT_COEX_TTC)
-		bt_cmd->flags |= cpu_to_le32(BT_COEX_TTC);
-
-	if (IWL_MVM_BT_COEX_RRC)
-		bt_cmd->flags |= cpu_to_le32(BT_COEX_RRC);
-
 	if (mvm->cfg->bt_shared_single_ant)
 		memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
 		       sizeof(iwl_single_shared_ant));
@@ -651,8 +649,8 @@
 
 	memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
 	       sizeof(iwl_bt_prio_boost));
-	bt_cmd->bt4_multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0);
-	bt_cmd->bt4_multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1);
+	memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
+	       sizeof(iwl_bt_mprio_lut));
 
 send_cmd:
 	memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
@@ -832,9 +830,6 @@
 	if (!vif->bss_conf.assoc)
 		smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
-	if (data->notif->rrc_enabled & BIT(mvmvif->phy_ctxt->id))
-		smps_mode = IEEE80211_SMPS_AUTOMATIC;
-
 	IWL_DEBUG_COEX(data->mvm,
 		       "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
 		       mvmvif->id, data->notif->bt_status, bt_activity_grading,
@@ -1167,12 +1162,6 @@
 	return lut_type != BT_COEX_LOOSE_LUT;
 }
 
-bool iwl_mvm_bt_coex_is_ant_avail_old(struct iwl_mvm *mvm, u8 ant)
-{
-	u32 ag = le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
-	return ag < BT_HIGH_TRAFFIC;
-}
-
 bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm)
 {
 	u32 ag = le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
index 3bd9347..d4dfbe4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -92,15 +92,8 @@
 #define IWL_MVM_BT_COEX_SYNC2SCO		1
 #define IWL_MVM_BT_COEX_CORUNNING		0
 #define IWL_MVM_BT_COEX_MPLUT			1
-#define IWL_MVM_BT_COEX_RRC			1
-#define IWL_MVM_BT_COEX_TTC			1
-#define IWL_MVM_BT_COEX_MPLUT_REG0		0x28412201
-#define IWL_MVM_BT_COEX_MPLUT_REG1		0x11118451
-#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS	30
 #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL	0
-#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL	0
 #define IWL_MVM_QUOTA_THRESHOLD			8
 #define IWL_MVM_RS_RSSI_BASED_INIT_RATE         0
-#define IWL_MVM_RS_DISABLE_MIMO			0
 
 #endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index db454c8..d45d6df 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -601,6 +601,33 @@
 	return ret;
 }
 
+struct iwl_d3_iter_data {
+	struct iwl_mvm *mvm;
+	struct ieee80211_vif *vif;
+	bool error;
+};
+
+static void iwl_mvm_d3_iface_iterator(void *_data, u8 *mac,
+				      struct ieee80211_vif *vif)
+{
+	struct iwl_d3_iter_data *data = _data;
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
+		return;
+
+	if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+		return;
+
+	if (data->vif) {
+		IWL_ERR(data->mvm, "More than one managed interface active!\n");
+		data->error = true;
+		return;
+	}
+
+	data->vif = vif;
+}
+
 static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 				struct ieee80211_sta *ap_sta)
 {
@@ -756,8 +783,144 @@
 		IWL_ERR(mvm, "failed to set non-QoS seqno\n");
 }
 
-static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
+static int
+iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm,
+			       const struct iwl_wowlan_config_cmd_v3 *cmd)
 {
+	/* start only with the v2 part of the command */
+	u16 cmd_len = sizeof(cmd->common);
+
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID)
+		cmd_len = sizeof(*cmd);
+
+	return iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
+				    cmd_len, cmd);
+}
+
+static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
+			     struct cfg80211_wowlan *wowlan,
+			     bool test)
+{
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	struct iwl_d3_iter_data suspend_iter_data = {
+		.mvm = mvm,
+	};
+	struct ieee80211_vif *vif;
+	struct iwl_mvm_vif *mvmvif;
+	struct ieee80211_sta *ap_sta;
+	struct iwl_mvm_sta *mvm_ap_sta;
+	struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {};
+	struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
+	struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
+	struct iwl_d3_manager_config d3_cfg_cmd_data = {
+		/*
+		 * Program the minimum sleep time to 10 seconds, as many
+		 * platforms have issues processing a wakeup signal while
+		 * still being in the process of suspending.
+		 */
+		.min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
+	};
+	struct iwl_host_cmd d3_cfg_cmd = {
+		.id = D3_CONFIG_CMD,
+		.flags = CMD_WANT_SKB,
+		.data[0] = &d3_cfg_cmd_data,
+		.len[0] = sizeof(d3_cfg_cmd_data),
+	};
+	struct wowlan_key_data key_data = {
+		.use_rsc_tsc = false,
+		.tkip = &tkip_cmd,
+		.use_tkip = false,
+	};
+	int ret;
+	int len __maybe_unused;
+
+	if (!wowlan) {
+		/*
+		 * mac80211 shouldn't get here, but for D3 test
+		 * it doesn't warrant a warning
+		 */
+		WARN_ON(!test);
+		return -EINVAL;
+	}
+
+	key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
+	if (!key_data.rsc_tsc)
+		return -ENOMEM;
+
+	mutex_lock(&mvm->mutex);
+
+	/* see if there's only a single BSS vif and it's associated */
+	ieee80211_iterate_active_interfaces_atomic(
+		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+		iwl_mvm_d3_iface_iterator, &suspend_iter_data);
+
+	if (suspend_iter_data.error || !suspend_iter_data.vif) {
+		ret = 1;
+		goto out_noreset;
+	}
+
+	vif = suspend_iter_data.vif;
+	mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+	ap_sta = rcu_dereference_protected(
+			mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
+			lockdep_is_held(&mvm->mutex));
+	if (IS_ERR_OR_NULL(ap_sta)) {
+		ret = -EINVAL;
+		goto out_noreset;
+	}
+
+	mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
+
+	/* TODO: wowlan_config_cmd.common.wowlan_ba_teardown_tids */
+
+	wowlan_config_cmd.common.is_11n_connection =
+					ap_sta->ht_cap.ht_supported;
+
+	/* Query the last used seqno and set it */
+	ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
+	if (ret < 0)
+		goto out_noreset;
+	wowlan_config_cmd.common.non_qos_seq = cpu_to_le16(ret);
+
+	iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd.common);
+
+	if (wowlan->disconnect)
+		wowlan_config_cmd.common.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
+				    IWL_WOWLAN_WAKEUP_LINK_CHANGE);
+	if (wowlan->magic_pkt)
+		wowlan_config_cmd.common.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET);
+	if (wowlan->gtk_rekey_failure)
+		wowlan_config_cmd.common.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
+	if (wowlan->eap_identity_req)
+		wowlan_config_cmd.common.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ);
+	if (wowlan->four_way_handshake)
+		wowlan_config_cmd.common.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
+	if (wowlan->n_patterns)
+		wowlan_config_cmd.common.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
+
+	if (wowlan->rfkill_release)
+		wowlan_config_cmd.common.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
+
+	if (wowlan->tcp) {
+		/*
+		 * Set the "link change" (really "link lost") flag as well
+		 * since that implies losing the TCP connection.
+		 */
+		wowlan_config_cmd.common.wakeup_filter |=
+			cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
+				    IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE |
+				    IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET |
+				    IWL_WOWLAN_WAKEUP_LINK_CHANGE);
+	}
+
 	iwl_mvm_cancel_scan(mvm);
 
 	iwl_trans_stop_device(mvm->trans);
@@ -782,99 +945,13 @@
 	mvm->ptk_ivlen = 0;
 	mvm->ptk_icvlen = 0;
 
-	return iwl_mvm_load_d3_fw(mvm);
-}
-
-static int
-iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
-			  struct cfg80211_wowlan *wowlan,
-			  struct iwl_wowlan_config_cmd *wowlan_config_cmd,
-			  struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
-			  struct ieee80211_sta *ap_sta)
-{
-	int ret;
-	struct iwl_mvm_sta *mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
-
-	/* TODO: wowlan_config_cmd->wowlan_ba_teardown_tids */
-
-	wowlan_config_cmd->is_11n_connection =
-					ap_sta->ht_cap.ht_supported;
-
-	/* Query the last used seqno and set it */
-	ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
-	if (ret < 0)
-		return ret;
-
-	wowlan_config_cmd->non_qos_seq = cpu_to_le16(ret);
-
-	iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, wowlan_config_cmd);
-
-	if (wowlan->disconnect)
-		wowlan_config_cmd->wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
-				    IWL_WOWLAN_WAKEUP_LINK_CHANGE);
-	if (wowlan->magic_pkt)
-		wowlan_config_cmd->wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET);
-	if (wowlan->gtk_rekey_failure)
-		wowlan_config_cmd->wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
-	if (wowlan->eap_identity_req)
-		wowlan_config_cmd->wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ);
-	if (wowlan->four_way_handshake)
-		wowlan_config_cmd->wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
-	if (wowlan->n_patterns)
-		wowlan_config_cmd->wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
-
-	if (wowlan->rfkill_release)
-		wowlan_config_cmd->wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
-
-	if (wowlan->tcp) {
-		/*
-		 * Set the "link change" (really "link lost") flag as well
-		 * since that implies losing the TCP connection.
-		 */
-		wowlan_config_cmd->wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
-				    IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE |
-				    IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET |
-				    IWL_WOWLAN_WAKEUP_LINK_CHANGE);
-	}
-
-	return 0;
-}
-
-static int
-iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
-		      struct cfg80211_wowlan *wowlan,
-		      struct iwl_wowlan_config_cmd *wowlan_config_cmd,
-		      struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
-		      struct ieee80211_sta *ap_sta)
-{
-	struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
-	struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
-	struct wowlan_key_data key_data = {
-		.use_rsc_tsc = false,
-		.tkip = &tkip_cmd,
-		.use_tkip = false,
-	};
-	int ret;
-
-	ret = iwl_mvm_switch_to_d3(mvm);
+	ret = iwl_mvm_load_d3_fw(mvm);
 	if (ret)
-		return ret;
+		goto out;
 
 	ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta);
 	if (ret)
-		return ret;
-
-	key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
-	if (!key_data.rsc_tsc)
-		return -ENOMEM;
+		goto out;
 
 	if (!iwlwifi_mod_params.sw_crypto) {
 		/*
@@ -933,9 +1010,7 @@
 		}
 	}
 
-	ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
-				   sizeof(*wowlan_config_cmd),
-				   wowlan_config_cmd);
+	ret = iwl_mvm_send_wowlan_config_cmd(mvm, &wowlan_config_cmd);
 	if (ret)
 		goto out;
 
@@ -948,153 +1023,8 @@
 		goto out;
 
 	ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp);
-
-out:
-	kfree(key_data.rsc_tsc);
-	return ret;
-}
-
-static int
-iwl_mvm_netdetect_config(struct iwl_mvm *mvm,
-			 struct cfg80211_wowlan *wowlan,
-			 struct cfg80211_sched_scan_request *nd_config,
-			 struct ieee80211_vif *vif)
-{
-	struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
-	int ret;
-
-	ret = iwl_mvm_switch_to_d3(mvm);
 	if (ret)
-		return ret;
-
-	/* rfkill release can be either for wowlan or netdetect */
-	if (wowlan->rfkill_release)
-		wowlan_config_cmd.wakeup_filter |=
-			cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
-
-	ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
-				   sizeof(wowlan_config_cmd),
-				   &wowlan_config_cmd);
-	if (ret)
-		return ret;
-
-	ret = iwl_mvm_scan_offload_start(mvm, vif, nd_config, &mvm->nd_ies);
-	if (ret)
-		return ret;
-
-	if (WARN_ON(mvm->nd_match_sets || mvm->nd_channels))
-		return -EBUSY;
-
-	/* save the sched scan matchsets... */
-	if (nd_config->n_match_sets) {
-		mvm->nd_match_sets = kmemdup(nd_config->match_sets,
-					     sizeof(*nd_config->match_sets) *
-					     nd_config->n_match_sets,
-					     GFP_KERNEL);
-		if (mvm->nd_match_sets)
-			mvm->n_nd_match_sets = nd_config->n_match_sets;
-	}
-
-	/* ...and the sched scan channels for later reporting */
-	mvm->nd_channels = kmemdup(nd_config->channels,
-				   sizeof(*nd_config->channels) *
-				   nd_config->n_channels,
-				   GFP_KERNEL);
-	if (mvm->nd_channels)
-		mvm->n_nd_channels = nd_config->n_channels;
-
-	return 0;
-}
-
-static void iwl_mvm_free_nd(struct iwl_mvm *mvm)
-{
-	kfree(mvm->nd_match_sets);
-	mvm->nd_match_sets = NULL;
-	mvm->n_nd_match_sets = 0;
-	kfree(mvm->nd_channels);
-	mvm->nd_channels = NULL;
-	mvm->n_nd_channels = 0;
-}
-
-static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
-			     struct cfg80211_wowlan *wowlan,
-			     bool test)
-{
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-	struct ieee80211_vif *vif = NULL;
-	struct iwl_mvm_vif *mvmvif = NULL;
-	struct ieee80211_sta *ap_sta = NULL;
-	struct iwl_d3_manager_config d3_cfg_cmd_data = {
-		/*
-		 * Program the minimum sleep time to 10 seconds, as many
-		 * platforms have issues processing a wakeup signal while
-		 * still being in the process of suspending.
-		 */
-		.min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
-	};
-	struct iwl_host_cmd d3_cfg_cmd = {
-		.id = D3_CONFIG_CMD,
-		.flags = CMD_WANT_SKB,
-		.data[0] = &d3_cfg_cmd_data,
-		.len[0] = sizeof(d3_cfg_cmd_data),
-	};
-	int ret;
-	int len __maybe_unused;
-
-	if (!wowlan) {
-		/*
-		 * mac80211 shouldn't get here, but for D3 test
-		 * it doesn't warrant a warning
-		 */
-		WARN_ON(!test);
-		return -EINVAL;
-	}
-
-	mutex_lock(&mvm->mutex);
-
-	vif = iwl_mvm_get_bss_vif(mvm);
-	if (IS_ERR_OR_NULL(vif)) {
-		ret = 1;
-		goto out_noreset;
-	}
-
-	mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
-	if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) {
-		/* if we're not associated, this must be netdetect */
-		if (!wowlan->nd_config && !mvm->nd_config) {
-			ret = 1;
-			goto out_noreset;
-		}
-
-		ret = iwl_mvm_netdetect_config(
-			mvm, wowlan, wowlan->nd_config ?: mvm->nd_config, vif);
-		if (ret)
-			goto out;
-
-		mvm->net_detect = true;
-	} else {
-		struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
-
-		ap_sta = rcu_dereference_protected(
-			mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
-			lockdep_is_held(&mvm->mutex));
-		if (IS_ERR_OR_NULL(ap_sta)) {
-			ret = -EINVAL;
-			goto out_noreset;
-		}
-
-		ret = iwl_mvm_get_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
-						vif, mvmvif, ap_sta);
-		if (ret)
-			goto out_noreset;
-		ret = iwl_mvm_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
-					    vif, mvmvif, ap_sta);
-		if (ret)
-			goto out;
-
-		mvm->net_detect = false;
-	}
+		goto out;
 
 	ret = iwl_mvm_power_update_device(mvm);
 	if (ret)
@@ -1127,11 +1057,11 @@
 
 	iwl_trans_d3_suspend(mvm->trans, test);
  out:
-	if (ret < 0) {
+	if (ret < 0)
 		ieee80211_restart_hw(mvm->hw);
-		iwl_mvm_free_nd(mvm);
-	}
  out_noreset:
+	kfree(key_data.rsc_tsc);
+
 	mutex_unlock(&mvm->mutex);
 
 	return ret;
@@ -1141,7 +1071,6 @@
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
-	iwl_trans_suspend(mvm->trans);
 	if (iwl_mvm_is_d0i3_supported(mvm)) {
 		mutex_lock(&mvm->d0i3_suspend_mutex);
 		__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
@@ -1520,8 +1449,9 @@
 	return true;
 }
 
-static struct iwl_wowlan_status *
-iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+/* releases the MVM mutex */
+static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
+					 struct ieee80211_vif *vif)
 {
 	u32 base = mvm->error_event_table;
 	struct error_table_start {
@@ -1533,15 +1463,19 @@
 		.id = WOWLAN_GET_STATUSES,
 		.flags = CMD_WANT_SKB,
 	};
-	struct iwl_wowlan_status *status, *fw_status;
-	int ret, len, status_size;
+	struct iwl_wowlan_status_data status;
+	struct iwl_wowlan_status *fw_status;
+	int ret, len, status_size, i;
+	bool keep;
+	struct ieee80211_sta *ap_sta;
+	struct iwl_mvm_sta *mvm_ap_sta;
 
 	iwl_trans_read_mem_bytes(mvm->trans, base,
 				 &err_info, sizeof(err_info));
 
 	if (err_info.valid) {
-		IWL_INFO(mvm, "error table is valid (%d) with error (%d)\n",
-			 err_info.valid, err_info.error_id);
+		IWL_INFO(mvm, "error table is valid (%d)\n",
+			 err_info.valid);
 		if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
 			struct cfg80211_wowlan_wakeup wakeup = {
 				.rfkill_release = true,
@@ -1549,7 +1483,7 @@
 			ieee80211_report_wowlan_wakeup(vif, &wakeup,
 						       GFP_KERNEL);
 		}
-		return ERR_PTR(-EIO);
+		goto out_unlock;
 	}
 
 	/* only for tracing for now */
@@ -1560,53 +1494,22 @@
 	ret = iwl_mvm_send_cmd(mvm, &cmd);
 	if (ret) {
 		IWL_ERR(mvm, "failed to query status (%d)\n", ret);
-		return ERR_PTR(ret);
+		goto out_unlock;
 	}
 
 	/* RF-kill already asserted again... */
-	if (!cmd.resp_pkt) {
-		ret = -ERFKILL;
-		goto out_free_resp;
-	}
+	if (!cmd.resp_pkt)
+		goto out_unlock;
 
 	status_size = sizeof(*fw_status);
 
 	len = iwl_rx_packet_payload_len(cmd.resp_pkt);
 	if (len < status_size) {
 		IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
-		ret = -EIO;
 		goto out_free_resp;
 	}
 
-	status = (void *)cmd.resp_pkt->data;
-	if (len != (status_size +
-		    ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4))) {
-		IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
-		ret = -EIO;
-		goto out_free_resp;
-	}
-
-	fw_status = kmemdup(status, len, GFP_KERNEL);
-
-out_free_resp:
-	iwl_free_resp(&cmd);
-	return ret ? ERR_PTR(ret) : fw_status;
-}
-
-/* releases the MVM mutex */
-static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
-					 struct ieee80211_vif *vif)
-{
-	struct iwl_wowlan_status_data status;
-	struct iwl_wowlan_status *fw_status;
-	int i;
-	bool keep;
-	struct ieee80211_sta *ap_sta;
-	struct iwl_mvm_sta *mvm_ap_sta;
-
-	fw_status = iwl_mvm_get_wakeup_status(mvm, vif);
-	if (IS_ERR_OR_NULL(fw_status))
-		goto out_unlock;
+	fw_status = (void *)cmd.resp_pkt->data;
 
 	status.pattern_number = le16_to_cpu(fw_status->pattern_number);
 	for (i = 0; i < 8; i++)
@@ -1619,12 +1522,17 @@
 		le32_to_cpu(fw_status->wake_packet_bufsize);
 	status.wake_packet = fw_status->wake_packet;
 
+	if (len != status_size + ALIGN(status.wake_packet_bufsize, 4)) {
+		IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
+		goto out_free_resp;
+	}
+
 	/* still at hard-coded place 0 for D3 image */
 	ap_sta = rcu_dereference_protected(
 			mvm->fw_id_to_mac_id[0],
 			lockdep_is_held(&mvm->mutex));
 	if (IS_ERR_OR_NULL(ap_sta))
-		goto out_free;
+		goto out_free_resp;
 
 	mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
 	for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
@@ -1641,151 +1549,16 @@
 
 	keep = iwl_mvm_setup_connection_keep(mvm, vif, fw_status);
 
-	kfree(fw_status);
+	iwl_free_resp(&cmd);
 	return keep;
 
-out_free:
-	kfree(fw_status);
-out_unlock:
+ out_free_resp:
+	iwl_free_resp(&cmd);
+ out_unlock:
 	mutex_unlock(&mvm->mutex);
 	return false;
 }
 
-struct iwl_mvm_nd_query_results {
-	u32 matched_profiles;
-	struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
-};
-
-static int
-iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
-				struct iwl_mvm_nd_query_results *results)
-{
-	struct iwl_scan_offload_profiles_query *query;
-	struct iwl_host_cmd cmd = {
-		.id = SCAN_OFFLOAD_PROFILES_QUERY_CMD,
-		.flags = CMD_WANT_SKB,
-	};
-	int ret, len;
-
-	ret = iwl_mvm_send_cmd(mvm, &cmd);
-	if (ret) {
-		IWL_ERR(mvm, "failed to query matched profiles (%d)\n", ret);
-		return ret;
-	}
-
-	/* RF-kill already asserted again... */
-	if (!cmd.resp_pkt) {
-		ret = -ERFKILL;
-		goto out_free_resp;
-	}
-
-	len = iwl_rx_packet_payload_len(cmd.resp_pkt);
-	if (len < sizeof(*query)) {
-		IWL_ERR(mvm, "Invalid scan offload profiles query response!\n");
-		ret = -EIO;
-		goto out_free_resp;
-	}
-
-	query = (void *)cmd.resp_pkt->data;
-
-	results->matched_profiles = le32_to_cpu(query->matched_profiles);
-	memcpy(results->matches, query->matches, sizeof(results->matches));
-
-out_free_resp:
-	iwl_free_resp(&cmd);
-	return ret;
-}
-
-static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
-					    struct ieee80211_vif *vif)
-{
-	struct cfg80211_wowlan_nd_info *net_detect = NULL;
-	struct cfg80211_wowlan_wakeup wakeup = {
-		.pattern_idx = -1,
-	};
-	struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;
-	struct iwl_mvm_nd_query_results query;
-	struct iwl_wowlan_status *fw_status;
-	unsigned long matched_profiles;
-	u32 reasons = 0;
-	int i, j, n_matches, ret;
-
-	fw_status = iwl_mvm_get_wakeup_status(mvm, vif);
-	if (!IS_ERR_OR_NULL(fw_status))
-		reasons = le32_to_cpu(fw_status->wakeup_reasons);
-
-	if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
-		wakeup.rfkill_release = true;
-
-	if (reasons != IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS)
-		goto out;
-
-	ret = iwl_mvm_netdetect_query_results(mvm, &query);
-	if (ret || !query.matched_profiles) {
-		wakeup_report = NULL;
-		goto out;
-	}
-
-	matched_profiles = query.matched_profiles;
-	if (mvm->n_nd_match_sets) {
-		n_matches = hweight_long(matched_profiles);
-	} else {
-		IWL_ERR(mvm, "no net detect match information available\n");
-		n_matches = 0;
-	}
-
-	net_detect = kzalloc(sizeof(*net_detect) +
-			     (n_matches * sizeof(net_detect->matches[0])),
-			     GFP_KERNEL);
-	if (!net_detect || !n_matches)
-		goto out_report_nd;
-
-	for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {
-		struct iwl_scan_offload_profile_match *fw_match;
-		struct cfg80211_wowlan_nd_match *match;
-		int n_channels = 0;
-
-		fw_match = &query.matches[i];
-
-		for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
-			n_channels += hweight8(fw_match->matching_channels[j]);
-
-		match = kzalloc(sizeof(*match) +
-				(n_channels * sizeof(*match->channels)),
-				GFP_KERNEL);
-		if (!match)
-			goto out_report_nd;
-
-		net_detect->matches[net_detect->n_matches++] = match;
-
-		match->ssid.ssid_len = mvm->nd_match_sets[i].ssid.ssid_len;
-		memcpy(match->ssid.ssid, mvm->nd_match_sets[i].ssid.ssid,
-		       match->ssid.ssid_len);
-
-		if (mvm->n_nd_channels < n_channels)
-			continue;
-
-		for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; j++)
-			if (fw_match->matching_channels[j / 8] & (BIT(j % 8)))
-				match->channels[match->n_channels++] =
-					mvm->nd_channels[j]->center_freq;
-	}
-
-out_report_nd:
-	wakeup.net_detect = net_detect;
-out:
-	iwl_mvm_free_nd(mvm);
-
-	mutex_unlock(&mvm->mutex);
-	ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);
-
-	if (net_detect) {
-		for (i = 0; i < net_detect->n_matches; i++)
-			kfree(net_detect->matches[i]);
-		kfree(net_detect);
-	}
-}
-
 static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
 {
 #ifdef CPTCFG_IWLWIFI_DEBUGFS
@@ -1819,6 +1592,9 @@
 
 static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
 {
+	struct iwl_d3_iter_data resume_iter_data = {
+		.mvm = mvm,
+	};
 	struct ieee80211_vif *vif = NULL;
 	int ret;
 	enum iwl_d3_status d3_status;
@@ -1827,10 +1603,15 @@
 	mutex_lock(&mvm->mutex);
 
 	/* get the BSS vif pointer again */
-	vif = iwl_mvm_get_bss_vif(mvm);
-	if (IS_ERR_OR_NULL(vif))
+	ieee80211_iterate_active_interfaces_atomic(
+		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+		iwl_mvm_d3_iface_iterator, &resume_iter_data);
+
+	if (WARN_ON(resume_iter_data.error || !resume_iter_data.vif))
 		goto out_unlock;
 
+	vif = resume_iter_data.vif;
+
 	ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test);
 	if (ret)
 		goto out_unlock;
@@ -1843,15 +1624,11 @@
 	/* query SRAM first in case we want event logging */
 	iwl_mvm_read_d3_sram(mvm);
 
-	if (mvm->net_detect) {
-		iwl_mvm_query_netdetect_reasons(mvm, vif);
-	} else {
-		keep = iwl_mvm_query_wakeup_reasons(mvm, vif);
+	keep = iwl_mvm_query_wakeup_reasons(mvm, vif);
 #ifdef CPTCFG_IWLWIFI_DEBUGFS
-		if (keep)
-			mvm->keep_vif = vif;
+	if (keep)
+		mvm->keep_vif = vif;
 #endif
-	}
 	/* has unlocked the mutex, so skip that */
 	goto out;
 
@@ -1866,7 +1643,6 @@
 
 	/* return 1 to reconfigure the device */
 	set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
-	set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
 	return 1;
 }
 
@@ -1874,10 +1650,18 @@
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
-	iwl_trans_resume(mvm->trans);
+	if (iwl_mvm_is_d0i3_supported(mvm)) {
+		bool exit_now;
 
-	if (iwl_mvm_is_d0i3_supported(mvm))
+		mutex_lock(&mvm->d0i3_suspend_mutex);
+		__clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
+		exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP,
+						&mvm->d0i3_suspend_flags);
+		mutex_unlock(&mvm->d0i3_suspend_mutex);
+		if (exit_now)
+			_iwl_mvm_exit_d0i3(mvm);
 		return 0;
+	}
 
 	return __iwl_mvm_resume(mvm, false);
 }
@@ -1957,9 +1741,7 @@
 	int remaining_time = 10;
 
 	mvm->d3_test_active = false;
-	rtnl_lock();
 	__iwl_mvm_resume(mvm, true);
-	rtnl_unlock();
 	iwl_abort_notification_waits(&mvm->notif_wait);
 	ieee80211_restart_hw(mvm->hw);
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 2c87e2d..7765c2b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -121,6 +121,78 @@
 	return ret;
 }
 
+static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
+{
+	struct iwl_mvm *mvm = inode->i_private;
+	int ret;
+
+	if (!mvm)
+		return -EINVAL;
+
+	mutex_lock(&mvm->mutex);
+	if (!mvm->fw_error_dump) {
+		ret = -ENODATA;
+		goto out;
+	}
+
+	file->private_data = mvm->fw_error_dump;
+	mvm->fw_error_dump = NULL;
+	ret = 0;
+
+out:
+	mutex_unlock(&mvm->mutex);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
+					    char __user *user_buf,
+					    size_t count, loff_t *ppos)
+{
+	struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
+	ssize_t bytes_read = 0;
+	ssize_t bytes_read_trans = 0;
+
+	if (*ppos < dump_ptrs->op_mode_len)
+		bytes_read +=
+			simple_read_from_buffer(user_buf, count, ppos,
+						dump_ptrs->op_mode_ptr,
+						dump_ptrs->op_mode_len);
+
+	if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
+		return bytes_read;
+
+	if (dump_ptrs->trans_ptr) {
+		*ppos -= dump_ptrs->op_mode_len;
+		bytes_read_trans =
+			simple_read_from_buffer(user_buf + bytes_read,
+						count - bytes_read, ppos,
+						dump_ptrs->trans_ptr->data,
+						dump_ptrs->trans_ptr->len);
+		*ppos += dump_ptrs->op_mode_len;
+
+		if (bytes_read_trans >= 0)
+			bytes_read += bytes_read_trans;
+		else if (!bytes_read)
+			/* propagate the failure */
+			return bytes_read_trans;
+	}
+
+	return bytes_read;
+
+}
+
+static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
+					   struct file *file)
+{
+	struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
+
+	vfree(dump_ptrs->op_mode_ptr);
+	vfree(dump_ptrs->trans_ptr);
+	kfree(dump_ptrs);
+
+	return 0;
+}
+
 static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
 				   size_t count, loff_t *ppos)
 {
@@ -936,11 +1008,7 @@
 	if (scan_rx_ant & ~mvm->fw->valid_rx_ant)
 		return -EINVAL;
 
-	if (mvm->scan_rx_ant != scan_rx_ant) {
-		mvm->scan_rx_ant = scan_rx_ant;
-		if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
-			iwl_mvm_config_scan(mvm);
-	}
+	mvm->scan_rx_ant = scan_rx_ant;
 
 	return count;
 }
@@ -1182,118 +1250,6 @@
 
 	return ret;
 }
-
-#define MAX_NUM_ND_MATCHSETS 10
-
-static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf,
-					 size_t count, loff_t *ppos)
-{
-	const char *seps = ",\n";
-	char *buf_ptr = buf;
-	char *value_str = NULL;
-	int ret, i;
-
-	/* TODO: don't free if write is being called several times in one go */
-	if (mvm->nd_config) {
-		kfree(mvm->nd_config->match_sets);
-		kfree(mvm->nd_config);
-		mvm->nd_config = NULL;
-	}
-
-	mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) +
-				 (11 * sizeof(struct ieee80211_channel *)),
-				 GFP_KERNEL);
-	if (!mvm->nd_config) {
-		ret = -ENOMEM;
-		goto out_free;
-	}
-
-	mvm->nd_config->n_channels = 11;
-	mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20;
-	mvm->nd_config->interval = 5;
-	mvm->nd_config->min_rssi_thold = -80;
-	for (i = 0; i < mvm->nd_config->n_channels; i++)
-		mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i];
-
-	mvm->nd_config->match_sets =
-		kcalloc(MAX_NUM_ND_MATCHSETS,
-			sizeof(*mvm->nd_config->match_sets),
-			GFP_KERNEL);
-	if (!mvm->nd_config->match_sets) {
-		ret = -ENOMEM;
-		goto out_free;
-	}
-
-	while ((value_str = strsep(&buf_ptr, seps)) &&
-	       strlen(value_str)) {
-		struct cfg80211_match_set *set;
-
-		if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) {
-			ret = -EINVAL;
-			goto out_free;
-		}
-
-		set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets];
-		set->ssid.ssid_len = strlen(value_str);
-
-		if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {
-			ret = -EINVAL;
-			goto out_free;
-		}
-
-		memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len);
-
-		mvm->nd_config->n_match_sets++;
-	}
-
-	ret = count;
-
-	if (mvm->nd_config->n_match_sets)
-		goto out;
-
-out_free:
-	if (mvm->nd_config)
-		kfree(mvm->nd_config->match_sets);
-	kfree(mvm->nd_config);
-	mvm->nd_config = NULL;
-out:
-	return ret;
-}
-
-static ssize_t
-iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf,
-			 size_t count, loff_t *ppos)
-{
-	struct iwl_mvm *mvm = file->private_data;
-	size_t bufsz, ret;
-	char *buf;
-	int i, n_match_sets, pos = 0;
-
-	n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0;
-
-	bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1;
-	buf = kzalloc(bufsz, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	for (i = 0; i < n_match_sets; i++) {
-		if (pos +
-		    mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) {
-			ret = -EIO;
-			goto out;
-		}
-
-		memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid,
-		       mvm->nd_config->match_sets[i].ssid.ssid_len);
-		pos += mvm->nd_config->match_sets[i].ssid.ssid_len;
-		buf[pos++] = '\n';
-	}
-
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-out:
-	kfree(buf);
-	return ret;
-}
 #endif
 
 #define PRINT_MVM_REF(ref) do {						\
@@ -1339,7 +1295,6 @@
 	PRINT_MVM_REF(IWL_MVM_REF_NMI);
 	PRINT_MVM_REF(IWL_MVM_REF_TM_CMD);
 	PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
-	PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
@@ -1460,6 +1415,12 @@
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
 
+static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
+	.open = iwl_dbgfs_fw_error_dump_open,
+	.read = iwl_dbgfs_fw_error_dump_read,
+	.release = iwl_dbgfs_fw_error_dump_release,
+};
+
 #ifdef CPTCFG_IWLWIFI_BCAST_FILTERING
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
@@ -1467,7 +1428,6 @@
 
 #ifdef CONFIG_PM_SLEEP
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384);
 #endif
 
 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
@@ -1486,6 +1446,7 @@
 			     S_IWUSR | S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
+	MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
@@ -1526,7 +1487,6 @@
 	if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
 				 mvm->debugfs_dir, &mvm->d3_wake_sysassert))
 		goto err;
-	MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
 #endif
 
 	if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR,
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
index f3b1189..816883f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
@@ -84,8 +84,6 @@
  * @BT_COEX_SYNC2SCO:
  * @BT_COEX_CORUNNING:
  * @BT_COEX_MPLUT:
- * @BT_COEX_TTC:
- * @BT_COEX_RRC:
  *
  * The COEX_MODE must be set for each command. Even if it is not changed.
  */
@@ -102,8 +100,6 @@
 	BT_COEX_SYNC2SCO		= BIT(7),
 	BT_COEX_CORUNNING		= BIT(8),
 	BT_COEX_MPLUT			= BIT(9),
-	BT_COEX_TTC			= BIT(20),
-	BT_COEX_RRC			= BIT(21),
 };
 
 /*
@@ -131,8 +127,6 @@
 	BT_VALID_TXTX_DELTA_FREQ_THRS	= BIT(16),
 	BT_VALID_TXRX_MAX_FREQ_0	= BIT(17),
 	BT_VALID_SYNC_TO_SCO		= BIT(18),
-	BT_VALID_TTC			= BIT(20),
-	BT_VALID_RRC			= BIT(21),
 };
 
 /**
@@ -512,8 +506,7 @@
 	u8 bt_agg_traffic_load;
 	u8 bt_ci_compliance;
 	u8 ttc_enabled;
-	u8 rrc_enabled;
-	u8 reserved;
+	__le16 reserved;
 
 	__le32 primary_ch_lut;
 	__le32 secondary_ch_lut;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
index 6d3bea5..e74cdf2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
@@ -241,12 +241,16 @@
 	IWL_WOWLAN_WAKEUP_BCN_FILTERING			= BIT(16),
 }; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */
 
-struct iwl_wowlan_config_cmd {
+struct iwl_wowlan_config_cmd_v2 {
 	__le32 wakeup_filter;
 	__le16 non_qos_seq;
 	__le16 qos_seq[8];
 	u8 wowlan_ba_teardown_tids;
 	u8 is_11n_connection;
+} __packed; /* WOWLAN_CONFIG_API_S_VER_2 */
+
+struct iwl_wowlan_config_cmd_v3 {
+	struct iwl_wowlan_config_cmd_v2 common;
 	u8 offloading_tid;
 	u8 reserved[3];
 } __packed; /* WOWLAN_CONFIG_API_S_VER_3 */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 4300200..27dd863 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -68,46 +68,13 @@
 
 /* Power Management Commands, Responses, Notifications */
 
-/**
- * enum iwl_ltr_config_flags - masks for LTR config command flags
- * @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status
- * @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow
- *	memory access
- * @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR
- *	reg change
- * @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from
- *	D0 to D3
- * @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
- * @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
- * @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
- */
-enum iwl_ltr_config_flags {
-	LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
-	LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1),
-	LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2),
-	LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3),
-	LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
-	LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
-	LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
-};
-
-/**
- * struct iwl_ltr_config_cmd - configures the LTR
- * @flags: See %enum iwl_ltr_config_flags
- */
-struct iwl_ltr_config_cmd {
-	__le32 flags;
-	__le32 static_long;
-	__le32 static_short;
-} __packed;
-
 /* Radio LP RX Energy Threshold measured in dBm */
 #define POWER_LPRX_RSSI_THRESHOLD	75
 #define POWER_LPRX_RSSI_THRESHOLD_MAX	94
 #define POWER_LPRX_RSSI_THRESHOLD_MIN	30
 
 /**
- * enum iwl_power_flags - masks for power table command flags
+ * enum iwl_scan_flags - masks for power table command flags
  * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
  *		receiver and transmitter. '0' - does not allow.
  * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
@@ -370,7 +337,7 @@
 #define IWL_BF_DEBUG_FLAG_DEFAULT 0
 #define IWL_BF_DEBUG_FLAG_D0I3 0
 
-#define IWL_BF_ESCAPE_TIMER_DEFAULT 0
+#define IWL_BF_ESCAPE_TIMER_DEFAULT 50
 #define IWL_BF_ESCAPE_TIMER_D0I3 0
 #define IWL_BF_ESCAPE_TIMER_MAX 1024
 #define IWL_BF_ESCAPE_TIMER_MIN 0
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 1f2acf4..1354c68 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -794,301 +794,4 @@
 	__le32 reserved;
 } __packed;
 
-/* UMAC Scan API */
-
-/**
- * struct iwl_mvm_umac_cmd_hdr - Command header for UMAC commands
- * @size:	size of the command (not including header)
- * @reserved0:	for future use and alignment
- * @ver:	API version number
- */
-struct iwl_mvm_umac_cmd_hdr {
-	__le16 size;
-	u8 reserved0;
-	u8 ver;
-} __packed;
-
-#define IWL_MVM_MAX_SIMULTANEOUS_SCANS 8
-
-enum scan_config_flags {
-	SCAN_CONFIG_FLAG_ACTIVATE			= BIT(0),
-	SCAN_CONFIG_FLAG_DEACTIVATE			= BIT(1),
-	SCAN_CONFIG_FLAG_FORBID_CHUB_REQS		= BIT(2),
-	SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS		= BIT(3),
-	SCAN_CONFIG_FLAG_SET_TX_CHAINS			= BIT(8),
-	SCAN_CONFIG_FLAG_SET_RX_CHAINS			= BIT(9),
-	SCAN_CONFIG_FLAG_SET_AUX_STA_ID			= BIT(10),
-	SCAN_CONFIG_FLAG_SET_ALL_TIMES			= BIT(11),
-	SCAN_CONFIG_FLAG_SET_EFFECTIVE_TIMES		= BIT(12),
-	SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS		= BIT(13),
-	SCAN_CONFIG_FLAG_SET_LEGACY_RATES		= BIT(14),
-	SCAN_CONFIG_FLAG_SET_MAC_ADDR			= BIT(15),
-	SCAN_CONFIG_FLAG_SET_FRAGMENTED			= BIT(16),
-	SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED		= BIT(17),
-	SCAN_CONFIG_FLAG_SET_CAM_MODE			= BIT(18),
-	SCAN_CONFIG_FLAG_CLEAR_CAM_MODE			= BIT(19),
-	SCAN_CONFIG_FLAG_SET_PROMISC_MODE		= BIT(20),
-	SCAN_CONFIG_FLAG_CLEAR_PROMISC_MODE		= BIT(21),
-
-	/* Bits 26-31 are for num of channels in channel_array */
-#define SCAN_CONFIG_N_CHANNELS(n) ((n) << 26)
-};
-
-enum scan_config_rates {
-	/* OFDM basic rates */
-	SCAN_CONFIG_RATE_6M	= BIT(0),
-	SCAN_CONFIG_RATE_9M	= BIT(1),
-	SCAN_CONFIG_RATE_12M	= BIT(2),
-	SCAN_CONFIG_RATE_18M	= BIT(3),
-	SCAN_CONFIG_RATE_24M	= BIT(4),
-	SCAN_CONFIG_RATE_36M	= BIT(5),
-	SCAN_CONFIG_RATE_48M	= BIT(6),
-	SCAN_CONFIG_RATE_54M	= BIT(7),
-	/* CCK basic rates */
-	SCAN_CONFIG_RATE_1M	= BIT(8),
-	SCAN_CONFIG_RATE_2M	= BIT(9),
-	SCAN_CONFIG_RATE_5M	= BIT(10),
-	SCAN_CONFIG_RATE_11M	= BIT(11),
-
-	/* Bits 16-27 are for supported rates */
-#define SCAN_CONFIG_SUPPORTED_RATE(rate)	((rate) << 16)
-};
-
-enum iwl_channel_flags {
-	IWL_CHANNEL_FLAG_EBS				= BIT(0),
-	IWL_CHANNEL_FLAG_ACCURATE_EBS			= BIT(1),
-	IWL_CHANNEL_FLAG_EBS_ADD			= BIT(2),
-	IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE	= BIT(3),
-};
-
-/**
- * struct iwl_scan_config
- * @hdr: umac command header
- * @flags:			enum scan_config_flags
- * @tx_chains:			valid_tx antenna - ANT_* definitions
- * @rx_chains:			valid_rx antenna - ANT_* definitions
- * @legacy_rates:		default legacy rates - enum scan_config_rates
- * @out_of_channel_time:	default max out of serving channel time
- * @suspend_time:		default max suspend time
- * @dwell_active:		default dwell time for active scan
- * @dwell_passive:		default dwell time for passive scan
- * @dwell_fragmented:		default dwell time for fragmented scan
- * @reserved:			for future use and alignment
- * @mac_addr:			default mac address to be used in probes
- * @bcast_sta_id:		the index of the station in the fw
- * @channel_flags:		default channel flags - enum iwl_channel_flags
- *				scan_config_channel_flag
- * @channel_array:		default supported channels
- */
-struct iwl_scan_config {
-	struct iwl_mvm_umac_cmd_hdr hdr;
-	__le32 flags;
-	__le32 tx_chains;
-	__le32 rx_chains;
-	__le32 legacy_rates;
-	__le32 out_of_channel_time;
-	__le32 suspend_time;
-	u8 dwell_active;
-	u8 dwell_passive;
-	u8 dwell_fragmented;
-	u8 reserved;
-	u8 mac_addr[ETH_ALEN];
-	u8 bcast_sta_id;
-	u8 channel_flags;
-	u8 channel_array[];
-} __packed; /* SCAN_CONFIG_DB_CMD_API_S */
-
-/**
- * iwl_umac_scan_flags
- *@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
- *	can be preempted by other scan requests with higher priority.
- *	The low priority scan is aborted.
- *@IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver
- *	when scan starts.
- */
-enum iwl_umac_scan_flags {
-	IWL_UMAC_SCAN_FLAG_PREEMPTIVE		= BIT(0),
-	IWL_UMAC_SCAN_FLAG_START_NOTIF		= BIT(1),
-};
-
-enum iwl_umac_scan_uid_offsets {
-	IWL_UMAC_SCAN_UID_TYPE_OFFSET		= 0,
-	IWL_UMAC_SCAN_UID_SEQ_OFFSET		= 8,
-};
-
-enum iwl_umac_scan_general_flags {
-	IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC	= BIT(0),
-	IWL_UMAC_SCAN_GEN_FLAGS_OVER_BT		= BIT(1),
-	IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL	= BIT(2),
-	IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE		= BIT(3),
-	IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT	= BIT(4),
-	IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE	= BIT(5),
-	IWL_UMAC_SCAN_GEN_FLAGS_MULTIPLE_SSID	= BIT(6),
-	IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED	= BIT(7),
-	IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED	= BIT(8),
-	IWL_UMAC_SCAN_GEN_FLAGS_MATCH		= BIT(9)
-};
-
-/**
- * struct iwl_scan_channel_cfg_umac
- * @flags:		bitmap - 0-19:	directed scan to i'th ssid.
- * @channel_num:	channel number 1-13 etc.
- * @iter_count:		repetition count for the channel.
- * @iter_interval:	interval between two scan interations on one channel.
- */
-struct iwl_scan_channel_cfg_umac {
-	__le32 flags;
-	u8 channel_num;
-	u8 iter_count;
-	__le16 iter_interval;
-} __packed; /* SCAN_CHANNEL_CFG_S_VER2 */
-
-/**
- * struct iwl_scan_umac_schedule
- * @interval: interval in seconds between scan iterations
- * @iter_count: num of scan iterations for schedule plan, 0xff for infinite loop
- * @reserved: for alignment and future use
- */
-struct iwl_scan_umac_schedule {
-	__le16 interval;
-	u8 iter_count;
-	u8 reserved;
-} __packed; /* SCAN_SCHED_PARAM_API_S_VER_1 */
-
-/**
- * struct iwl_scan_req_umac_tail - the rest of the UMAC scan request command
- *      parameters following channels configuration array.
- * @schedule: two scheduling plans.
- * @delay: delay in TUs before starting the first scan iteration
- * @reserved: for future use and alignment
- * @preq: probe request with IEs blocks
- * @direct_scan: list of SSIDs for directed active scan
- */
-struct iwl_scan_req_umac_tail {
-	/* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
-	struct iwl_scan_umac_schedule schedule[2];
-	__le16 delay;
-	__le16 reserved;
-	/* SCAN_PROBE_PARAMS_API_S_VER_1 */
-	struct iwl_scan_probe_req preq;
-	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
-} __packed;
-
-/**
- * struct iwl_scan_req_umac
- * @hdr: umac command header
- * @flags: &enum iwl_umac_scan_flags
- * @uid: scan id, &enum iwl_umac_scan_uid_offsets
- * @ooc_priority: out of channel priority - &enum iwl_scan_priority
- * @general_flags: &enum iwl_umac_scan_general_flags
- * @reserved1: for future use and alignment
- * @active_dwell: dwell time for active scan
- * @passive_dwell: dwell time for passive scan
- * @fragmented_dwell: dwell time for fragmented passive scan
- * @max_out_time: max out of serving channel time
- * @suspend_time: max suspend time
- * @scan_priority: scan internal prioritization &enum iwl_scan_priority
- * @channel_flags: &enum iwl_scan_channel_flags
- * @n_channels: num of channels in scan request
- * @reserved2: for future use and alignment
- * @data: &struct iwl_scan_channel_cfg_umac and
- *	&struct iwl_scan_req_umac_tail
- */
-struct iwl_scan_req_umac {
-	struct iwl_mvm_umac_cmd_hdr hdr;
-	__le32 flags;
-	__le32 uid;
-	__le32 ooc_priority;
-	/* SCAN_GENERAL_PARAMS_API_S_VER_1 */
-	__le32 general_flags;
-	u8 reserved1;
-	u8 active_dwell;
-	u8 passive_dwell;
-	u8 fragmented_dwell;
-	__le32 max_out_time;
-	__le32 suspend_time;
-	__le32 scan_priority;
-	/* SCAN_CHANNEL_PARAMS_API_S_VER_1 */
-	u8 channel_flags;
-	u8 n_channels;
-	__le16 reserved2;
-	u8 data[];
-} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */
-
-/**
- * struct iwl_umac_scan_abort
- * @hdr: umac command header
- * @uid: scan id, &enum iwl_umac_scan_uid_offsets
- * @flags: reserved
- */
-struct iwl_umac_scan_abort {
-	struct iwl_mvm_umac_cmd_hdr hdr;
-	__le32 uid;
-	__le32 flags;
-} __packed; /* SCAN_ABORT_CMD_UMAC_API_S_VER_1 */
-
-/**
- * struct iwl_umac_scan_complete
- * @uid: scan id, &enum iwl_umac_scan_uid_offsets
- * @last_schedule: last scheduling line
- * @last_iter:	last scan iteration number
- * @scan status: &enum iwl_scan_offload_complete_status
- * @ebs_status: &enum iwl_scan_ebs_status
- * @time_from_last_iter: time elapsed from last iteration
- * @reserved: for future use
- */
-struct iwl_umac_scan_complete {
-	__le32 uid;
-	u8 last_schedule;
-	u8 last_iter;
-	u8 status;
-	u8 ebs_status;
-	__le32 time_from_last_iter;
-	__le32 reserved;
-} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */
-
-#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 5
-/**
- * struct iwl_scan_offload_profile_match - match information
- * @bssid: matched bssid
- * @channel: channel where the match occurred
- * @energy:
- * @matching_feature:
- * @matching_channels: bitmap of channels that matched, referencing
- *	the channels passed in tue scan offload request
- */
-struct iwl_scan_offload_profile_match {
-	u8 bssid[ETH_ALEN];
-	__le16 reserved;
-	u8 channel;
-	u8 energy;
-	u8 matching_feature;
-	u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN];
-} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */
-
-/**
- * struct iwl_scan_offload_profiles_query - match results query response
- * @matched_profiles: bitmap of matched profiles, referencing the
- *	matches passed in the scan offload request
- * @last_scan_age: age of the last offloaded scan
- * @n_scans_done: number of offloaded scans done
- * @gp2_d0u: GP2 when D0U occurred
- * @gp2_invoked: GP2 when scan offload was invoked
- * @resume_while_scanning: not used
- * @self_recovery: obsolete
- * @reserved: reserved
- * @matches: array of match information, one for each match
- */
-struct iwl_scan_offload_profiles_query {
-	__le32 matched_profiles;
-	__le32 last_scan_age;
-	__le32 n_scans_done;
-	__le32 gp2_d0u;
-	__le32 gp2_invoked;
-	u8 resume_while_scanning;
-	u8 self_recovery;
-	__le16 reserved;
-	struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
-} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
-
 #endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 88af6dd..667a922 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -106,12 +106,6 @@
 	DBG_CFG = 0x9,
 	ANTENNA_COUPLING_NOTIFICATION = 0xa,
 
-	/* UMAC scan commands */
-	SCAN_CFG_CMD = 0xc,
-	SCAN_REQ_UMAC = 0xd,
-	SCAN_ABORT_UMAC = 0xe,
-	SCAN_COMPLETE_UMAC = 0xf,
-
 	/* station table */
 	ADD_STA_KEY = 0x17,
 	ADD_STA = 0x18,
@@ -128,11 +122,6 @@
 	/* global key */
 	WEP_KEY = 0x20,
 
-	/* TDLS */
-	TDLS_CHANNEL_SWITCH_CMD = 0x27,
-	TDLS_CHANNEL_SWITCH_NOTIFICATION = 0xaa,
-	TDLS_CONFIG_CMD = 0xa7,
-
 	/* MAC and Binding commands */
 	MAC_CONTEXT_CMD = 0x28,
 	TIME_EVENT_CMD = 0x29, /* both CMD and response */
@@ -168,7 +157,6 @@
 	/* Power - legacy power table command */
 	POWER_TABLE_CMD = 0x77,
 	PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
-	LTR_CONFIG = 0xee,
 
 	/* Thermal Throttling*/
 	REPLY_THERMAL_MNG_BACKOFF = 0x7e,
@@ -201,8 +189,6 @@
 	/* Power - new power table command */
 	MAC_PM_POWER_TABLE = 0xa9,
 
-	MFUART_LOAD_NOTIFICATION = 0xb1,
-
 	REPLY_RX_PHY_CMD = 0xc0,
 	REPLY_RX_MPDU_CMD = 0xc1,
 	BA_NOTIF = 0xc5,
@@ -249,9 +235,11 @@
 	WOWLAN_TX_POWER_PER_DB = 0xe6,
 
 	/* and for NetDetect */
-	SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56,
-	SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD = 0x58,
-	SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD = 0x59,
+	NET_DETECT_CONFIG_CMD = 0x54,
+	NET_DETECT_PROFILES_QUERY_CMD = 0x56,
+	NET_DETECT_PROFILES_CMD = 0x57,
+	NET_DETECT_HOTSPOTS_CMD = 0x58,
+	NET_DETECT_HOTSPOTS_QUERY_CMD = 0x59,
 
 	REPLY_MAX = 0xff,
 };
@@ -1212,21 +1200,6 @@
 } __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
 
 /**
- * struct iwl_mfuart_load_notif - mfuart image version & status
- * ( MFUART_LOAD_NOTIFICATION = 0xb1 )
- * @installed_ver: installed image version
- * @external_ver: external image version
- * @status: MFUART loading status
- * @duration: MFUART loading time
-*/
-struct iwl_mfuart_load_notif {
-	__le32 installed_ver;
-	__le32 external_ver;
-	__le32 status;
-	__le32 duration;
-} __packed; /*MFU_LOADER_NTFY_API_S_VER_1*/
-
-/**
  * struct iwl_set_calib_default_cmd - set default value for calibration.
  * ( SET_CALIB_DEFAULT_CMD = 0x8e )
  * @calib_index: the calibration to set value for
@@ -1615,7 +1588,7 @@
 #define SF_NUM_TIMEOUT_TYPES 2		/* Aging timer and Idle timer */
 
 /* smart FIFO default values */
-#define SF_W_MARK_SISO 6144
+#define SF_W_MARK_SISO 4096
 #define SF_W_MARK_MIMO2 8192
 #define SF_W_MARK_MIMO3 6144
 #define SF_W_MARK_LEGACY 4096
@@ -1737,145 +1710,4 @@
 	u8 flags;
 } __packed;
 
-/***********************************
- * TDLS API
- ***********************************/
-
-/* Type of TDLS request */
-enum iwl_tdls_channel_switch_type {
-	TDLS_SEND_CHAN_SW_REQ = 0,
-	TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH,
-	TDLS_MOVE_CH,
-}; /* TDLS_STA_CHANNEL_SWITCH_CMD_TYPE_API_E_VER_1 */
-
-/**
- * Switch timing sub-element in a TDLS channel-switch command
- * @frame_timestamp: GP2 timestamp of channel-switch request/response packet
- *	received from peer
- * @max_offchan_duration: What amount of microseconds out of a DTIM is given
- *	to the TDLS off-channel communication. For instance if the DTIM is
- *	200TU and the TDLS peer is to be given 25% of the time, the value
- *	given will be 50TU, or 50 * 1024 if translated into microseconds.
- * @switch_time: switch time the peer sent in its channel switch timing IE
- * @switch_timout: switch timeout the peer sent in its channel switch timing IE
- */
-struct iwl_tdls_channel_switch_timing {
-	__le32 frame_timestamp; /* GP2 time of peer packet Rx */
-	__le32 max_offchan_duration; /* given in micro-seconds */
-	__le32 switch_time; /* given in micro-seconds */
-	__le32 switch_timeout; /* given in micro-seconds */
-} __packed; /* TDLS_STA_CHANNEL_SWITCH_TIMING_DATA_API_S_VER_1 */
-
-#define IWL_TDLS_CH_SW_FRAME_MAX_SIZE 200
-
-/**
- * TDLS channel switch frame template
- *
- * A template representing a TDLS channel-switch request or response frame
- *
- * @switch_time_offset: offset to the channel switch timing IE in the template
- * @tx_cmd: Tx parameters for the frame
- * @data: frame data
- */
-struct iwl_tdls_channel_switch_frame {
-	__le32 switch_time_offset;
-	struct iwl_tx_cmd tx_cmd;
-	u8 data[IWL_TDLS_CH_SW_FRAME_MAX_SIZE];
-} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
-
-/**
- * TDLS channel switch command
- *
- * The command is sent to initiate a channel switch and also in response to
- * incoming TDLS channel-switch request/response packets from remote peers.
- *
- * @switch_type: see &enum iwl_tdls_channel_switch_type
- * @peer_sta_id: station id of TDLS peer
- * @ci: channel we switch to
- * @timing: timing related data for command
- * @frame: channel-switch request/response template, depending to switch_type
- */
-struct iwl_tdls_channel_switch_cmd {
-	u8 switch_type;
-	__le32 peer_sta_id;
-	struct iwl_fw_channel_info ci;
-	struct iwl_tdls_channel_switch_timing timing;
-	struct iwl_tdls_channel_switch_frame frame;
-} __packed; /* TDLS_STA_CHANNEL_SWITCH_CMD_API_S_VER_1 */
-
-/**
- * TDLS channel switch start notification
- *
- * @status: non-zero on success
- * @offchannel_duration: duration given in microseconds
- * @sta_id: peer currently performing the channel-switch with
- */
-struct iwl_tdls_channel_switch_notif {
-	__le32 status;
-	__le32 offchannel_duration;
-	__le32 sta_id;
-} __packed; /* TDLS_STA_CHANNEL_SWITCH_NTFY_API_S_VER_1 */
-
-/**
- * TDLS station info
- *
- * @sta_id: station id of the TDLS peer
- * @tx_to_peer_tid: TID reserved vs. the peer for FW based Tx
- * @tx_to_peer_ssn: initial SSN the FW should use for Tx on its TID vs the peer
- * @is_initiator: 1 if the peer is the TDLS link initiator, 0 otherwise
- */
-struct iwl_tdls_sta_info {
-	u8 sta_id;
-	u8 tx_to_peer_tid;
-	__le16 tx_to_peer_ssn;
-	__le32 is_initiator;
-} __packed; /* TDLS_STA_INFO_VER_1 */
-
-/**
- * TDLS basic config command
- *
- * @id_and_color: MAC id and color being configured
- * @tdls_peer_count: amount of currently connected TDLS peers
- * @tx_to_ap_tid: TID reverved vs. the AP for FW based Tx
- * @tx_to_ap_ssn: initial SSN the FW should use for Tx on its TID vs. the AP
- * @sta_info: per-station info. Only the first tdls_peer_count entries are set
- * @pti_req_data_offset: offset of network-level data for the PTI template
- * @pti_req_tx_cmd: Tx parameters for PTI request template
- * @pti_req_template: PTI request template data
- */
-struct iwl_tdls_config_cmd {
-	__le32 id_and_color; /* mac id and color */
-	u8 tdls_peer_count;
-	u8 tx_to_ap_tid;
-	__le16 tx_to_ap_ssn;
-	struct iwl_tdls_sta_info sta_info[IWL_MVM_TDLS_STA_COUNT];
-
-	__le32 pti_req_data_offset;
-	struct iwl_tx_cmd pti_req_tx_cmd;
-	u8 pti_req_template[0];
-} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */
-
-/**
- * TDLS per-station config information from FW
- *
- * @sta_id: station id of the TDLS peer
- * @tx_to_peer_last_seq: last sequence number used by FW during FW-based Tx to
- *	the peer
- */
-struct iwl_tdls_config_sta_info_res {
-	__le16 sta_id;
-	__le16 tx_to_peer_last_seq;
-} __packed; /* TDLS_STA_INFO_RSP_VER_1 */
-
-/**
- * TDLS config information from FW
- *
- * @tx_to_ap_last_seq: last sequence number used by FW during FW-based Tx to AP
- * @sta_info: per-station TDLS config information
- */
-struct iwl_tdls_config_res {
-	__le32 tx_to_ap_last_seq;
-	struct iwl_tdls_config_sta_info_res sta_info[IWL_MVM_TDLS_STA_COUNT];
-} __packed; /* TDLS_CONFIG_RSP_API_S_VER_1 */
-
 #endif /* __fw_api_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index d0fa6e9..23fd711 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -186,12 +186,7 @@
 	static const u8 alive_cmd[] = { MVM_ALIVE };
 	struct iwl_sf_region st_fwrd_space;
 
-	if (ucode_type == IWL_UCODE_REGULAR &&
-	    iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_CUSTOM) &&
-	    iwl_fw_dbg_conf_enabled(mvm->fw, FW_DBG_CUSTOM))
-		fw = iwl_get_ucode_image(mvm, IWL_UCODE_REGULAR_USNIFFER);
-	else
-		fw = iwl_get_ucode_image(mvm, ucode_type);
+	fw = iwl_get_ucode_image(mvm, ucode_type);
 	if (WARN_ON(!fw))
 		return -EINVAL;
 	mvm->cur_ucode = ucode_type;
@@ -232,10 +227,6 @@
 	st_fwrd_space.addr = mvm->sf_space.addr;
 	st_fwrd_space.size = mvm->sf_space.size;
 	ret = iwl_trans_update_sf(mvm->trans, &st_fwrd_space);
-	if (ret) {
-		IWL_ERR(mvm, "Failed to update SF size. ret %d\n", ret);
-		return ret;
-	}
 
 	iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
 
@@ -293,7 +284,7 @@
 
 	lockdep_assert_held(&mvm->mutex);
 
-	if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating))
+	if (WARN_ON_ONCE(mvm->init_ucode_complete))
 		return 0;
 
 	iwl_init_notification_wait(&mvm->notif_wait,
@@ -343,8 +334,6 @@
 		goto out;
 	}
 
-	mvm->calibrating = true;
-
 	/* Send TX valid antennas before triggering calibrations */
 	ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
 	if (ret)
@@ -369,17 +358,11 @@
 			MVM_UCODE_CALIB_TIMEOUT);
 	if (!ret)
 		mvm->init_ucode_complete = true;
-
-	if (ret && iwl_mvm_is_radio_killed(mvm)) {
-		IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
-		ret = 1;
-	}
 	goto out;
 
 error:
 	iwl_remove_notification(&mvm->notif_wait, &calib_wait);
 out:
-	mvm->calibrating = false;
 	if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
 		/* we want to debug INIT and we have no NVM - fake */
 		mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
@@ -399,42 +382,6 @@
 	return ret;
 }
 
-static int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm,
-				     enum iwl_fw_dbg_conf conf_id)
-{
-	u8 *ptr;
-	int ret;
-	int i;
-
-	if (WARN_ONCE(conf_id >= ARRAY_SIZE(mvm->fw->dbg_conf_tlv),
-		      "Invalid configuration %d\n", conf_id))
-		return -EINVAL;
-
-	if (!mvm->fw->dbg_conf_tlv[conf_id])
-		return -EINVAL;
-
-	if (mvm->fw_dbg_conf != FW_DBG_INVALID)
-		IWL_WARN(mvm, "FW already configured (%d) - re-configuring\n",
-			 mvm->fw_dbg_conf);
-
-	/* Send all HCMDs for configuring the FW debug */
-	ptr = (void *)&mvm->fw->dbg_conf_tlv[conf_id]->hcmd;
-	for (i = 0; i < mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds; i++) {
-		struct iwl_fw_dbg_conf_hcmd *cmd = (void *)ptr;
-
-		ret = iwl_mvm_send_cmd_pdu(mvm, cmd->id, 0,
-					   le16_to_cpu(cmd->len), cmd->data);
-		if (ret)
-			return ret;
-
-		ptr += sizeof(*cmd);
-		ptr += le16_to_cpu(cmd->len);
-	}
-
-	mvm->fw_dbg_conf = conf_id;
-	return ret;
-}
-
 int iwl_mvm_up(struct iwl_mvm *mvm)
 {
 	int ret, i;
@@ -486,9 +433,6 @@
 	if (ret)
 		IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
 
-	mvm->fw_dbg_conf = FW_DBG_INVALID;
-	iwl_mvm_start_fw_dbg_conf(mvm, FW_DBG_CUSTOM);
-
 	ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
 	if (ret)
 		goto error;
@@ -510,8 +454,6 @@
 	for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
 		RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
 
-	mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
-
 	/* reset quota debouncing buffer - 0xff will yield invalid data */
 	memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
 
@@ -538,25 +480,10 @@
 	/* Initialize tx backoffs to the minimal possible */
 	iwl_mvm_tt_tx_backoff(mvm, 0);
 
-	if (mvm->trans->ltr_enabled) {
-		struct iwl_ltr_config_cmd cmd = {
-			.flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
-		};
-
-		WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
-					     sizeof(cmd), &cmd));
-	}
-
 	ret = iwl_mvm_power_update_device(mvm);
 	if (ret)
 		goto error;
 
-	if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
-		ret = iwl_mvm_config_scan(mvm);
-		if (ret)
-			goto error;
-	}
-
 	/* allow FW/transport low power modes if not during restart */
 	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
 		iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
@@ -643,19 +570,3 @@
 		       le32_to_cpu(radio_version->radio_dash));
 	return 0;
 }
-
-int iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm,
-			    struct iwl_rx_cmd_buffer *rxb,
-			    struct iwl_device_cmd *cmd)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_mfuart_load_notif *mfuart_notif = (void *)pkt->data;
-
-	IWL_DEBUG_INFO(mvm,
-		       "MFUART: installed ver: 0x%08x, external ver: 0x%08x, status: 0x%08x, duration: 0x%08x\n",
-		       le32_to_cpu(mfuart_notif->installed_ver),
-		       le32_to_cpu(mfuart_notif->external_ver),
-		       le32_to_cpu(mfuart_notif->status),
-		       le32_to_cpu(mfuart_notif->duration));
-	return 0;
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index f6d86cc..0c5c0b0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -83,15 +83,11 @@
 	struct ieee80211_vif *vif;
 	unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
 	unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
+	u32 used_hw_queues;
 	enum iwl_tsf_id preferred_tsf;
 	bool found_vif;
 };
 
-struct iwl_mvm_hw_queues_iface_iterator_data {
-	struct ieee80211_vif *exclude_vif;
-	unsigned long used_hw_queues;
-};
-
 static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
 				    struct ieee80211_vif *vif)
 {
@@ -201,7 +197,8 @@
 /*
  * Get the mask of the queues used by the vif
  */
-u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif)
+u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
+				struct ieee80211_vif *vif)
 {
 	u32 qmask = 0, ac;
 
@@ -217,54 +214,6 @@
 	return qmask;
 }
 
-static void iwl_mvm_iface_hw_queues_iter(void *_data, u8 *mac,
-					 struct ieee80211_vif *vif)
-{
-	struct iwl_mvm_hw_queues_iface_iterator_data *data = _data;
-
-	/* exclude the given vif */
-	if (vif == data->exclude_vif)
-		return;
-
-	data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif);
-}
-
-static void iwl_mvm_mac_sta_hw_queues_iter(void *_data,
-					   struct ieee80211_sta *sta)
-{
-	struct iwl_mvm_hw_queues_iface_iterator_data *data = _data;
-	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
-	/* Mark the queues used by the sta */
-	data->used_hw_queues |= mvmsta->tfd_queue_msk;
-}
-
-unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
-					 struct ieee80211_vif *exclude_vif)
-{
-	struct iwl_mvm_hw_queues_iface_iterator_data data = {
-		.exclude_vif = exclude_vif,
-		.used_hw_queues =
-			BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
-			BIT(mvm->aux_queue) |
-			BIT(IWL_MVM_CMD_QUEUE),
-	};
-
-	lockdep_assert_held(&mvm->mutex);
-
-	/* mark all VIF used hw queues */
-	ieee80211_iterate_active_interfaces_atomic(
-		mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-		iwl_mvm_iface_hw_queues_iter, &data);
-
-	/* don't assign the same hw queues as TDLS stations */
-	ieee80211_iterate_stations_atomic(mvm->hw,
-					  iwl_mvm_mac_sta_hw_queues_iter,
-					  &data);
-
-	return data.used_hw_queues;
-}
-
 static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
 				       struct ieee80211_vif *vif)
 {
@@ -277,6 +226,9 @@
 		return;
 	}
 
+	/* Mark the queues used by the vif */
+	data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(data->mvm, vif);
+
 	/* Mark MAC IDs as used by clearing the available bit, and
 	 * (below) mark TSFs as used if their existing use is not
 	 * compatible with the new interface type.
@@ -323,6 +275,10 @@
 		.available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
 		/* no preference yet */
 		.preferred_tsf = NUM_TSF_IDS,
+		.used_hw_queues =
+			BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
+			BIT(mvm->aux_queue) |
+			BIT(IWL_MVM_CMD_QUEUE),
 		.found_vif = false,
 	};
 	u32 ac;
@@ -361,8 +317,6 @@
 		mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
 		iwl_mvm_mac_iface_iterator, &data);
 
-	used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, vif);
-
 	/*
 	 * In the case we're getting here during resume, it's similar to
 	 * firmware restart, and with RESUME_ALL the iterator will find
@@ -412,6 +366,8 @@
 		return 0;
 	}
 
+	used_hw_queues = data.used_hw_queues;
+
 	/* Find available queues, and allocate them to the ACs */
 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
 		u8 queue = find_first_zero_bit(&used_hw_queues,
@@ -1263,25 +1219,17 @@
 }
 
 static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
-				   struct ieee80211_vif *csa_vif, u32 gp2,
-				   bool tx_success)
+				   struct ieee80211_vif *csa_vif, u32 gp2)
 {
 	struct iwl_mvm_vif *mvmvif =
 			iwl_mvm_vif_from_mac80211(csa_vif);
 
-	/* Don't start to countdown from a failed beacon */
-	if (!tx_success && !mvmvif->csa_countdown)
-		return;
-
-	mvmvif->csa_countdown = true;
-
 	if (!ieee80211_csa_is_complete(csa_vif)) {
 		int c = ieee80211_csa_update_counter(csa_vif);
 
 		iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
 		if (csa_vif->p2p &&
-		    !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2 &&
-		    tx_success) {
+		    !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2) {
 			u32 rel_time = (c + 1) *
 				       csa_vif->bss_conf.beacon_int -
 				       IWL_MVM_CHANNEL_SWITCH_TIME_GO;
@@ -1304,30 +1252,38 @@
 			    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
 	struct iwl_mvm_tx_resp *beacon_notify_hdr;
 	struct ieee80211_vif *csa_vif;
 	struct ieee80211_vif *tx_blocked_vif;
-	u16 status;
+	u64 tsf;
 
 	lockdep_assert_held(&mvm->mutex);
 
-	beacon_notify_hdr = &beacon->beacon_notify_hdr;
-	mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_CAPA_EXTENDED_BEACON) {
+		struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
 
-	status = le16_to_cpu(beacon_notify_hdr->status.status) & TX_STATUS_MSK;
+		beacon_notify_hdr = &beacon->beacon_notify_hdr;
+		tsf = le64_to_cpu(beacon->tsf);
+		mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
+	} else {
+		struct iwl_beacon_notif *beacon = (void *)pkt->data;
+
+		beacon_notify_hdr = &beacon->beacon_notify_hdr;
+		tsf = le64_to_cpu(beacon->tsf);
+	}
+
 	IWL_DEBUG_RX(mvm,
 		     "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n",
-		     status, beacon_notify_hdr->failure_frame,
-		     le64_to_cpu(beacon->tsf),
+		     le16_to_cpu(beacon_notify_hdr->status.status) &
+								TX_STATUS_MSK,
+		     beacon_notify_hdr->failure_frame, tsf,
 		     mvm->ap_last_beacon_gp2,
 		     le32_to_cpu(beacon_notify_hdr->initial_rate));
 
 	csa_vif = rcu_dereference_protected(mvm->csa_vif,
 					    lockdep_is_held(&mvm->mutex));
 	if (unlikely(csa_vif && csa_vif->csa_active))
-		iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2,
-				       (status == TX_STATUS_SUCCESS));
+		iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2);
 
 	tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif,
 						lockdep_is_held(&mvm->mutex));
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 137f3da..fec128f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -69,7 +69,6 @@
 #include <linux/etherdevice.h>
 #include <linux/ip.h>
 #include <linux/if_arp.h>
-#include <linux/devcoredump.h>
 #include <net/mac80211.h>
 #include <net/ieee80211_radiotap.h>
 #include <net/tcp.h>
@@ -254,26 +253,6 @@
 	spin_unlock_bh(&mvm->refs_lock);
 }
 
-bool iwl_mvm_ref_taken(struct iwl_mvm *mvm)
-{
-	int i;
-	bool taken = false;
-
-	if (!iwl_mvm_is_d0i3_supported(mvm))
-		return true;
-
-	spin_lock_bh(&mvm->refs_lock);
-	for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
-		if (mvm->refs[i]) {
-			taken = true;
-			break;
-		}
-	}
-	spin_unlock_bh(&mvm->refs_lock);
-
-	return taken;
-}
-
 int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
 {
 	iwl_mvm_ref(mvm, ref_type);
@@ -323,8 +302,7 @@
 	hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
 	hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
 				    IEEE80211_RADIOTAP_MCS_HAVE_STBC;
-	hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
-		IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED;
+	hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;
 	hw->rate_control_algorithm = "iwl-mvm-rs";
 
 	/*
@@ -337,19 +315,15 @@
 		hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
 	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
+	    IWL_UCODE_API(mvm->fw->ucode_ver) >= 9 &&
 	    !iwlwifi_mod_params.uapsd_disable) {
 		hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
 		hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
 		hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
 	}
 
-	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN ||
-	    mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
 		hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
-		hw->wiphy->features |=
-			NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
-			NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
-	}
 
 	hw->sta_data_size = sizeof(struct iwl_mvm_sta);
 	hw->vif_data_size = sizeof(struct iwl_mvm_vif);
@@ -369,7 +343,8 @@
 	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)
 		hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
 
-	hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_CSA_FLOW)
+		hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
 	hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
 	hw->wiphy->n_iface_combinations =
@@ -427,8 +402,7 @@
 			       NL80211_FEATURE_LOW_PRIORITY_SCAN |
 			       NL80211_FEATURE_P2P_GO_OPPPS |
 			       NL80211_FEATURE_DYNAMIC_SMPS |
-			       NL80211_FEATURE_STATIC_SMPS |
-			       NL80211_FEATURE_SUPPORTS_WMM_ADMISSION;
+			       NL80211_FEATURE_STATIC_SMPS;
 
 	if (mvm->fw->ucode_capa.capa[0] &
 	    IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT)
@@ -466,8 +440,7 @@
 		mvm->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
 				    WIPHY_WOWLAN_DISCONNECT |
 				    WIPHY_WOWLAN_EAP_IDENTITY_REQ |
-				    WIPHY_WOWLAN_RFKILL_RELEASE |
-				    WIPHY_WOWLAN_NET_DETECT;
+				    WIPHY_WOWLAN_RFKILL_RELEASE;
 		if (!iwlwifi_mod_params.sw_crypto)
 			mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
 					     WIPHY_WOWLAN_GTK_REKEY_FAILURE |
@@ -476,7 +449,6 @@
 		mvm->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
 		mvm->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
 		mvm->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
-		mvm->wowlan.max_nd_match_sets = IWL_SCAN_MAX_PROFILES;
 		mvm->wowlan.tcp = &iwl_mvm_wowlan_tcp_support;
 		hw->wiphy->wowlan = &mvm->wowlan;
 	}
@@ -491,17 +463,6 @@
 	if (ret)
 		return ret;
 
-	if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_TDLS_SUPPORT) {
-		IWL_DEBUG_TDLS(mvm, "TDLS supported\n");
-		hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
-	}
-
-	if (mvm->fw->ucode_capa.capa[0] &
-	    IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH) {
-		IWL_DEBUG_TDLS(mvm, "TDLS channel switch supported\n");
-		hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
-	}
-
 	ret = ieee80211_register_hw(mvm->hw);
 	if (ret)
 		iwl_mvm_leds_exit(mvm);
@@ -565,8 +526,7 @@
 	}
 
 	if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
-	    !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) &&
-	    !test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
+	    !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
 		goto drop;
 
 	/* treat non-bufferable MMPDUs as broadcast if sta is sleeping */
@@ -718,51 +678,10 @@
 	memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
 }
 
-static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
-				     const void *data, size_t datalen)
-{
-	const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
-	ssize_t bytes_read;
-	ssize_t bytes_read_trans;
-
-	if (offset < dump_ptrs->op_mode_len) {
-		bytes_read = min_t(ssize_t, count,
-				   dump_ptrs->op_mode_len - offset);
-		memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
-		       bytes_read);
-		offset += bytes_read;
-		count -= bytes_read;
-
-		if (count == 0)
-			return bytes_read;
-	} else {
-		bytes_read = 0;
-	}
-
-	if (!dump_ptrs->trans_ptr)
-		return bytes_read;
-
-	offset -= dump_ptrs->op_mode_len;
-	bytes_read_trans = min_t(ssize_t, count,
-				 dump_ptrs->trans_ptr->len - offset);
-	memcpy(buffer + bytes_read,
-	       (u8 *)dump_ptrs->trans_ptr->data + offset,
-	       bytes_read_trans);
-
-	return bytes_read + bytes_read_trans;
-}
-
-static void iwl_mvm_free_coredump(const void *data)
-{
-	const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
-
-	vfree(fw_error_dump->op_mode_ptr);
-	vfree(fw_error_dump->trans_ptr);
-	kfree(fw_error_dump);
-}
-
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
 void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 {
+	static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL };
 	struct iwl_fw_error_dump_file *dump_file;
 	struct iwl_fw_error_dump_data *dump_data;
 	struct iwl_fw_error_dump_info *dump_info;
@@ -775,7 +694,10 @@
 
 	lockdep_assert_held(&mvm->mutex);
 
-	fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
+	if (mvm->fw_error_dump)
+		return;
+
+	fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
 	if (!fw_error_dump)
 		return;
 
@@ -850,25 +772,21 @@
 	if (fw_error_dump->trans_ptr)
 		file_len += fw_error_dump->trans_ptr->len;
 	dump_file->file_len = cpu_to_le32(file_len);
+	mvm->fw_error_dump = fw_error_dump;
 
-	dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
-		      GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
+	/* notify the userspace about the error we had */
+	kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env);
 }
+#endif
 
 static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 {
-	/* clear the D3 reconfig, we only need it to avoid dumping a
-	 * firmware coredump on reconfiguration, we shouldn't do that
-	 * on D3->D0 transition
-	 */
-	if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status))
-		iwl_mvm_fw_error_dump(mvm);
+	iwl_mvm_fw_error_dump(mvm);
 
 	iwl_trans_stop_device(mvm->trans);
 
 	mvm->scan_status = IWL_MVM_SCAN_NONE;
 	mvm->ps_disabled = false;
-	mvm->calibrating = false;
 
 	/* just in case one was running */
 	ieee80211_remain_on_channel_expired(mvm->hw);
@@ -883,7 +801,6 @@
 	iwl_mvm_reset_phy_ctxts(mvm);
 	memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
 	memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
-	memset(mvm->tfd_drained, 0, sizeof(mvm->tfd_drained));
 	memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
 	memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
 	memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
@@ -940,8 +857,9 @@
 	return ret;
 }
 
-static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
+static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)
 {
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	int ret;
 
 	mutex_lock(&mvm->mutex);
@@ -956,50 +874,9 @@
 	/* allow transport/FW low power modes */
 	iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
 
-	/*
-	 * If we have TDLS peers, remove them. We don't know the last seqno/PN
-	 * of packets the FW sent out, so we must reconnect.
-	 */
-	iwl_mvm_teardown_tdls_peers(mvm);
-
 	mutex_unlock(&mvm->mutex);
 }
 
-static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
-{
-	bool exit_now;
-
-	if (!iwl_mvm_is_d0i3_supported(mvm))
-		return;
-
-	mutex_lock(&mvm->d0i3_suspend_mutex);
-	__clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
-	exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP,
-					&mvm->d0i3_suspend_flags);
-	mutex_unlock(&mvm->d0i3_suspend_mutex);
-
-	if (exit_now) {
-		IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
-		_iwl_mvm_exit_d0i3(mvm);
-	}
-}
-
-static void
-iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
-			      enum ieee80211_reconfig_type reconfig_type)
-{
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-
-	switch (reconfig_type) {
-	case IEEE80211_RECONFIG_TYPE_RESTART:
-		iwl_mvm_restart_complete(mvm);
-		break;
-	case IEEE80211_RECONFIG_TYPE_SUSPEND:
-		iwl_mvm_resume_complete(mvm);
-		break;
-	}
-}
-
 void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
 {
 	lockdep_assert_held(&mvm->mutex);
@@ -1208,7 +1085,7 @@
 static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
 					struct ieee80211_vif *vif)
 {
-	u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
+	u32 tfd_msk = iwl_mvm_mac_get_queues_mask(mvm, vif);
 
 	if (tfd_msk) {
 		mutex_lock(&mvm->mutex);
@@ -1504,9 +1381,6 @@
 		.cmd = cmd,
 	};
 
-	if (IWL_MVM_FW_BCAST_FILTER_PASS_ALL)
-		return false;
-
 	memset(cmd, 0, sizeof(*cmd));
 	cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters);
 	cmd->max_macs = ARRAY_SIZE(cmd->macs);
@@ -1860,13 +1734,6 @@
 	if (changes & BSS_CHANGED_BEACON &&
 	    iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
 		IWL_WARN(mvm, "Failed updating beacon data\n");
-
-	if (changes & BSS_CHANGED_TXPOWER) {
-		IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
-				bss_conf->txpower);
-		iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
-	}
-
 }
 
 static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
@@ -1959,11 +1826,9 @@
 	    req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
 		return -EINVAL;
 
-	if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
-		ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
-		if (ret)
-			return ret;
-	}
+	ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
+	if (ret)
+		return ret;
 
 	mutex_lock(&mvm->mutex);
 
@@ -1974,9 +1839,7 @@
 
 	iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
 
-	if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
-		ret = iwl_mvm_scan_umac(mvm, vif, hw_req);
-	else if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
 		ret = iwl_mvm_unified_scan_lmac(mvm, vif, hw_req);
 	else
 		ret = iwl_mvm_scan_request(mvm, vif, req);
@@ -2193,15 +2056,6 @@
  out_unlock:
 	mutex_unlock(&mvm->mutex);
 
-	if (sta->tdls && ret == 0) {
-		if (old_state == IEEE80211_STA_NOTEXIST &&
-		    new_state == IEEE80211_STA_NONE)
-			ieee80211_reserve_tid(sta, IWL_MVM_TDLS_FW_TID);
-		else if (old_state == IEEE80211_STA_NONE &&
-			 new_state == IEEE80211_STA_NOTEXIST)
-			ieee80211_unreserve_tid(sta, IWL_MVM_TDLS_FW_TID);
-	}
-
 	return ret;
 }
 
@@ -2284,11 +2138,9 @@
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	int ret;
 
-	if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
-		ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
-		if (ret)
-			return ret;
-	}
+	ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
+	if (ret)
+		return ret;
 
 	mutex_lock(&mvm->mutex);
 
@@ -2308,10 +2160,27 @@
 		goto out;
 	}
 
-	ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies);
-	if (ret)
-		mvm->scan_status = IWL_MVM_SCAN_NONE;
+	mvm->scan_status = IWL_MVM_SCAN_SCHED;
 
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+		ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
+		if (ret)
+			goto err;
+	}
+
+	ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
+	if (ret)
+		goto err;
+
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+		ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
+	else
+		ret = iwl_mvm_sched_scan_start(mvm, req);
+
+	if (!ret)
+		goto out;
+err:
+	mvm->scan_status = IWL_MVM_SCAN_NONE;
 out:
 	mutex_unlock(&mvm->mutex);
 	return ret;
@@ -2329,7 +2198,6 @@
 	iwl_mvm_wait_for_async_handlers(mvm);
 
 	return ret;
-
 }
 
 static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
@@ -2358,16 +2226,12 @@
 		break;
 	case WLAN_CIPHER_SUITE_WEP40:
 	case WLAN_CIPHER_SUITE_WEP104:
-		/* For non-client mode, only use WEP keys for TX as we probably
-		 * don't have a station yet anyway and would then have to keep
-		 * track of the keys, linking them to each of the clients/peers
-		 * as they appear. For now, don't do that, for performance WEP
-		 * offload doesn't really matter much, but we need it for some
-		 * other offload features in client mode.
+		/*
+		 * Support for TX only, at least for now, so accept
+		 * the key and do nothing else. Then mac80211 will
+		 * pass it for TX but we don't have to use it for RX.
 		 */
-		if (vif->type != NL80211_IFTYPE_STATION)
-			return 0;
-		break;
+		return 0;
 	default:
 		/* currently FW supports only one optional cipher scheme */
 		if (hw->n_cipher_schemes &&
@@ -2503,19 +2367,14 @@
 	/* Set the node address */
 	memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
 
-	lockdep_assert_held(&mvm->mutex);
-
-	spin_lock_bh(&mvm->time_event_lock);
-
-	if (WARN_ON(te_data->id == HOT_SPOT_CMD)) {
-		spin_unlock_bh(&mvm->time_event_lock);
-		return -EIO;
-	}
-
 	te_data->vif = vif;
 	te_data->duration = duration;
 	te_data->id = HOT_SPOT_CMD;
 
+	lockdep_assert_held(&mvm->mutex);
+
+	spin_lock_bh(&mvm->time_event_lock);
+	list_add_tail(&te_data->list, &mvm->time_event_list);
 	spin_unlock_bh(&mvm->time_event_lock);
 
 	/*
@@ -2571,29 +2430,22 @@
 	IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
 			   duration, type);
 
-	mutex_lock(&mvm->mutex);
-
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
-		if (mvm->fw->ucode_capa.capa[0] &
-		    IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT) {
-			/* Use aux roc framework (HS20) */
-			ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
-						       vif, duration);
-			goto out_unlock;
-		}
-		IWL_ERR(mvm, "hotspot not supported\n");
-		ret = -EINVAL;
-		goto out_unlock;
+		/* Use aux roc framework (HS20) */
+		ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
+					       vif, duration);
+		return ret;
 	case NL80211_IFTYPE_P2P_DEVICE:
 		/* handle below */
 		break;
 	default:
 		IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
-		ret = -EINVAL;
-		goto out_unlock;
+		return -EINVAL;
 	}
 
+	mutex_lock(&mvm->mutex);
+
 	for (i = 0; i < NUM_PHY_CTX; i++) {
 		phy_ctxt = &mvm->phy_ctxts[i];
 		if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt)
@@ -2690,7 +2542,7 @@
 	IWL_DEBUG_MAC80211(mvm, "enter\n");
 
 	mutex_lock(&mvm->mutex);
-	iwl_mvm_stop_roc(mvm);
+	iwl_mvm_stop_p2p_roc(mvm);
 	mutex_unlock(&mvm->mutex);
 
 	IWL_DEBUG_MAC80211(mvm, "leave\n");
@@ -2803,8 +2655,8 @@
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_AP:
-		/* only needed if we're switching chanctx (i.e. during CSA) */
-		if (switching_chanctx) {
+		/* Unless it's a CSA flow we have nothing to do here */
+		if (vif->csa_active) {
 			mvmvif->ap_ibss_active = true;
 			break;
 		}
@@ -2848,32 +2700,23 @@
 	}
 
 	/* Handle binding during CSA */
-	if (vif->type == NL80211_IFTYPE_AP) {
+	if ((vif->type == NL80211_IFTYPE_AP) ||
+	    (switching_chanctx && (vif->type == NL80211_IFTYPE_STATION))) {
 		iwl_mvm_update_quotas(mvm, NULL);
 		iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
 	}
 
-	if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
-		u32 duration = 2 * vif->bss_conf.beacon_int;
+	if (vif->csa_active && vif->type == NL80211_IFTYPE_STATION) {
+		struct iwl_mvm_sta *mvmsta;
 
-		/* iwl_mvm_protect_session() reads directly from the
-		 * device (the system time), so make sure it is
-		 * available.
-		 */
-		ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
-		if (ret)
-			goto out_remove_binding;
+		mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
+							  mvmvif->ap_sta_id);
 
-		/* Protect the session to make sure we hear the first
-		 * beacon on the new channel.
-		 */
-		iwl_mvm_protect_session(mvm, vif, duration, duration,
-					vif->bss_conf.beacon_int / 2,
-					true);
+		if (WARN_ON(!mvmsta))
+			goto out;
 
-		iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
-
-		iwl_mvm_update_quotas(mvm, NULL);
+		/* TODO: only re-enable after the first beacon */
+		iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
 	}
 
 	goto out;
@@ -2907,6 +2750,7 @@
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct ieee80211_vif *disabled_vif = NULL;
+	struct iwl_mvm_sta *mvmsta;
 
 	lockdep_assert_held(&mvm->mutex);
 
@@ -2921,11 +2765,9 @@
 		break;
 	case NL80211_IFTYPE_AP:
 		/* This part is triggered only during CSA */
-		if (!switching_chanctx || !mvmvif->ap_ibss_active)
+		if (!vif->csa_active || !mvmvif->ap_ibss_active)
 			goto out;
 
-		mvmvif->csa_countdown = false;
-
 		/* Set CS bit on all the stations */
 		iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
 
@@ -2940,6 +2782,12 @@
 
 		disabled_vif = vif;
 
+		mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
+							  mvmvif->ap_sta_id);
+
+		if (!WARN_ON(!mvmsta))
+			iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, true);
+
 		iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
 		break;
 	default:
@@ -2965,12 +2813,18 @@
 	mutex_unlock(&mvm->mutex);
 }
 
-static int
-iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
-				struct ieee80211_vif_chanctx_switch *vifs)
+static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
+				      struct ieee80211_vif_chanctx_switch *vifs,
+				      int n_vifs,
+				      enum ieee80211_chanctx_switch_mode mode)
 {
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	int ret;
 
+	/* we only support SWAP_CONTEXTS and with a single-vif right now */
+	if (mode != CHANCTX_SWMODE_SWAP_CONTEXTS || n_vifs > 1)
+		return -EOPNOTSUPP;
+
 	mutex_lock(&mvm->mutex);
 	__iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
 	__iwl_mvm_remove_chanctx(mvm, vifs[0].old_ctx);
@@ -2999,51 +2853,15 @@
 	__iwl_mvm_remove_chanctx(mvm, vifs[0].new_ctx);
 
 out_reassign:
-	if (__iwl_mvm_add_chanctx(mvm, vifs[0].old_ctx)) {
+	ret = __iwl_mvm_add_chanctx(mvm, vifs[0].old_ctx);
+	if (ret) {
 		IWL_ERR(mvm, "failed to add old_ctx back after failure.\n");
 		goto out_restart;
 	}
 
-	if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
-					 true)) {
-		IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
-		goto out_restart;
-	}
-
-	goto out;
-
-out_restart:
-	/* things keep failing, better restart the hw */
-	iwl_mvm_nic_restart(mvm, false);
-
-out:
-	mutex_unlock(&mvm->mutex);
-
-	return ret;
-}
-
-static int
-iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
-				    struct ieee80211_vif_chanctx_switch *vifs)
-{
-	int ret;
-
-	mutex_lock(&mvm->mutex);
-	__iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
-
-	ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
+	ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
 					   true);
 	if (ret) {
-		IWL_ERR(mvm,
-			"failed to assign new_ctx during channel switch\n");
-		goto out_reassign;
-	}
-
-	goto out;
-
-out_reassign:
-	if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
-					 true)) {
 		IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
 		goto out_restart;
 	}
@@ -3056,34 +2874,6 @@
 
 out:
 	mutex_unlock(&mvm->mutex);
-
-	return ret;
-}
-
-static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
-				      struct ieee80211_vif_chanctx_switch *vifs,
-				      int n_vifs,
-				      enum ieee80211_chanctx_switch_mode mode)
-{
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-	int ret;
-
-	/* we only support a single-vif right now */
-	if (n_vifs > 1)
-		return -EOPNOTSUPP;
-
-	switch (mode) {
-	case CHANCTX_SWMODE_SWAP_CONTEXTS:
-		ret = iwl_mvm_switch_vif_chanctx_swap(mvm, vifs);
-		break;
-	case CHANCTX_SWMODE_REASSIGN_VIF:
-		ret = iwl_mvm_switch_vif_chanctx_reassign(mvm, vifs);
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-		break;
-	}
-
 	return ret;
 }
 
@@ -3169,134 +2959,27 @@
 }
 #endif
 
-static void iwl_mvm_channel_switch(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif,
-				   struct ieee80211_channel_switch *chsw)
-{
-	/* By implementing this operation, we prevent mac80211 from
-	 * starting its own channel switch timer, so that we can call
-	 * ieee80211_chswitch_done() ourselves at the right time
-	 * (which is when the absence time event starts).
-	 */
-
-	IWL_DEBUG_MAC80211(IWL_MAC80211_GET_MVM(hw),
-			   "dummy channel switch op\n");
-}
-
-static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
-				      struct ieee80211_vif *vif,
-				      struct ieee80211_channel_switch *chsw)
+static void iwl_mvm_channel_switch_beacon(struct ieee80211_hw *hw,
+					  struct ieee80211_vif *vif,
+					  struct cfg80211_chan_def *chandef)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	struct ieee80211_vif *csa_vif;
-	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	u32 apply_time;
-	int ret;
 
 	mutex_lock(&mvm->mutex);
 
-	IWL_DEBUG_MAC80211(mvm, "pre CSA to freq %d\n",
-			   chsw->chandef.center_freq1);
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_AP:
-		csa_vif =
-			rcu_dereference_protected(mvm->csa_vif,
-						  lockdep_is_held(&mvm->mutex));
-		if (WARN_ONCE(csa_vif && csa_vif->csa_active,
-			      "Another CSA is already in progress")) {
-			ret = -EBUSY;
-			goto out_unlock;
-		}
-
-		rcu_assign_pointer(mvm->csa_vif, vif);
-
-		if (WARN_ONCE(mvmvif->csa_countdown,
-			      "Previous CSA countdown didn't complete")) {
-			ret = -EBUSY;
-			goto out_unlock;
-		}
-
-		break;
-	case NL80211_IFTYPE_STATION:
-		/* Schedule the time event to a bit before beacon 1,
-		 * to make sure we're in the new channel when the
-		 * GO/AP arrives.
-		 */
-		apply_time = chsw->device_timestamp +
-			((vif->bss_conf.beacon_int * (chsw->count - 1) -
-			  IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
-
-		if (chsw->block_tx)
-			iwl_mvm_csa_client_absent(mvm, vif);
-
-		iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
-					    apply_time);
-		if (mvmvif->bf_data.bf_enabled) {
-			ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
-			if (ret)
-				goto out_unlock;
-		}
-
-		break;
-	default:
-		break;
-	}
-
-	mvmvif->ps_disabled = true;
-
-	ret = iwl_mvm_power_update_ps(mvm);
-	if (ret)
+	csa_vif = rcu_dereference_protected(mvm->csa_vif,
+					    lockdep_is_held(&mvm->mutex));
+	if (WARN(csa_vif && csa_vif->csa_active,
+		 "Another CSA is already in progress"))
 		goto out_unlock;
 
-	/* we won't be on this channel any longer */
-	iwl_mvm_teardown_tdls_peers(mvm);
+	IWL_DEBUG_MAC80211(mvm, "CSA started to freq %d\n",
+			   chandef->center_freq1);
+	rcu_assign_pointer(mvm->csa_vif, vif);
 
 out_unlock:
 	mutex_unlock(&mvm->mutex);
-
-	return ret;
-}
-
-static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif)
-{
-	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-	int ret;
-
-	mutex_lock(&mvm->mutex);
-
-	if (vif->type == NL80211_IFTYPE_STATION) {
-		struct iwl_mvm_sta *mvmsta;
-
-		mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
-							  mvmvif->ap_sta_id);
-
-		if (WARN_ON(!mvmsta)) {
-			ret = -EIO;
-			goto out_unlock;
-		}
-
-		iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
-
-		iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
-
-		ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
-		if (ret)
-			goto out_unlock;
-
-		iwl_mvm_stop_session_protection(mvm, vif);
-	}
-
-	mvmvif->ps_disabled = false;
-
-	ret = iwl_mvm_power_update_ps(mvm);
-
-out_unlock:
-	mutex_unlock(&mvm->mutex);
-
-	return ret;
 }
 
 static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
@@ -3305,52 +2988,33 @@
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	struct iwl_mvm_vif *mvmvif;
 	struct iwl_mvm_sta *mvmsta;
-	struct ieee80211_sta *sta;
-	int i;
-	u32 msk = 0;
 
 	if (!vif || vif->type != NL80211_IFTYPE_STATION)
 		return;
 
 	mutex_lock(&mvm->mutex);
 	mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
 
-	/* flush the AP-station and all TDLS peers */
-	for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
-		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
-						lockdep_is_held(&mvm->mutex));
-		if (IS_ERR_OR_NULL(sta))
-			continue;
-
-		mvmsta = iwl_mvm_sta_from_mac80211(sta);
-		if (mvmsta->vif != vif)
-			continue;
-
-		/* make sure only TDLS peers or the AP are flushed */
-		WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
-
-		msk |= mvmsta->tfd_queue_msk;
-	}
+	if (WARN_ON_ONCE(!mvmsta))
+		goto done;
 
 	if (drop) {
-		if (iwl_mvm_flush_tx_path(mvm, msk, true))
+		if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))
 			IWL_ERR(mvm, "flush request fail\n");
-		mutex_unlock(&mvm->mutex);
 	} else {
-		mutex_unlock(&mvm->mutex);
-
-		/* this can take a while, and we may need/want other operations
-		 * to succeed while doing this, so do it without the mutex held
-		 */
-		iwl_trans_wait_tx_queue_empty(mvm->trans, msk);
+		iwl_trans_wait_tx_queue_empty(mvm->trans,
+					      mvmsta->tfd_queue_msk);
 	}
+done:
+	mutex_unlock(&mvm->mutex);
 }
 
 const struct ieee80211_ops iwl_mvm_hw_ops = {
 	.tx = iwl_mvm_mac_tx,
 	.ampdu_action = iwl_mvm_mac_ampdu_action,
 	.start = iwl_mvm_mac_start,
-	.reconfig_complete = iwl_mvm_mac_reconfig_complete,
+	.restart_complete = iwl_mvm_mac_restart_complete,
 	.stop = iwl_mvm_mac_stop,
 	.add_interface = iwl_mvm_mac_add_interface,
 	.remove_interface = iwl_mvm_mac_remove_interface,
@@ -3391,13 +3055,7 @@
 
 	.set_tim = iwl_mvm_set_tim,
 
-	.channel_switch = iwl_mvm_channel_switch,
-	.pre_channel_switch = iwl_mvm_pre_channel_switch,
-	.post_channel_switch = iwl_mvm_post_channel_switch,
-
-	.tdls_channel_switch = iwl_mvm_tdls_channel_switch,
-	.tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
-	.tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
+	.channel_switch_beacon = iwl_mvm_channel_switch_beacon,
 
 	CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index d4d4d72..a1d1fc2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -87,18 +87,12 @@
 /* A TimeUnit is 1024 microsecond */
 #define MSEC_TO_TU(_msec)	(_msec*1000/1024)
 
-/* For GO, this value represents the number of TUs before CSA "beacon
- * 0" TBTT when the CSA time-event needs to be scheduled to start.  It
- * must be big enough to ensure that we switch in time.
+/* This value represents the number of TUs before CSA "beacon 0" TBTT
+ * when the CSA time-event needs to be scheduled to start.  It must be
+ * big enough to ensure that we switch in time.
  */
 #define IWL_MVM_CHANNEL_SWITCH_TIME_GO		40
 
-/* For client, this value represents the number of TUs before CSA
- * "beacon 1" TBTT, instead.  This is because we don't know when the
- * GO/AP will be in the new channel, so we switch early enough.
- */
-#define IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT	10
-
 /*
  * This value (in TUs) is used to fine tune the CSA NoA end time which should
  * be just before "beacon 0" TBTT.
@@ -275,7 +269,6 @@
 	IWL_MVM_REF_NMI,
 	IWL_MVM_REF_TM_CMD,
 	IWL_MVM_REF_EXIT_WORK,
-	IWL_MVM_REF_PROTECT_CSA,
 
 	/* update debugfs.c when changing this */
 
@@ -295,6 +288,7 @@
 * struct iwl_mvm_vif_bf_data - beacon filtering related data
 * @bf_enabled: indicates if beacon filtering is enabled
 * @ba_enabled: indicated if beacon abort is enabled
+* @last_beacon_signal: last beacon rssi signal in dbm
 * @ave_beacon_signal: average beacon signal
 * @last_cqm_event: rssi of the last cqm event
 * @bt_coex_min_thold: minimum threshold for BT coex
@@ -405,9 +399,6 @@
 
 	/* FW identified misbehaving AP */
 	u8 uapsd_misbehaving_bssid[ETH_ALEN];
-
-	/* Indicates that CSA countdown may be started */
-	bool csa_countdown;
 };
 
 static inline struct iwl_mvm_vif *
@@ -528,13 +519,6 @@
 #define IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -100
 #define IWL_MVM_DEBUG_SET_TEMPERATURE_MAX 200
 
-enum iwl_mvm_tdls_cs_state {
-	IWL_MVM_TDLS_SW_IDLE = 0,
-	IWL_MVM_TDLS_SW_REQ_SENT,
-	IWL_MVM_TDLS_SW_REQ_RCVD,
-	IWL_MVM_TDLS_SW_ACTIVE,
-};
-
 struct iwl_mvm {
 	/* for logger access */
 	struct device *dev;
@@ -564,7 +548,6 @@
 	enum iwl_ucode_type cur_ucode;
 	bool ucode_loaded;
 	bool init_ucode_complete;
-	bool calibrating;
 	u32 error_event_table;
 	u32 log_event_table;
 	u32 umac_error_event_table;
@@ -594,7 +577,6 @@
 	struct work_struct sta_drained_wk;
 	unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)];
 	atomic_t pending_frames[IWL_MVM_STATION_COUNT];
-	u32 tfd_drained[IWL_MVM_STATION_COUNT];
 	u8 rx_ba_sessions;
 
 	/* configured by mac80211 */
@@ -605,10 +587,6 @@
 	void *scan_cmd;
 	struct iwl_mcast_filter_cmd *mcast_filter_cmd;
 
-	/* UMAC scan tracking */
-	u32 scan_uid[IWL_MVM_MAX_SIMULTANEOUS_SCANS];
-	u8 scan_seq_num, sched_scan_seq_num;
-
 	/* rx chain antennas set through debugfs for the scan command */
 	u8 scan_rx_ant;
 
@@ -670,7 +648,7 @@
 	/* -1 for always, 0 for never, >0 for that many times */
 	s8 restart_fw;
 	struct work_struct fw_error_dump_wk;
-	enum iwl_fw_dbg_conf fw_dbg_conf;
+	struct iwl_mvm_dump_ptrs *fw_error_dump;
 
 #ifdef CPTCFG_IWLWIFI_LEDS
 	struct led_classdev led;
@@ -681,15 +659,6 @@
 #ifdef CONFIG_PM_SLEEP
 	struct wiphy_wowlan_support wowlan;
 	int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
-
-	/* sched scan settings for net detect */
-	struct cfg80211_sched_scan_request *nd_config;
-	struct ieee80211_scan_ies nd_ies;
-	struct cfg80211_match_set *nd_match_sets;
-	int n_nd_match_sets;
-	struct ieee80211_channel **nd_channels;
-	int n_nd_channels;
-	bool net_detect;
 #ifdef CPTCFG_IWLWIFI_DEBUGFS
 	u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */
 	bool d3_test_active;
@@ -762,28 +731,6 @@
 	u32 ap_last_beacon_gp2;
 
 	u8 low_latency_agg_frame_limit;
-
-	/* TDLS channel switch data */
-	struct {
-		struct delayed_work dwork;
-		enum iwl_mvm_tdls_cs_state state;
-
-		/*
-		 * Current cs sta - might be different from periodic cs peer
-		 * station. Value is meaningless when the cs-state is idle.
-		 */
-		u8 cur_sta_id;
-
-		/* TDLS periodic channel-switch peer */
-		struct {
-			u8 sta_id;
-			u8 op_class;
-			bool initiator; /* are we the link initiator */
-			struct cfg80211_chan_def chandef;
-			struct sk_buff *skb; /* ch sw template */
-			u32 ch_sw_tm_ie;
-		} peer;
-	} tdls_cs;
 };
 
 /* Extract MVM priv from op_mode and _hw */
@@ -800,7 +747,6 @@
 	IWL_MVM_STATUS_IN_HW_RESTART,
 	IWL_MVM_STATUS_IN_D0I3,
 	IWL_MVM_STATUS_ROC_AUX_RUNNING,
-	IWL_MVM_STATUS_D3_RECONFIG,
 };
 
 static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -809,26 +755,6 @@
 	       test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
 }
 
-/* Must be called with rcu_read_lock() held and it can only be
- * released when mvmsta is not needed anymore.
- */
-static inline struct iwl_mvm_sta *
-iwl_mvm_sta_from_staid_rcu(struct iwl_mvm *mvm, u8 sta_id)
-{
-	struct ieee80211_sta *sta;
-
-	if (sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))
-		return NULL;
-
-	sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
-
-	/* This can happen if the station has been removed right now */
-	if (IS_ERR_OR_NULL(sta))
-		return NULL;
-
-	return iwl_mvm_sta_from_mac80211(sta);
-}
-
 static inline struct iwl_mvm_sta *
 iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)
 {
@@ -902,16 +828,6 @@
 int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
 		   struct ieee80211_sta *sta);
 int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
-void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
-			struct iwl_tx_cmd *tx_cmd,
-			struct ieee80211_tx_info *info, u8 sta_id);
-void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
-			       struct ieee80211_tx_info *info,
-			       struct iwl_tx_cmd *tx_cmd,
-			       struct sk_buff *skb_frag);
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
-			    struct ieee80211_tx_info *info,
-			    struct ieee80211_sta *sta, __le16 fc);
 #ifdef CPTCFG_IWLWIFI_DEBUG
 const char *iwl_mvm_get_tx_fail_reason(u32 status);
 #else
@@ -968,8 +884,6 @@
 				struct iwl_device_cmd *cmd);
 int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 			 struct iwl_device_cmd *cmd);
-int iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
-			    struct iwl_device_cmd *cmd);
 
 /* MVM PHY */
 int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
@@ -983,8 +897,6 @@
 void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
 			    struct iwl_mvm_phy_ctxt *ctxt);
 int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
-u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef);
-u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);
 
 /* MAC (virtual interface) programming */
 int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -993,7 +905,8 @@
 int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			     bool force_assoc_off, const u8 *bssid_override);
 int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif);
+u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
+				struct ieee80211_vif *vif);
 int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
 				    struct ieee80211_vif *vif);
 int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
@@ -1004,8 +917,6 @@
 				    struct iwl_device_cmd *cmd);
 void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
 				    struct ieee80211_vif *vif);
-unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
-					 struct ieee80211_vif *exclude_vif);
 
 /* Bindings */
 int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -1016,7 +927,6 @@
 			  struct ieee80211_vif *disabled_vif);
 
 /* Scanning */
-int iwl_mvm_scan_size(struct iwl_mvm *mvm);
 int iwl_mvm_scan_request(struct iwl_mvm *mvm,
 			 struct ieee80211_vif *vif,
 			 struct cfg80211_scan_request *req);
@@ -1039,10 +949,6 @@
 				       struct cfg80211_sched_scan_request *req);
 int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
 			     struct cfg80211_sched_scan_request *req);
-int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
-			       struct ieee80211_vif *vif,
-			       struct cfg80211_sched_scan_request *req,
-			       struct ieee80211_scan_ies *ies);
 int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify);
 int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
 				    struct iwl_rx_cmd_buffer *rxb,
@@ -1057,17 +963,6 @@
 				    struct cfg80211_sched_scan_request *req,
 				    struct ieee80211_scan_ies *ies);
 
-/* UMAC scan */
-int iwl_mvm_config_scan(struct iwl_mvm *mvm);
-int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-		      struct ieee80211_scan_request *req);
-int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-			    struct cfg80211_sched_scan_request *req,
-			    struct ieee80211_scan_ies *ies);
-int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
-					struct iwl_rx_cmd_buffer *rxb,
-					struct iwl_device_cmd *cmd);
-
 /* MVM debugfs */
 #ifdef CPTCFG_IWLWIFI_DEBUGFS
 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
@@ -1147,7 +1042,7 @@
 }
 #endif
 void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
-				struct iwl_wowlan_config_cmd *cmd);
+				struct iwl_wowlan_config_cmd_v2 *cmd);
 int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
 			       struct ieee80211_vif *vif,
 			       bool disable_offloading,
@@ -1157,7 +1052,6 @@
 void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
 void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
 int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
-bool iwl_mvm_ref_taken(struct iwl_mvm *mvm);
 void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
 int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
 
@@ -1173,14 +1067,12 @@
 				struct ieee80211_sta *sta);
 bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
 				     struct ieee80211_sta *sta);
-bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant);
 bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm);
 bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
 				    enum ieee80211_band band);
 u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
 			   struct ieee80211_tx_info *info, u8 ac);
 
-bool iwl_mvm_bt_coex_is_ant_avail_old(struct iwl_mvm *mvm, u8 ant);
 bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm);
 void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm);
 int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm);
@@ -1296,10 +1188,6 @@
 
 /* Thermal management and CT-kill */
 void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff);
-void iwl_mvm_tt_temp_changed(struct iwl_mvm *mvm, u32 temp);
-int iwl_mvm_temp_notif(struct iwl_mvm *mvm,
-		       struct iwl_rx_cmd_buffer *rxb,
-		       struct iwl_device_cmd *cmd);
 void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
 void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff);
 void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
@@ -1311,37 +1199,18 @@
 		      bool added_vif);
 
 /* TDLS */
-
-/*
- * We use TID 4 (VI) as a FW-used-only TID when TDLS connections are present.
- * This TID is marked as used vs the AP and all connected TDLS peers.
- */
-#define IWL_MVM_TDLS_FW_TID 4
-
 int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
 void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm);
 void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			       bool sta_added);
 void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
 					   struct ieee80211_vif *vif);
-int iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif,
-				struct ieee80211_sta *sta, u8 oper_class,
-				struct cfg80211_chan_def *chandef,
-				struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie);
-void iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw,
-				      struct ieee80211_vif *vif,
-				      struct ieee80211_tdls_ch_sw_params *params);
-void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
-					struct ieee80211_vif *vif,
-					struct ieee80211_sta *sta);
-int iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
-			  struct iwl_device_cmd *cmd);
-void iwl_mvm_tdls_ch_switch_work(struct work_struct *work);
-
-struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
 
 void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
 void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
+#else
+static inline void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) {}
+#endif
 
 #endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index 98203ab..f23b8fd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -339,15 +339,11 @@
 	} *file_sec;
 	const u8 *eof, *temp;
 	int max_section_size;
-	const __le32 *dword_buff;
 
 #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
 #define NVM_WORD2_ID(x) (x >> 12)
 #define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8))
 #define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4)
-#define NVM_HEADER_0	(0x2A504C54)
-#define NVM_HEADER_1	(0x4E564D2A)
-#define NVM_HEADER_SIZE	(4 * sizeof(u32))
 
 	IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
 
@@ -376,6 +372,12 @@
 	IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n",
 		 mvm->nvm_file_name, fw_entry->size);
 
+	if (fw_entry->size < sizeof(*file_sec)) {
+		IWL_ERR(mvm, "NVM file too small\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
 	if (fw_entry->size > MAX_NVM_FILE_LEN) {
 		IWL_ERR(mvm, "NVM file too large\n");
 		ret = -EINVAL;
@@ -383,25 +385,8 @@
 	}
 
 	eof = fw_entry->data + fw_entry->size;
-	dword_buff = (__le32 *)fw_entry->data;
 
-	/* some NVM file will contain a header.
-	 * The header is identified by 2 dwords header as follow:
-	 * dword[0] = 0x2A504C54
-	 * dword[1] = 0x4E564D2A
-	 *
-	 * This header must be skipped when providing the NVM data to the FW.
-	 */
-	if (fw_entry->size > NVM_HEADER_SIZE &&
-	    dword_buff[0] == cpu_to_le32(NVM_HEADER_0) &&
-	    dword_buff[1] == cpu_to_le32(NVM_HEADER_1)) {
-		file_sec = (void *)(fw_entry->data + NVM_HEADER_SIZE);
-		IWL_INFO(mvm, "NVM Version %08X\n", le32_to_cpu(dword_buff[2]));
-		IWL_INFO(mvm, "NVM Manufacturing date %08X\n",
-			 le32_to_cpu(dword_buff[3]));
-	} else {
-		file_sec = (void *)fw_entry->data;
-	}
+	file_sec = (void *)fw_entry->data;
 
 	while (true) {
 		if (file_sec->data > eof) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/offloading.c b/drivers/net/wireless/iwlwifi/mvm/offloading.c
index 68b0169..adcbf4c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/offloading.c
+++ b/drivers/net/wireless/iwlwifi/mvm/offloading.c
@@ -67,7 +67,7 @@
 #include "mvm.h"
 
 void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
-				struct iwl_wowlan_config_cmd *cmd)
+				struct iwl_wowlan_config_cmd_v2 *cmd)
 {
 	int i;
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index f10c327..4de8ec8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -244,8 +244,6 @@
 		   iwl_mvm_rx_scan_offload_complete_notif, true),
 	RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results,
 		   false),
-	RX_HANDLER(SCAN_COMPLETE_UMAC, iwl_mvm_rx_umac_scan_complete_notif,
-		   true),
 
 	RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
 	RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
@@ -256,12 +254,6 @@
 	RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false),
 	RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION,
 		   iwl_mvm_power_uapsd_misbehaving_ap_notif, false),
-	RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true),
-
-	RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif,
-		   true),
-	RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, false),
-
 };
 #undef RX_HANDLER
 #define CMD(x) [x] = #x
@@ -325,9 +317,11 @@
 	CMD(WOWLAN_KEK_KCK_MATERIAL),
 	CMD(WOWLAN_GET_STATUSES),
 	CMD(WOWLAN_TX_POWER_PER_DB),
-	CMD(SCAN_OFFLOAD_PROFILES_QUERY_CMD),
-	CMD(SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD),
-	CMD(SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD),
+	CMD(NET_DETECT_CONFIG_CMD),
+	CMD(NET_DETECT_PROFILES_QUERY_CMD),
+	CMD(NET_DETECT_PROFILES_CMD),
+	CMD(NET_DETECT_HOTSPOTS_CMD),
+	CMD(NET_DETECT_HOTSPOTS_QUERY_CMD),
 	CMD(CARD_STATE_NOTIFICATION),
 	CMD(MISSED_BEACONS_NOTIFICATION),
 	CMD(BT_COEX_PRIO_TABLE),
@@ -342,7 +336,6 @@
 	CMD(DTS_MEASUREMENT_NOTIFICATION),
 	CMD(REPLY_THERMAL_MNG_BACKOFF),
 	CMD(MAC_PM_POWER_TABLE),
-	CMD(LTR_CONFIG),
 	CMD(BT_COEX_CI),
 	CMD(BT_COEX_UPDATE_SW_BOOST),
 	CMD(BT_COEX_UPDATE_CORUN_LUT),
@@ -350,13 +343,6 @@
 	CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
 	CMD(ANTENNA_COUPLING_NOTIFICATION),
 	CMD(SCD_QUEUE_CFG),
-	CMD(SCAN_CFG_CMD),
-	CMD(SCAN_REQ_UMAC),
-	CMD(SCAN_ABORT_UMAC),
-	CMD(SCAN_COMPLETE_UMAC),
-	CMD(TDLS_CHANNEL_SWITCH_CMD),
-	CMD(TDLS_CHANNEL_SWITCH_NOTIFICATION),
-	CMD(TDLS_CONFIG_CMD),
 };
 #undef CMD
 
@@ -416,9 +402,6 @@
 	if (cfg->max_rx_agg_size)
 		hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
 
-	if (cfg->max_tx_agg_size)
-		hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size;
-
 	op_mode = hw->priv;
 	op_mode->ops = &iwl_mvm_ops;
 
@@ -440,7 +423,6 @@
 	}
 	mvm->sf_state = SF_UNINIT;
 	mvm->low_latency_agg_frame_limit = 6;
-	mvm->cur_ucode = IWL_UCODE_INIT;
 
 	mutex_init(&mvm->mutex);
 	mutex_init(&mvm->d0i3_suspend_mutex);
@@ -455,7 +437,6 @@
 	INIT_WORK(&mvm->sta_drained_wk, iwl_mvm_sta_drained_wk);
 	INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
 	INIT_WORK(&mvm->fw_error_dump_wk, iwl_mvm_fw_error_dump_wk);
-	INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work);
 
 	spin_lock_init(&mvm->d0i3_tx_lock);
 	spin_lock_init(&mvm->refs_lock);
@@ -496,10 +477,6 @@
 
 	trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
 	trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
-	trans->dbg_dest_tlv = mvm->fw->dbg_dest_tlv;
-	trans->dbg_dest_reg_num = mvm->fw->dbg_dest_reg_num;
-	memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv,
-	       sizeof(trans->dbg_conf_tlv));
 
 	/* set up notification wait support */
 	iwl_notification_wait_init(&mvm->notif_wait);
@@ -543,8 +520,7 @@
 
 		mutex_lock(&mvm->mutex);
 		err = iwl_run_init_mvm_ucode(mvm, true);
-		if (!err || !iwlmvm_mod_params.init_dbg)
-			iwl_trans_stop_device(trans);
+		iwl_trans_stop_device(trans);
 		mutex_unlock(&mvm->mutex);
 		/* returns 0 if successful, 1 if success but in rfkill */
 		if (err < 0 && !iwlmvm_mod_params.init_dbg) {
@@ -553,7 +529,16 @@
 		}
 	}
 
-	scan_size = iwl_mvm_scan_size(mvm);
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+		scan_size = sizeof(struct iwl_scan_req_unified_lmac) +
+			sizeof(struct iwl_scan_channel_cfg_lmac) *
+				mvm->fw->ucode_capa.n_scan_channels +
+			sizeof(struct iwl_scan_probe_req);
+	else
+		scan_size = sizeof(struct iwl_scan_cmd) +
+			mvm->fw->ucode_capa.max_probe_length +
+			mvm->fw->ucode_capa.n_scan_channels *
+				sizeof(struct iwl_scan_channel);
 
 	mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL);
 	if (!mvm->scan_cmd)
@@ -598,16 +583,16 @@
 	ieee80211_unregister_hw(mvm->hw);
 
 	kfree(mvm->scan_cmd);
+	if (mvm->fw_error_dump) {
+		vfree(mvm->fw_error_dump->op_mode_ptr);
+		vfree(mvm->fw_error_dump->trans_ptr);
+		kfree(mvm->fw_error_dump);
+	}
 	kfree(mvm->mcast_filter_cmd);
 	mvm->mcast_filter_cmd = NULL;
 
 #if defined(CONFIG_PM_SLEEP) && defined(CPTCFG_IWLWIFI_DEBUGFS)
 	kfree(mvm->d3_resume_sram);
-	if (mvm->nd_config) {
-		kfree(mvm->nd_config->match_sets);
-		kfree(mvm->nd_config);
-		mvm->nd_config = NULL;
-	}
 #endif
 
 	iwl_trans_op_mode_leave(mvm->trans);
@@ -766,7 +751,6 @@
 static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 {
 	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-	bool calibrating = ACCESS_ONCE(mvm->calibrating);
 
 	if (state)
 		set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
@@ -775,15 +759,7 @@
 
 	wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
 
-	/* iwl_run_init_mvm_ucode is waiting for results, abort it */
-	if (calibrating)
-		iwl_abort_notification_waits(&mvm->notif_wait);
-
-	/*
-	 * Stop the device if we run OPERATIONAL firmware or if we are in the
-	 * middle of the calibrations.
-	 */
-	return state && (mvm->cur_ucode != IWL_UCODE_INIT || calibrating);
+	return state && mvm->cur_ucode != IWL_UCODE_INIT;
 }
 
 static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
@@ -1004,7 +980,7 @@
 }
 
 static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
-				    struct iwl_wowlan_config_cmd *cmd,
+				    struct iwl_wowlan_config_cmd_v3 *cmd,
 				    struct iwl_d0i3_iter_data *iter_data)
 {
 	struct ieee80211_sta *ap_sta;
@@ -1020,14 +996,14 @@
 		goto out;
 
 	mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta);
-	cmd->is_11n_connection = ap_sta->ht_cap.ht_supported;
+	cmd->common.is_11n_connection = ap_sta->ht_cap.ht_supported;
 	cmd->offloading_tid = iter_data->offloading_tid;
 
 	/*
 	 * The d0i3 uCode takes care of the nonqos counters,
 	 * so configure only the qos seq ones.
 	 */
-	iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, cmd);
+	iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &cmd->common);
 out:
 	rcu_read_unlock();
 }
@@ -1039,11 +1015,14 @@
 	struct iwl_d0i3_iter_data d0i3_iter_data = {
 		.mvm = mvm,
 	};
-	struct iwl_wowlan_config_cmd wowlan_config_cmd = {
-		.wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
-					     IWL_WOWLAN_WAKEUP_BEACON_MISS |
-					     IWL_WOWLAN_WAKEUP_LINK_CHANGE |
-					     IWL_WOWLAN_WAKEUP_BCN_FILTERING),
+	struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {
+		.common = {
+			.wakeup_filter =
+				cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
+					    IWL_WOWLAN_WAKEUP_BEACON_MISS |
+					    IWL_WOWLAN_WAKEUP_LINK_CHANGE |
+					    IWL_WOWLAN_WAKEUP_BCN_FILTERING),
+		},
 	};
 	struct iwl_d3_manager_config d3_cfg_cmd = {
 		.min_sleep_time = cpu_to_le32(1000),
@@ -1055,19 +1034,6 @@
 	set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
 	synchronize_net();
 
-	/*
-	 * iwl_mvm_ref_sync takes a reference before checking the flag.
-	 * so by checking there is no held reference we prevent a state
-	 * in which iwl_mvm_ref_sync continues successfully while we
-	 * configure the firmware to enter d0i3
-	 */
-	if (iwl_mvm_ref_taken(mvm)) {
-		IWL_DEBUG_RPM(mvm->trans, "abort d0i3 due to taken ref\n");
-		clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
-		wake_up(&mvm->d0i3_exit_waitq);
-		return 1;
-	}
-
 	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
 						   IEEE80211_IFACE_ITER_NORMAL,
 						   iwl_mvm_enter_d0i3_iterator,
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index 1c0d4a4..12283b5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -68,7 +68,7 @@
 #include "mvm.h"
 
 /* Maps the driver specific channel width definition to the the fw values */
-u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
+static inline u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
 {
 	switch (chandef->width) {
 	case NL80211_CHAN_WIDTH_20_NOHT:
@@ -90,7 +90,7 @@
  * Maps the driver specific control channel position (relative to the center
  * freq) definitions to the the fw values
  */
-u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
+static inline u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
 {
 	switch (chandef->chan->center_freq - chandef->center_freq1) {
 	case -70:
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index a33a46e..27db05b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -286,27 +286,6 @@
 	return true;
 }
 
-static int iwl_mvm_power_get_skip_over_dtim(int dtimper, int bi)
-{
-	int numerator;
-	int dtim_interval = dtimper * bi;
-
-	if (WARN_ON(!dtim_interval))
-		return 0;
-
-	if (dtimper == 1) {
-		if (bi > 100)
-			numerator = 408;
-		else
-			numerator = 510;
-	} else if (dtimper < 10) {
-		numerator = 612;
-	} else {
-		return 0;
-	}
-	return max(1, (numerator / dtim_interval));
-}
-
 static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
 {
 	struct ieee80211_chanctx_conf *chanctx_conf;
@@ -329,7 +308,7 @@
 				    struct ieee80211_vif *vif,
 				    struct iwl_mac_power_cmd *cmd)
 {
-	int dtimper, bi;
+	int dtimper, dtimper_msec;
 	int keep_alive;
 	bool radar_detect = false;
 	struct iwl_mvm_vif *mvmvif __maybe_unused =
@@ -338,7 +317,6 @@
 	cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
 							    mvmvif->color));
 	dtimper = vif->bss_conf.dtim_period;
-	bi = vif->bss_conf.beacon_int;
 
 	/*
 	 * Regardless of power management state the driver must set
@@ -346,9 +324,10 @@
 	 * immediately after association. Check that keep alive period
 	 * is at least 3 * DTIM
 	 */
-	keep_alive = DIV_ROUND_UP(ieee80211_tu_to_usec(3 * dtimper * bi),
-				  USEC_PER_SEC);
-	keep_alive = max(keep_alive, POWER_KEEP_ALIVE_PERIOD_SEC);
+	dtimper_msec = dtimper * vif->bss_conf.beacon_int;
+	keep_alive = max_t(int, 3 * dtimper_msec,
+			   MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
+	keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
 	cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
 
 	if (mvm->ps_disabled)
@@ -373,14 +352,11 @@
 	radar_detect = iwl_mvm_power_is_radar(vif);
 
 	/* Check skip over DTIM conditions */
-	if (!radar_detect && (dtimper < 10) &&
+	if (!radar_detect && (dtimper <= 10) &&
 	    (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
 	     mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
-		cmd->skip_dtim_periods =
-			iwl_mvm_power_get_skip_over_dtim(dtimper, bi);
-		if (cmd->skip_dtim_periods)
-			cmd->flags |=
-				cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+		cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+		cmd->skip_dtim_periods = 3;
 	}
 
 	if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index cf25e6b..287e744 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -158,12 +158,6 @@
 	allow_column_func_t checks[MAX_COLUMN_CHECKS];
 };
 
-static bool rs_ant_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-			 struct iwl_scale_tbl_info *tbl)
-{
-	return iwl_mvm_bt_coex_is_ant_avail(mvm, tbl->rate.ant);
-}
-
 static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 			  struct iwl_scale_tbl_info *tbl)
 {
@@ -224,9 +218,6 @@
 			RS_COLUMN_INVALID,
 			RS_COLUMN_INVALID,
 		},
-		.checks = {
-			rs_ant_allow,
-		},
 	},
 	[RS_COLUMN_LEGACY_ANT_B] = {
 		.mode = RS_LEGACY,
@@ -240,9 +231,6 @@
 			RS_COLUMN_INVALID,
 			RS_COLUMN_INVALID,
 		},
-		.checks = {
-			rs_ant_allow,
-		},
 	},
 	[RS_COLUMN_SISO_ANT_A] = {
 		.mode = RS_SISO,
@@ -258,7 +246,6 @@
 		},
 		.checks = {
 			rs_siso_allow,
-			rs_ant_allow,
 		},
 	},
 	[RS_COLUMN_SISO_ANT_B] = {
@@ -275,7 +262,6 @@
 		},
 		.checks = {
 			rs_siso_allow,
-			rs_ant_allow,
 		},
 	},
 	[RS_COLUMN_SISO_ANT_A_SGI] = {
@@ -293,7 +279,6 @@
 		},
 		.checks = {
 			rs_siso_allow,
-			rs_ant_allow,
 			rs_sgi_allow,
 		},
 	},
@@ -312,7 +297,6 @@
 		},
 		.checks = {
 			rs_siso_allow,
-			rs_ant_allow,
 			rs_sgi_allow,
 		},
 	},
@@ -521,11 +505,10 @@
 static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
 				const char *prefix)
 {
-	IWL_DEBUG_RATE(mvm,
-		       "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC: %d\n",
+	IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d\n",
 		       prefix, rs_pretty_lq_type(rate->type),
 		       rate->index, rs_pretty_ant(rate->ant),
-		       rate->bw, rate->sgi, rate->ldpc, rate->stbc);
+		       rate->bw, rate->sgi, rate->ldpc);
 }
 
 static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
@@ -758,12 +741,6 @@
 		IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type);
 	}
 
-	if (is_siso(rate) && rate->stbc) {
-		/* To enable STBC we need to set both a flag and ANT_AB */
-		ucode_rate |= RATE_MCS_ANT_AB_MSK;
-		ucode_rate |= RATE_MCS_VHT_STBC_MSK;
-	}
-
 	ucode_rate |= rate->bw;
 	if (rate->sgi)
 		ucode_rate |= RATE_MCS_SGI_MSK;
@@ -808,8 +785,6 @@
 		rate->sgi = true;
 	if (ucode_rate & RATE_MCS_LDPC_MSK)
 		rate->ldpc = true;
-	if (ucode_rate & RATE_MCS_VHT_STBC_MSK)
-		rate->stbc = true;
 
 	rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
 
@@ -819,7 +794,7 @@
 
 		if (nss == 1) {
 			rate->type = LQ_HT_SISO;
-			WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
+			WARN_ON_ONCE(num_of_ant != 1);
 		} else if (nss == 2) {
 			rate->type = LQ_HT_MIMO2;
 			WARN_ON_ONCE(num_of_ant != 2);
@@ -832,7 +807,7 @@
 
 		if (nss == 1) {
 			rate->type = LQ_VHT_SISO;
-			WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
+			WARN_ON_ONCE(num_of_ant != 1);
 		} else if (nss == 2) {
 			rate->type = LQ_VHT_MIMO2;
 			WARN_ON_ONCE(num_of_ant != 2);
@@ -1017,15 +992,7 @@
 static inline bool rs_rate_match(struct rs_rate *a,
 				 struct rs_rate *b)
 {
-	bool ant_match;
-
-	if (a->stbc)
-		ant_match = (b->ant == ANT_A || b->ant == ANT_B);
-	else
-		ant_match = (a->ant == b->ant);
-
-	return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi)
-		&& ant_match;
+	return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi);
 }
 
 static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
@@ -1126,11 +1093,10 @@
 
 	if (time_after(jiffies,
 		       (unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) {
-		int t;
-
+		int tid;
 		IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
-		for (t = 0; t < IWL_MAX_TID_COUNT; t++)
-			ieee80211_stop_tx_ba_session(sta, t);
+		for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+			ieee80211_stop_tx_ba_session(sta, tid);
 
 		iwl_mvm_rs_rate_init(mvm, sta, info->band, false);
 		return;
@@ -1171,15 +1137,16 @@
 		/* Rate did match, so reset the missed_rate_counter */
 		lq_sta->missed_rate_counter = 0;
 
-	if (!lq_sta->search_better_tbl) {
+	/* Figure out if rate scale algorithm is in active or search table */
+	if (rs_rate_match(&rate,
+			  &(lq_sta->lq_info[lq_sta->active_tbl].rate))) {
 		curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
 		other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-	} else {
+	} else if (rs_rate_match(&rate,
+			 &lq_sta->lq_info[1 - lq_sta->active_tbl].rate)) {
 		curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
 		other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-	}
-
-	if (WARN_ON_ONCE(!rs_rate_match(&rate, &curr_tbl->rate))) {
+	} else {
 		IWL_DEBUG_RATE(mvm,
 			       "Neither active nor search matches tx rate\n");
 		tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -1204,13 +1171,6 @@
 	 * first index into rate scale table.
 	 */
 	if (info->flags & IEEE80211_TX_STAT_AMPDU) {
-		/* ampdu_ack_len = 0 marks no BA was received. In this case
-		 * treat it as a single frame loss as we don't want the success
-		 * ratio to dip too quickly because a BA wasn't received
-		 */
-		if (info->status.ampdu_ack_len == 0)
-			info->status.ampdu_len = 1;
-
 		ucode_rate = le32_to_cpu(table->rs_table[0]);
 		rs_rate_from_ucode_rate(ucode_rate, info->band, &rate);
 		rs_collect_tx_data(lq_sta, curr_tbl, rate.index,
@@ -1265,7 +1225,7 @@
 	IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
 done:
 	/* See if there's a better rate or modulation mode to try. */
-	if (sta->supp_rates[info->band])
+	if (sta && sta->supp_rates[info->band])
 		rs_rate_scale_perform(mvm, sta, lq_sta, tid);
 }
 
@@ -1663,8 +1623,6 @@
 		else
 			rate->type = LQ_LEGACY_G;
 
-		rate->bw = RATE_MCS_CHAN_WIDTH_20;
-		rate->ldpc = false;
 		rate_mask = lq_sta->active_legacy_rate;
 	} else if (column->mode == RS_SISO) {
 		rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;
@@ -1676,11 +1634,8 @@
 		WARN_ON_ONCE("Bad column mode");
 	}
 
-	if (column->mode != RS_LEGACY) {
-		rate->bw = rs_bw_from_sta_bw(sta);
-		rate->ldpc = lq_sta->ldpc;
-	}
-
+	rate->bw = rs_bw_from_sta_bw(sta);
+	rate->ldpc = lq_sta->ldpc;
 	search_tbl->column = col_id;
 	rs_set_expected_tpt_table(lq_sta, search_tbl);
 
@@ -1799,29 +1754,6 @@
 	return action;
 }
 
-static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-			  struct iwl_lq_sta *lq_sta)
-{
-	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	struct ieee80211_vif *vif = mvmsta->vif;
-	bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
-				!vif->bss_conf.ps);
-
-	/* Our chip supports Tx STBC and the peer is an HT/VHT STA which
-	 * supports STBC of at least 1*SS
-	 */
-	if (!lq_sta->stbc)
-		return false;
-
-	if (!mvm->ps_disabled && !sta_ps_disabled)
-		return false;
-
-	if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
-		return false;
-
-	return true;
-}
-
 static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
 				int *weaker, int *stronger)
 {
@@ -2743,11 +2675,6 @@
 		if (mvm->cfg->ht_params->ldpc &&
 		    (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING))
 			lq_sta->ldpc = true;
-
-		if (mvm->cfg->ht_params->stbc &&
-		    (num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
-		    (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC))
-			lq_sta->stbc = true;
 	} else {
 		rs_vht_set_enabled_rates(sta, vht_cap, lq_sta);
 		lq_sta->is_vht = true;
@@ -2755,16 +2682,8 @@
 		if (mvm->cfg->ht_params->ldpc &&
 		    (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))
 			lq_sta->ldpc = true;
-
-		if (mvm->cfg->ht_params->stbc &&
-		    (num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
-		    (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))
-			lq_sta->stbc = true;
 	}
 
-	if (IWL_MVM_RS_DISABLE_MIMO)
-		lq_sta->active_mimo2_rate = 0;
-
 	lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
 						    BITS_PER_LONG);
 	lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate,
@@ -2773,11 +2692,11 @@
 						   BITS_PER_LONG);
 
 	IWL_DEBUG_RATE(mvm,
-		       "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC%d\n",
+		       "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d\n",
 		       lq_sta->active_legacy_rate,
 		       lq_sta->active_siso_rate,
 		       lq_sta->active_mimo2_rate,
-		       lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc);
+		       lq_sta->is_vht, lq_sta->ldpc);
 	IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
 		       lq_sta->max_legacy_rate_idx,
 		       lq_sta->max_siso_rate_idx,
@@ -2901,7 +2820,6 @@
  * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps
  */
 static void rs_build_rates_table(struct iwl_mvm *mvm,
-				 struct ieee80211_sta *sta,
 				 struct iwl_lq_sta *lq_sta,
 				 const struct rs_rate *initial_rate)
 {
@@ -2914,7 +2832,6 @@
 	memcpy(&rate, initial_rate, sizeof(rate));
 
 	valid_tx_ant = mvm->fw->valid_tx_ant;
-	rate.stbc = rs_stbc_allow(mvm, sta, lq_sta);
 
 	if (is_siso(&rate)) {
 		num_rates = RS_INITIAL_SISO_NUM_RATES;
@@ -2986,7 +2903,7 @@
 	if (WARN_ON_ONCE(!sta || !initial_rate))
 		return;
 
-	rs_build_rates_table(mvm, sta, lq_sta, initial_rate);
+	rs_build_rates_table(mvm, lq_sta, initial_rate);
 
 	if (num_of_ant(initial_rate->ant) == 1)
 		lq_cmd->single_stream_ant_msk = initial_rate->ant;
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index fdd0da5..bcb4b1d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -208,7 +208,6 @@
 	u32 bw;
 	bool sgi;
 	bool ldpc;
-	bool stbc;
 };
 
 
@@ -332,7 +331,6 @@
 	u64 last_tx;
 	bool is_vht;
 	bool ldpc;              /* LDPC Rx is supported by the STA */
-	bool stbc;              /* Tx STBC is supported by chip and Rx by STA */
 	enum ieee80211_band band;
 
 	/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index 0f6a40d..e61514b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -96,27 +96,27 @@
  * Adds the rxb to a new skb and give it to mac80211
  */
 static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
-					    struct sk_buff *skb,
 					    struct ieee80211_hdr *hdr, u16 len,
-					    u32 ampdu_status, u8 crypt_len,
-					    struct iwl_rx_cmd_buffer *rxb)
+					    u32 ampdu_status,
+					    struct iwl_rx_cmd_buffer *rxb,
+					    struct ieee80211_rx_status *stats)
 {
+	struct sk_buff *skb;
 	unsigned int hdrlen, fraglen;
 
-	/* If frame is small enough to fit in skb->head, pull it completely.
-	 * If not, only pull ieee80211_hdr (including crypto if present, and
-	 * an additional 8 bytes for SNAP/ethertype, see below) so that
-	 * splice() or TCP coalesce are more efficient.
-	 *
-	 * Since, in addition, ieee80211_data_to_8023() always pull in at
-	 * least 8 bytes (possibly more for mesh) we can do the same here
-	 * to save the cost of doing it later. That still doesn't pull in
-	 * the actual IP header since the typical case has a SNAP header.
-	 * If the latter changes (there are efforts in the standards group
-	 * to do so) we should revisit this and ieee80211_data_to_8023().
+	/* Dont use dev_alloc_skb(), we'll have enough headroom once
+	 * ieee80211_hdr pulled.
 	 */
-	hdrlen = (len <= skb_tailroom(skb)) ? len :
-					      sizeof(*hdr) + crypt_len + 8;
+	skb = alloc_skb(128, GFP_ATOMIC);
+	if (!skb) {
+		IWL_ERR(mvm, "alloc_skb failed\n");
+		return;
+	}
+	/* If frame is small enough to fit in skb->head, pull it completely.
+	 * If not, only pull ieee80211_hdr so that splice() or TCP coalesce
+	 * are more efficient.
+	 */
+	hdrlen = (len <= skb_tailroom(skb)) ? len : sizeof(*hdr);
 
 	memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
 	fraglen = len - hdrlen;
@@ -129,6 +129,8 @@
 				fraglen, rxb->truesize);
 	}
 
+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
 	ieee80211_rx(mvm->hw, skb);
 }
 
@@ -183,8 +185,7 @@
 static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
 					struct ieee80211_hdr *hdr,
 					struct ieee80211_rx_status *stats,
-					u32 rx_pkt_status,
-					u8 *crypt_len)
+					u32 rx_pkt_status)
 {
 	if (!ieee80211_has_protected(hdr->frame_control) ||
 	    (rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
@@ -204,14 +205,12 @@
 
 		stats->flag |= RX_FLAG_DECRYPTED;
 		IWL_DEBUG_WEP(mvm, "hw decrypted CCMP successfully\n");
-		*crypt_len = IEEE80211_CCMP_HDR_LEN;
 		return 0;
 
 	case RX_MPDU_RES_STATUS_SEC_TKIP_ENC:
 		/* Don't drop the frame and decrypt it in SW */
 		if (!(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK))
 			return 0;
-		*crypt_len = IEEE80211_TKIP_IV_LEN;
 		/* fall through if TTAK OK */
 
 	case RX_MPDU_RES_STATUS_SEC_WEP_ENC:
@@ -219,9 +218,6 @@
 			return -1;
 
 		stats->flag |= RX_FLAG_DECRYPTED;
-		if ((rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
-				RX_MPDU_RES_STATUS_SEC_WEP_ENC)
-			*crypt_len = IEEE80211_WEP_IV_LEN;
 		return 0;
 
 	case RX_MPDU_RES_STATUS_SEC_EXT_ENC:
@@ -246,17 +242,15 @@
 		       struct iwl_device_cmd *cmd)
 {
 	struct ieee80211_hdr *hdr;
-	struct ieee80211_rx_status *rx_status;
+	struct ieee80211_rx_status rx_status = {};
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_rx_phy_info *phy_info;
 	struct iwl_rx_mpdu_res_start *rx_res;
 	struct ieee80211_sta *sta;
-	struct sk_buff *skb;
 	u32 len;
 	u32 ampdu_status;
 	u32 rate_n_flags;
 	u32 rx_pkt_status;
-	u8 crypt_len = 0;
 
 	phy_info = &mvm->last_phy_info;
 	rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
@@ -265,32 +259,20 @@
 	rx_pkt_status = le32_to_cpup((__le32 *)
 		(pkt->data + sizeof(*rx_res) + len));
 
-	/* Dont use dev_alloc_skb(), we'll have enough headroom once
-	 * ieee80211_hdr pulled.
-	 */
-	skb = alloc_skb(128, GFP_ATOMIC);
-	if (!skb) {
-		IWL_ERR(mvm, "alloc_skb failed\n");
-		return 0;
-	}
-
-	rx_status = IEEE80211_SKB_RXCB(skb);
+	memset(&rx_status, 0, sizeof(rx_status));
 
 	/*
 	 * drop the packet if it has failed being decrypted by HW
 	 */
-	if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status,
-					 &crypt_len)) {
+	if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, &rx_status, rx_pkt_status)) {
 		IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n",
 			       rx_pkt_status);
-		kfree_skb(skb);
 		return 0;
 	}
 
 	if ((unlikely(phy_info->cfg_phy_cnt > 20))) {
 		IWL_DEBUG_DROP(mvm, "dsp size out of range [0,20]: %d\n",
 			       phy_info->cfg_phy_cnt);
-		kfree_skb(skb);
 		return 0;
 	}
 
@@ -301,31 +283,31 @@
 	if (!(rx_pkt_status & RX_MPDU_RES_STATUS_CRC_OK) ||
 	    !(rx_pkt_status & RX_MPDU_RES_STATUS_OVERRUN_OK)) {
 		IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status);
-		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+		rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 	}
 
 	/* This will be used in several places later */
 	rate_n_flags = le32_to_cpu(phy_info->rate_n_flags);
 
 	/* rx_status carries information about the packet to mac80211 */
-	rx_status->mactime = le64_to_cpu(phy_info->timestamp);
-	rx_status->device_timestamp = le32_to_cpu(phy_info->system_timestamp);
-	rx_status->band =
+	rx_status.mactime = le64_to_cpu(phy_info->timestamp);
+	rx_status.device_timestamp = le32_to_cpu(phy_info->system_timestamp);
+	rx_status.band =
 		(phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
 				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-	rx_status->freq =
+	rx_status.freq =
 		ieee80211_channel_to_frequency(le16_to_cpu(phy_info->channel),
-					       rx_status->band);
+					       rx_status.band);
 	/*
 	 * TSF as indicated by the fw is at INA time, but mac80211 expects the
 	 * TSF at the beginning of the MPDU.
 	 */
-	/*rx_status->flag |= RX_FLAG_MACTIME_MPDU;*/
+	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
 
-	iwl_mvm_get_signal_strength(mvm, phy_info, rx_status);
+	iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
 
-	IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status->signal,
-			      (unsigned long long)rx_status->mactime);
+	IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
+			      (unsigned long long)rx_status.mactime);
 
 	rcu_read_lock();
 	/*
@@ -344,14 +326,15 @@
 	if (sta) {
 		struct iwl_mvm_sta *mvmsta;
 		mvmsta = iwl_mvm_sta_from_mac80211(sta);
-		rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
+		rs_update_last_rssi(mvm, &mvmsta->lq_sta,
+				    &rx_status);
 	}
 
 	rcu_read_unlock();
 
 	/* set the preamble flag if appropriate */
 	if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
-		rx_status->flag |= RX_FLAG_SHORTPRE;
+		rx_status.flag |= RX_FLAG_SHORTPRE;
 
 	if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) {
 		/*
@@ -359,8 +342,8 @@
 		 * together since we get a single PHY response
 		 * from the firmware for all of them
 		 */
-		rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
-		rx_status->ampdu_reference = mvm->ampdu_ref;
+		rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
+		rx_status.ampdu_reference = mvm->ampdu_ref;
 	}
 
 	/* Set up the HT phy flags */
@@ -368,50 +351,50 @@
 	case RATE_MCS_CHAN_WIDTH_20:
 		break;
 	case RATE_MCS_CHAN_WIDTH_40:
-		rx_status->flag |= RX_FLAG_40MHZ;
+		rx_status.flag |= RX_FLAG_40MHZ;
 		break;
 	case RATE_MCS_CHAN_WIDTH_80:
-		rx_status->vht_flag |= RX_VHT_FLAG_80MHZ;
+		rx_status.vht_flag |= RX_VHT_FLAG_80MHZ;
 		break;
 	case RATE_MCS_CHAN_WIDTH_160:
-		rx_status->vht_flag |= RX_VHT_FLAG_160MHZ;
+		rx_status.vht_flag |= RX_VHT_FLAG_160MHZ;
 		break;
 	}
 	if (rate_n_flags & RATE_MCS_SGI_MSK)
-		rx_status->flag |= RX_FLAG_SHORT_GI;
+		rx_status.flag |= RX_FLAG_SHORT_GI;
 	if (rate_n_flags & RATE_HT_MCS_GF_MSK)
-		rx_status->flag |= RX_FLAG_HT_GF;
+		rx_status.flag |= RX_FLAG_HT_GF;
 	if (rate_n_flags & RATE_MCS_LDPC_MSK)
-		rx_status->flag |= RX_FLAG_LDPC;
+		rx_status.flag |= RX_FLAG_LDPC;
 	if (rate_n_flags & RATE_MCS_HT_MSK) {
 		u8 stbc = (rate_n_flags & RATE_MCS_HT_STBC_MSK) >>
 				RATE_MCS_STBC_POS;
-		rx_status->flag |= RX_FLAG_HT;
-		rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
-		rx_status->flag |= stbc << RX_FLAG_STBC_SHIFT;
+		rx_status.flag |= RX_FLAG_HT;
+		rx_status.rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
+		rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
 	} else if (rate_n_flags & RATE_MCS_VHT_MSK) {
 		u8 stbc = (rate_n_flags & RATE_MCS_VHT_STBC_MSK) >>
 				RATE_MCS_STBC_POS;
-		rx_status->vht_nss =
+		rx_status.vht_nss =
 			((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
 						RATE_VHT_MCS_NSS_POS) + 1;
-		rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
-		rx_status->flag |= RX_FLAG_VHT;
-		rx_status->flag |= stbc << RX_FLAG_STBC_SHIFT;
+		rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
+		rx_status.flag |= RX_FLAG_VHT;
+		rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
 		if (rate_n_flags & RATE_MCS_BF_MSK)
-			rx_status->vht_flag |= RX_VHT_FLAG_BF;
+			rx_status.vht_flag |= RX_VHT_FLAG_BF;
 	} else {
-		rx_status->rate_idx =
+		rx_status.rate_idx =
 			iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
-							    rx_status->band);
+							    rx_status.band);
 	}
 
 #ifdef CPTCFG_IWLWIFI_DEBUGFS
 	iwl_mvm_update_frame_stats(mvm, &mvm->drv_rx_stats, rate_n_flags,
-				   rx_status->flag & RX_FLAG_AMPDU_DETAILS);
+				   rx_status.flag & RX_FLAG_AMPDU_DETAILS);
 #endif
-	iwl_mvm_pass_packet_to_mac80211(mvm, skb, hdr, len, ampdu_status,
-					crypt_len, rxb);
+	iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, ampdu_status,
+					rxb, &rx_status);
 	return 0;
 }
 
@@ -517,8 +500,29 @@
 		.mvm = mvm,
 	};
 
-	iwl_mvm_tt_temp_changed(mvm, le32_to_cpu(common->temperature));
+	/*
+	 * set temperature debug enabled - ignore FW temperature updates
+	 * and use the user set temperature.
+	 */
+	if (mvm->temperature_test) {
+		if (mvm->temperature < le32_to_cpu(common->temperature))
+			IWL_DEBUG_TEMP(mvm,
+				       "Ignoring FW temperature update that is greater than the debug set temperature (debug temp = %d, fw temp = %d)\n",
+				       mvm->temperature,
+				       le32_to_cpu(common->temperature));
+		/*
+		 * skip iwl_mvm_tt_handler since we are in
+		 * temperature debug mode and we are ignoring
+		 * the new temperature value
+		 */
+		goto update;
+	}
 
+	if (mvm->temperature != le32_to_cpu(common->temperature)) {
+		mvm->temperature = le32_to_cpu(common->temperature);
+		iwl_mvm_tt_handler(mvm);
+	}
+update:
 	iwl_mvm_update_rx_statistics(mvm, stats);
 
 	ieee80211_iterate_active_interfaces(mvm->hw,
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index e5294d0..cb85e63 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -83,29 +83,15 @@
 	} dwell[IEEE80211_NUM_BANDS];
 };
 
-enum iwl_umac_scan_uid_type {
-	IWL_UMAC_SCAN_UID_REG_SCAN	= BIT(0),
-	IWL_UMAC_SCAN_UID_SCHED_SCAN	= BIT(1),
-	IWL_UMAC_SCAN_UID_ALL		= IWL_UMAC_SCAN_UID_REG_SCAN |
-					  IWL_UMAC_SCAN_UID_SCHED_SCAN,
-};
-
-static int iwl_umac_scan_stop(struct iwl_mvm *mvm,
-			      enum iwl_umac_scan_uid_type type, bool notify);
-
-static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
-{
-	if (mvm->scan_rx_ant != ANT_NONE)
-		return mvm->scan_rx_ant;
-	return mvm->fw->valid_rx_ant;
-}
-
 static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
 {
 	u16 rx_chain;
 	u8 rx_ant;
 
-	rx_ant = iwl_mvm_scan_rx_ant(mvm);
+	if (mvm->scan_rx_ant != ANT_NONE)
+		rx_ant = mvm->scan_rx_ant;
+	else
+		rx_ant = mvm->fw->valid_rx_ant;
 	rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;
 	rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
 	rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS;
@@ -284,8 +270,7 @@
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	bool *global_bound = data;
 
-	if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt &&
-	    mvmvif->phy_ctxt->id < MAX_PHYS)
+	if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < MAX_PHYS)
 		*global_bound = true;
 }
 
@@ -380,10 +365,6 @@
 	    !is_sched_scan)
 		max_probe_len -= 32;
 
-	/* DS parameter set element is added on 2.4GHZ band if required */
-	if (iwl_mvm_rrm_scan_needed(mvm))
-		max_probe_len -= 3;
-
 	return max_probe_len;
 }
 
@@ -478,8 +459,7 @@
 				basic_ssid ? 1 : 0);
 
 	cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
-					   3 << TX_CMD_FLG_BT_PRIO_POS);
-
+					   TX_CMD_FLG_BT_DIS);
 	cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id;
 	cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
 	cmd->tx_cmd.rate_n_flags =
@@ -555,17 +535,23 @@
 				    struct iwl_device_cmd *cmd)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u8 client_bitmap = 0;
 
-	if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) &&
-	    !(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+	if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
 		struct iwl_sched_scan_results *notif = (void *)pkt->data;
 
-		if (!(notif->client_bitmap & SCAN_CLIENT_SCHED_SCAN))
-			return 0;
+		client_bitmap = notif->client_bitmap;
 	}
 
-	IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
-	ieee80211_sched_scan_results(mvm->hw);
+	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN ||
+	    client_bitmap & SCAN_CLIENT_SCHED_SCAN) {
+		if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
+			IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
+			ieee80211_sched_scan_results(mvm->hw);
+		} else {
+			IWL_DEBUG_SCAN(mvm, "Scan results\n");
+		}
+	}
 
 	return 0;
 }
@@ -615,6 +601,16 @@
 					       SCAN_COMPLETE_NOTIFICATION };
 	int ret;
 
+	if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+		return 0;
+
+	if (iwl_mvm_is_radio_killed(mvm)) {
+		ieee80211_scan_completed(mvm->hw, true);
+		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+		mvm->scan_status = IWL_MVM_SCAN_NONE;
+		return 0;
+	}
+
 	iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
 				   scan_abort_notif,
 				   ARRAY_SIZE(scan_abort_notif),
@@ -675,7 +671,6 @@
 		mvm->scan_status = IWL_MVM_SCAN_NONE;
 		ieee80211_scan_completed(mvm->hw,
 					 status == IWL_SCAN_OFFLOAD_ABORTED);
-		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
 	}
 
 	mvm->last_ebs_successful = !ebs_status;
@@ -977,20 +972,6 @@
 	return ret;
 }
 
-static bool iwl_mvm_scan_pass_all(struct iwl_mvm *mvm,
-				  struct cfg80211_sched_scan_request *req)
-{
-	if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
-		IWL_DEBUG_SCAN(mvm,
-			       "Sending scheduled scan with filtering, n_match_sets %d\n",
-			       req->n_match_sets);
-		return false;
-	}
-
-	IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n");
-	return true;
-}
-
 int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
 			     struct cfg80211_sched_scan_request *req)
 {
@@ -1006,8 +987,15 @@
 		.schedule_line[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER,
 	};
 
-	if (iwl_mvm_scan_pass_all(mvm, req))
+	if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
+		IWL_DEBUG_SCAN(mvm,
+			       "Sending scheduled scan with filtering, filter len %d\n",
+			       req->n_match_sets);
+	} else {
+		IWL_DEBUG_SCAN(mvm,
+			       "Sending Scheduled scan without filtering\n");
 		scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL);
+	}
 
 	if (mvm->last_ebs_successful &&
 	    mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT)
@@ -1018,38 +1006,6 @@
 				    sizeof(scan_req), &scan_req);
 }
 
-int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
-			       struct ieee80211_vif *vif,
-			       struct cfg80211_sched_scan_request *req,
-			       struct ieee80211_scan_ies *ies)
-{
-	int ret;
-
-	if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
-		ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
-		if (ret)
-			return ret;
-		ret = iwl_mvm_sched_scan_umac(mvm, vif, req, ies);
-	} else if ((mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
-		mvm->scan_status = IWL_MVM_SCAN_SCHED;
-		ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
-		if (ret)
-			return ret;
-		ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
-	} else {
-		mvm->scan_status = IWL_MVM_SCAN_SCHED;
-		ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
-		if (ret)
-			return ret;
-		ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
-		if (ret)
-			return ret;
-		ret = iwl_mvm_sched_scan_start(mvm, req);
-	}
-
-	return ret;
-}
-
 static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
 {
 	int ret;
@@ -1094,10 +1050,6 @@
 
 	lockdep_assert_held(&mvm->mutex);
 
-	if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
-		return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN,
-					  notify);
-
 	if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
 	    (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) ||
 	     mvm->scan_status != IWL_MVM_SCAN_OS)) {
@@ -1128,12 +1080,8 @@
 	/*
 	 * Clear the scan status so the next scan requests will succeed. This
 	 * also ensures the Rx handler doesn't do anything, as the scan was
-	 * stopped from above. Since the rx handler won't do anything now,
-	 * we have to release the scan reference here.
+	 * stopped from above.
 	 */
-	if (mvm->scan_status == IWL_MVM_SCAN_OS)
-		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-
 	mvm->scan_status = IWL_MVM_SCAN_NONE;
 
 	if (notify) {
@@ -1185,64 +1133,20 @@
 	}
 }
 
-static u8 *iwl_mvm_copy_and_insert_ds_elem(struct iwl_mvm *mvm, const u8 *ies,
-					   size_t len, u8 *const pos)
-{
-	static const u8 before_ds_params[] = {
-			WLAN_EID_SSID,
-			WLAN_EID_SUPP_RATES,
-			WLAN_EID_REQUEST,
-			WLAN_EID_EXT_SUPP_RATES,
-	};
-	size_t offs;
-	u8 *newpos = pos;
-
-	if (!iwl_mvm_rrm_scan_needed(mvm)) {
-		memcpy(newpos, ies, len);
-		return newpos + len;
-	}
-
-	offs = ieee80211_ie_split(ies, len,
-				  before_ds_params,
-				  ARRAY_SIZE(before_ds_params),
-				  0);
-
-	memcpy(newpos, ies, offs);
-	newpos += offs;
-
-	/* Add a placeholder for DS Parameter Set element */
-	*newpos++ = WLAN_EID_DS_PARAMS;
-	*newpos++ = 1;
-	*newpos++ = 0;
-
-	memcpy(newpos, ies + offs, len - offs);
-	newpos += len - offs;
-
-	return newpos;
-}
-
 static void
 iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 				 struct ieee80211_scan_ies *ies,
-				 struct iwl_scan_probe_req *preq,
-				 const u8 *mac_addr, const u8 *mac_addr_mask)
+				 struct iwl_scan_req_unified_lmac *cmd)
 {
+	struct iwl_scan_probe_req *preq = (void *)(cmd->data +
+		sizeof(struct iwl_scan_channel_cfg_lmac) *
+			mvm->fw->ucode_capa.n_scan_channels);
 	struct ieee80211_mgmt *frame = (struct ieee80211_mgmt *)preq->buf;
-	u8 *pos, *newpos;
-
-	/*
-	 * Unfortunately, right now the offload scan doesn't support randomising
-	 * within the firmware, so until the firmware API is ready we implement
-	 * it in the driver. This means that the scan iterations won't really be
-	 * random, only when it's restarted, but at least that helps a bit.
-	 */
-	if (mac_addr)
-		get_random_mask_addr(frame->sa, mac_addr, mac_addr_mask);
-	else
-		memcpy(frame->sa, vif->addr, ETH_ALEN);
+	u8 *pos;
 
 	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
 	eth_broadcast_addr(frame->da);
+	memcpy(frame->sa, vif->addr, ETH_ALEN);
 	eth_broadcast_addr(frame->bssid);
 	frame->seq_ctrl = 0;
 
@@ -1253,14 +1157,11 @@
 	preq->mac_header.offset = 0;
 	preq->mac_header.len = cpu_to_le16(24 + 2);
 
-	/* Insert ds parameter set element on 2.4 GHz band */
-	newpos = iwl_mvm_copy_and_insert_ds_elem(mvm,
-						 ies->ies[IEEE80211_BAND_2GHZ],
-						 ies->len[IEEE80211_BAND_2GHZ],
-						 pos);
+	memcpy(pos, ies->ies[IEEE80211_BAND_2GHZ],
+	       ies->len[IEEE80211_BAND_2GHZ]);
 	preq->band_data[0].offset = cpu_to_le16(pos - preq->buf);
-	preq->band_data[0].len = cpu_to_le16(newpos - pos);
-	pos = newpos;
+	preq->band_data[0].len = cpu_to_le16(ies->len[IEEE80211_BAND_2GHZ]);
+	pos += ies->len[IEEE80211_BAND_2GHZ];
 
 	memcpy(pos, ies->ies[IEEE80211_BAND_5GHZ],
 	       ies->len[IEEE80211_BAND_5GHZ]);
@@ -1321,10 +1222,9 @@
 		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
 	};
 	struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
-	struct iwl_scan_probe_req *preq;
 	struct iwl_mvm_scan_params params = {};
 	u32 flags;
-	u32 ssid_bitmap = 0;
+	int ssid_bitmap = 0;
 	int ret, i;
 
 	lockdep_assert_held(&mvm->mutex);
@@ -1383,13 +1283,7 @@
 				       req->req.n_channels, ssid_bitmap,
 				       cmd);
 
-	preq = (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
-			mvm->fw->ucode_capa.n_scan_channels);
-
-	iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, preq,
-		req->req.flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
-			req->req.mac_addr : NULL,
-		req->req.mac_addr_mask);
+	iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, cmd);
 
 	ret = iwl_mvm_send_cmd(mvm, &hcmd);
 	if (!ret) {
@@ -1422,7 +1316,6 @@
 		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
 	};
 	struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
-	struct iwl_scan_probe_req *preq;
 	struct iwl_mvm_scan_params params = {};
 	int ret;
 	u32 flags = 0, ssid_bitmap = 0;
@@ -1446,8 +1339,15 @@
 
 	cmd->n_channels = (u8)req->n_channels;
 
-	if (iwl_mvm_scan_pass_all(mvm, req))
+	if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
+		IWL_DEBUG_SCAN(mvm,
+			       "Sending scheduled scan with filtering, n_match_sets %d\n",
+			       req->n_match_sets);
+	} else {
+		IWL_DEBUG_SCAN(mvm,
+			       "Sending Scheduled scan without filtering\n");
 		flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
+	}
 
 	if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0)
 		flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;
@@ -1477,13 +1377,7 @@
 	iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels,
 				       ssid_bitmap, cmd);
 
-	preq = (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
-			mvm->fw->ucode_capa.n_scan_channels);
-
-	iwl_mvm_build_unified_scan_probe(mvm, vif, ies, preq,
-		req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
-			req->mac_addr : NULL,
-		req->mac_addr_mask);
+	iwl_mvm_build_unified_scan_probe(mvm, vif, ies, cmd);
 
 	ret = iwl_mvm_send_cmd(mvm, &hcmd);
 	if (!ret) {
@@ -1505,594 +1399,7 @@
 
 int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
 {
-	if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
-		return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_REG_SCAN,
-					  true);
-
-	if (mvm->scan_status == IWL_MVM_SCAN_NONE)
-		return 0;
-
-	if (iwl_mvm_is_radio_killed(mvm)) {
-		ieee80211_scan_completed(mvm->hw, true);
-		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-		mvm->scan_status = IWL_MVM_SCAN_NONE;
-		return 0;
-	}
-
 	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
 		return iwl_mvm_scan_offload_stop(mvm, true);
 	return iwl_mvm_cancel_regular_scan(mvm);
 }
-
-/* UMAC scan API */
-
-struct iwl_umac_scan_done {
-	struct iwl_mvm *mvm;
-	enum iwl_umac_scan_uid_type type;
-};
-
-static int rate_to_scan_rate_flag(unsigned int rate)
-{
-	static const int rate_to_scan_rate[IWL_RATE_COUNT] = {
-		[IWL_RATE_1M_INDEX]	= SCAN_CONFIG_RATE_1M,
-		[IWL_RATE_2M_INDEX]	= SCAN_CONFIG_RATE_2M,
-		[IWL_RATE_5M_INDEX]	= SCAN_CONFIG_RATE_5M,
-		[IWL_RATE_11M_INDEX]	= SCAN_CONFIG_RATE_11M,
-		[IWL_RATE_6M_INDEX]	= SCAN_CONFIG_RATE_6M,
-		[IWL_RATE_9M_INDEX]	= SCAN_CONFIG_RATE_9M,
-		[IWL_RATE_12M_INDEX]	= SCAN_CONFIG_RATE_12M,
-		[IWL_RATE_18M_INDEX]	= SCAN_CONFIG_RATE_18M,
-		[IWL_RATE_24M_INDEX]	= SCAN_CONFIG_RATE_24M,
-		[IWL_RATE_36M_INDEX]	= SCAN_CONFIG_RATE_36M,
-		[IWL_RATE_48M_INDEX]	= SCAN_CONFIG_RATE_48M,
-		[IWL_RATE_54M_INDEX]	= SCAN_CONFIG_RATE_54M,
-	};
-
-	return rate_to_scan_rate[rate];
-}
-
-static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm)
-{
-	struct ieee80211_supported_band *band;
-	unsigned int rates = 0;
-	int i;
-
-	band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ];
-	for (i = 0; i < band->n_bitrates; i++)
-		rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value);
-	band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
-	for (i = 0; i < band->n_bitrates; i++)
-		rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value);
-
-	/* Set both basic rates and supported rates */
-	rates |= SCAN_CONFIG_SUPPORTED_RATE(rates);
-
-	return cpu_to_le32(rates);
-}
-
-int iwl_mvm_config_scan(struct iwl_mvm *mvm)
-{
-
-	struct iwl_scan_config *scan_config;
-	struct ieee80211_supported_band *band;
-	int num_channels =
-		mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels +
-		mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
-	int ret, i, j = 0, cmd_size, data_size;
-	struct iwl_host_cmd cmd = {
-		.id = SCAN_CFG_CMD,
-	};
-
-	if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
-		return -ENOBUFS;
-
-	cmd_size = sizeof(*scan_config) + mvm->fw->ucode_capa.n_scan_channels;
-
-	scan_config = kzalloc(cmd_size, GFP_KERNEL);
-	if (!scan_config)
-		return -ENOMEM;
-
-	data_size = cmd_size - sizeof(struct iwl_mvm_umac_cmd_hdr);
-	scan_config->hdr.size = cpu_to_le16(data_size);
-	scan_config->flags = cpu_to_le32(SCAN_CONFIG_FLAG_ACTIVATE |
-					 SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
-					 SCAN_CONFIG_FLAG_SET_TX_CHAINS |
-					 SCAN_CONFIG_FLAG_SET_RX_CHAINS |
-					 SCAN_CONFIG_FLAG_SET_ALL_TIMES |
-					 SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
-					 SCAN_CONFIG_FLAG_SET_MAC_ADDR |
-					 SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
-					 SCAN_CONFIG_N_CHANNELS(num_channels));
-	scan_config->tx_chains = cpu_to_le32(mvm->fw->valid_tx_ant);
-	scan_config->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
-	scan_config->legacy_rates = iwl_mvm_scan_config_rates(mvm);
-	scan_config->out_of_channel_time = cpu_to_le32(170);
-	scan_config->suspend_time = cpu_to_le32(30);
-	scan_config->dwell_active = 20;
-	scan_config->dwell_passive = 110;
-	scan_config->dwell_fragmented = 20;
-
-	memcpy(&scan_config->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
-
-	scan_config->bcast_sta_id = mvm->aux_sta.sta_id;
-	scan_config->channel_flags = IWL_CHANNEL_FLAG_EBS |
-				     IWL_CHANNEL_FLAG_ACCURATE_EBS |
-				     IWL_CHANNEL_FLAG_EBS_ADD |
-				     IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
-
-	band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ];
-	for (i = 0; i < band->n_channels; i++, j++)
-		scan_config->channel_array[j] = band->channels[i].center_freq;
-	band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
-	for (i = 0; i < band->n_channels; i++, j++)
-		scan_config->channel_array[j] = band->channels[i].center_freq;
-
-	cmd.data[0] = scan_config;
-	cmd.len[0] = cmd_size;
-	cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
-
-	IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");
-
-	ret = iwl_mvm_send_cmd(mvm, &cmd);
-
-	kfree(scan_config);
-	return ret;
-}
-
-static int iwl_mvm_find_scan_uid(struct iwl_mvm *mvm, u32 uid)
-{
-	int i;
-
-	for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++)
-		if (mvm->scan_uid[i] == uid)
-			return i;
-
-	return i;
-}
-
-static int iwl_mvm_find_free_scan_uid(struct iwl_mvm *mvm)
-{
-	return iwl_mvm_find_scan_uid(mvm, 0);
-}
-
-static bool iwl_mvm_find_scan_type(struct iwl_mvm *mvm,
-				   enum iwl_umac_scan_uid_type type)
-{
-	int i;
-
-	for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++)
-		if (mvm->scan_uid[i] & type)
-			return true;
-
-	return false;
-}
-
-static u32 iwl_generate_scan_uid(struct iwl_mvm *mvm,
-				 enum iwl_umac_scan_uid_type type)
-{
-	u32 uid;
-
-	/* make sure exactly one bit is on in scan type */
-	WARN_ON(hweight8(type) != 1);
-
-	/*
-	 * Make sure scan uids are unique. If one scan lasts long time while
-	 * others are completing frequently, the seq number will wrap up and
-	 * we may have more than one scan with the same uid.
-	 */
-	do {
-		uid = type | (mvm->scan_seq_num <<
-			      IWL_UMAC_SCAN_UID_SEQ_OFFSET);
-		mvm->scan_seq_num++;
-	} while (iwl_mvm_find_scan_uid(mvm, uid) <
-		 IWL_MVM_MAX_SIMULTANEOUS_SCANS);
-
-	IWL_DEBUG_SCAN(mvm, "Generated scan UID %u\n", uid);
-
-	return uid;
-}
-
-static void
-iwl_mvm_build_generic_umac_scan_cmd(struct iwl_mvm *mvm,
-				    struct iwl_scan_req_umac *cmd,
-				    struct iwl_mvm_scan_params *params)
-{
-	memset(cmd, 0, ksize(cmd));
-	cmd->hdr.size = cpu_to_le16(iwl_mvm_scan_size(mvm) -
-				    sizeof(struct iwl_mvm_umac_cmd_hdr));
-	cmd->active_dwell = params->dwell[IEEE80211_BAND_2GHZ].active;
-	cmd->passive_dwell = params->dwell[IEEE80211_BAND_2GHZ].passive;
-	if (params->passive_fragmented)
-		cmd->fragmented_dwell =
-				params->dwell[IEEE80211_BAND_2GHZ].passive;
-	cmd->max_out_time = cpu_to_le32(params->max_out_time);
-	cmd->suspend_time = cpu_to_le32(params->suspend_time);
-	cmd->scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
-}
-
-static void
-iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
-			       struct ieee80211_channel **channels,
-			       int n_channels, u32 ssid_bitmap,
-			       struct iwl_scan_req_umac *cmd)
-{
-	struct iwl_scan_channel_cfg_umac *channel_cfg = (void *)&cmd->data;
-	int i;
-
-	for (i = 0; i < n_channels; i++) {
-		channel_cfg[i].flags = cpu_to_le32(ssid_bitmap);
-		channel_cfg[i].channel_num = channels[i]->hw_value;
-		channel_cfg[i].iter_count = 1;
-		channel_cfg[i].iter_interval = 0;
-	}
-}
-
-static u32 iwl_mvm_scan_umac_common_flags(struct iwl_mvm *mvm, int n_ssids,
-					  struct cfg80211_ssid *ssids,
-					  int fragmented)
-{
-	int flags = 0;
-
-	if (n_ssids == 0)
-		flags = IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE;
-
-	if (n_ssids == 1 && ssids[0].ssid_len != 0)
-		flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT;
-
-	if (fragmented)
-		flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED;
-
-	if (iwl_mvm_rrm_scan_needed(mvm))
-		flags |= IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED;
-
-	return flags;
-}
-
-int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-		      struct ieee80211_scan_request *req)
-{
-	struct iwl_host_cmd hcmd = {
-		.id = SCAN_REQ_UMAC,
-		.len = { iwl_mvm_scan_size(mvm), },
-		.data = { mvm->scan_cmd, },
-		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
-	};
-	struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
-	struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
-		sizeof(struct iwl_scan_channel_cfg_umac) *
-			mvm->fw->ucode_capa.n_scan_channels;
-	struct iwl_mvm_scan_params params = {};
-	u32 uid, flags;
-	u32 ssid_bitmap = 0;
-	int ret, i, uid_idx;
-
-	lockdep_assert_held(&mvm->mutex);
-
-	uid_idx = iwl_mvm_find_free_scan_uid(mvm);
-	if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
-		return -EBUSY;
-
-	/* we should have failed registration if scan_cmd was NULL */
-	if (WARN_ON(mvm->scan_cmd == NULL))
-		return -ENOMEM;
-
-	if (WARN_ON(req->req.n_ssids > PROBE_OPTION_MAX ||
-		    req->ies.common_ie_len +
-		    req->ies.len[NL80211_BAND_2GHZ] +
-		    req->ies.len[NL80211_BAND_5GHZ] + 24 + 2 >
-		    SCAN_OFFLOAD_PROBE_REQ_SIZE || req->req.n_channels >
-		    mvm->fw->ucode_capa.n_scan_channels))
-		return -ENOBUFS;
-
-	iwl_mvm_scan_calc_params(mvm, vif, req->req.n_ssids, req->req.flags,
-				 &params);
-
-	iwl_mvm_build_generic_umac_scan_cmd(mvm, cmd, &params);
-
-	uid = iwl_generate_scan_uid(mvm, IWL_UMAC_SCAN_UID_REG_SCAN);
-	mvm->scan_uid[uid_idx] = uid;
-	cmd->uid = cpu_to_le32(uid);
-
-	cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
-
-	flags = iwl_mvm_scan_umac_common_flags(mvm, req->req.n_ssids,
-					       req->req.ssids,
-					       params.passive_fragmented);
-
-	flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL;
-
-	cmd->general_flags = cpu_to_le32(flags);
-	cmd->n_channels = req->req.n_channels;
-
-	for (i = 0; i < req->req.n_ssids; i++)
-		ssid_bitmap |= BIT(i);
-
-	iwl_mvm_umac_scan_cfg_channels(mvm, req->req.channels,
-				       req->req.n_channels, ssid_bitmap, cmd);
-
-	sec_part->schedule[0].iter_count = 1;
-	sec_part->delay = 0;
-
-	iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, &sec_part->preq,
-		req->req.flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
-			req->req.mac_addr : NULL,
-		req->req.mac_addr_mask);
-
-	iwl_mvm_scan_fill_ssids(sec_part->direct_scan, req->req.ssids,
-				req->req.n_ssids, 0);
-
-	ret = iwl_mvm_send_cmd(mvm, &hcmd);
-	if (!ret) {
-		IWL_DEBUG_SCAN(mvm,
-			       "Scan request was sent successfully\n");
-	} else {
-		/*
-		 * If the scan failed, it usually means that the FW was unable
-		 * to allocate the time events. Warn on it, but maybe we
-		 * should try to send the command again with different params.
-		 */
-		IWL_ERR(mvm, "Scan failed! ret %d\n", ret);
-	}
-	return ret;
-}
-
-int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
-			    struct cfg80211_sched_scan_request *req,
-			    struct ieee80211_scan_ies *ies)
-{
-
-	struct iwl_host_cmd hcmd = {
-		.id = SCAN_REQ_UMAC,
-		.len = { iwl_mvm_scan_size(mvm), },
-		.data = { mvm->scan_cmd, },
-		.dataflags = { IWL_HCMD_DFL_NOCOPY, },
-	};
-	struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
-	struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
-		sizeof(struct iwl_scan_channel_cfg_umac) *
-			mvm->fw->ucode_capa.n_scan_channels;
-	struct iwl_mvm_scan_params params = {};
-	u32 uid, flags;
-	u32 ssid_bitmap = 0;
-	int ret, uid_idx;
-
-	lockdep_assert_held(&mvm->mutex);
-
-	uid_idx = iwl_mvm_find_free_scan_uid(mvm);
-	if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
-		return -EBUSY;
-
-	/* we should have failed registration if scan_cmd was NULL */
-	if (WARN_ON(mvm->scan_cmd == NULL))
-		return -ENOMEM;
-
-	if (WARN_ON(req->n_ssids > PROBE_OPTION_MAX ||
-		    ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] +
-		    ies->len[NL80211_BAND_5GHZ] + 24 + 2 >
-		    SCAN_OFFLOAD_PROBE_REQ_SIZE || req->n_channels >
-		    mvm->fw->ucode_capa.n_scan_channels))
-		return -ENOBUFS;
-
-	iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, req->flags,
-					 &params);
-
-	iwl_mvm_build_generic_umac_scan_cmd(mvm, cmd, &params);
-
-	cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
-
-	uid = iwl_generate_scan_uid(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN);
-	mvm->scan_uid[uid_idx] = uid;
-	cmd->uid = cpu_to_le32(uid);
-
-	cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_LOW);
-
-	flags = iwl_mvm_scan_umac_common_flags(mvm, req->n_ssids, req->ssids,
-					       params.passive_fragmented);
-
-	flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
-
-	if (iwl_mvm_scan_pass_all(mvm, req))
-		flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL;
-	else
-		flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH;
-
-	cmd->general_flags = cpu_to_le32(flags);
-
-	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT &&
-	    mvm->last_ebs_successful)
-		cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
-				     IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
-				     IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
-
-	cmd->n_channels = req->n_channels;
-
-	iwl_scan_offload_build_ssid(req, sec_part->direct_scan, &ssid_bitmap,
-				    false);
-
-	/* This API uses bits 0-19 instead of 1-20. */
-	ssid_bitmap = ssid_bitmap >> 1;
-
-	iwl_mvm_umac_scan_cfg_channels(mvm, req->channels, req->n_channels,
-				       ssid_bitmap, cmd);
-
-	sec_part->schedule[0].interval =
-				cpu_to_le16(req->interval / MSEC_PER_SEC);
-	sec_part->schedule[0].iter_count = 0xff;
-
-	sec_part->delay = 0;
-
-	iwl_mvm_build_unified_scan_probe(mvm, vif, ies, &sec_part->preq,
-		req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
-			req->mac_addr : NULL,
-		req->mac_addr_mask);
-
-	ret = iwl_mvm_send_cmd(mvm, &hcmd);
-	if (!ret) {
-		IWL_DEBUG_SCAN(mvm,
-			       "Sched scan request was sent successfully\n");
-	} else {
-		/*
-		 * If the scan failed, it usually means that the FW was unable
-		 * to allocate the time events. Warn on it, but maybe we
-		 * should try to send the command again with different params.
-		 */
-		IWL_ERR(mvm, "Sched scan failed! ret %d\n", ret);
-	}
-	return ret;
-}
-
-int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
-					struct iwl_rx_cmd_buffer *rxb,
-					struct iwl_device_cmd *cmd)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_umac_scan_complete *notif = (void *)pkt->data;
-	u32 uid = __le32_to_cpu(notif->uid);
-	bool sched = !!(uid & IWL_UMAC_SCAN_UID_SCHED_SCAN);
-	int uid_idx = iwl_mvm_find_scan_uid(mvm, uid);
-
-	/*
-	 * Scan uid may be set to zero in case of scan abort request from above.
-	 */
-	if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
-		return 0;
-
-	IWL_DEBUG_SCAN(mvm,
-		       "Scan completed, uid %u type %s, status %s, EBS status %s\n",
-		       uid, sched ? "sched" : "regular",
-		       notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
-				"completed" : "aborted",
-		       notif->ebs_status == IWL_SCAN_EBS_SUCCESS ?
-				"success" : "failed");
-
-	mvm->last_ebs_successful = !notif->ebs_status;
-	mvm->scan_uid[uid_idx] = 0;
-
-	if (!sched) {
-		ieee80211_scan_completed(mvm->hw,
-					 notif->status ==
-						IWL_SCAN_OFFLOAD_ABORTED);
-		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-	} else if (!iwl_mvm_find_scan_type(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN)) {
-		ieee80211_sched_scan_stopped(mvm->hw);
-	} else {
-		IWL_DEBUG_SCAN(mvm, "Another sched scan is running\n");
-	}
-
-	return 0;
-}
-
-static bool iwl_scan_umac_done_check(struct iwl_notif_wait_data *notif_wait,
-				     struct iwl_rx_packet *pkt, void *data)
-{
-	struct iwl_umac_scan_done *scan_done = data;
-	struct iwl_umac_scan_complete *notif = (void *)pkt->data;
-	u32 uid = __le32_to_cpu(notif->uid);
-	int uid_idx = iwl_mvm_find_scan_uid(scan_done->mvm, uid);
-
-	if (WARN_ON(pkt->hdr.cmd != SCAN_COMPLETE_UMAC))
-		return false;
-
-	if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
-		return false;
-
-	/*
-	 * Clear scan uid of scans that was aborted from above and completed
-	 * in FW so the RX handler does nothing.
-	 */
-	scan_done->mvm->scan_uid[uid_idx] = 0;
-
-	return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type);
-}
-
-static int iwl_umac_scan_abort_one(struct iwl_mvm *mvm, u32 uid)
-{
-	struct iwl_umac_scan_abort cmd = {
-		.hdr.size = cpu_to_le16(sizeof(struct iwl_umac_scan_abort) -
-					sizeof(struct iwl_mvm_umac_cmd_hdr)),
-		.uid = cpu_to_le32(uid),
-	};
-
-	lockdep_assert_held(&mvm->mutex);
-
-	IWL_DEBUG_SCAN(mvm, "Sending scan abort, uid %u\n", uid);
-
-	return iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_UMAC, 0, sizeof(cmd), &cmd);
-}
-
-static int iwl_umac_scan_stop(struct iwl_mvm *mvm,
-			      enum iwl_umac_scan_uid_type type, bool notify)
-{
-	struct iwl_notification_wait wait_scan_done;
-	static const u8 scan_done_notif[] = { SCAN_COMPLETE_UMAC, };
-	struct iwl_umac_scan_done scan_done = {
-		.mvm = mvm,
-		.type = type,
-	};
-	int i, ret = -EIO;
-
-	iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
-				   scan_done_notif,
-				   ARRAY_SIZE(scan_done_notif),
-				   iwl_scan_umac_done_check, &scan_done);
-
-	IWL_DEBUG_SCAN(mvm, "Preparing to stop scan, type %x\n", type);
-
-	for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++) {
-		if (mvm->scan_uid[i] & type) {
-			int err;
-
-			if (iwl_mvm_is_radio_killed(mvm) &&
-			    (type & IWL_UMAC_SCAN_UID_REG_SCAN)) {
-				ieee80211_scan_completed(mvm->hw, true);
-				iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-				break;
-			}
-
-			err = iwl_umac_scan_abort_one(mvm, mvm->scan_uid[i]);
-			if (!err)
-				ret = 0;
-		}
-	}
-
-	if (ret) {
-		IWL_DEBUG_SCAN(mvm, "Couldn't stop scan\n");
-		iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
-		return ret;
-	}
-
-	ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
-	if (ret)
-		return ret;
-
-	if (notify) {
-		if (type & IWL_UMAC_SCAN_UID_SCHED_SCAN)
-			ieee80211_sched_scan_stopped(mvm->hw);
-		if (type & IWL_UMAC_SCAN_UID_REG_SCAN) {
-			ieee80211_scan_completed(mvm->hw, true);
-			iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-		}
-	}
-
-	return ret;
-}
-
-int iwl_mvm_scan_size(struct iwl_mvm *mvm)
-{
-	if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
-		return sizeof(struct iwl_scan_req_umac) +
-			sizeof(struct iwl_scan_channel_cfg_umac) *
-				mvm->fw->ucode_capa.n_scan_channels +
-			sizeof(struct iwl_scan_req_umac_tail);
-
-	if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
-		return sizeof(struct iwl_scan_req_unified_lmac) +
-			sizeof(struct iwl_scan_channel_cfg_lmac) *
-				mvm->fw->ucode_capa.n_scan_channels +
-			sizeof(struct iwl_scan_probe_req);
-
-	return sizeof(struct iwl_scan_cmd) +
-		mvm->fw->ucode_capa.max_probe_length +
-			mvm->fw->ucode_capa.n_scan_channels *
-		sizeof(struct iwl_scan_channel);
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index d86fe43..1731c20 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -204,56 +204,6 @@
 	return ret;
 }
 
-static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm,
-				 struct ieee80211_sta *sta)
-{
-	unsigned long used_hw_queues;
-	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	u32 ac;
-
-	lockdep_assert_held(&mvm->mutex);
-
-	used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, NULL);
-
-	/* Find available queues, and allocate them to the ACs */
-	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-		u8 queue = find_first_zero_bit(&used_hw_queues,
-					       mvm->first_agg_queue);
-
-		if (queue >= mvm->first_agg_queue) {
-			IWL_ERR(mvm, "Failed to allocate STA queue\n");
-			return -EBUSY;
-		}
-
-		__set_bit(queue, &used_hw_queues);
-		mvmsta->hw_queue[ac] = queue;
-	}
-
-	/* Found a place for all queues - enable them */
-	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-		iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac],
-				      iwl_mvm_ac_to_tx_fifo[ac]);
-		mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]);
-	}
-
-	return 0;
-}
-
-static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm,
-				    struct ieee80211_sta *sta)
-{
-	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	unsigned long sta_msk;
-	int i;
-
-	lockdep_assert_held(&mvm->mutex);
-
-	/* disable the TDLS STA-specific queues */
-	sta_msk = mvmsta->tfd_queue_msk;
-	for_each_set_bit(i, &sta_msk, sizeof(sta_msk))
-		iwl_mvm_disable_txq(mvm, i);
-}
-
 int iwl_mvm_add_sta(struct iwl_mvm *mvm,
 		    struct ieee80211_vif *vif,
 		    struct ieee80211_sta *sta)
@@ -287,17 +237,9 @@
 	atomic_set(&mvm->pending_frames[sta_id], 0);
 	mvm_sta->tid_disable_agg = 0;
 	mvm_sta->tfd_queue_msk = 0;
-
-	/* allocate new queues for a TDLS station */
-	if (sta->tdls) {
-		ret = iwl_mvm_tdls_sta_init(mvm, sta);
-		if (ret)
-			return ret;
-	} else {
-		for (i = 0; i < IEEE80211_NUM_ACS; i++)
-			if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
-				mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
-	}
+	for (i = 0; i < IEEE80211_NUM_ACS; i++)
+		if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
+			mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
 
 	/* for HW restart - reset everything but the sequence number */
 	for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
@@ -309,7 +251,7 @@
 
 	ret = iwl_mvm_sta_send_to_fw(mvm, sta, false);
 	if (ret)
-		goto err;
+		return ret;
 
 	if (vif->type == NL80211_IFTYPE_STATION) {
 		if (!sta->tdls) {
@@ -323,10 +265,6 @@
 	rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
 
 	return 0;
-
-err:
-	iwl_mvm_tdls_sta_deinit(mvm, sta);
-	return ret;
 }
 
 int iwl_mvm_update_sta(struct iwl_mvm *mvm,
@@ -460,17 +398,6 @@
 		}
 		RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
 		clear_bit(sta_id, mvm->sta_drained);
-
-		if (mvm->tfd_drained[sta_id]) {
-			unsigned long i, msk = mvm->tfd_drained[sta_id];
-
-			for_each_set_bit(i, &msk, sizeof(msk))
-				iwl_mvm_disable_txq(mvm, i);
-
-			mvm->tfd_drained[sta_id] = 0;
-			IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n",
-				       sta_id, msk);
-		}
 	}
 
 	mutex_unlock(&mvm->mutex);
@@ -504,15 +431,6 @@
 	}
 
 	/*
-	 * This shouldn't happen - the TDLS channel switch should be canceled
-	 * before the STA is removed.
-	 */
-	if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == mvm_sta->sta_id)) {
-		mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
-		cancel_delayed_work(&mvm->tdls_cs.dwork);
-	}
-
-	/*
 	 * Make sure that the tx response code sees the station as -EBUSY and
 	 * calls the drain worker.
 	 */
@@ -525,22 +443,9 @@
 		rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
 				   ERR_PTR(-EBUSY));
 		spin_unlock_bh(&mvm_sta->lock);
-
-		/* disable TDLS sta queues on drain complete */
-		if (sta->tdls) {
-			mvm->tfd_drained[mvm_sta->sta_id] =
-							mvm_sta->tfd_queue_msk;
-			IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n",
-				       mvm_sta->sta_id);
-		}
-
 		ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
 	} else {
 		spin_unlock_bh(&mvm_sta->lock);
-
-		if (sta->tdls)
-			iwl_mvm_tdls_sta_deinit(mvm, sta);
-
 		ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
 		RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
 	}
@@ -704,7 +609,7 @@
 
 	lockdep_assert_held(&mvm->mutex);
 
-	qmask = iwl_mvm_mac_get_queues_mask(vif);
+	qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
 
 	/*
 	 * The firmware defines the TFD queue mask to only be relevant
@@ -1166,16 +1071,15 @@
 
 static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
 				struct iwl_mvm_sta *mvm_sta,
-				struct ieee80211_key_conf *keyconf, bool mcast,
-				u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags)
+				struct ieee80211_key_conf *keyconf,
+				u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
+				u32 cmd_flags)
 {
 	struct iwl_mvm_add_sta_key_cmd cmd = {};
 	__le16 key_flags;
-	int ret;
-	u32 status;
+	int ret, status;
 	u16 keyidx;
 	int i;
-	u8 sta_id = mvm_sta->sta_id;
 
 	keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
 		 STA_KEY_FLG_KEYID_MSK;
@@ -1194,18 +1098,12 @@
 		key_flags |= cpu_to_le16(STA_KEY_FLG_CCM);
 		memcpy(cmd.key, keyconf->key, keyconf->keylen);
 		break;
-	case WLAN_CIPHER_SUITE_WEP104:
-		key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_13BYTES);
-	case WLAN_CIPHER_SUITE_WEP40:
-		key_flags |= cpu_to_le16(STA_KEY_FLG_WEP);
-		memcpy(cmd.key + 3, keyconf->key, keyconf->keylen);
-		break;
 	default:
 		key_flags |= cpu_to_le16(STA_KEY_FLG_EXT);
 		memcpy(cmd.key, keyconf->key, keyconf->keylen);
 	}
 
-	if (mcast)
+	if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 		key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
 
 	cmd.key_offset = keyconf->hw_key_idx;
@@ -1297,88 +1195,17 @@
 	return NULL;
 }
 
-static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
-				 struct ieee80211_vif *vif,
-				 struct ieee80211_sta *sta,
-				 struct ieee80211_key_conf *keyconf,
-				 bool mcast)
-{
-	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
-	int ret;
-	const u8 *addr;
-	struct ieee80211_key_seq seq;
-	u16 p1k[5];
-
-	switch (keyconf->cipher) {
-	case WLAN_CIPHER_SUITE_TKIP:
-		addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
-		/* get phase 1 key from mac80211 */
-		ieee80211_get_key_rx_seq(keyconf, 0, &seq);
-		ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
-		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
-					   seq.tkip.iv32, p1k, 0);
-		break;
-	case WLAN_CIPHER_SUITE_CCMP:
-	case WLAN_CIPHER_SUITE_WEP40:
-	case WLAN_CIPHER_SUITE_WEP104:
-		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
-					   0, NULL, 0);
-		break;
-	default:
-		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
-					   0, NULL, 0);
-	}
-
-	return ret;
-}
-
-static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
-				    struct ieee80211_key_conf *keyconf,
-				    bool mcast)
-{
-	struct iwl_mvm_add_sta_key_cmd cmd = {};
-	__le16 key_flags;
-	int ret;
-	u32 status;
-
-	key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
-				 STA_KEY_FLG_KEYID_MSK);
-	key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
-	key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
-
-	if (mcast)
-		key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
-
-	cmd.key_flags = key_flags;
-	cmd.key_offset = keyconf->hw_key_idx;
-	cmd.sta_id = sta_id;
-
-	status = ADD_STA_SUCCESS;
-	ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
-					  &cmd, &status);
-
-	switch (status) {
-	case ADD_STA_SUCCESS:
-		IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
-		break;
-	default:
-		ret = -EIO;
-		IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
-		break;
-	}
-
-	return ret;
-}
-
 int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
 			struct ieee80211_vif *vif,
 			struct ieee80211_sta *sta,
 			struct ieee80211_key_conf *keyconf,
 			bool have_key_offset)
 {
-	bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
-	u8 sta_id;
+	struct iwl_mvm_sta *mvm_sta;
 	int ret;
+	u8 *addr, sta_id;
+	struct ieee80211_key_seq seq;
+	u16 p1k[5];
 
 	lockdep_assert_held(&mvm->mutex);
 
@@ -1407,7 +1234,8 @@
 		}
 	}
 
-	if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
+	mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv;
+	if (WARN_ON_ONCE(mvm_sta->vif != vif))
 		return -EINVAL;
 
 	if (!have_key_offset) {
@@ -1421,26 +1249,26 @@
 			return -ENOSPC;
 	}
 
-	ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, mcast);
-	if (ret) {
-		__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
-		goto end;
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_TKIP:
+		addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
+		/* get phase 1 key from mac80211 */
+		ieee80211_get_key_rx_seq(keyconf, 0, &seq);
+		ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
+		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
+					   seq.tkip.iv32, p1k, 0);
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
+					   0, NULL, 0);
+		break;
+	default:
+		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
+					   sta_id, 0, NULL, 0);
 	}
 
-	/*
-	 * For WEP, the same key is used for multicast and unicast. Upload it
-	 * again, using the same key offset, and now pointing the other one
-	 * to the same key slot (offset).
-	 * If this fails, remove the original as well.
-	 */
-	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
-		ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, !mcast);
-		if (ret) {
-			__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
-			__iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
-		}
-	}
+	if (ret)
+		__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
 
 end:
 	IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
@@ -1454,9 +1282,11 @@
 			   struct ieee80211_sta *sta,
 			   struct ieee80211_key_conf *keyconf)
 {
-	bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
+	struct iwl_mvm_sta *mvm_sta;
+	struct iwl_mvm_add_sta_key_cmd cmd = {};
+	__le16 key_flags;
+	int ret, status;
 	u8 sta_id;
-	int ret;
 
 	lockdep_assert_held(&mvm->mutex);
 
@@ -1469,7 +1299,8 @@
 	if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
 		return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
 
-	if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) {
+	ret = __test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
+	if (!ret) {
 		IWL_ERR(mvm, "offset %d not used in fw key table.\n",
 			keyconf->hw_key_idx);
 		return -ENOENT;
@@ -1495,17 +1326,35 @@
 		}
 	}
 
-	if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
+	mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv;
+	if (WARN_ON_ONCE(mvm_sta->vif != vif))
 		return -EINVAL;
 
-	ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
-	if (ret)
-		return ret;
+	key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
+				 STA_KEY_FLG_KEYID_MSK);
+	key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
+	key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
 
-	/* delete WEP key twice to get rid of (now useless) offset */
-	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
-		ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, !mcast);
+	if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
+
+	cmd.key_flags = key_flags;
+	cmd.key_offset = keyconf->hw_key_idx;
+	cmd.sta_id = sta_id;
+
+	status = ADD_STA_SUCCESS;
+	ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
+					  &cmd, &status);
+
+	switch (status) {
+	case ADD_STA_SUCCESS:
+		IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
+		break;
+	default:
+		ret = -EIO;
+		IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
+		break;
+	}
 
 	return ret;
 }
@@ -1518,7 +1367,6 @@
 {
 	struct iwl_mvm_sta *mvm_sta;
 	u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
-	bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
 
 	if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
 		return;
@@ -1533,8 +1381,8 @@
 		}
 	}
 
-	mvm_sta = iwl_mvm_sta_from_mac80211(sta);
-	iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
+	mvm_sta = (void *)sta->drv_priv;
+	iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
 			     iv32, phase1key, CMD_ASYNC);
 	rcu_read_unlock();
 }
@@ -1732,18 +1580,3 @@
 		iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, disable);
 	}
 }
-
-void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
-	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	struct iwl_mvm_sta *mvmsta;
-
-	rcu_read_lock();
-
-	mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
-
-	if (!WARN_ON(!mvmsta))
-		iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, true);
-
-	rcu_read_unlock();
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index d8f4897..d9c0d7b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -264,7 +264,6 @@
  *	the first packet to be sent in legacy HW queue in Tx AGG stop flow.
  *	Basically when next_reclaimed reaches ssn, we can tell mac80211 that
  *	we are ready to finish the Tx AGG stop / start flow.
- * @tx_time: medium time consumed by this A-MPDU
  */
 struct iwl_mvm_tid_data {
 	u16 seq_number;
@@ -275,7 +274,6 @@
 	enum iwl_mvm_agg_state state;
 	u16 txq_id;
 	u16 ssn;
-	u16 tx_time;
 };
 
 static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data)
@@ -288,7 +286,6 @@
  * struct iwl_mvm_sta - representation of a station in the driver
  * @sta_id: the index of the station in the fw (will be replaced by id_n_color)
  * @tfd_queue_msk: the tfd queues used by the station
- * @hw_queue: per-AC mapping of the TFD queues used by station
  * @mac_id_n_color: the MAC context this station is linked to
  * @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
  *	tid.
@@ -312,7 +309,6 @@
 struct iwl_mvm_sta {
 	u32 sta_id;
 	u32 tfd_queue_msk;
-	u8 hw_queue[IEEE80211_NUM_ACS];
 	u32 mac_id_n_color;
 	u16 tid_disable_agg;
 	u8 max_agg_bufsize;
@@ -422,6 +418,5 @@
 void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
 				       struct iwl_mvm_vif *mvmvif,
 				       bool disable);
-void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
 
 #endif /* __sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/tdls.c b/drivers/net/wireless/iwlwifi/mvm/tdls.c
index c0e00ba..66c82df 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tdls.c
@@ -61,13 +61,9 @@
  *
  *****************************************************************************/
 
-#include <linux/etherdevice.h>
 #include "mvm.h"
 #include "time-event.h"
 
-#define TU_TO_US(x) (x * 1024)
-#define TU_TO_MS(x) (TU_TO_US(x) / 1000)
-
 void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
 {
 	struct ieee80211_sta *sta;
@@ -117,85 +113,17 @@
 	return count;
 }
 
-static void iwl_mvm_tdls_config(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
-	struct iwl_rx_packet *pkt;
-	struct iwl_tdls_config_res *resp;
-	struct iwl_tdls_config_cmd tdls_cfg_cmd = {};
-	struct iwl_host_cmd cmd = {
-		.id = TDLS_CONFIG_CMD,
-		.flags = CMD_WANT_SKB,
-		.data = { &tdls_cfg_cmd, },
-		.len = { sizeof(struct iwl_tdls_config_cmd), },
-	};
-	struct ieee80211_sta *sta;
-	int ret, i, cnt;
-	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
-	lockdep_assert_held(&mvm->mutex);
-
-	tdls_cfg_cmd.id_and_color =
-		cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
-	tdls_cfg_cmd.tx_to_ap_tid = IWL_MVM_TDLS_FW_TID;
-	tdls_cfg_cmd.tx_to_ap_ssn = cpu_to_le16(0); /* not used for now */
-
-	/* for now the Tx cmd is empty and unused */
-
-	/* populate TDLS peer data */
-	cnt = 0;
-	for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
-		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
-						lockdep_is_held(&mvm->mutex));
-		if (IS_ERR_OR_NULL(sta) || !sta->tdls)
-			continue;
-
-		tdls_cfg_cmd.sta_info[cnt].sta_id = i;
-		tdls_cfg_cmd.sta_info[cnt].tx_to_peer_tid =
-							IWL_MVM_TDLS_FW_TID;
-		tdls_cfg_cmd.sta_info[cnt].tx_to_peer_ssn = cpu_to_le16(0);
-		tdls_cfg_cmd.sta_info[cnt].is_initiator =
-				cpu_to_le32(sta->tdls_initiator ? 1 : 0);
-
-		cnt++;
-	}
-
-	tdls_cfg_cmd.tdls_peer_count = cnt;
-	IWL_DEBUG_TDLS(mvm, "send TDLS config to FW for %d peers\n", cnt);
-
-	ret = iwl_mvm_send_cmd(mvm, &cmd);
-	if (WARN_ON_ONCE(ret))
-		return;
-
-	pkt = cmd.resp_pkt;
-	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-		IWL_ERR(mvm, "Bad return from TDLS_CONFIG_COMMAND (0x%08X)\n",
-			pkt->hdr.flags);
-		goto exit;
-	}
-
-	if (WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) != sizeof(*resp)))
-		goto exit;
-
-	/* we don't really care about the response at this point */
-
-exit:
-	iwl_free_resp(&cmd);
-}
-
 void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			       bool sta_added)
 {
 	int tdls_sta_cnt = iwl_mvm_tdls_sta_count(mvm, vif);
 
-	/* when the first peer joins, send a power update first */
-	if (tdls_sta_cnt == 1 && sta_added)
-		iwl_mvm_power_update_mac(mvm);
-
-	/* configure the FW with TDLS peer info */
-	iwl_mvm_tdls_config(mvm, vif);
-
-	/* when the last peer leaves, send a power update last */
-	if (tdls_sta_cnt == 0 && !sta_added)
+	/*
+	 * Disable ps when the first TDLS sta is added and re-enable it
+	 * when the last TDLS sta is removed
+	 */
+	if ((tdls_sta_cnt == 1 && sta_added) ||
+	    (tdls_sta_cnt == 0 && !sta_added))
 		iwl_mvm_power_update_mac(mvm);
 }
 
@@ -219,488 +147,3 @@
 
 	iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
 }
-
-static const char *
-iwl_mvm_tdls_cs_state_str(enum iwl_mvm_tdls_cs_state state)
-{
-	switch (state) {
-	case IWL_MVM_TDLS_SW_IDLE:
-		return "IDLE";
-	case IWL_MVM_TDLS_SW_REQ_SENT:
-		return "REQ SENT";
-	case IWL_MVM_TDLS_SW_REQ_RCVD:
-		return "REQ RECEIVED";
-	case IWL_MVM_TDLS_SW_ACTIVE:
-		return "ACTIVE";
-	}
-
-	return NULL;
-}
-
-static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm,
-					 enum iwl_mvm_tdls_cs_state state)
-{
-	if (mvm->tdls_cs.state == state)
-		return;
-
-	IWL_DEBUG_TDLS(mvm, "TDLS channel switch state: %s -> %s\n",
-		       iwl_mvm_tdls_cs_state_str(mvm->tdls_cs.state),
-		       iwl_mvm_tdls_cs_state_str(state));
-	mvm->tdls_cs.state = state;
-
-	if (state == IWL_MVM_TDLS_SW_IDLE)
-		mvm->tdls_cs.cur_sta_id = IWL_MVM_STATION_COUNT;
-}
-
-int iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
-			  struct iwl_device_cmd *cmd)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_tdls_channel_switch_notif *notif = (void *)pkt->data;
-	struct ieee80211_sta *sta;
-	unsigned int delay;
-	struct iwl_mvm_sta *mvmsta;
-	struct ieee80211_vif *vif;
-	u32 sta_id = le32_to_cpu(notif->sta_id);
-
-	lockdep_assert_held(&mvm->mutex);
-
-	/* can fail sometimes */
-	if (!le32_to_cpu(notif->status)) {
-		iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
-		goto out;
-	}
-
-	if (WARN_ON(sta_id >= IWL_MVM_STATION_COUNT))
-		goto out;
-
-	sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
-					lockdep_is_held(&mvm->mutex));
-	/* the station may not be here, but if it is, it must be a TDLS peer */
-	if (IS_ERR_OR_NULL(sta) || WARN_ON(!sta->tdls))
-		goto out;
-
-	mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	vif = mvmsta->vif;
-
-	/*
-	 * Update state and possibly switch again after this is over (DTIM).
-	 * Also convert TU to msec.
-	 */
-	delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
-	mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
-			 msecs_to_jiffies(delay));
-
-	iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_ACTIVE);
-
-out:
-	return 0;
-}
-
-static int
-iwl_mvm_tdls_check_action(struct iwl_mvm *mvm,
-			  enum iwl_tdls_channel_switch_type type,
-			  const u8 *peer, bool peer_initiator)
-{
-	bool same_peer = false;
-	int ret = 0;
-
-	/* get the existing peer if it's there */
-	if (mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE &&
-	    mvm->tdls_cs.cur_sta_id != IWL_MVM_STATION_COUNT) {
-		struct ieee80211_sta *sta = rcu_dereference_protected(
-				mvm->fw_id_to_mac_id[mvm->tdls_cs.cur_sta_id],
-				lockdep_is_held(&mvm->mutex));
-		if (!IS_ERR_OR_NULL(sta))
-			same_peer = ether_addr_equal(peer, sta->addr);
-	}
-
-	switch (mvm->tdls_cs.state) {
-	case IWL_MVM_TDLS_SW_IDLE:
-		/*
-		 * might be spurious packet from the peer after the switch is
-		 * already done
-		 */
-		if (type == TDLS_MOVE_CH)
-			ret = -EINVAL;
-		break;
-	case IWL_MVM_TDLS_SW_REQ_SENT:
-		/*
-		 * We received a ch-switch request while an outgoing one is
-		 * pending. Allow it to proceed if the other peer is the same
-		 * one we sent to, and we are not the link initiator.
-		 */
-		if (type == TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH) {
-			if (!same_peer)
-				ret = -EBUSY;
-			else if (!peer_initiator) /* we are the initiator */
-				ret = -EBUSY;
-		}
-		break;
-	case IWL_MVM_TDLS_SW_REQ_RCVD:
-		/* as above, allow the link initiator to proceed */
-		if (type == TDLS_SEND_CHAN_SW_REQ) {
-			if (!same_peer)
-				ret = -EBUSY;
-			else if (peer_initiator) /* they are the initiator */
-				ret = -EBUSY;
-		} else if (type == TDLS_MOVE_CH) {
-			ret = -EINVAL;
-		}
-		break;
-	case IWL_MVM_TDLS_SW_ACTIVE:
-		/* we don't allow initiations during active channel switch */
-		if (type == TDLS_SEND_CHAN_SW_REQ)
-			ret = -EINVAL;
-		break;
-	}
-
-	if (ret)
-		IWL_DEBUG_TDLS(mvm,
-			       "Invalid TDLS action %d state %d peer %pM same_peer %d initiator %d\n",
-			       type, mvm->tdls_cs.state, peer, same_peer,
-			       peer_initiator);
-
-	return ret;
-}
-
-static int
-iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
-				   struct ieee80211_vif *vif,
-				   enum iwl_tdls_channel_switch_type type,
-				   const u8 *peer, bool peer_initiator,
-				   u8 oper_class,
-				   struct cfg80211_chan_def *chandef,
-				   u32 timestamp, u16 switch_time,
-				   u16 switch_timeout, struct sk_buff *skb,
-				   u32 ch_sw_tm_ie)
-{
-	struct ieee80211_sta *sta;
-	struct iwl_mvm_sta *mvmsta;
-	struct ieee80211_tx_info *info;
-	struct ieee80211_hdr *hdr;
-	struct iwl_tdls_channel_switch_cmd cmd = {0};
-	int ret;
-
-	lockdep_assert_held(&mvm->mutex);
-
-	ret = iwl_mvm_tdls_check_action(mvm, type, peer, peer_initiator);
-	if (ret)
-		return ret;
-
-	if (!skb || WARN_ON(skb->len > IWL_TDLS_CH_SW_FRAME_MAX_SIZE)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	cmd.switch_type = type;
-	cmd.timing.frame_timestamp = cpu_to_le32(timestamp);
-	cmd.timing.switch_time = cpu_to_le32(switch_time);
-	cmd.timing.switch_timeout = cpu_to_le32(switch_timeout);
-
-	rcu_read_lock();
-	sta = ieee80211_find_sta(vif, peer);
-	if (!sta) {
-		rcu_read_unlock();
-		ret = -ENOENT;
-		goto out;
-	}
-	mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	cmd.peer_sta_id = cpu_to_le32(mvmsta->sta_id);
-
-	if (!chandef) {
-		if (mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
-		    mvm->tdls_cs.peer.chandef.chan) {
-			/* actually moving to the channel */
-			chandef = &mvm->tdls_cs.peer.chandef;
-		} else if (mvm->tdls_cs.state == IWL_MVM_TDLS_SW_ACTIVE &&
-			   type == TDLS_MOVE_CH) {
-			/* we need to return to base channel */
-			struct ieee80211_chanctx_conf *chanctx =
-					rcu_dereference(vif->chanctx_conf);
-
-			if (WARN_ON_ONCE(!chanctx)) {
-				rcu_read_unlock();
-				goto out;
-			}
-
-			chandef = &chanctx->def;
-		}
-	}
-
-	if (chandef) {
-		cmd.ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ?
-			       PHY_BAND_24 : PHY_BAND_5);
-		cmd.ci.channel = chandef->chan->hw_value;
-		cmd.ci.width = iwl_mvm_get_channel_width(chandef);
-		cmd.ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef);
-	}
-
-	/* keep quota calculation simple for now - 50% of DTIM for TDLS */
-	cmd.timing.max_offchan_duration =
-			cpu_to_le32(TU_TO_US(vif->bss_conf.dtim_period *
-					     vif->bss_conf.beacon_int) / 2);
-
-	/* Switch time is the first element in the switch-timing IE. */
-	cmd.frame.switch_time_offset = cpu_to_le32(ch_sw_tm_ie + 2);
-
-	info = IEEE80211_SKB_CB(skb);
-	if (info->control.hw_key)
-		iwl_mvm_set_tx_cmd_crypto(mvm, info, &cmd.frame.tx_cmd, skb);
-
-	iwl_mvm_set_tx_cmd(mvm, skb, &cmd.frame.tx_cmd, info,
-			   mvmsta->sta_id);
-
-	hdr = (void *)skb->data;
-	iwl_mvm_set_tx_cmd_rate(mvm, &cmd.frame.tx_cmd, info, sta,
-				hdr->frame_control);
-	rcu_read_unlock();
-
-	memcpy(cmd.frame.data, skb->data, skb->len);
-
-	ret = iwl_mvm_send_cmd_pdu(mvm, TDLS_CHANNEL_SWITCH_CMD, 0,
-				   sizeof(cmd), &cmd);
-	if (ret) {
-		IWL_ERR(mvm, "Failed to send TDLS_CHANNEL_SWITCH cmd: %d\n",
-			ret);
-		goto out;
-	}
-
-	/* channel switch has started, update state */
-	if (type != TDLS_MOVE_CH) {
-		mvm->tdls_cs.cur_sta_id = mvmsta->sta_id;
-		iwl_mvm_tdls_update_cs_state(mvm,
-					     type == TDLS_SEND_CHAN_SW_REQ ?
-					     IWL_MVM_TDLS_SW_REQ_SENT :
-					     IWL_MVM_TDLS_SW_REQ_RCVD);
-	}
-
-out:
-
-	/* channel switch failed - we are idle */
-	if (ret)
-		iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
-
-	return ret;
-}
-
-void iwl_mvm_tdls_ch_switch_work(struct work_struct *work)
-{
-	struct iwl_mvm *mvm;
-	struct ieee80211_sta *sta;
-	struct iwl_mvm_sta *mvmsta;
-	struct ieee80211_vif *vif;
-	unsigned int delay;
-	int ret;
-
-	mvm = container_of(work, struct iwl_mvm, tdls_cs.dwork.work);
-	mutex_lock(&mvm->mutex);
-
-	/* called after an active channel switch has finished or timed-out */
-	iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
-
-	/* station might be gone, in that case do nothing */
-	if (mvm->tdls_cs.peer.sta_id == IWL_MVM_STATION_COUNT)
-		goto out;
-
-	sta = rcu_dereference_protected(
-				mvm->fw_id_to_mac_id[mvm->tdls_cs.peer.sta_id],
-				lockdep_is_held(&mvm->mutex));
-	/* the station may not be here, but if it is, it must be a TDLS peer */
-	if (!sta || IS_ERR(sta) || WARN_ON(!sta->tdls))
-		goto out;
-
-	mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	vif = mvmsta->vif;
-	ret = iwl_mvm_tdls_config_channel_switch(mvm, vif,
-						 TDLS_SEND_CHAN_SW_REQ,
-						 sta->addr,
-						 mvm->tdls_cs.peer.initiator,
-						 mvm->tdls_cs.peer.op_class,
-						 &mvm->tdls_cs.peer.chandef,
-						 0, 0, 0,
-						 mvm->tdls_cs.peer.skb,
-						 mvm->tdls_cs.peer.ch_sw_tm_ie);
-	if (ret)
-		IWL_ERR(mvm, "Not sending TDLS channel switch: %d\n", ret);
-
-	/* retry after a DTIM if we failed sending now */
-	delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
-	queue_delayed_work(system_wq, &mvm->tdls_cs.dwork,
-			   msecs_to_jiffies(delay));
-out:
-	mutex_unlock(&mvm->mutex);
-}
-
-int
-iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
-			    struct ieee80211_vif *vif,
-			    struct ieee80211_sta *sta, u8 oper_class,
-			    struct cfg80211_chan_def *chandef,
-			    struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie)
-{
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-	struct iwl_mvm_sta *mvmsta;
-	unsigned int delay;
-	int ret;
-
-	mutex_lock(&mvm->mutex);
-
-	IWL_DEBUG_TDLS(mvm, "TDLS channel switch with %pM ch %d width %d\n",
-		       sta->addr, chandef->chan->center_freq, chandef->width);
-
-	/* we only support a single peer for channel switching */
-	if (mvm->tdls_cs.peer.sta_id != IWL_MVM_STATION_COUNT) {
-		IWL_DEBUG_TDLS(mvm,
-			       "Existing peer. Can't start switch with %pM\n",
-			       sta->addr);
-		ret = -EBUSY;
-		goto out;
-	}
-
-	ret = iwl_mvm_tdls_config_channel_switch(mvm, vif,
-						 TDLS_SEND_CHAN_SW_REQ,
-						 sta->addr, sta->tdls_initiator,
-						 oper_class, chandef, 0, 0, 0,
-						 tmpl_skb, ch_sw_tm_ie);
-	if (ret)
-		goto out;
-
-	/*
-	 * Mark the peer as "in tdls switch" for this vif. We only allow a
-	 * single such peer per vif.
-	 */
-	mvm->tdls_cs.peer.skb = skb_copy(tmpl_skb, GFP_KERNEL);
-	if (!mvm->tdls_cs.peer.skb) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	mvm->tdls_cs.peer.sta_id = mvmsta->sta_id;
-	mvm->tdls_cs.peer.chandef = *chandef;
-	mvm->tdls_cs.peer.initiator = sta->tdls_initiator;
-	mvm->tdls_cs.peer.op_class = oper_class;
-	mvm->tdls_cs.peer.ch_sw_tm_ie = ch_sw_tm_ie;
-
-	/*
-	 * Wait for 2 DTIM periods before attempting the next switch. The next
-	 * switch will be made sooner if the current one completes before that.
-	 */
-	delay = 2 * TU_TO_MS(vif->bss_conf.dtim_period *
-			     vif->bss_conf.beacon_int);
-	mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
-			 msecs_to_jiffies(delay));
-
-out:
-	mutex_unlock(&mvm->mutex);
-	return ret;
-}
-
-void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
-					struct ieee80211_vif *vif,
-					struct ieee80211_sta *sta)
-{
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-	struct ieee80211_sta *cur_sta;
-	bool wait_for_phy = false;
-
-	mutex_lock(&mvm->mutex);
-
-	IWL_DEBUG_TDLS(mvm, "TDLS cancel channel switch with %pM\n", sta->addr);
-
-	/* we only support a single peer for channel switching */
-	if (mvm->tdls_cs.peer.sta_id == IWL_MVM_STATION_COUNT) {
-		IWL_DEBUG_TDLS(mvm, "No ch switch peer - %pM\n", sta->addr);
-		goto out;
-	}
-
-	cur_sta = rcu_dereference_protected(
-				mvm->fw_id_to_mac_id[mvm->tdls_cs.peer.sta_id],
-				lockdep_is_held(&mvm->mutex));
-	/* make sure it's the same peer */
-	if (cur_sta != sta)
-		goto out;
-
-	/*
-	 * If we're currently in a switch because of the now canceled peer,
-	 * wait a DTIM here to make sure the phy is back on the base channel.
-	 * We can't otherwise force it.
-	 */
-	if (mvm->tdls_cs.cur_sta_id == mvm->tdls_cs.peer.sta_id &&
-	    mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE)
-		wait_for_phy = true;
-
-	mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
-	dev_kfree_skb(mvm->tdls_cs.peer.skb);
-	mvm->tdls_cs.peer.skb = NULL;
-
-out:
-	mutex_unlock(&mvm->mutex);
-
-	/* make sure the phy is on the base channel */
-	if (wait_for_phy)
-		msleep(TU_TO_MS(vif->bss_conf.dtim_period *
-				vif->bss_conf.beacon_int));
-
-	/* flush the channel switch state */
-	flush_delayed_work(&mvm->tdls_cs.dwork);
-
-	IWL_DEBUG_TDLS(mvm, "TDLS ending channel switch with %pM\n", sta->addr);
-}
-
-void
-iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif,
-				 struct ieee80211_tdls_ch_sw_params *params)
-{
-	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-	enum iwl_tdls_channel_switch_type type;
-	unsigned int delay;
-
-	mutex_lock(&mvm->mutex);
-
-	IWL_DEBUG_TDLS(mvm,
-		       "Received TDLS ch switch action %d from %pM status %d\n",
-		       params->action_code, params->sta->addr, params->status);
-
-	/*
-	 * we got a non-zero status from a peer we were switching to - move to
-	 * the idle state and retry again later
-	 */
-	if (params->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE &&
-	    params->status != 0 &&
-	    mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
-	    mvm->tdls_cs.cur_sta_id != IWL_MVM_STATION_COUNT) {
-		struct ieee80211_sta *cur_sta;
-
-		/* make sure it's the same peer */
-		cur_sta = rcu_dereference_protected(
-				mvm->fw_id_to_mac_id[mvm->tdls_cs.cur_sta_id],
-				lockdep_is_held(&mvm->mutex));
-		if (cur_sta == params->sta) {
-			iwl_mvm_tdls_update_cs_state(mvm,
-						     IWL_MVM_TDLS_SW_IDLE);
-			goto retry;
-		}
-	}
-
-	type = (params->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST) ?
-	       TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH : TDLS_MOVE_CH;
-
-	iwl_mvm_tdls_config_channel_switch(mvm, vif, type, params->sta->addr,
-					   params->sta->tdls_initiator, 0,
-					   params->chandef, params->timestamp,
-					   params->switch_time,
-					   params->switch_timeout,
-					   params->tmpl_skb,
-					   params->ch_sw_tm_ie);
-
-retry:
-	/* register a timeout in case we don't succeed in switching */
-	delay = vif->bss_conf.dtim_period * vif->bss_conf.beacon_int *
-		1024 / 1000;
-	mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
-			 msecs_to_jiffies(delay));
-	mutex_unlock(&mvm->mutex);
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 54fafbf..b7f9e61 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -191,35 +191,6 @@
 	return true;
 }
 
-static void
-iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm,
-			     struct iwl_mvm_time_event_data *te_data,
-			     struct iwl_time_event_notif *notif)
-{
-	if (!le32_to_cpu(notif->status)) {
-		IWL_DEBUG_TE(mvm, "CSA time event failed to start\n");
-		iwl_mvm_te_clear_data(mvm, te_data);
-		return;
-	}
-
-	switch (te_data->vif->type) {
-	case NL80211_IFTYPE_AP:
-		iwl_mvm_csa_noa_start(mvm);
-		break;
-	case NL80211_IFTYPE_STATION:
-		iwl_mvm_csa_client_absent(mvm, te_data->vif);
-		ieee80211_chswitch_done(te_data->vif, true);
-		break;
-	default:
-		/* should never happen */
-		WARN_ON_ONCE(1);
-		break;
-	}
-
-	/* we don't need it anymore */
-	iwl_mvm_te_clear_data(mvm, te_data);
-}
-
 /*
  * Handles a FW notification for an event that is known to the driver.
  *
@@ -281,8 +252,14 @@
 			set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
 			iwl_mvm_ref(mvm, IWL_MVM_REF_ROC);
 			ieee80211_ready_on_channel(mvm->hw);
-		} else if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) {
-			iwl_mvm_te_handle_notify_csa(mvm, te_data, notif);
+		} else if (te_data->vif->type == NL80211_IFTYPE_AP) {
+			if (le32_to_cpu(notif->status))
+				iwl_mvm_csa_noa_start(mvm);
+			else
+				IWL_DEBUG_TE(mvm, "CSA NOA failed to start\n");
+
+			/* we don't need it anymore */
+			iwl_mvm_te_clear_data(mvm, te_data);
 		}
 	} else {
 		IWL_WARN(mvm, "Got TE with unknown action\n");
@@ -328,8 +305,8 @@
 		te_data->running = false;
 		te_data->vif = NULL;
 		te_data->uid = 0;
-		te_data->id = TE_MAX;
 	} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
+		set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
 		set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
 		te_data->running = true;
 		ieee80211_ready_on_channel(mvm->hw); /* Start TE */
@@ -572,11 +549,18 @@
 	}
 }
 
-static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
-					struct iwl_mvm_time_event_data *te_data,
-					u32 *uid)
+/*
+ * Explicit request to remove a time event. The removal of a time event needs to
+ * be synchronized with the flow of a time event's end notification, which also
+ * removes the time event from the op mode data structures.
+ */
+void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
+			       struct iwl_mvm_vif *mvmvif,
+			       struct iwl_mvm_time_event_data *te_data)
 {
-	u32 id;
+	struct iwl_time_event_cmd time_cmd = {};
+	u32 id, uid;
+	int ret;
 
 	/*
 	 * It is possible that by the time we got to this point the time
@@ -585,7 +569,7 @@
 	spin_lock_bh(&mvm->time_event_lock);
 
 	/* Save time event uid before clearing its data */
-	*uid = te_data->uid;
+	uid = te_data->uid;
 	id = te_data->id;
 
 	/*
@@ -600,59 +584,10 @@
 	 * send a removal command.
 	 */
 	if (id == TE_MAX) {
-		IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid);
-		return false;
+		IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", uid);
+		return;
 	}
 
-	return true;
-}
-
-/*
- * Explicit request to remove a aux roc time event. The removal of a time
- * event needs to be synchronized with the flow of a time event's end
- * notification, which also removes the time event from the op mode
- * data structures.
- */
-static void iwl_mvm_remove_aux_roc_te(struct iwl_mvm *mvm,
-				      struct iwl_mvm_vif *mvmvif,
-				      struct iwl_mvm_time_event_data *te_data)
-{
-	struct iwl_hs20_roc_req aux_cmd = {};
-	u32 uid;
-	int ret;
-
-	if (!__iwl_mvm_remove_time_event(mvm, te_data, &uid))
-		return;
-
-	aux_cmd.event_unique_id = cpu_to_le32(uid);
-	aux_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
-	aux_cmd.id_and_color =
-		cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
-	IWL_DEBUG_TE(mvm, "Removing BSS AUX ROC TE 0x%x\n",
-		     le32_to_cpu(aux_cmd.event_unique_id));
-	ret = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0,
-				   sizeof(aux_cmd), &aux_cmd);
-
-	if (WARN_ON(ret))
-		return;
-}
-
-/*
- * Explicit request to remove a time event. The removal of a time event needs to
- * be synchronized with the flow of a time event's end notification, which also
- * removes the time event from the op mode data structures.
- */
-void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
-			       struct iwl_mvm_vif *mvmvif,
-			       struct iwl_mvm_time_event_data *te_data)
-{
-	struct iwl_time_event_cmd time_cmd = {};
-	u32 uid;
-	int ret;
-
-	if (!__iwl_mvm_remove_time_event(mvm, te_data, &uid))
-		return;
-
 	/* When we remove a TE, the UID is to be set in the id field */
 	time_cmd.id = cpu_to_le32(uid);
 	time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
@@ -731,17 +666,13 @@
 	return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
 }
 
-void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
+void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm)
 {
 	struct iwl_mvm_vif *mvmvif;
 	struct iwl_mvm_time_event_data *te_data;
-	bool is_p2p = false;
 
 	lockdep_assert_held(&mvm->mutex);
 
-	mvmvif = NULL;
-	spin_lock_bh(&mvm->time_event_lock);
-
 	/*
 	 * Iterate over the list of time events and find the time event that is
 	 * associated with a P2P_DEVICE interface.
@@ -749,41 +680,22 @@
 	 * event at any given time and this time event coresponds to a ROC
 	 * request
 	 */
+	mvmvif = NULL;
+	spin_lock_bh(&mvm->time_event_lock);
 	list_for_each_entry(te_data, &mvm->time_event_list, list) {
-		if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE &&
-		    te_data->running) {
+		if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
 			mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
-			is_p2p = true;
-			goto remove_te;
+			break;
 		}
 	}
-
-	/*
-	 * Iterate over the list of aux roc time events and find the time
-	 * event that is associated with a BSS interface.
-	 * This assumes that a BSS interface can have only a single time
-	 * event at any given time and this time event coresponds to a ROC
-	 * request
-	 */
-	list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
-		if (te_data->running) {
-			mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
-			goto remove_te;
-		}
-	}
-
-remove_te:
 	spin_unlock_bh(&mvm->time_event_lock);
 
 	if (!mvmvif) {
-		IWL_WARN(mvm, "No remain on channel event\n");
+		IWL_WARN(mvm, "P2P_DEVICE no remain on channel event\n");
 		return;
 	}
 
-	if (is_p2p)
-		iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
-	else
-		iwl_mvm_remove_aux_roc_te(mvm, mvmvif, te_data);
+	iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
 
 	iwl_mvm_roc_finished(mvm);
 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h
index 6f6b35d..b350e47 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h
@@ -182,14 +182,14 @@
 			  int duration, enum ieee80211_roc_type type);
 
 /**
- * iwl_mvm_stop_roc - stop remain on channel functionality
+ * iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity
  * @mvm: the mvm component
  *
  * This function can be used to cancel an ongoing ROC session.
  * The function is async, it will instruct the FW to stop serving the ROC
  * session, but will not wait for the actual stopping of the session.
  */
-void iwl_mvm_stop_roc(struct iwl_mvm *mvm);
+void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm);
 
 /**
  * iwl_mvm_remove_time_event - general function to clean up of time event
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index 2b1e61f..acca44a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -64,6 +64,10 @@
  *****************************************************************************/
 
 #include "mvm.h"
+#include "iwl-config.h"
+#include "iwl-io.h"
+#include "iwl-csr.h"
+#include "iwl-prph.h"
 
 #define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT	HZ
 
@@ -95,81 +99,32 @@
 	iwl_mvm_set_hw_ctkill_state(mvm, false);
 }
 
-void iwl_mvm_tt_temp_changed(struct iwl_mvm *mvm, u32 temp)
-{
-	/* ignore the notification if we are in test mode */
-	if (mvm->temperature_test)
-		return;
-
-	if (mvm->temperature == temp)
-		return;
-
-	mvm->temperature = temp;
-	iwl_mvm_tt_handler(mvm);
-}
-
-static int iwl_mvm_temp_notif_parse(struct iwl_mvm *mvm,
-				    struct iwl_rx_packet *pkt)
-{
-	struct iwl_dts_measurement_notif *notif;
-	int len = iwl_rx_packet_payload_len(pkt);
-	int temp;
-
-	if (WARN_ON_ONCE(len != sizeof(*notif))) {
-		IWL_ERR(mvm, "Invalid DTS_MEASUREMENT_NOTIFICATION\n");
-		return -EINVAL;
-	}
-
-	notif = (void *)pkt->data;
-
-	temp = le32_to_cpu(notif->temp);
-
-	/* shouldn't be negative, but since it's s32, make sure it isn't */
-	if (WARN_ON_ONCE(temp < 0))
-		temp = 0;
-
-	IWL_DEBUG_TEMP(mvm, "DTS_MEASUREMENT_NOTIFICATION - %d\n", temp);
-
-	return temp;
-}
-
-static bool iwl_mvm_temp_notif_wait(struct iwl_notif_wait_data *notif_wait,
-				    struct iwl_rx_packet *pkt, void *data)
+static bool iwl_mvm_temp_notif(struct iwl_notif_wait_data *notif_wait,
+			       struct iwl_rx_packet *pkt, void *data)
 {
 	struct iwl_mvm *mvm =
 		container_of(notif_wait, struct iwl_mvm, notif_wait);
 	int *temp = data;
-	int ret;
+	struct iwl_dts_measurement_notif *notif;
+	int len = iwl_rx_packet_payload_len(pkt);
 
-	ret = iwl_mvm_temp_notif_parse(mvm, pkt);
-	if (ret < 0)
+	if (WARN_ON_ONCE(len != sizeof(*notif))) {
+		IWL_ERR(mvm, "Invalid DTS_MEASUREMENT_NOTIFICATION\n");
 		return true;
+	}
 
-	*temp = ret;
+	notif = (void *)pkt->data;
 
+	*temp = le32_to_cpu(notif->temp);
+
+	/* shouldn't be negative, but since it's s32, make sure it isn't */
+	if (WARN_ON_ONCE(*temp < 0))
+		*temp = 0;
+
+	IWL_DEBUG_TEMP(mvm, "DTS_MEASUREMENT_NOTIFICATION - %d\n", *temp);
 	return true;
 }
 
-int iwl_mvm_temp_notif(struct iwl_mvm *mvm,
-		       struct iwl_rx_cmd_buffer *rxb,
-		       struct iwl_device_cmd *cmd)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	int temp;
-
-	/* the notification is handled synchronously in ctkill, so skip here */
-	if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status))
-		return 0;
-
-	temp = iwl_mvm_temp_notif_parse(mvm, pkt);
-	if (temp < 0)
-		return 0;
-
-	iwl_mvm_tt_temp_changed(mvm, temp);
-
-	return 0;
-}
-
 static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm)
 {
 	struct iwl_dts_measurement_cmd cmd = {
@@ -190,7 +145,7 @@
 
 	iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif,
 				   temp_notif, ARRAY_SIZE(temp_notif),
-				   iwl_mvm_temp_notif_wait, &temp);
+				   iwl_mvm_temp_notif, &temp);
 
 	ret = iwl_mvm_get_temp_cmd(mvm);
 	if (ret) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 178bdce..9877937 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -73,9 +73,9 @@
 /*
  * Sets most of the Tx cmd's fields
  */
-void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
-			struct iwl_tx_cmd *tx_cmd,
-			struct ieee80211_tx_info *info, u8 sta_id)
+static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
+			       struct iwl_tx_cmd *tx_cmd,
+			       struct ieee80211_tx_info *info, u8 sta_id)
 {
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	__le16 fc = hdr->frame_control;
@@ -149,9 +149,11 @@
 /*
  * Sets the fields in the Tx cmd that are rate related
  */
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
-			    struct ieee80211_tx_info *info,
-			    struct ieee80211_sta *sta, __le16 fc)
+static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
+				    struct iwl_tx_cmd *tx_cmd,
+				    struct ieee80211_tx_info *info,
+				    struct ieee80211_sta *sta,
+				    __le16 fc)
 {
 	u32 rate_flags;
 	int rate_idx;
@@ -173,10 +175,14 @@
 
 	/*
 	 * for data packets, rate info comes from the table inside the fw. This
-	 * table is controlled by LINK_QUALITY commands
+	 * table is controlled by LINK_QUALITY commands. Exclude ctrl port
+	 * frames like EAPOLs which should be treated as mgmt frames. This
+	 * avoids them being sent initially in high rates which increases the
+	 * chances for completion of the 4-Way handshake.
 	 */
 
-	if (ieee80211_is_data(fc) && sta) {
+	if (ieee80211_is_data(fc) && sta &&
+	    !(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) {
 		tx_cmd->initial_rate_index = 0;
 		tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
 		return;
@@ -187,10 +193,8 @@
 
 	/* HT rate doesn't make sense for a non data frame */
 	WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS,
-		  "Got an HT rate (flags:0x%x/mcs:%d) for a non data frame (fc:0x%x)\n",
-		  info->control.rates[0].flags,
-		  info->control.rates[0].idx,
-		  le16_to_cpu(fc));
+		  "Got an HT rate for a non data frame 0x%x\n",
+		  info->control.rates[0].flags);
 
 	rate_idx = info->control.rates[0].idx;
 	/* if the rate isn't a well known legacy rate, take the lowest one */
@@ -230,10 +234,10 @@
 /*
  * Sets the fields in the Tx cmd that are crypto related
  */
-void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
-			       struct ieee80211_tx_info *info,
-			       struct iwl_tx_cmd *tx_cmd,
-			       struct sk_buff *skb_frag)
+static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
+				      struct ieee80211_tx_info *info,
+				      struct iwl_tx_cmd *tx_cmd,
+				      struct sk_buff *skb_frag)
 {
 	struct ieee80211_key_conf *keyconf = info->control.hw_key;
 
@@ -424,13 +428,6 @@
 
 	WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);
 
-	if (sta->tdls) {
-		/* default to TID 0 for non-QoS packets */
-		u8 tdls_tid = tid == IWL_MAX_TID_COUNT ? 0 : tid;
-
-		txq_id = mvmsta->hw_queue[tid_to_mac80211_ac[tdls_tid]];
-	}
-
 	if (is_ampdu) {
 		if (WARN_ON_ONCE(mvmsta->tid_data[tid].state != IWL_AGG_ON))
 			goto drop_unlock_sta;
@@ -665,12 +662,6 @@
 			seq_ctl = le16_to_cpu(hdr->seq_ctrl);
 		}
 
-		/*
-		 * TODO: this is not accurate if we are freeing more than one
-		 * packet.
-		 */
-		info->status.tx_time =
-			le16_to_cpu(tx_resp->wireless_media_time);
 		BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1);
 		info->status.status_driver_data[0] =
 				(void *)(uintptr_t)tx_resp->reduced_tpc;
@@ -863,8 +854,6 @@
 		mvmsta->tid_data[tid].rate_n_flags =
 			le32_to_cpu(tx_resp->initial_rate);
 		mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc;
-		mvmsta->tid_data[tid].tx_time =
-			le16_to_cpu(tx_resp->wireless_media_time);
 	}
 
 	rcu_read_unlock();
@@ -893,8 +882,6 @@
 	info->status.ampdu_len = ba_notif->txed;
 	iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags,
 				    info);
-	/* TODO: not accounted if the whole A-MPDU failed */
-	info->status.tx_time = tid_data->tx_time;
 	info->status.status_driver_data[0] =
 		(void *)(uintptr_t)tid_data->reduced_tpc;
 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 8497660..ee6e5f9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -734,40 +734,3 @@
 
 	return idle;
 }
-
-struct iwl_bss_iter_data {
-	struct ieee80211_vif *vif;
-	bool error;
-};
-
-static void iwl_mvm_bss_iface_iterator(void *_data, u8 *mac,
-				       struct ieee80211_vif *vif)
-{
-	struct iwl_bss_iter_data *data = _data;
-
-	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
-		return;
-
-	if (data->vif) {
-		data->error = true;
-		return;
-	}
-
-	data->vif = vif;
-}
-
-struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
-{
-	struct iwl_bss_iter_data bss_iter_data = {};
-
-	ieee80211_iterate_active_interfaces_atomic(
-		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
-		iwl_mvm_bss_iface_iterator, &bss_iter_data);
-
-	if (bss_iter_data.error) {
-		IWL_ERR(mvm, "More than one managed interface active!\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	return bss_iter_data.vif;
-}
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 14d92d1..082d286 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -499,7 +499,6 @@
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-	const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
 	struct iwl_trans *iwl_trans;
 	struct iwl_trans_pcie *trans_pcie;
 	int ret;
@@ -508,25 +507,6 @@
 	if (IS_ERR(iwl_trans))
 		return PTR_ERR(iwl_trans);
 
-#if IS_ENABLED(CPTCFG_IWLMVM)
-	/*
-	 * special-case 7265D, it has the same PCI IDs.
-	 *
-	 * Note that because we already pass the cfg to the transport above,
-	 * all the parameters that the transport uses must, until that is
-	 * changed, be identical to the ones in the 7265D configuration.
-	 */
-	if (cfg == &iwl7265_2ac_cfg)
-		cfg_7265d = &iwl7265d_2ac_cfg;
-	else if (cfg == &iwl7265_2n_cfg)
-		cfg_7265d = &iwl7265d_2n_cfg;
-	else if (cfg == &iwl7265_n_cfg)
-		cfg_7265d = &iwl7265d_n_cfg;
-	if (cfg_7265d &&
-	    (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
-		cfg = cfg_7265d;
-#endif
-
 	pci_set_drvdata(pdev, iwl_trans);
 
 	trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 93a9e59..9062249 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -78,11 +78,6 @@
 #include "iwl-agn-hw.h"
 #include "iwl-fw-error-dump.h"
 #include "internal.h"
-#include "iwl-fh.h"
-
-/* extended range in FW SRAM */
-#define IWL_FW_MEM_EXTENDED_START	0x40000
-#define IWL_FW_MEM_EXTENDED_END		0x57FFF
 
 static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
 {
@@ -138,7 +133,7 @@
 		break;
 	}
 
-	if (WARN_ON_ONCE(!page))
+	if (!page)
 		return;
 
 	trans_pcie->fw_mon_page = page;
@@ -179,7 +174,6 @@
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u16 lctl;
-	u16 cap;
 
 	/*
 	 * HW bug W/A for instability in PCIe bus L0S->L1 transition.
@@ -190,17 +184,16 @@
 	 *    power savings, even without L1.
 	 */
 	pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
-	if (lctl & PCI_EXP_LNKCTL_ASPM_L1)
+	if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
+		/* L1-ASPM enabled; disable(!) L0S */
 		iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
-	else
+		dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
+	} else {
+		/* L1-ASPM disabled; enable(!) L0S */
 		iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
+		dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
+	}
 	trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
-
-	pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
-	trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
-	dev_info(trans->dev, "L1 %sabled - LTR %sabled\n",
-		 (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
-		 trans->ltr_enabled ? "En" : "Dis");
 }
 
 /*
@@ -435,7 +428,7 @@
 	ret = iwl_poll_bit(trans, CSR_RESET,
 			   CSR_RESET_REG_FLAG_MASTER_DISABLED,
 			   CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
-	if (ret < 0)
+	if (ret)
 		IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n");
 
 	IWL_DEBUG_INFO(trans, "stop master\n");
@@ -517,9 +510,6 @@
 			   CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
 			   HW_READY_TIMEOUT);
 
-	if (ret >= 0)
-		iwl_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE);
-
 	IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : "");
 	return ret;
 }
@@ -554,7 +544,7 @@
 		msleep(25);
 	}
 
-	IWL_ERR(trans, "Couldn't prepare the card\n");
+	IWL_DEBUG_INFO(trans, "got NIC after %d iterations\n", iter);
 
 	return ret;
 }
@@ -632,28 +622,14 @@
 	}
 
 	for (offset = 0; offset < section->len; offset += chunk_sz) {
-		u32 copy_size, dst_addr;
-		bool extended_addr = false;
+		u32 copy_size;
 
 		copy_size = min_t(u32, chunk_sz, section->len - offset);
-		dst_addr = section->offset + offset;
-
-		if (dst_addr >= IWL_FW_MEM_EXTENDED_START &&
-		    dst_addr <= IWL_FW_MEM_EXTENDED_END)
-			extended_addr = true;
-
-		if (extended_addr)
-			iwl_set_bits_prph(trans, LMPM_CHICK,
-					  LMPM_CHICK_EXTENDED_ADDR_SPACE);
 
 		memcpy(v_addr, (u8 *)section->data + offset, copy_size);
-		ret = iwl_pcie_load_firmware_chunk(trans, dst_addr, p_addr,
-						   copy_size);
-
-		if (extended_addr)
-			iwl_clear_bits_prph(trans, LMPM_CHICK,
-					    LMPM_CHICK_EXTENDED_ADDR_SPACE);
-
+		ret = iwl_pcie_load_firmware_chunk(trans,
+						   section->offset + offset,
+						   p_addr, copy_size);
 		if (ret) {
 			IWL_ERR(trans,
 				"Could not load the [%d] uCode section\n",
@@ -666,14 +642,14 @@
 	return ret;
 }
 
-static int iwl_pcie_load_cpu_sections_8000b(struct iwl_trans *trans,
-					    const struct fw_img *image,
-					    int cpu,
-					    int *first_ucode_section)
+static int iwl_pcie_load_cpu_secured_sections(struct iwl_trans *trans,
+					      const struct fw_img *image,
+					      int cpu,
+					      int *first_ucode_section)
 {
 	int shift_param;
-	int i, ret = 0, sec_num = 0x1;
-	u32 val, last_read_idx = 0;
+	int i, ret = 0;
+	u32 last_read_idx = 0;
 
 	if (cpu == 1) {
 		shift_param = 0;
@@ -694,16 +670,21 @@
 			break;
 		}
 
+		if (i == (*first_ucode_section) + 1)
+			/* set CPU to started */
+			iwl_set_bits_prph(trans,
+					  CSR_UCODE_LOAD_STATUS_ADDR,
+					  LMPM_CPU_HDRS_LOADING_COMPLETED
+					  << shift_param);
+
 		ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
 		if (ret)
 			return ret;
-
-		/* Notify the ucode of the loaded section number and status */
-		val = iwl_read_direct32(trans, FH_UCODE_LOAD_STATUS);
-		val = val | (sec_num << shift_param);
-		iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, val);
-		sec_num = (sec_num << 1) | 0x1;
 	}
+	/* image loading complete */
+	iwl_set_bits_prph(trans,
+			  CSR_UCODE_LOAD_STATUS_ADDR,
+			  LMPM_CPU_UCODE_LOADING_COMPLETED << shift_param);
 
 	*first_ucode_section = last_read_idx;
 
@@ -756,64 +737,6 @@
 	return 0;
 }
 
-static void iwl_pcie_apply_destination(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	const struct iwl_fw_dbg_dest_tlv *dest = trans->dbg_dest_tlv;
-	int i;
-
-	if (dest->version)
-		IWL_ERR(trans,
-			"DBG DEST version is %d - expect issues\n",
-			dest->version);
-
-	IWL_INFO(trans, "Applying debug destination %s\n",
-		 get_fw_dbg_mode_string(dest->monitor_mode));
-
-	if (dest->monitor_mode == EXTERNAL_MODE)
-		iwl_pcie_alloc_fw_monitor(trans);
-	else
-		IWL_WARN(trans, "PCI should have external buffer debug\n");
-
-	for (i = 0; i < trans->dbg_dest_reg_num; i++) {
-		u32 addr = le32_to_cpu(dest->reg_ops[i].addr);
-		u32 val = le32_to_cpu(dest->reg_ops[i].val);
-
-		switch (dest->reg_ops[i].op) {
-		case CSR_ASSIGN:
-			iwl_write32(trans, addr, val);
-			break;
-		case CSR_SETBIT:
-			iwl_set_bit(trans, addr, BIT(val));
-			break;
-		case CSR_CLEARBIT:
-			iwl_clear_bit(trans, addr, BIT(val));
-			break;
-		case PRPH_ASSIGN:
-			iwl_write_prph(trans, addr, val);
-			break;
-		case PRPH_SETBIT:
-			iwl_set_bits_prph(trans, addr, BIT(val));
-			break;
-		case PRPH_CLEARBIT:
-			iwl_clear_bits_prph(trans, addr, BIT(val));
-			break;
-		default:
-			IWL_ERR(trans, "FW debug - unknown OP %d\n",
-				dest->reg_ops[i].op);
-			break;
-		}
-	}
-
-	if (dest->monitor_mode == EXTERNAL_MODE && trans_pcie->fw_mon_size) {
-		iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
-			       trans_pcie->fw_mon_phys >> dest->base_shift);
-		iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
-			       (trans_pcie->fw_mon_phys +
-				trans_pcie->fw_mon_size) >> dest->end_shift);
-	}
-}
-
 static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
 				const struct fw_img *image)
 {
@@ -821,13 +744,42 @@
 	int ret = 0;
 	int first_ucode_section;
 
-	IWL_DEBUG_FW(trans, "working with %s CPU\n",
+	IWL_DEBUG_FW(trans,
+		     "working with %s image\n",
+		     image->is_secure ? "Secured" : "Non Secured");
+	IWL_DEBUG_FW(trans,
+		     "working with %s CPU\n",
 		     image->is_dual_cpus ? "Dual" : "Single");
 
-	/* load to FW the binary non secured sections of CPU1 */
-	ret = iwl_pcie_load_cpu_sections(trans, image, 1, &first_ucode_section);
-	if (ret)
-		return ret;
+	/* configure the ucode to be ready to get the secured image */
+	if (image->is_secure) {
+		/* set secure boot inspector addresses */
+		iwl_write_prph(trans,
+			       LMPM_SECURE_INSPECTOR_CODE_ADDR,
+			       LMPM_SECURE_INSPECTOR_CODE_MEM_SPACE);
+
+		iwl_write_prph(trans,
+			       LMPM_SECURE_INSPECTOR_DATA_ADDR,
+			       LMPM_SECURE_INSPECTOR_DATA_MEM_SPACE);
+
+		/* set CPU1 header address */
+		iwl_write_prph(trans,
+			       LMPM_SECURE_UCODE_LOAD_CPU1_HDR_ADDR,
+			       LMPM_SECURE_CPU1_HDR_MEM_SPACE);
+
+		/* load to FW the binary Secured sections of CPU1 */
+		ret = iwl_pcie_load_cpu_secured_sections(trans, image, 1,
+							 &first_ucode_section);
+		if (ret)
+			return ret;
+
+	} else {
+		/* load to FW the binary Non secured sections of CPU1 */
+		ret = iwl_pcie_load_cpu_sections(trans, image, 1,
+						 &first_ucode_section);
+		if (ret)
+			return ret;
+	}
 
 	if (image->is_dual_cpus) {
 		/* set CPU2 header address */
@@ -836,8 +788,13 @@
 			       LMPM_SECURE_CPU2_HDR_MEM_SPACE);
 
 		/* load to FW the binary sections of CPU2 */
-		ret = iwl_pcie_load_cpu_sections(trans, image, 2,
-						 &first_ucode_section);
+		if (image->is_secure)
+			ret = iwl_pcie_load_cpu_secured_sections(
+							trans, image, 2,
+							&first_ucode_section);
+		else
+			ret = iwl_pcie_load_cpu_sections(trans, image, 2,
+							 &first_ucode_section);
 		if (ret)
 			return ret;
 	}
@@ -854,8 +811,6 @@
 				       (trans_pcie->fw_mon_phys +
 					trans_pcie->fw_mon_size) >> 4);
 		}
-	} else if (trans->dbg_dest_tlv) {
-		iwl_pcie_apply_destination(trans);
 	}
 
 	/* release CPU reset */
@@ -864,50 +819,18 @@
 	else
 		iwl_write32(trans, CSR_RESET, 0);
 
-	return 0;
-}
+	if (image->is_secure) {
+		/* wait for image verification to complete  */
+		ret = iwl_poll_prph_bit(trans,
+					LMPM_SECURE_BOOT_CPU1_STATUS_ADDR,
+					LMPM_SECURE_BOOT_STATUS_SUCCESS,
+					LMPM_SECURE_BOOT_STATUS_SUCCESS,
+					LMPM_SECURE_TIME_OUT);
 
-static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
-					   const struct fw_img *image)
-{
-	int ret = 0;
-	int first_ucode_section;
-	u32 reg;
-
-	IWL_DEBUG_FW(trans, "working with %s CPU\n",
-		     image->is_dual_cpus ? "Dual" : "Single");
-
-	/* configure the ucode to be ready to get the secured image */
-	/* release CPU reset */
-	iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
-
-	/* load to FW the binary Secured sections of CPU1 */
-	ret = iwl_pcie_load_cpu_sections_8000b(trans, image, 1,
-					       &first_ucode_section);
-	if (ret)
-		return ret;
-
-	/* load to FW the binary sections of CPU2 */
-	ret = iwl_pcie_load_cpu_sections_8000b(trans, image, 2,
-					       &first_ucode_section);
-	if (ret)
-		return ret;
-
-	/* Notify FW loading is done */
-	iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFFFFFF);
-
-	/* wait for image verification to complete  */
-	ret = iwl_poll_prph_bit(trans, LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0,
-				LMPM_SECURE_BOOT_STATUS_SUCCESS,
-				LMPM_SECURE_BOOT_STATUS_SUCCESS,
-				LMPM_SECURE_TIME_OUT);
-	if (ret < 0) {
-		reg = iwl_read_prph(trans,
-				    LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0);
-
-		IWL_ERR(trans, "Timeout on secure boot process, reg = %x\n",
-			reg);
-		return ret;
+		if (ret < 0) {
+			IWL_ERR(trans, "Time out on secure boot process\n");
+			return ret;
+		}
 	}
 
 	return 0;
@@ -959,11 +882,7 @@
 	iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 
 	/* Load the given image to the HW */
-	if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) &&
-	    (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_B_STEP))
-		return iwl_pcie_load_given_ucode_8000b(trans, fw);
-	else
-		return iwl_pcie_load_given_ucode(trans, fw);
+	return iwl_pcie_load_given_ucode(trans, fw);
 }
 
 static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
@@ -994,8 +913,7 @@
 	 * restart. So don't process again if the device is
 	 * already dead.
 	 */
-	if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
-		IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n");
+	if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
 		iwl_pcie_tx_stop(trans);
 		iwl_pcie_rx_stop(trans);
 
@@ -1020,12 +938,12 @@
 	spin_unlock(&trans_pcie->irq_lock);
 
 	/* stop and reset the on-board processor */
-	iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-	udelay(20);
+	iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 
 	/* clear all status bits */
 	clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
 	clear_bit(STATUS_INT_ENABLED, &trans->status);
+	clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
 	clear_bit(STATUS_TPOWER_PMI, &trans->status);
 	clear_bit(STATUS_RFKILL, &trans->status);
 
@@ -1054,9 +972,6 @@
 		clear_bit(STATUS_RFKILL, &trans->status);
 	if (hw_rfkill != was_hw_rfkill)
 		iwl_trans_pcie_rf_kill(trans, hw_rfkill);
-
-	/* re-take ownership to prevent other users from stealing the deivce */
-	iwl_pcie_prepare_card_hw(trans);
 }
 
 void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state)
@@ -1106,6 +1021,14 @@
 		return 0;
 	}
 
+	iwl_pcie_set_pwr(trans, false);
+
+	val = iwl_read32(trans, CSR_RESET);
+	if (val & CSR_RESET_REG_FLAG_NEVO_RESET) {
+		*status = IWL_D3_STATUS_RESET;
+		return 0;
+	}
+
 	/*
 	 * Also enables interrupts - none will happen as the device doesn't
 	 * know we're waking it up, only when the opmode actually tells it
@@ -1116,20 +1039,15 @@
 	iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 	iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
 
-	if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
-		udelay(2);
-
 	ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
 			   CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
 			   CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
 			   25000);
-	if (ret < 0) {
+	if (ret) {
 		IWL_ERR(trans, "Failed to resume the device (mac ready)\n");
 		return ret;
 	}
 
-	iwl_pcie_set_pwr(trans, false);
-
 	iwl_trans_pcie_tx_reset(trans);
 
 	ret = iwl_pcie_rx_init(trans);
@@ -1138,12 +1056,7 @@
 		return ret;
 	}
 
-	val = iwl_read32(trans, CSR_RESET);
-	if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
-		*status = IWL_D3_STATUS_RESET;
-	else
-		*status = IWL_D3_STATUS_ALIVE;
-
+	*status = IWL_D3_STATUS_ALIVE;
 	return 0;
 }
 
@@ -1321,8 +1234,6 @@
 	/* this bit wakes up the NIC */
 	__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
 				 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-	if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
-		udelay(2);
 
 	/*
 	 * These bits say the device is running, and should keep running for
@@ -1854,13 +1765,6 @@
 	IWL_ERR(trans, "failed to create the trans debugfs entry\n");
 	return -ENOMEM;
 }
-#else
-static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
-					 struct dentry *dir)
-{
-	return 0;
-}
-#endif /*CPTCFG_IWLWIFI_DEBUGFS */
 
 static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
 {
@@ -1988,7 +1892,8 @@
 		int reg;
 		__le32 *val;
 
-		prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk;
+		prph_len += sizeof(*data) + sizeof(*prph) +
+			num_bytes_in_chunk;
 
 		(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
 		(*data)->len = cpu_to_le32(sizeof(*prph) +
@@ -2031,31 +1936,6 @@
 	return csr_len;
 }
 
-static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
-				       struct iwl_fw_error_dump_data **data)
-{
-	u32 fh_regs_len = FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND;
-	unsigned long flags;
-	__le32 *val;
-	int i;
-
-	if (!iwl_trans_grab_nic_access(trans, false, &flags))
-		return 0;
-
-	(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FH_REGS);
-	(*data)->len = cpu_to_le32(fh_regs_len);
-	val = (void *)(*data)->data;
-
-	for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND; i += sizeof(u32))
-		*val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
-
-	iwl_trans_release_nic_access(trans, &flags);
-
-	*data = iwl_fw_error_next_data(*data);
-
-	return sizeof(**data) + fh_regs_len;
-}
-
 static
 struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
 {
@@ -2065,7 +1945,6 @@
 	struct iwl_fw_error_dump_txcmd *txcmd;
 	struct iwl_trans_dump_data *dump_data;
 	u32 len;
-	u32 monitor_len;
 	int i, ptr;
 
 	/* transport dump header */
@@ -2088,34 +1967,10 @@
 			num_bytes_in_chunk;
 	}
 
-	/* FH registers */
-	len += sizeof(*data) + (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
-
 	/* FW monitor */
-	if (trans_pcie->fw_mon_page) {
+	if (trans_pcie->fw_mon_page)
 		len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
-		       trans_pcie->fw_mon_size;
-		monitor_len = trans_pcie->fw_mon_size;
-	} else if (trans->dbg_dest_tlv) {
-		u32 base, end;
-
-		base = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
-		end = le32_to_cpu(trans->dbg_dest_tlv->end_reg);
-
-		base = iwl_read_prph(trans, base) <<
-		       trans->dbg_dest_tlv->base_shift;
-		end = iwl_read_prph(trans, end) <<
-		      trans->dbg_dest_tlv->end_shift;
-
-		/* Make "end" point to the actual end */
-		if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
-			end += (1 << trans->dbg_dest_tlv->end_shift);
-		monitor_len = end - base;
-		len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
-		       monitor_len;
-	} else {
-		monitor_len = 0;
-	}
+			trans_pcie->fw_mon_size;
 
 	dump_data = vzalloc(len);
 	if (!dump_data)
@@ -2152,77 +2007,49 @@
 
 	len += iwl_trans_pcie_dump_prph(trans, &data);
 	len += iwl_trans_pcie_dump_csr(trans, &data);
-	len += iwl_trans_pcie_fh_regs_dump(trans, &data);
 	/* data is already pointing to the next section */
 
-	if ((trans_pcie->fw_mon_page &&
-	     trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) ||
-	    trans->dbg_dest_tlv) {
+	if (trans_pcie->fw_mon_page) {
 		struct iwl_fw_error_dump_fw_mon *fw_mon_data;
-		u32 base, write_ptr, wrap_cnt;
-
-		/* If there was a dest TLV - use the values from there */
-		if (trans->dbg_dest_tlv) {
-			write_ptr =
-				le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg);
-			wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count);
-			base = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
-		} else {
-			base = MON_BUFF_BASE_ADDR;
-			write_ptr = MON_BUFF_WRPTR;
-			wrap_cnt = MON_BUFF_CYCLE_CNT;
-		}
 
 		data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
+		data->len = cpu_to_le32(trans_pcie->fw_mon_size +
+					sizeof(*fw_mon_data));
 		fw_mon_data = (void *)data->data;
 		fw_mon_data->fw_mon_wr_ptr =
-			cpu_to_le32(iwl_read_prph(trans, write_ptr));
+			cpu_to_le32(iwl_read_prph(trans, MON_BUFF_WRPTR));
 		fw_mon_data->fw_mon_cycle_cnt =
-			cpu_to_le32(iwl_read_prph(trans, wrap_cnt));
+			cpu_to_le32(iwl_read_prph(trans, MON_BUFF_CYCLE_CNT));
 		fw_mon_data->fw_mon_base_ptr =
-			cpu_to_le32(iwl_read_prph(trans, base));
+			cpu_to_le32(iwl_read_prph(trans, MON_BUFF_BASE_ADDR));
 
-		len += sizeof(*data) + sizeof(*fw_mon_data);
-		if (trans_pcie->fw_mon_page) {
-			data->len = cpu_to_le32(trans_pcie->fw_mon_size +
-						sizeof(*fw_mon_data));
+		/*
+		 * The firmware is now asserted, it won't write anything to
+		 * the buffer. CPU can take ownership to fetch the data.
+		 * The buffer will be handed back to the device before the
+		 * firmware will be restarted.
+		 */
+		dma_sync_single_for_cpu(trans->dev, trans_pcie->fw_mon_phys,
+					trans_pcie->fw_mon_size,
+					DMA_FROM_DEVICE);
+		memcpy(fw_mon_data->data, page_address(trans_pcie->fw_mon_page),
+		       trans_pcie->fw_mon_size);
 
-			/*
-			 * The firmware is now asserted, it won't write anything
-			 * to the buffer. CPU can take ownership to fetch the
-			 * data. The buffer will be handed back to the device
-			 * before the firmware will be restarted.
-			 */
-			dma_sync_single_for_cpu(trans->dev,
-						trans_pcie->fw_mon_phys,
-						trans_pcie->fw_mon_size,
-						DMA_FROM_DEVICE);
-			memcpy(fw_mon_data->data,
-			       page_address(trans_pcie->fw_mon_page),
-			       trans_pcie->fw_mon_size);
-
-			len += trans_pcie->fw_mon_size;
-		} else {
-			/* If we are here then the buffer is internal */
-
-			/*
-			 * Update pointers to reflect actual values after
-			 * shifting
-			 */
-			base = iwl_read_prph(trans, base) <<
-			       trans->dbg_dest_tlv->base_shift;
-			iwl_trans_read_mem(trans, base, fw_mon_data->data,
-					   monitor_len / sizeof(u32));
-			data->len = cpu_to_le32(sizeof(*fw_mon_data) +
-						monitor_len);
-			len += monitor_len;
-		}
+		len += sizeof(*data) + sizeof(*fw_mon_data) +
+			trans_pcie->fw_mon_size;
 	}
 
 	dump_data->len = len;
 
 	return dump_data;
 }
+#else
+static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
+					 struct dentry *dir)
+{
+	return 0;
+}
+#endif /*CPTCFG_IWLWIFI_DEBUGFS */
 
 static const struct iwl_trans_ops trans_ops_pcie = {
 	.start_hw = iwl_trans_pcie_start_hw,
@@ -2259,7 +2086,9 @@
 	.release_nic_access = iwl_trans_pcie_release_nic_access,
 	.set_bits_mask = iwl_trans_pcie_set_bits_mask,
 
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
 	.dump_data = iwl_trans_pcie_dump_data,
+#endif
 };
 
 struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 8a6c7a0..eb8e298 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -989,65 +989,6 @@
 	spin_unlock_bh(&txq->lock);
 }
 
-static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	int ret;
-
-	lockdep_assert_held(&trans_pcie->reg_lock);
-
-	if (trans_pcie->cmd_in_flight)
-		return 0;
-
-	trans_pcie->cmd_in_flight = true;
-
-	/*
-	 * wake up the NIC to make sure that the firmware will see the host
-	 * command - we will let the NIC sleep once all the host commands
-	 * returned. This needs to be done only on NICs that have
-	 * apmg_wake_up_wa set.
-	 */
-	if (trans->cfg->base_params->apmg_wake_up_wa) {
-		__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
-					 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-		if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
-			udelay(2);
-
-		ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
-				   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
-				   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
-				    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
-				   15000);
-		if (ret < 0) {
-			__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
-					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-			trans_pcie->cmd_in_flight = false;
-			IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
-			return -EIO;
-		}
-	}
-
-	return 0;
-}
-
-static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-	lockdep_assert_held(&trans_pcie->reg_lock);
-
-	if (WARN_ON(!trans_pcie->cmd_in_flight))
-		return 0;
-
-	trans_pcie->cmd_in_flight = false;
-
-	if (trans->cfg->base_params->apmg_wake_up_wa)
-		__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
-					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
-	return 0;
-}
-
 /*
  * iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd
  *
@@ -1083,9 +1024,14 @@
 		}
 	}
 
-	if (q->read_ptr == q->write_ptr) {
+	if (trans->cfg->base_params->apmg_wake_up_wa &&
+	    q->read_ptr == q->write_ptr) {
 		spin_lock_irqsave(&trans_pcie->reg_lock, flags);
-		iwl_pcie_clear_cmd_in_flight(trans);
+		WARN_ON(!trans_pcie->cmd_in_flight);
+		trans_pcie->cmd_in_flight = false;
+		__iwl_trans_pcie_clear_bit(trans,
+					   CSR_GP_CNTRL,
+					   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 		spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
 	}
 
@@ -1473,11 +1419,32 @@
 		mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
 
 	spin_lock_irqsave(&trans_pcie->reg_lock, flags);
-	ret = iwl_pcie_set_cmd_in_flight(trans);
-	if (ret < 0) {
-		idx = ret;
-		spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
-		goto out;
+
+	/*
+	 * wake up the NIC to make sure that the firmware will see the host
+	 * command - we will let the NIC sleep once all the host commands
+	 * returned. This needs to be done only on NICs that have
+	 * apmg_wake_up_wa set.
+	 */
+	if (trans->cfg->base_params->apmg_wake_up_wa &&
+	    !trans_pcie->cmd_in_flight) {
+		trans_pcie->cmd_in_flight = true;
+		__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
+					 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+		ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
+				   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+				   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+				    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
+				   15000);
+		if (ret < 0) {
+			__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
+				   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+			spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
+			trans_pcie->cmd_in_flight = false;
+			IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
+			idx = -EIO;
+			goto out;
+		}
 	}
 
 	/* Increment and update queue's write index */
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c6755b8..a3f2e06 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -395,6 +395,7 @@
 static struct platform_driver mac80211_hwsim_driver = {
 	.driver = {
 		.name = "mac80211_hwsim",
+		.owner = THIS_MODULE,
 	},
 };
 
@@ -411,11 +412,6 @@
 	struct mac_address addresses[2];
 	int channels, idx;
 	bool use_chanctx;
-	bool destroy_on_close;
-	struct work_struct destroy_work;
-	u32 portid;
-	char alpha2[2];
-	const struct ieee80211_regdomain *regd;
 
 	struct ieee80211_channel *tmp_chan;
 	struct delayed_work roc_done;
@@ -423,7 +419,6 @@
 	struct cfg80211_scan_request *hw_scan_request;
 	struct ieee80211_vif *hw_scan_vif;
 	int scan_chan_idx;
-	u8 scan_addr[ETH_ALEN];
 
 	struct ieee80211_channel *channel;
 	u64 beacon_int	/* beacon interval in us */;
@@ -441,7 +436,7 @@
 	/*
 	 * Only radios in the same group can communicate together (the
 	 * channel has to match too). Each bit represents a group. A
-	 * radio can be in more than one group.
+	 * radio can be in more then one group.
 	 */
 	u64 group;
 
@@ -452,14 +447,6 @@
 	s64 bcn_delta;
 	/* absolute beacon transmission time. Used to cover up "tx" delay. */
 	u64 abs_bcn_ts;
-
-	/* Stats */
-	u64 tx_pkts;
-	u64 rx_pkts;
-	u64 tx_bytes;
-	u64 rx_bytes;
-	u64 tx_dropped;
-	u64 tx_failed;
 };
 
 
@@ -489,14 +476,6 @@
 	.maxattr = HWSIM_ATTR_MAX,
 };
 
-enum hwsim_multicast_groups {
-	HWSIM_MCGRP_CONFIG,
-};
-
-static __genl_const struct genl_multicast_group hwsim_mcgrps[] = {
-	[HWSIM_MCGRP_CONFIG] = { .name = "config", },
-};
-
 /* MAC80211_HWSIM netlink policy */
 
 static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
@@ -517,10 +496,6 @@
 	[HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 },
 	[HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG },
 	[HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG },
-	[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG },
-	[HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING },
-	[HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG },
-	[HWSIM_ATTR_FREQ] = { .type = NLA_U32 },
 };
 
 static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
@@ -832,9 +807,6 @@
 		.ret = false,
 	};
 
-	if (data->scanning && memcmp(addr, data->scan_addr, ETH_ALEN) == 0)
-		return true;
-
 	memcpy(md.addr, addr, ETH_ALEN);
 
 	ieee80211_iterate_active_interfaces_atomic(data->hw,
@@ -889,10 +861,8 @@
 	/* If the queue contains MAX_QUEUE skb's drop some */
 	if (skb_queue_len(&data->pending) >= MAX_QUEUE) {
 		/* Droping until WARN_QUEUE level */
-		while (skb_queue_len(&data->pending) >= WARN_QUEUE) {
-			ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
-			data->tx_dropped++;
-		}
+		while (skb_queue_len(&data->pending) >= WARN_QUEUE)
+			skb_dequeue(&data->pending);
 	}
 
 	skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -926,9 +896,6 @@
 	if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags))
 		goto nla_put_failure;
 
-	if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq))
-		goto nla_put_failure;
-
 	/* We get the tx control (rate and retries) info*/
 
 	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
@@ -950,14 +917,10 @@
 
 	/* Enqueue the packet */
 	skb_queue_tail(&data->pending, my_skb);
-	data->tx_pkts++;
-	data->tx_bytes += my_skb->len;
 	return;
 
 nla_put_failure:
 	printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
-	ieee80211_free_txskb(hw, my_skb);
-	data->tx_failed++;
 }
 
 static bool hwsim_chans_compat(struct ieee80211_channel *c1,
@@ -989,53 +952,6 @@
 	data->receive = true;
 }
 
-static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb)
-{
-	/*
-	 * To enable this code, #define the HWSIM_RADIOTAP_OUI,
-	 * e.g. like this:
-	 * #define HWSIM_RADIOTAP_OUI "\x02\x00\x00"
-	 * (but you should use a valid OUI, not that)
-	 *
-	 * If anyone wants to 'donate' a radiotap OUI/subns code
-	 * please send a patch removing this #ifdef and changing
-	 * the values accordingly.
-	 */
-#ifdef HWSIM_RADIOTAP_OUI
-	struct ieee80211_vendor_radiotap *rtap;
-
-	/*
-	 * Note that this code requires the headroom in the SKB
-	 * that was allocated earlier.
-	 */
-	rtap = (void *)skb_push(skb, sizeof(*rtap) + 8 + 4);
-	rtap->oui[0] = HWSIM_RADIOTAP_OUI[0];
-	rtap->oui[1] = HWSIM_RADIOTAP_OUI[1];
-	rtap->oui[2] = HWSIM_RADIOTAP_OUI[2];
-	rtap->subns = 127;
-
-	/*
-	 * Radiotap vendor namespaces can (and should) also be
-	 * split into fields by using the standard radiotap
-	 * presence bitmap mechanism. Use just BIT(0) here for
-	 * the presence bitmap.
-	 */
-	rtap->present = BIT(0);
-	/* We have 8 bytes of (dummy) data */
-	rtap->len = 8;
-	/* For testing, also require it to be aligned */
-	rtap->align = 8;
-	/* And also test that padding works, 4 bytes */
-	rtap->pad = 4;
-	/* push the data */
-	memcpy(rtap->data, "ABCDEFGH", 8);
-	/* make sure to clear padding, mac80211 doesn't */
-	memset(rtap->data + 8, 0, 4);
-
-	IEEE80211_SKB_RXCB(skb)->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
-#endif
-}
-
 static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 					  struct sk_buff *skb,
 					  struct ieee80211_channel *chan)
@@ -1150,11 +1066,6 @@
 		rx_status.mactime = now + data2->tsf_offset;
 
 		memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
-
-		mac80211_hwsim_add_vendor_rtap(nskb);
-
-		data2->rx_pkts++;
-		data2->rx_bytes += nskb->len;
 		ieee80211_rx_irqsafe(data2->hw, nskb);
 	}
 	spin_unlock(&hwsim_radio_lock);
@@ -1222,8 +1133,6 @@
 		return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
 
 	/* NO wmediumd detected, perfect medium simulation */
-	data->tx_pkts++;
-	data->tx_bytes += skb->len;
 	ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel);
 
 	if (ack && skb->len >= 16) {
@@ -1807,7 +1716,7 @@
 			struct sk_buff *probe;
 
 			probe = ieee80211_probereq_get(hwsim->hw,
-						       hwsim->scan_addr,
+						       hwsim->hw_scan_vif,
 						       req->ssids[i].ssid,
 						       req->ssids[i].ssid_len,
 						       req->ie_len);
@@ -1845,12 +1754,6 @@
 	hwsim->hw_scan_request = req;
 	hwsim->hw_scan_vif = vif;
 	hwsim->scan_chan_idx = 0;
-	if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
-		get_random_mask_addr(hwsim->scan_addr,
-				     hw_req->req.mac_addr,
-				     hw_req->req.mac_addr_mask);
-	else
-		memcpy(hwsim->scan_addr, vif->addr, ETH_ALEN);
 	mutex_unlock(&hwsim->mutex);
 
 	wiphy_debug(hw->wiphy, "hwsim hw_scan request\n");
@@ -1877,9 +1780,7 @@
 	mutex_unlock(&hwsim->mutex);
 }
 
-static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif,
-				   const u8 *mac_addr)
+static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw)
 {
 	struct mac80211_hwsim_data *hwsim = hw->priv;
 
@@ -1891,16 +1792,13 @@
 	}
 
 	printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n");
-
-	memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN);
 	hwsim->scanning = true;
 
 out:
 	mutex_unlock(&hwsim->mutex);
 }
 
-static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw,
-					    struct ieee80211_vif *vif)
+static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct mac80211_hwsim_data *hwsim = hw->priv;
 
@@ -1908,7 +1806,6 @@
 
 	printk(KERN_DEBUG "hwsim sw_scan_complete\n");
 	hwsim->scanning = false;
-	memset(hwsim->scan_addr, 0, ETH_ALEN);
 
 	mutex_unlock(&hwsim->mutex);
 }
@@ -2019,57 +1916,6 @@
 	hwsim_check_chanctx_magic(ctx);
 }
 
-static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = {
-	"tx_pkts_nic",
-	"tx_bytes_nic",
-	"rx_pkts_nic",
-	"rx_bytes_nic",
-	"d_tx_dropped",
-	"d_tx_failed",
-	"d_ps_mode",
-	"d_group",
-	"d_tx_power",
-};
-
-#define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats)
-
-static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw,
-					  struct ieee80211_vif *vif,
-					  u32 sset, u8 *data)
-{
-	if (sset == ETH_SS_STATS)
-		memcpy(data, *mac80211_hwsim_gstrings_stats,
-		       sizeof(mac80211_hwsim_gstrings_stats));
-}
-
-static int mac80211_hwsim_get_et_sset_count(struct ieee80211_hw *hw,
-					    struct ieee80211_vif *vif, int sset)
-{
-	if (sset == ETH_SS_STATS)
-		return MAC80211_HWSIM_SSTATS_LEN;
-	return 0;
-}
-
-static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw,
-					struct ieee80211_vif *vif,
-					struct ethtool_stats *stats, u64 *data)
-{
-	struct mac80211_hwsim_data *ar = hw->priv;
-	int i = 0;
-
-	data[i++] = ar->tx_pkts;
-	data[i++] = ar->tx_bytes;
-	data[i++] = ar->rx_pkts;
-	data[i++] = ar->rx_bytes;
-	data[i++] = ar->tx_dropped;
-	data[i++] = ar->tx_failed;
-	data[i++] = ar->ps;
-	data[i++] = ar->group;
-	data[i++] = ar->power_level;
-
-	WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
-}
-
 static const struct ieee80211_ops mac80211_hwsim_ops = {
 	.tx = mac80211_hwsim_tx,
 	.start = mac80211_hwsim_start,
@@ -2093,131 +1939,14 @@
 	.flush = mac80211_hwsim_flush,
 	.get_tsf = mac80211_hwsim_get_tsf,
 	.set_tsf = mac80211_hwsim_set_tsf,
-	.get_et_sset_count = mac80211_hwsim_get_et_sset_count,
-	.get_et_stats = mac80211_hwsim_get_et_stats,
-	.get_et_strings = mac80211_hwsim_get_et_strings,
 };
 
 static struct ieee80211_ops mac80211_hwsim_mchan_ops;
 
-struct hwsim_new_radio_params {
-	unsigned int channels;
-	const char *reg_alpha2;
-	const struct ieee80211_regdomain *regd;
-	bool reg_strict;
-	bool p2p_device;
-	bool use_chanctx;
-	bool destroy_on_close;
-	const char *hwname;
-	bool no_vif;
-};
-
-static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
-				   struct genl_info *info)
-{
-	if (info)
-		genl_notify(&hwsim_genl_family, mcast_skb,
-			    genl_info_net(info), genl_info_snd_portid(info),
-			    HWSIM_MCGRP_CONFIG, info->nlhdr, GFP_KERNEL);
-	else
-		genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0,
-				  HWSIM_MCGRP_CONFIG, GFP_KERNEL);
-}
-
-static int append_radio_msg(struct sk_buff *skb, int id,
-			    struct hwsim_new_radio_params *param)
-{
-	int ret;
-
-	ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id);
-	if (ret < 0)
-		return ret;
-
-	if (param->channels) {
-		ret = nla_put_u32(skb, HWSIM_ATTR_CHANNELS, param->channels);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (param->reg_alpha2) {
-		ret = nla_put(skb, HWSIM_ATTR_REG_HINT_ALPHA2, 2,
-			      param->reg_alpha2);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (param->regd) {
-		int i;
-
-		for (i = 0; hwsim_world_regdom_custom[i] != param->regd &&
-		     i < ARRAY_SIZE(hwsim_world_regdom_custom); i++)
-			;
-
-		if (i < ARRAY_SIZE(hwsim_world_regdom_custom)) {
-			ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i);
-			if (ret < 0)
-				return ret;
-		}
-	}
-
-	if (param->reg_strict) {
-		ret = nla_put_flag(skb, HWSIM_ATTR_REG_STRICT_REG);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (param->p2p_device) {
-		ret = nla_put_flag(skb, HWSIM_ATTR_SUPPORT_P2P_DEVICE);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (param->use_chanctx) {
-		ret = nla_put_flag(skb, HWSIM_ATTR_USE_CHANCTX);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (param->hwname) {
-		ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME,
-			      strlen(param->hwname), param->hwname);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-static void hwsim_mcast_new_radio(int id, struct genl_info *info,
-				  struct hwsim_new_radio_params *param)
-{
-	struct sk_buff *mcast_skb;
-	void *data;
-
-	mcast_skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!mcast_skb)
-		return;
-
-	data = genlmsg_put(mcast_skb, 0, 0, &hwsim_genl_family, 0,
-			   HWSIM_CMD_NEW_RADIO);
-	if (!data)
-		goto out_err;
-
-	if (append_radio_msg(mcast_skb, id, param) < 0)
-		goto out_err;
-
-	genlmsg_end(mcast_skb, data);
-
-	hwsim_mcast_config_msg(mcast_skb, info);
-	return;
-
-out_err:
-	genlmsg_cancel(mcast_skb, data);
-	nlmsg_free(mcast_skb);
-}
-
-static int mac80211_hwsim_new_radio(struct genl_info *info,
-				    struct hwsim_new_radio_params *param)
+static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
+				       const struct ieee80211_regdomain *regd,
+				       bool reg_strict, bool p2p_device,
+				       bool use_chanctx)
 {
 	int err;
 	u8 addr[ETH_ALEN];
@@ -2227,16 +1956,16 @@
 	const struct ieee80211_ops *ops = &mac80211_hwsim_ops;
 	int idx;
 
-	if (WARN_ON(param->channels > 1 && !param->use_chanctx))
+	if (WARN_ON(channels > 1 && !use_chanctx))
 		return -EINVAL;
 
 	spin_lock_bh(&hwsim_radio_lock);
 	idx = hwsim_radio_idx++;
 	spin_unlock_bh(&hwsim_radio_lock);
 
-	if (param->use_chanctx)
+	if (use_chanctx)
 		ops = &mac80211_hwsim_mchan_ops;
-	hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname);
+	hw = ieee80211_alloc_hw(sizeof(*data), ops);
 	if (!hw) {
 		printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n");
 		err = -ENOMEM;
@@ -2258,7 +1987,7 @@
 	if (err != 0) {
 		printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n",
 		       err);
-		goto failed_bind;
+		goto failed_hw;
 	}
 
 	skb_queue_head_init(&data->pending);
@@ -2274,12 +2003,9 @@
 	hw->wiphy->n_addresses = 2;
 	hw->wiphy->addresses = data->addresses;
 
-	data->channels = param->channels;
-	data->use_chanctx = param->use_chanctx;
+	data->channels = channels;
+	data->use_chanctx = use_chanctx;
 	data->idx = idx;
-	data->destroy_on_close = param->destroy_on_close;
-	if (info)
-		data->portid = genl_info_snd_portid(info);
 
 	if (data->use_chanctx) {
 		hw->wiphy->max_scan_ssids = 255;
@@ -2288,12 +2014,12 @@
 		/* For channels > 1 DFS is not allowed */
 		hw->wiphy->n_iface_combinations = 1;
 		hw->wiphy->iface_combinations = &data->if_combination;
-		if (param->p2p_device)
+		if (p2p_device)
 			data->if_combination = hwsim_if_comb_p2p_dev[0];
 		else
 			data->if_combination = hwsim_if_comb[0];
 		data->if_combination.num_different_channels = data->channels;
-	} else if (param->p2p_device) {
+	} else if (p2p_device) {
 		hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev;
 		hw->wiphy->n_iface_combinations =
 			ARRAY_SIZE(hwsim_if_comb_p2p_dev);
@@ -2314,7 +2040,7 @@
 				     BIT(NL80211_IFTYPE_ADHOC) |
 				     BIT(NL80211_IFTYPE_MESH_POINT);
 
-	if (param->p2p_device)
+	if (p2p_device)
 		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
 
 	hw->flags = IEEE80211_HW_MFP_CAPABLE |
@@ -2334,8 +2060,7 @@
 	hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR |
 			       NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
 			       NL80211_FEATURE_STATIC_SMPS |
-			       NL80211_FEATURE_DYNAMIC_SMPS |
-			       NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+			       NL80211_FEATURE_DYNAMIC_SMPS;
 
 	/* ask mac80211 to reserve space for magic */
 	hw->vif_data_size = sizeof(struct hwsim_vif_priv);
@@ -2370,7 +2095,6 @@
 		sband->ht_cap.ht_supported = true;
 		sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
 				    IEEE80211_HT_CAP_GRN_FLD |
-				    IEEE80211_HT_CAP_SGI_20 |
 				    IEEE80211_HT_CAP_SGI_40 |
 				    IEEE80211_HT_CAP_DSSSCCK40;
 		sband->ht_cap.ampdu_factor = 0x3;
@@ -2387,6 +2111,7 @@
 		sband->vht_cap.cap =
 			IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
 			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
+			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
 			IEEE80211_VHT_CAP_RXLDPC |
 			IEEE80211_VHT_CAP_SHORT_GI_80 |
 			IEEE80211_VHT_CAP_SHORT_GI_160 |
@@ -2417,19 +2142,15 @@
 	hw->max_rates = 4;
 	hw->max_rate_tries = 11;
 
-	if (param->reg_strict)
+	if (reg_strict)
 		hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
-	if (param->regd) {
-		data->regd = param->regd;
+	if (regd) {
 		hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
-		wiphy_apply_custom_regulatory(hw->wiphy, param->regd);
+		wiphy_apply_custom_regulatory(hw->wiphy, regd);
 		/* give the regulatory workqueue a chance to run */
 		schedule_timeout_interruptible(1);
 	}
 
-	if (param->no_vif)
-		hw->flags |= IEEE80211_HW_NO_AUTO_VIF;
-
 	err = ieee80211_register_hw(hw);
 	if (err < 0) {
 		printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n",
@@ -2439,11 +2160,8 @@
 
 	wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr);
 
-	if (param->reg_alpha2) {
-		data->alpha2[0] = param->reg_alpha2[0];
-		data->alpha2[1] = param->reg_alpha2[1];
-		regulatory_hint(hw->wiphy, param->reg_alpha2);
-	}
+	if (reg_alpha2)
+		regulatory_hint(hw->wiphy, reg_alpha2);
 
 	data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir);
 	debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps);
@@ -2462,14 +2180,9 @@
 	list_add_tail(&data->list, &hwsim_radios);
 	spin_unlock_bh(&hwsim_radio_lock);
 
-	if (idx > 0)
-		hwsim_mcast_new_radio(idx, info, param);
-
 	return idx;
 
 failed_hw:
-	device_release_driver(data->dev);
-failed_bind:
 	device_unregister(data->dev);
 failed_drvdata:
 	ieee80211_free_hw(hw);
@@ -2477,46 +2190,8 @@
 	return err;
 }
 
-static void hwsim_mcast_del_radio(int id, const char *hwname,
-				  struct genl_info *info)
+static void mac80211_hwsim_destroy_radio(struct mac80211_hwsim_data *data)
 {
-	struct sk_buff *skb;
-	void *data;
-	int ret;
-
-	skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!skb)
-		return;
-
-	data = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
-			   HWSIM_CMD_DEL_RADIO);
-	if (!data)
-		goto error;
-
-	ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id);
-	if (ret < 0)
-		goto error;
-
-	ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, strlen(hwname),
-		      hwname);
-	if (ret < 0)
-		goto error;
-
-	genlmsg_end(skb, data);
-
-	hwsim_mcast_config_msg(skb, info);
-
-	return;
-
-error:
-	nlmsg_free(skb);
-}
-
-static void mac80211_hwsim_del_radio(struct mac80211_hwsim_data *data,
-				     const char *hwname,
-				     struct genl_info *info)
-{
-	hwsim_mcast_del_radio(data->idx, hwname, info);
 	debugfs_remove_recursive(data->debugfs);
 	ieee80211_unregister_hw(data->hw);
 	device_release_driver(data->dev);
@@ -2524,46 +2199,6 @@
 	ieee80211_free_hw(data->hw);
 }
 
-static int mac80211_hwsim_get_radio(struct sk_buff *skb,
-				    struct mac80211_hwsim_data *data,
-				    u32 portid, u32 seq,
-				    struct netlink_callback *cb, int flags)
-{
-	void *hdr;
-	struct hwsim_new_radio_params param = { };
-	int res = -EMSGSIZE;
-
-	hdr = genlmsg_put(skb, portid, seq, &hwsim_genl_family, flags,
-			  HWSIM_CMD_GET_RADIO);
-	if (!hdr)
-		return -EMSGSIZE;
-
-	if (cb)
-		genl_dump_check_consistent(cb, hdr, &hwsim_genl_family);
-
-	if (data->alpha2[0] && data->alpha2[1])
-		param.reg_alpha2 = data->alpha2;
-
-	param.reg_strict = !!(data->hw->wiphy->regulatory_flags &
-					REGULATORY_STRICT_REG);
-	param.p2p_device = !!(data->hw->wiphy->interface_modes &
-					BIT(NL80211_IFTYPE_P2P_DEVICE));
-	param.use_chanctx = data->use_chanctx;
-	param.regd = data->regd;
-	param.channels = data->channels;
-	param.hwname = wiphy_name(data->hw->wiphy);
-
-	res = append_radio_msg(skb, data->idx, &param);
-	if (res < 0)
-		goto out_err;
-
-	return genlmsg_end(skb, hdr);
-
-out_err:
-	genlmsg_cancel(skb, hdr);
-	return res;
-}
-
 static void mac80211_hwsim_free(void)
 {
 	struct mac80211_hwsim_data *data;
@@ -2574,8 +2209,7 @@
 						list))) {
 		list_del(&data->list);
 		spin_unlock_bh(&hwsim_radio_lock);
-		mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
-					 NULL);
+		mac80211_hwsim_destroy_radio(data);
 		spin_lock_bh(&hwsim_radio_lock);
 	}
 	spin_unlock_bh(&hwsim_radio_lock);
@@ -2703,6 +2337,7 @@
 static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 					  struct genl_info *info)
 {
+
 	struct mac80211_hwsim_data *data2;
 	struct ieee80211_rx_status rx_status;
 	const u8 *dst;
@@ -2745,22 +2380,18 @@
 
 	/* A frame is received from user space */
 	memset(&rx_status, 0, sizeof(rx_status));
-	/* TODO: Check ATTR_FREQ if it exists, and maybe throw away off-channel
-	 * packets?
-	 */
 	rx_status.freq = data2->channel->center_freq;
 	rx_status.band = data2->channel->band;
 	rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
 	rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
 
 	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
-	data2->rx_pkts++;
-	data2->rx_bytes += skb->len;
 	ieee80211_rx_irqsafe(data2->hw, skb);
 
 	return 0;
 err:
 	printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
+	goto out;
 out:
 	dev_kfree_skb(skb);
 	return -EINVAL;
@@ -2797,84 +2428,42 @@
 	return 0;
 }
 
-static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
+static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info)
 {
-	struct hwsim_new_radio_params param = { 0 };
-
-	param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
-	param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
-	param.channels = channels;
-	param.destroy_on_close =
-		info->attrs[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE];
+	unsigned int chans = channels;
+	const char *alpha2 = NULL;
+	const struct ieee80211_regdomain *regd = NULL;
+	bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
+	bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
+	bool use_chanctx;
 
 	if (info->attrs[HWSIM_ATTR_CHANNELS])
-		param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
-
-	if (info->attrs[HWSIM_ATTR_NO_VIF])
-		param.no_vif = true;
-
-	if (info->attrs[HWSIM_ATTR_RADIO_NAME])
-		param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]);
+		chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
 
 	if (info->attrs[HWSIM_ATTR_USE_CHANCTX])
-		param.use_chanctx = true;
+		use_chanctx = true;
 	else
-		param.use_chanctx = (param.channels > 1);
+		use_chanctx = (chans > 1);
 
 	if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2])
-		param.reg_alpha2 =
-			nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]);
+		alpha2 = nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]);
 
 	if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) {
 		u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]);
 
 		if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom))
 			return -EINVAL;
-		param.regd = hwsim_world_regdom_custom[idx];
+		regd = hwsim_world_regdom_custom[idx];
 	}
 
-	return mac80211_hwsim_new_radio(info, &param);
+	return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict,
+					   p2p_device, use_chanctx);
 }
 
-static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
+static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info)
 {
 	struct mac80211_hwsim_data *data;
-	s64 idx = -1;
-	const char *hwname = NULL;
-
-	if (info->attrs[HWSIM_ATTR_RADIO_ID])
-		idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
-	else if (info->attrs[HWSIM_ATTR_RADIO_NAME])
-		hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]);
-	else
-		return -EINVAL;
-
-	spin_lock_bh(&hwsim_radio_lock);
-	list_for_each_entry(data, &hwsim_radios, list) {
-		if (idx >= 0) {
-			if (data->idx != idx)
-				continue;
-		} else {
-			if (strcmp(hwname, wiphy_name(data->hw->wiphy)))
-				continue;
-		}
-
-		list_del(&data->list);
-		spin_unlock_bh(&hwsim_radio_lock);
-		mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
-					 info);
-		return 0;
-	}
-	spin_unlock_bh(&hwsim_radio_lock);
-
-	return -ENODEV;
-}
-
-static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
-{
-	struct mac80211_hwsim_data *data;
-	struct sk_buff *skb;
-	int idx, res = -ENODEV;
+	int idx;
 
 	if (!info->attrs[HWSIM_ATTR_RADIO_ID])
 		return -EINVAL;
@@ -2884,62 +2473,14 @@
 	list_for_each_entry(data, &hwsim_radios, list) {
 		if (data->idx != idx)
 			continue;
-
-		skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-		if (!skb) {
-			res = -ENOMEM;
-			goto out_err;
-		}
-
-		res = mac80211_hwsim_get_radio(skb, data,
-					       genl_info_snd_portid(info),
-					       info->snd_seq, NULL, 0);
-		if (res < 0) {
-			nlmsg_free(skb);
-			goto out_err;
-		}
-
-		genlmsg_reply(skb, info);
-		break;
+		list_del(&data->list);
+		spin_unlock_bh(&hwsim_radio_lock);
+		mac80211_hwsim_destroy_radio(data);
+		return 0;
 	}
-
-out_err:
 	spin_unlock_bh(&hwsim_radio_lock);
 
-	return res;
-}
-
-static int hwsim_dump_radio_nl(struct sk_buff *skb,
-			       struct netlink_callback *cb)
-{
-	int idx = cb->args[0];
-	struct mac80211_hwsim_data *data = NULL;
-	int res;
-
-	spin_lock_bh(&hwsim_radio_lock);
-
-	if (idx == hwsim_radio_idx)
-		goto done;
-
-	list_for_each_entry(data, &hwsim_radios, list) {
-		if (data->idx < idx)
-			continue;
-
-		res = mac80211_hwsim_get_radio(skb, data,
-					       NETLINK_CB_PORTID(cb->skb),
-					       cb->nlh->nlmsg_seq, cb,
-					       NLM_F_MULTI);
-		if (res < 0)
-			break;
-
-		idx = data->idx + 1;
-	}
-
-	cb->args[0] = idx;
-
-done:
-	spin_unlock_bh(&hwsim_radio_lock);
-	return skb->len;
+	return -ENODEV;
 }
 
 /* Generic Netlink operations array */
@@ -2961,48 +2502,19 @@
 		.doit = hwsim_tx_info_frame_received_nl,
 	},
 	{
-		.cmd = HWSIM_CMD_NEW_RADIO,
+		.cmd = HWSIM_CMD_CREATE_RADIO,
 		.policy = hwsim_genl_policy,
-		.doit = hwsim_new_radio_nl,
+		.doit = hwsim_create_radio_nl,
 		.flags = GENL_ADMIN_PERM,
 	},
 	{
-		.cmd = HWSIM_CMD_DEL_RADIO,
+		.cmd = HWSIM_CMD_DESTROY_RADIO,
 		.policy = hwsim_genl_policy,
-		.doit = hwsim_del_radio_nl,
+		.doit = hwsim_destroy_radio_nl,
 		.flags = GENL_ADMIN_PERM,
 	},
-	{
-		.cmd = HWSIM_CMD_GET_RADIO,
-		.policy = hwsim_genl_policy,
-		.doit = hwsim_get_radio_nl,
-		.dumpit = hwsim_dump_radio_nl,
-	},
 };
 
-static void destroy_radio(struct work_struct *work)
-{
-	struct mac80211_hwsim_data *data =
-		container_of(work, struct mac80211_hwsim_data, destroy_work);
-
-	mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL);
-}
-
-static void remove_user_radios(u32 portid)
-{
-	struct mac80211_hwsim_data *entry, *tmp;
-
-	spin_lock_bh(&hwsim_radio_lock);
-	list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) {
-		if (entry->destroy_on_close && entry->portid == portid) {
-			list_del(&entry->list);
-			INIT_WORK(&entry->destroy_work, destroy_radio);
-			schedule_work(&entry->destroy_work);
-		}
-	}
-	spin_unlock_bh(&hwsim_radio_lock);
-}
-
 static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
 					 unsigned long state,
 					 void *_notify)
@@ -3012,8 +2524,6 @@
 	if (state != NETLINK_URELEASE)
 		return NOTIFY_DONE;
 
-	remove_user_radios(netlink_notify_portid(notify));
-
 	if (netlink_notify_portid(notify) == wmediumd_portid) {
 		printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink"
 		       " socket, switching to perfect channel medium\n");
@@ -3033,9 +2543,7 @@
 
 	printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
 
-	rc = genl_register_family_with_ops_groups(&hwsim_genl_family,
-						  hwsim_ops,
-						  hwsim_mcgrps);
+	rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops);
 	if (rc)
 		goto failure;
 
@@ -3096,73 +2604,69 @@
 		goto out_unregister_driver;
 	}
 
-	err = hwsim_init_netlink();
-	if (err < 0)
-		goto out_unregister_driver;
-
 	for (i = 0; i < radios; i++) {
-		struct hwsim_new_radio_params param = { 0 };
-
-		param.channels = channels;
+		const char *reg_alpha2 = NULL;
+		const struct ieee80211_regdomain *regd = NULL;
+		bool reg_strict = false;
 
 		switch (regtest) {
 		case HWSIM_REGTEST_DIFF_COUNTRY:
 			if (i < ARRAY_SIZE(hwsim_alpha2s))
-				param.reg_alpha2 = hwsim_alpha2s[i];
+				reg_alpha2 = hwsim_alpha2s[i];
 			break;
 		case HWSIM_REGTEST_DRIVER_REG_FOLLOW:
 			if (!i)
-				param.reg_alpha2 = hwsim_alpha2s[0];
+				reg_alpha2 = hwsim_alpha2s[0];
 			break;
 		case HWSIM_REGTEST_STRICT_ALL:
-			param.reg_strict = true;
+			reg_strict = true;
 		case HWSIM_REGTEST_DRIVER_REG_ALL:
-			param.reg_alpha2 = hwsim_alpha2s[0];
+			reg_alpha2 = hwsim_alpha2s[0];
 			break;
 		case HWSIM_REGTEST_WORLD_ROAM:
 			if (i == 0)
-				param.regd = &hwsim_world_regdom_custom_01;
+				regd = &hwsim_world_regdom_custom_01;
 			break;
 		case HWSIM_REGTEST_CUSTOM_WORLD:
-			param.regd = &hwsim_world_regdom_custom_01;
+			regd = &hwsim_world_regdom_custom_01;
 			break;
 		case HWSIM_REGTEST_CUSTOM_WORLD_2:
 			if (i == 0)
-				param.regd = &hwsim_world_regdom_custom_01;
+				regd = &hwsim_world_regdom_custom_01;
 			else if (i == 1)
-				param.regd = &hwsim_world_regdom_custom_02;
+				regd = &hwsim_world_regdom_custom_02;
 			break;
 		case HWSIM_REGTEST_STRICT_FOLLOW:
 			if (i == 0) {
-				param.reg_strict = true;
-				param.reg_alpha2 = hwsim_alpha2s[0];
+				reg_strict = true;
+				reg_alpha2 = hwsim_alpha2s[0];
 			}
 			break;
 		case HWSIM_REGTEST_STRICT_AND_DRIVER_REG:
 			if (i == 0) {
-				param.reg_strict = true;
-				param.reg_alpha2 = hwsim_alpha2s[0];
+				reg_strict = true;
+				reg_alpha2 = hwsim_alpha2s[0];
 			} else if (i == 1) {
-				param.reg_alpha2 = hwsim_alpha2s[1];
+				reg_alpha2 = hwsim_alpha2s[1];
 			}
 			break;
 		case HWSIM_REGTEST_ALL:
 			switch (i) {
 			case 0:
-				param.regd = &hwsim_world_regdom_custom_01;
+				regd = &hwsim_world_regdom_custom_01;
 				break;
 			case 1:
-				param.regd = &hwsim_world_regdom_custom_02;
+				regd = &hwsim_world_regdom_custom_02;
 				break;
 			case 2:
-				param.reg_alpha2 = hwsim_alpha2s[0];
+				reg_alpha2 = hwsim_alpha2s[0];
 				break;
 			case 3:
-				param.reg_alpha2 = hwsim_alpha2s[1];
+				reg_alpha2 = hwsim_alpha2s[1];
 				break;
 			case 4:
-				param.reg_strict = true;
-				param.reg_alpha2 = hwsim_alpha2s[2];
+				reg_strict = true;
+				reg_alpha2 = hwsim_alpha2s[2];
 				break;
 			}
 			break;
@@ -3170,10 +2674,10 @@
 			break;
 		}
 
-		param.p2p_device = support_p2p_device;
-		param.use_chanctx = channels > 1;
-
-		err = mac80211_hwsim_new_radio(NULL, &param);
+		err = mac80211_hwsim_create_radio(channels, reg_alpha2,
+						  regd, reg_strict,
+						  support_p2p_device,
+						  channels > 1);
 		if (err < 0)
 			goto out_free_radios;
 	}
@@ -3199,6 +2703,10 @@
 	}
 	rtnl_unlock();
 
+	err = hwsim_init_netlink();
+	if (err < 0)
+		goto out_free_mon;
+
 	return 0;
 
 out_free_mon:
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
index 66e1c73..c9d0315 100644
--- a/drivers/net/wireless/mac80211_hwsim.h
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -60,17 +60,14 @@
  * space, uses:
  *	%HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER,
  *	%HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE,
- *	%HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE, %HWSIM_ATTR_FREQ (optional)
+ *	%HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
  * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to
  * kernel, uses:
  *	%HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
  *	%HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
- * @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters,
- *	returns the radio ID (>= 0) or negative on errors, if successful
- *	then multicast the result
- * @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted
- * @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses:
- *	%HWSIM_ATTR_RADIO_ID
+ * @HWSIM_CMD_CREATE_RADIO: create a new radio with the given parameters,
+ *	returns the radio ID (>= 0) or negative on errors
+ * @HWSIM_CMD_DESTROY_RADIO: destroy a radio
  * @__HWSIM_CMD_MAX: enum limit
  */
 enum {
@@ -78,16 +75,12 @@
 	HWSIM_CMD_REGISTER,
 	HWSIM_CMD_FRAME,
 	HWSIM_CMD_TX_INFO_FRAME,
-	HWSIM_CMD_NEW_RADIO,
-	HWSIM_CMD_DEL_RADIO,
-	HWSIM_CMD_GET_RADIO,
+	HWSIM_CMD_CREATE_RADIO,
+	HWSIM_CMD_DESTROY_RADIO,
 	__HWSIM_CMD_MAX,
 };
 #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
 
-#define HWSIM_CMD_CREATE_RADIO   HWSIM_CMD_NEW_RADIO
-#define HWSIM_CMD_DESTROY_RADIO  HWSIM_CMD_DEL_RADIO
-
 /**
  * enum hwsim_attrs - hwsim netlink attributes
  *
@@ -118,11 +111,6 @@
  * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO
  *	command to force use of channel contexts even when only a
  *	single channel is supported
- * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO
- *	command to force radio removal when process that created the radio dies
- * @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666
- * @HWSIM_ATTR_NO_VIF:  Do not create vif (wlanX) when creating radio.
- * @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received.
  * @__HWSIM_ATTR_MAX: enum limit
  */
 
@@ -144,10 +132,6 @@
 	HWSIM_ATTR_REG_STRICT_REG,
 	HWSIM_ATTR_SUPPORT_P2P_DEVICE,
 	HWSIM_ATTR_USE_CHANCTX,
-	HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE,
-	HWSIM_ATTR_RADIO_NAME,
-	HWSIM_ATTR_NO_VIF,
-	HWSIM_ATTR_FREQ,
 	__HWSIM_ATTR_MAX,
 };
 #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 9d4786e..62f5dbe 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -544,7 +544,6 @@
 	u32 tx_win_size = priv->add_ba_param.tx_win_size;
 	static u8 dialog_tok;
 	int ret;
-	unsigned long flags;
 	u16 block_ack_param_set;
 
 	dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid);
@@ -555,18 +554,15 @@
 	    memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
 		struct mwifiex_sta_node *sta_ptr;
 
-		spin_lock_irqsave(&priv->sta_list_spinlock, flags);
 		sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
 		if (!sta_ptr) {
 			dev_warn(priv->adapter->dev,
 				 "BA setup with unknown TDLS peer %pM!\n",
 				peer_mac);
-			spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 			return -1;
 		}
 		if (sta_ptr->is_11ac_enabled)
 			tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
-		spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 	}
 
 	block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) |
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index f275675..2ee268b 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -84,8 +84,6 @@
 {
 	struct mwifiex_tx_ba_stream_tbl *tx_tbl;
 
-	if (is_broadcast_ether_addr(ptr->ra))
-		return false;
 	tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra);
 	if (tx_tbl)
 		return tx_tbl->amsdu;
@@ -98,8 +96,6 @@
 mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,
 			 struct mwifiex_ra_list_tbl *ptr, int tid)
 {
-	if (is_broadcast_ether_addr(ptr->ra))
-		return false;
 	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
 		return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
 	} else {
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index d73fda3..4005707 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -196,7 +196,6 @@
 	mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
 
 	del_timer_sync(&tbl->timer_context.timer);
-	tbl->timer_context.timer_is_set = false;
 
 	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
 	list_del(&tbl->list);
@@ -298,7 +297,6 @@
 		(struct reorder_tmr_cnxt *) context;
 	int start_win, seq_num;
 
-	ctx->timer_is_set = false;
 	seq_num = mwifiex_11n_find_last_seq_num(ctx);
 
 	if (seq_num < 0)
@@ -351,7 +349,6 @@
 	new_node->init_win = seq_num;
 	new_node->flags = 0;
 
-	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
 	if (mwifiex_queuing_ra_based(priv)) {
 		dev_dbg(priv->adapter->dev,
 			"info: AP/ADHOC:last_seq=%d start_win=%d\n",
@@ -368,7 +365,6 @@
 		else
 			last_seq = priv->rx_seq[tid];
 	}
-	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 
 	if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
 	    last_seq >= new_node->start_win) {
@@ -389,7 +385,6 @@
 
 	new_node->timer_context.ptr = new_node;
 	new_node->timer_context.priv = priv;
-	new_node->timer_context.timer_is_set = false;
 
 	init_timer(&new_node->timer_context.timer);
 	new_node->timer_context.timer.function = mwifiex_flush_data;
@@ -404,22 +399,6 @@
 	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
 }
 
-static void
-mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl)
-{
-	u32 min_flush_time;
-
-	if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32)
-		min_flush_time = MIN_FLUSH_TIMER_15_MS;
-	else
-		min_flush_time = MIN_FLUSH_TIMER_MS;
-
-	mod_timer(&tbl->timer_context.timer,
-		  jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size));
-
-	tbl->timer_context.timer_is_set = true;
-}
-
 /*
  * This function prepares command for adding a BA request.
  *
@@ -457,26 +436,22 @@
 	u32 rx_win_size = priv->add_ba_param.rx_win_size;
 	u8 tid;
 	int win_size;
-	unsigned long flags;
 	uint16_t block_ack_param_set;
 
 	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
 	    ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
 	    priv->adapter->is_hw_11ac_capable &&
 	    memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
-		spin_lock_irqsave(&priv->sta_list_spinlock, flags);
 		sta_ptr = mwifiex_get_sta_entry(priv,
 						cmd_addba_req->peer_mac_addr);
 		if (!sta_ptr) {
 			dev_warn(priv->adapter->dev,
 				 "BA setup with unknown TDLS peer %pM!\n",
 				 cmd_addba_req->peer_mac_addr);
-			spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 			return -1;
 		}
 		if (sta_ptr->is_11ac_enabled)
 			rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
-		spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 	}
 
 	cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
@@ -548,31 +523,31 @@
 				u8 *ta, u8 pkt_type, void *payload)
 {
 	struct mwifiex_rx_reorder_tbl *tbl;
-	int prev_start_win, start_win, end_win, win_size;
+	int start_win, end_win, win_size;
 	u16 pkt_index;
 	bool init_window_shift = false;
-	int ret = 0;
 
 	tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
 	if (!tbl) {
 		if (pkt_type != PKT_TYPE_BAR)
 			mwifiex_11n_dispatch_pkt(priv, payload);
-		return ret;
+		return 0;
 	}
 
 	if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
 		mwifiex_11n_dispatch_pkt(priv, payload);
-		return ret;
+		return 0;
 	}
 
 	start_win = tbl->start_win;
-	prev_start_win = start_win;
 	win_size = tbl->win_size;
 	end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
 	if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
 		init_window_shift = true;
 		tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
 	}
+	mod_timer(&tbl->timer_context.timer,
+		  jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size));
 
 	if (tbl->flags & RXREOR_FORCE_NO_DROP) {
 		dev_dbg(priv->adapter->dev,
@@ -593,14 +568,11 @@
 		if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
 			if (seq_num >= ((start_win + TWOPOW11) &
 					(MAX_TID_VALUE - 1)) &&
-			    seq_num < start_win) {
-				ret = -1;
-				goto done;
-			}
+			    seq_num < start_win)
+				return -1;
 		} else if ((seq_num < start_win) ||
-			   (seq_num >= (start_win + TWOPOW11))) {
-			ret = -1;
-			goto done;
+			   (seq_num > (start_win + TWOPOW11))) {
+			return -1;
 		}
 	}
 
@@ -629,10 +601,8 @@
 		else
 			pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
 
-		if (tbl->rx_reorder_ptr[pkt_index]) {
-			ret = -1;
-			goto done;
-		}
+		if (tbl->rx_reorder_ptr[pkt_index])
+			return -1;
 
 		tbl->rx_reorder_ptr[pkt_index] = payload;
 	}
@@ -643,11 +613,7 @@
 	 */
 	mwifiex_11n_scan_and_dispatch(priv, tbl);
 
-done:
-	if (!tbl->timer_context.timer_is_set ||
-	    prev_start_win != tbl->start_win)
-		mwifiex_11n_rxreorder_timer_restart(tbl);
-	return ret;
+	return 0;
 }
 
 /*
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 63ecea8..3a87bb0 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -21,8 +21,6 @@
 #define _MWIFIEX_11N_RXREORDER_H_
 
 #define MIN_FLUSH_TIMER_MS		50
-#define MIN_FLUSH_TIMER_15_MS		15
-#define MWIFIEX_BA_WIN_SIZE_32		32
 
 #define PKT_TYPE_BAR 0xE7
 #define MAX_TID_VALUE			(2 << 11)
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 689cf90..43e31bf 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -34,7 +34,7 @@
 	  mwifiex_pcie.
 
 config MWIFIEX_USB
-	tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897"
+	tristate "Marvell WiFi-Ex Driver for USB8797/8897"
 	depends on m
 	depends on MWIFIEX && USB
 	depends on FW_LOADER
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 4a66a65..0dd6729 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -194,18 +194,11 @@
 	tx_info->pkt_len = pkt_len;
 
 	mwifiex_form_mgmt_frame(skb, buf, len);
-	*cookie = prandom_u32() | 1;
-
-	if (ieee80211_is_action(mgmt->frame_control))
-		skb = mwifiex_clone_skb_for_tx_status(priv,
-						      skb,
-				MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie);
-	else
-		cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
-					GFP_ATOMIC);
-
 	mwifiex_queue_tx_pkt(priv, skb);
 
+	*cookie = prandom_u32() | 1;
+	cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC);
+
 	wiphy_dbg(wiphy, "info: management frame transmitted\n");
 	return 0;
 }
@@ -999,52 +992,6 @@
 	return mwifiex_dump_station_info(priv, sinfo);
 }
 
-static int
-mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
-			     int idx, struct survey_info *survey)
-{
-	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-	struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;
-	enum ieee80211_band band;
-
-	dev_dbg(priv->adapter->dev, "dump_survey idx=%d\n", idx);
-
-	memset(survey, 0, sizeof(struct survey_info));
-
-	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-	    priv->media_connected && idx == 0) {
-			u8 curr_bss_band = priv->curr_bss_params.band;
-			u32 chan = priv->curr_bss_params.bss_descriptor.channel;
-
-			band = mwifiex_band_to_radio_type(curr_bss_band);
-			survey->channel = ieee80211_get_channel(wiphy,
-				ieee80211_channel_to_frequency(chan, band));
-
-			if (priv->bcn_nf_last) {
-				survey->filled = SURVEY_INFO_NOISE_DBM;
-				survey->noise = priv->bcn_nf_last;
-			}
-			return 0;
-	}
-
-	if (idx >= priv->adapter->num_in_chan_stats)
-		return -ENOENT;
-
-	if (!pchan_stats[idx].cca_scan_dur)
-		return 0;
-
-	band = pchan_stats[idx].bandcfg;
-	survey->channel = ieee80211_get_channel(wiphy,
-	    ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));
-	survey->filled = SURVEY_INFO_NOISE_DBM |
-		SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY;
-	survey->noise = pchan_stats[idx].noise;
-	survey->channel_time = pchan_stats[idx].cca_scan_dur;
-	survey->channel_time_busy = pchan_stats[idx].cca_busy_dur;
-
-	return 0;
-}
-
 /* Supported rates to be advertised to the cfg80211 */
 static struct ieee80211_rate mwifiex_rates[] = {
 	{.bitrate = 10, .hw_value = 2, },
@@ -1292,34 +1239,36 @@
  */
 static int
 mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
-			     struct station_del_parameters *params)
+			     const u8 *mac)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 	struct mwifiex_sta_node *sta_node;
-	u8 deauth_mac[ETH_ALEN];
 	unsigned long flags;
 
 	if (list_empty(&priv->sta_list) || !priv->bss_started)
 		return 0;
 
-	if (!params->mac || is_broadcast_ether_addr(params->mac))
-		return 0;
-
-	wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, params->mac);
-
-	memset(deauth_mac, 0, ETH_ALEN);
-
-	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-	sta_node = mwifiex_get_sta_entry(priv, params->mac);
-	if (sta_node)
-		ether_addr_copy(deauth_mac, params->mac);
-	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
-	if (is_valid_ether_addr(deauth_mac)) {
-		if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
-				     HostCmd_ACT_GEN_SET, 0,
-				     deauth_mac, true))
-			return -1;
+	if (!mac || is_broadcast_ether_addr(mac)) {
+		wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__);
+		list_for_each_entry(sta_node, &priv->sta_list, list) {
+			if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
+					     HostCmd_ACT_GEN_SET, 0,
+					     sta_node->mac_addr, true))
+				return -1;
+			mwifiex_uap_del_sta_data(priv, sta_node);
+		}
+	} else {
+		wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, mac);
+		spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+		sta_node = mwifiex_get_sta_entry(priv, mac);
+		spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+		if (sta_node) {
+			if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
+					     HostCmd_ACT_GEN_SET, 0,
+					     sta_node->mac_addr, true))
+				return -1;
+			mwifiex_uap_del_sta_data(priv, sta_node);
+		}
 	}
 
 	return 0;
@@ -1810,10 +1759,6 @@
 		dev_dbg(priv->adapter->dev,
 			"info: associated to bssid %pM successfully\n",
 			priv->cfg_bssid);
-		if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-		    priv->adapter->auto_tdls &&
-		    priv->bss_type == MWIFIEX_BSS_TYPE_STA)
-			mwifiex_setup_auto_tdls_timer(priv);
 	} else {
 		dev_dbg(priv->adapter->dev,
 			"info: association to bssid %pM failed\n",
@@ -2685,13 +2630,11 @@
 		dev_dbg(priv->adapter->dev,
 			"Send TDLS Setup Request to %pM status_code=%d\n", peer,
 			 status_code);
-		mwifiex_add_auto_tdls_peer(priv, peer);
 		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
 						   dialog_token, status_code,
 						   extra_ies, extra_ies_len);
 		break;
 	case WLAN_TDLS_SETUP_RESPONSE:
-		mwifiex_add_auto_tdls_peer(priv, peer);
 		dev_dbg(priv->adapter->dev,
 			"Send TDLS Setup Response to %pM status_code=%d\n",
 			peer, status_code);
@@ -2836,7 +2779,6 @@
 	.disconnect = mwifiex_cfg80211_disconnect,
 	.get_station = mwifiex_cfg80211_get_station,
 	.dump_station = mwifiex_cfg80211_dump_station,
-	.dump_survey = mwifiex_cfg80211_dump_survey,
 	.set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
 	.join_ibss = mwifiex_cfg80211_join_ibss,
 	.leave_ibss = mwifiex_cfg80211_leave_ibss,
@@ -2898,25 +2840,6 @@
 	.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
 };
 
-int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
-{
-	u32 n_channels_bg, n_channels_a = 0;
-
-	n_channels_bg = mwifiex_band_2ghz.n_channels;
-
-	if (adapter->config_bands & BAND_A)
-		n_channels_a = mwifiex_band_5ghz.n_channels;
-
-	adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a);
-	adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
-				      adapter->num_in_chan_stats);
-
-	if (!adapter->chan_stats)
-		return -ENOMEM;
-
-	return 0;
-}
-
 /*
  * This function registers the device with CFG802.11 subsystem.
  *
@@ -2992,9 +2915,6 @@
 			   NL80211_FEATURE_INACTIVITY_TIMER |
 			   NL80211_FEATURE_NEED_OBSS_SCAN;
 
-	if (adapter->fw_api_ver == MWIFIEX_FW_V15)
-		wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
-
 	/* Reserve space for mwifiex specific private data for BSS */
 	wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
 
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 343240a..9c054d2 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -76,8 +76,6 @@
 #define MWIFIEX_BUF_FLAG_REQUEUED_PKT      BIT(0)
 #define MWIFIEX_BUF_FLAG_BRIDGED_PKT	   BIT(1)
 #define MWIFIEX_BUF_FLAG_TDLS_PKT	   BIT(2)
-#define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS   BIT(3)
-#define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS  BIT(4)
 
 #define MWIFIEX_BRIDGED_PKTS_THR_HIGH      1024
 #define MWIFIEX_BRIDGED_PKTS_THR_LOW        128
@@ -87,11 +85,6 @@
 #define MWIFIEX_TDLS_CREATE_LINK              0x02
 #define MWIFIEX_TDLS_CONFIG_LINK              0x03
 
-#define MWIFIEX_TDLS_RSSI_HIGH		50
-#define MWIFIEX_TDLS_RSSI_LOW		55
-#define MWIFIEX_TDLS_MAX_FAIL_COUNT      4
-#define MWIFIEX_AUTO_TDLS_IDLE_TIME     10
-
 enum mwifiex_bss_type {
 	MWIFIEX_BSS_TYPE_STA = 0,
 	MWIFIEX_BSS_TYPE_UAP = 1,
@@ -161,8 +154,6 @@
 	u8 bss_num;
 	u8 bss_type;
 	u32 pkt_len;
-	u8 ack_frame_id;
-	u64 cookie;
 };
 
 enum mwifiex_wmm_ac_e {
@@ -194,14 +185,4 @@
 	u8 ar_tha[ETH_ALEN];
 	u8 ar_tip[4];
 } __packed;
-
-struct mwifiex_chan_stats {
-	u8 chan_num;
-	u8 bandcfg;
-	u8 flags;
-	s8 noise;
-	u16 total_bss;
-	u16 cca_scan_dur;
-	u16 cca_busy_dur;
-} __packed;
 #endif /* !_MWIFIEX_DECL_H_ */
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index fb5936e..1eb6173 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -172,7 +172,6 @@
 #define TLV_TYPE_TDLS_IDLE_TIMEOUT  (PROPRIETARY_TLV_BASE_ID + 194)
 #define TLV_TYPE_SCAN_CHANNEL_GAP   (PROPRIETARY_TLV_BASE_ID + 197)
 #define TLV_TYPE_API_REV            (PROPRIETARY_TLV_BASE_ID + 199)
-#define TLV_TYPE_CHANNEL_STATS      (PROPRIETARY_TLV_BASE_ID + 198)
 
 #define MWIFIEX_TX_DATA_BUF_SIZE_2K        2048
 
@@ -494,7 +493,6 @@
 #define EVENT_TDLS_GENERIC_EVENT        0x00000052
 #define EVENT_EXT_SCAN_REPORT           0x00000058
 #define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
-#define EVENT_TX_STATUS_REPORT		0x00000074
 
 #define EVENT_ID_MASK                   0xffff
 #define BSS_NUM_MASK                    0xf
@@ -543,7 +541,6 @@
 #define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08
 #define MWIFIEX_TXPD_FLAGS_TDLS_PACKET      0x10
 #define MWIFIEX_RXPD_FLAGS_TDLS_PACKET      0x01
-#define MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS    0x20
 
 struct txpd {
 	u8 bss_type;
@@ -555,9 +552,7 @@
 	u8 priority;
 	u8 flags;
 	u8 pkt_delay_2ms;
-	u8 reserved1[2];
-	u8 tx_token_id;
-	u8 reserved[2];
+	u8 reserved1;
 } __packed;
 
 struct rxpd {
@@ -588,7 +583,6 @@
 	 * [Bit 7] Reserved
 	 */
 	u8 ht_info;
-	u8 reserved[3];
 	u8 flags;
 } __packed;
 
@@ -602,9 +596,8 @@
 	u8 priority;
 	u8 flags;
 	u8 pkt_delay_2ms;
-	u8 reserved1[2];
-	u8 tx_token_id;
-	u8 reserved[2];
+	u8 reserved1;
+	__le32 reserved2;
 };
 
 struct uap_rxpd {
@@ -618,16 +611,6 @@
 	u8 reserved1;
 };
 
-struct mwifiex_fw_chan_stats {
-	u8 chan_num;
-	u8 bandcfg;
-	u8 flags;
-	s8 noise;
-	__le16 total_bss;
-	__le16 cca_scan_dur;
-	__le16 cca_busy_dur;
-} __packed;
-
 enum mwifiex_chan_scan_mode_bitmasks {
 	MWIFIEX_PASSIVE_SCAN = BIT(0),
 	MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
@@ -677,11 +660,6 @@
 	__le16 chan_gap;
 } __packed;
 
-struct mwifiex_ietypes_chanstats {
-	struct mwifiex_ie_types_header header;
-	struct mwifiex_fw_chan_stats chanstats[0];
-} __packed;
-
 struct mwifiex_ie_types_wildcard_ssid_params {
 	struct mwifiex_ie_types_header header;
 	u8 max_ssid_length;
@@ -1229,12 +1207,6 @@
 	u8 num_of_set;
 } __packed;
 
-struct tx_status_event {
-	u8 packet_type;
-	u8 tx_token_id;
-	u8 status;
-} __packed;
-
 #define MWIFIEX_USER_SCAN_CHAN_MAX             50
 
 #define MWIFIEX_MAX_SSID_LIST_LENGTH         10
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 520ad4a..580aa45 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -137,7 +137,6 @@
 	priv->csa_expire_time = 0;
 	priv->del_list_idx = 0;
 	priv->hs2_enabled = false;
-	priv->check_tdls_tx = false;
 	memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID);
 
 	return mwifiex_add_bss_prio_tbl(priv);
@@ -367,7 +366,6 @@
 			list_del(&priv->tx_ba_stream_tbl_ptr);
 			list_del(&priv->rx_reorder_tbl_ptr);
 			list_del(&priv->sta_list);
-			list_del(&priv->auto_tdls_list);
 		}
 	}
 }
@@ -436,7 +434,6 @@
 			spin_lock_init(&priv->wmm.ra_list_spinlock);
 			spin_lock_init(&priv->curr_bcn_buf_lock);
 			spin_lock_init(&priv->sta_list_spinlock);
-			spin_lock_init(&priv->auto_tdls_lock);
 		}
 	}
 
@@ -452,6 +449,7 @@
 	spin_lock_init(&adapter->scan_pending_q_lock);
 	spin_lock_init(&adapter->rx_proc_lock);
 
+	skb_queue_head_init(&adapter->usb_rx_data_q);
 	skb_queue_head_init(&adapter->rx_data_q);
 
 	for (i = 0; i < adapter->priv_num; ++i) {
@@ -468,14 +466,10 @@
 		INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
 		INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
 		INIT_LIST_HEAD(&priv->sta_list);
-		INIT_LIST_HEAD(&priv->auto_tdls_list);
 		skb_queue_head_init(&priv->tdls_txq);
 
 		spin_lock_init(&priv->tx_ba_stream_tbl_lock);
 		spin_lock_init(&priv->rx_reorder_tbl_lock);
-
-		spin_lock_init(&priv->ack_status_lock);
-		idr_init(&priv->ack_status_frames);
 	}
 
 	return 0;
@@ -652,7 +646,6 @@
 		if (adapter->priv[i]) {
 			priv = adapter->priv[i];
 
-			mwifiex_clean_auto_tdls(priv);
 			mwifiex_clean_txrx(priv);
 			mwifiex_delete_bss_prio_tbl(priv);
 		}
@@ -675,6 +668,19 @@
 
 	spin_lock(&adapter->mwifiex_lock);
 
+	if (adapter->if_ops.data_complete) {
+		while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) {
+			struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
+
+			priv = adapter->priv[rx_info->bss_num];
+			if (priv)
+				priv->stats.rx_dropped++;
+
+			dev_kfree_skb_any(skb);
+			adapter->if_ops.data_complete(adapter);
+		}
+	}
+
 	mwifiex_adapter_cleanup(adapter);
 
 	spin_unlock(&adapter->mwifiex_lock);
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 411a6c2..8d6c259 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -880,7 +880,9 @@
 
 	/* Set Capability info */
 	bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS;
-	tmp_cap = WLAN_CAPABILITY_IBSS;
+	tmp_cap = le16_to_cpu(adhoc_start->cap_info_bitmap);
+	tmp_cap &= ~WLAN_CAPABILITY_ESS;
+	tmp_cap |= WLAN_CAPABILITY_IBSS;
 
 	/* Set up privacy in bss_desc */
 	if (priv->sec_info.encryption_mode) {
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 875eb77..6044804 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -28,11 +28,6 @@
 static char *cal_data_cfg;
 module_param(cal_data_cfg, charp, 0);
 
-static unsigned short driver_mode;
-module_param(driver_mode, ushort, 0);
-MODULE_PARM_DESC(driver_mode,
-		 "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7");
-
 /*
  * This function registers the device and performs all the necessary
  * initializations.
@@ -127,7 +122,6 @@
 		}
 	}
 
-	vfree(adapter->chan_stats);
 	kfree(adapter);
 	return 0;
 }
@@ -149,11 +143,8 @@
 	/* Check for Rx data */
 	while ((skb = skb_dequeue(&adapter->rx_data_q))) {
 		atomic_dec(&adapter->rx_pending);
-		if ((adapter->delay_main_work ||
-		     adapter->iface_type == MWIFIEX_USB) &&
+		if (adapter->delay_main_work &&
 		    (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) {
-			if (adapter->if_ops.submit_rem_rx_urbs)
-				adapter->if_ops.submit_rem_rx_urbs(adapter);
 			adapter->delay_main_work = false;
 			queue_work(adapter->workqueue, &adapter->main_work);
 		}
@@ -186,6 +177,7 @@
 {
 	int ret = 0;
 	unsigned long flags;
+	struct sk_buff *skb;
 
 	spin_lock_irqsave(&adapter->main_proc_lock, flags);
 
@@ -203,15 +195,12 @@
 		    (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY))
 			break;
 
-		/* For non-USB interfaces, If we process interrupts first, it
-		 * would increase RX pending even further. Avoid this by
-		 * checking if rx_pending has crossed high threshold and
-		 * schedule rx work queue and then process interrupts.
-		 * For USB interface, there are no interrupts. We already have
-		 * HIGH_RX_PENDING check in usb.c
+		/* If we process interrupts first, it would increase RX pending
+		 * even further. Avoid this by checking if rx_pending has
+		 * crossed high threshold and schedule rx work queue
+		 * and then process interrupts
 		 */
-		if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING &&
-		    adapter->iface_type != MWIFIEX_USB) {
+		if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING) {
 			adapter->delay_main_work = true;
 			if (!adapter->rx_processing)
 				queue_work(adapter->rx_workqueue,
@@ -263,6 +252,11 @@
 			}
 		}
 
+		/* Check Rx data for USB */
+		if (adapter->iface_type == MWIFIEX_USB)
+			while ((skb = skb_dequeue(&adapter->usb_rx_data_q)))
+				mwifiex_handle_rx_packet(adapter, skb);
+
 		/* Check for event */
 		if (adapter->event_received) {
 			adapter->event_received = false;
@@ -453,16 +447,6 @@
 		goto err_init_fw;
 	}
 
-	if (mwifiex_init_channel_scan_gap(adapter)) {
-		dev_err(adapter->dev, "could not init channel stats table\n");
-		goto err_init_fw;
-	}
-
-	if (driver_mode) {
-		driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK;
-		driver_mode |= MWIFIEX_DRIVER_MODE_STA;
-	}
-
 	rtnl_lock();
 	/* Create station interface by default */
 	wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",
@@ -472,28 +456,6 @@
 		rtnl_unlock();
 		goto err_add_intf;
 	}
-
-	if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) {
-		wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d",
-						NL80211_IFTYPE_AP, NULL, NULL);
-		if (IS_ERR(wdev)) {
-			dev_err(adapter->dev, "cannot create AP interface\n");
-			rtnl_unlock();
-			goto err_add_intf;
-		}
-	}
-
-	if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) {
-		wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d",
-						NL80211_IFTYPE_P2P_CLIENT, NULL,
-						NULL);
-		if (IS_ERR(wdev)) {
-			dev_err(adapter->dev,
-				"cannot create p2p client interface\n");
-			rtnl_unlock();
-			goto err_add_intf;
-		}
-	}
 	rtnl_unlock();
 
 	mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
@@ -608,48 +570,6 @@
 	return 0;
 }
 
-struct sk_buff *
-mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
-				struct sk_buff *skb, u8 flag, u64 *cookie)
-{
-	struct sk_buff *orig_skb = skb;
-	struct mwifiex_txinfo *tx_info, *orig_tx_info;
-
-	skb = skb_clone(skb, GFP_ATOMIC);
-	if (skb) {
-		unsigned long flags;
-		int id;
-
-		spin_lock_irqsave(&priv->ack_status_lock, flags);
-		id = idr_alloc(&priv->ack_status_frames, orig_skb,
-			       1, 0xff, GFP_ATOMIC);
-		spin_unlock_irqrestore(&priv->ack_status_lock, flags);
-
-		if (id >= 0) {
-			tx_info = MWIFIEX_SKB_TXCB(skb);
-			tx_info->ack_frame_id = id;
-			tx_info->flags |= flag;
-			orig_tx_info = MWIFIEX_SKB_TXCB(orig_skb);
-			orig_tx_info->ack_frame_id = id;
-			orig_tx_info->flags |= flag;
-
-			if (flag == MWIFIEX_BUF_FLAG_ACTION_TX_STATUS && cookie)
-				orig_tx_info->cookie = *cookie;
-
-		} else if (skb_shared(skb)) {
-			kfree_skb(orig_skb);
-		} else {
-			kfree_skb(skb);
-			skb = orig_skb;
-		}
-	} else {
-		/* couldn't clone -- lose tx status ... */
-		skb = orig_skb;
-	}
-
-	return skb;
-}
-
 /*
  * CFG802.11 network device handler for data transmission.
  */
@@ -659,9 +579,6 @@
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 	struct sk_buff *new_skb;
 	struct mwifiex_txinfo *tx_info;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
-	bool multicast;
-#endif
 
 	dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
 		jiffies, priv->bss_type, priv->bss_num);
@@ -702,17 +619,6 @@
 	tx_info->bss_type = priv->bss_type;
 	tx_info->pkt_len = skb->len;
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
-	multicast = is_multicast_ether_addr(skb->data);
-
-	if (unlikely(!multicast && skb->sk &&
-		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS &&
-		     priv->adapter->fw_api_ver == MWIFIEX_FW_V15))
-		skb = mwifiex_clone_skb_for_tx_status(priv,
-						      skb,
-					MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS, NULL);
-#endif
-
 	/* Record the current time the packet was queued; used to
 	 * determine the amount of time the packet was queued in
 	 * the driver before it was sent to the firmware.
@@ -722,13 +628,6 @@
 	 */
 	__net_timestamp(skb);
 
-	if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-	    priv->bss_type == MWIFIEX_BSS_TYPE_STA &&
-	    !ether_addr_equal_unaligned(priv->cfg_bssid, skb->data)) {
-		if (priv->adapter->auto_tdls && priv->check_tdls_tx)
-			mwifiex_tdls_check_tx(priv, skb);
-	}
-
 	mwifiex_queue_tx_pkt(priv, skb);
 
 	return 0;
@@ -969,7 +868,7 @@
 	adapter->cmd_wait_q.status = 0;
 	adapter->scan_wait_q_woken = false;
 
-	if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) {
+	if (num_possible_cpus() > 1) {
 		adapter->rx_work_enabled = true;
 		pr_notice("rx work enabled, cpus %d\n", num_possible_cpus());
 	}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index e66993c..e263574 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -34,7 +34,6 @@
 #include <linux/firmware.h>
 #include <linux/ctype.h>
 #include <linux/of.h>
-#include <linux/idr.h>
 
 #include "decl.h"
 #include "ioctl.h"
@@ -49,11 +48,6 @@
 	MWIFIEX_SYNC_CMD
 };
 
-#define MWIFIEX_DRIVER_MODE_STA			BIT(0)
-#define MWIFIEX_DRIVER_MODE_UAP			BIT(1)
-#define MWIFIEX_DRIVER_MODE_P2P			BIT(2)
-#define MWIFIEX_DRIVER_MODE_BITMASK		(BIT(0) | BIT(1) | BIT(2))
-
 #define MWIFIEX_MAX_AP				64
 
 #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT	(5 * HZ)
@@ -112,7 +106,10 @@
  */
 #define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \
 				adapter->event_received || \
-				adapter->data_received)
+				((adapter->iface_type != MWIFIEX_USB) && \
+				adapter->data_received) || \
+				((adapter->iface_type == MWIFIEX_USB) && \
+				!skb_queue_empty(&adapter->usb_rx_data_q)))
 
 #define MWIFIEX_TYPE_CMD				1
 #define MWIFIEX_TYPE_DATA				0
@@ -507,11 +504,8 @@
 	struct mwifiex_wmm_desc wmm;
 	atomic_t wmm_tx_pending[IEEE80211_NUM_ACS];
 	struct list_head sta_list;
-	/* spin lock for associated station/TDLS peers list */
+	/* spin lock for associated station list */
 	spinlock_t sta_list_spinlock;
-	struct list_head auto_tdls_list;
-	/* spin lock for auto TDLS peer list */
-	spinlock_t auto_tdls_lock;
 	struct list_head tx_ba_stream_tbl_ptr;
 	/* spin lock for tx_ba_stream_tbl_ptr queue */
 	spinlock_t tx_ba_stream_tbl_lock;
@@ -576,12 +570,6 @@
 	bool hs2_enabled;
 	struct station_parameters *sta_params;
 	struct sk_buff_head tdls_txq;
-	u8 check_tdls_tx;
-	struct timer_list auto_tdls_timer;
-	bool auto_tdls_timer_active;
-	struct idr ack_status_frames;
-	/* spin lock for ack status */
-	spinlock_t ack_status_lock;
 };
 
 enum mwifiex_ba_status {
@@ -604,7 +592,6 @@
 	struct timer_list timer;
 	struct mwifiex_rx_reorder_tbl *ptr;
 	struct mwifiex_private *priv;
-	u8 timer_is_set;
 };
 
 struct mwifiex_rx_reorder_tbl {
@@ -682,17 +669,6 @@
 	struct mwifiex_tdls_capab tdls_cap;
 };
 
-struct mwifiex_auto_tdls_peer {
-	struct list_head list;
-	u8 mac_addr[ETH_ALEN];
-	u8 tdls_status;
-	int rssi;
-	long rssi_jiffies;
-	u8 failure_count;
-	u8 do_discover;
-	u8 do_setup;
-};
-
 struct mwifiex_if_ops {
 	int (*init_if) (struct mwifiex_adapter *);
 	void (*cleanup_if) (struct mwifiex_adapter *);
@@ -713,13 +689,13 @@
 	void (*cleanup_mpa_buf) (struct mwifiex_adapter *);
 	int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *);
 	int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
+	int (*data_complete) (struct mwifiex_adapter *);
 	int (*init_fw_port) (struct mwifiex_adapter *);
 	int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
 	void (*card_reset) (struct mwifiex_adapter *);
 	void (*fw_dump)(struct mwifiex_adapter *);
 	int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
 	void (*iface_work)(struct work_struct *work);
-	void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
 };
 
 struct mwifiex_adapter {
@@ -790,6 +766,7 @@
 	spinlock_t scan_pending_q_lock;
 	/* spin lock for RX processing routine */
 	spinlock_t rx_proc_lock;
+	struct sk_buff_head usb_rx_data_q;
 	u32 scan_processing;
 	u16 region_code;
 	struct mwifiex_802_11d_domain_reg domain_reg;
@@ -867,10 +844,6 @@
 	u8 curr_mem_idx;
 	bool scan_chan_gap_enabled;
 	struct sk_buff_head rx_data_q;
-	struct mwifiex_chan_stats *chan_stats;
-	u32 num_in_chan_stats;
-	int survey_idx;
-	bool auto_tdls;
 };
 
 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -975,8 +948,6 @@
 int mwifiex_process_sta_event(struct mwifiex_private *);
 int mwifiex_process_uap_event(struct mwifiex_private *);
 void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
-void mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv,
-				  const u8 *ra_addr);
 void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
 void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
 int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
@@ -1059,8 +1030,7 @@
 int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
 				struct host_cmd_ds_command *cmd,
 				void *data_buf);
-int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
-				struct host_cmd_ds_command *resp);
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv);
 int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
 					 void *buf);
 
@@ -1330,24 +1300,6 @@
 				 u32 pri_chan, u8 chan_bw);
 int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter);
 
-int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb);
-void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv);
-void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
-					  const u8 *mac, u8 link_status);
-void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
-					  u8 *mac, s8 snr, s8 nflr);
-void mwifiex_check_auto_tdls(unsigned long context);
-void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac);
-void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv);
-void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
-
-void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
-				   void *event_body);
-
-struct sk_buff *
-mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
-				struct sk_buff *skb, u8 flag, u64 *cookie);
-
 #ifdef CONFIG_DEBUG_FS
 void mwifiex_debugfs_init(void);
 void mwifiex_debugfs_remove(void);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 984a7a4..ca64d4c 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1623,7 +1623,7 @@
 
 	if (*bytes_left >= sizeof(beacon_size)) {
 		/* Extract & convert beacon size from command buffer */
-		beacon_size = le16_to_cpu(*(__le16 *)(*bss_info));
+		memcpy(&beacon_size, *bss_info, sizeof(beacon_size));
 		*bytes_left -= sizeof(beacon_size);
 		*bss_info += sizeof(beacon_size);
 	}
@@ -1755,7 +1755,6 @@
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 
-	adapter->survey_idx = 0;
 	if (adapter->curr_cmd->wait_q_enabled) {
 		adapter->cmd_wait_q.status = 0;
 		if (!priv->scan_request) {
@@ -1977,53 +1976,10 @@
 	return 0;
 }
 
-static void
-mwifiex_update_chan_statistics(struct mwifiex_private *priv,
-			       struct mwifiex_ietypes_chanstats *tlv_stat)
-{
-	struct mwifiex_adapter *adapter = priv->adapter;
-	u8 i, num_chan;
-	struct mwifiex_fw_chan_stats *fw_chan_stats;
-	struct mwifiex_chan_stats chan_stats;
-
-	fw_chan_stats = (void *)((u8 *)tlv_stat +
-			      sizeof(struct mwifiex_ie_types_header));
-	num_chan = le16_to_cpu(tlv_stat->header.len) /
-					      sizeof(struct mwifiex_chan_stats);
-
-	for (i = 0 ; i < num_chan; i++) {
-		chan_stats.chan_num = fw_chan_stats->chan_num;
-		chan_stats.bandcfg = fw_chan_stats->bandcfg;
-		chan_stats.flags = fw_chan_stats->flags;
-		chan_stats.noise = fw_chan_stats->noise;
-		chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
-		chan_stats.cca_scan_dur =
-				       le16_to_cpu(fw_chan_stats->cca_scan_dur);
-		chan_stats.cca_busy_dur =
-				       le16_to_cpu(fw_chan_stats->cca_busy_dur);
-		dev_dbg(adapter->dev,
-			"chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
-			chan_stats.chan_num,
-			chan_stats.noise,
-			chan_stats.total_bss,
-			chan_stats.cca_scan_dur,
-			chan_stats.cca_busy_dur);
-		memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
-		       sizeof(struct mwifiex_chan_stats));
-		fw_chan_stats++;
-	}
-}
-
 /* This function handles the command response of extended scan */
-int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
-				struct host_cmd_ds_command *resp)
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
-	struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
-	struct mwifiex_ie_types_header *tlv;
-	struct mwifiex_ietypes_chanstats *tlv_stat;
-	u16 buf_left, type, len;
-
 	struct host_cmd_ds_command *cmd_ptr;
 	struct cmd_ctrl_node *cmd_node;
 	unsigned long cmd_flags, scan_flags;
@@ -2031,36 +1987,6 @@
 
 	dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");
 
-	ext_scan_resp = &resp->params.ext_scan;
-
-	tlv = (void *)ext_scan_resp->tlv_buffer;
-	buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
-					      - 1);
-
-	while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
-		type = le16_to_cpu(tlv->type);
-		len = le16_to_cpu(tlv->len);
-
-		if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
-			dev_err(adapter->dev,
-				"error processing scan response TLVs");
-			break;
-		}
-
-		switch (type) {
-		case TLV_TYPE_CHANNEL_STATS:
-			tlv_stat = (void *)tlv;
-			mwifiex_update_chan_statistics(priv, tlv_stat);
-			break;
-		default:
-			break;
-		}
-
-		buf_left -= len + sizeof(struct mwifiex_ie_types_header);
-		tlv = (void *)((u8 *)tlv + len +
-			       sizeof(struct mwifiex_ie_types_header));
-	}
-
 	spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
 	spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
 	if (list_empty(&adapter->scan_pending_q)) {
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index a6ab0a8..78e36e5 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -106,7 +106,6 @@
 		card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size;
 		card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size;
 		card->supports_fw_dump = data->supports_fw_dump;
-		card->auto_tdls = data->auto_tdls;
 	}
 
 	sdio_claim_host(func);
@@ -1881,7 +1880,6 @@
 		return -1;
 	}
 
-	adapter->auto_tdls = card->auto_tdls;
 	return ret;
 }
 
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 54c0715..20cd9ad 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -246,7 +246,6 @@
 	u8 curr_wr_port;
 
 	u8 *mp_regs;
-	u8 auto_tdls;
 
 	struct mwifiex_sdio_mpa_tx mpa_tx;
 	struct mwifiex_sdio_mpa_rx mpa_rx;
@@ -263,7 +262,6 @@
 	u16 tx_buf_size;
 	u32 mp_tx_agg_buf_size;
 	u32 mp_rx_agg_buf_size;
-	u8 auto_tdls;
 };
 
 static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = {
@@ -389,7 +387,6 @@
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.supports_fw_dump = false,
-	.auto_tdls = false,
 };
 
 static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
@@ -403,7 +400,6 @@
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.supports_fw_dump = false,
-	.auto_tdls = false,
 };
 
 static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
@@ -417,7 +413,6 @@
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
 	.supports_fw_dump = false,
-	.auto_tdls = false,
 };
 
 static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
@@ -431,7 +426,6 @@
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
 	.supports_fw_dump = true,
-	.auto_tdls = false,
 };
 
 static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = {
@@ -445,7 +439,6 @@
 	.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
 	.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
 	.supports_fw_dump = false,
-	.auto_tdls = true,
 };
 
 /*
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index b65e101..4aad446 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -983,7 +983,7 @@
 		adapter->curr_cmd->wait_q_enabled = false;
 		break;
 	case HostCmd_CMD_802_11_SCAN_EXT:
-		ret = mwifiex_ret_802_11_scan_ext(priv, resp);
+		ret = mwifiex_ret_802_11_scan_ext(priv);
 		adapter->curr_cmd->wait_q_enabled = false;
 		break;
 	case HostCmd_CMD_802_11_BG_SCAN_QUERY:
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index b8c171d..f1c240e 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -55,13 +55,9 @@
 	priv->scan_block = false;
 
 	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
-	    ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) {
+	    ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
 		mwifiex_disable_all_tdls_links(priv);
 
-		if (priv->adapter->auto_tdls)
-			mwifiex_clean_auto_tdls(priv);
-	}
-
 	/* Free Tx and Rx packets, report disconnect to upper layer */
 	mwifiex_clean_txrx(priv);
 
@@ -167,6 +163,9 @@
 					   NL80211_TDLS_TEARDOWN,
 					   le16_to_cpu(tdls_evt->u.reason_code),
 					   GFP_KERNEL);
+		ret = mwifiex_tdls_oper(priv, tdls_evt->peer_mac,
+					MWIFIEX_TDLS_DISABLE_LINK);
+		queue_work(adapter->workqueue, &adapter->main_work);
 		break;
 	default:
 		break;
@@ -504,11 +503,6 @@
 		ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
 		break;
 
-	case EVENT_TX_STATUS_REPORT:
-		dev_dbg(adapter->dev, "event: TX_STATUS Report\n");
-		mwifiex_parse_tx_status_event(priv, adapter->event_body);
-		break;
-
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
 			eventcause);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 1626868..92f3eb8 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -1026,12 +1026,12 @@
 			       int max_len)
 {
 	union {
-		__le32 l;
+		u32 l;
 		u8 c[4];
 	} ver;
 	char fw_ver[32];
 
-	ver.l = cpu_to_le32(adapter->fw_release_number);
+	ver.l = adapter->fw_release_number;
 	sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
 
 	snprintf(version, max_len, driver_version, fw_ver);
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 860fbb9..308e781 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -232,9 +232,6 @@
 			if (sta_ptr)
 				sta_ptr->rx_seq[local_rx_pd->priority] =
 					      le16_to_cpu(local_rx_pd->seq_num);
-			mwifiex_auto_tdls_update_peer_signal(priv, ta,
-							     local_rx_pd->snr,
-							     local_rx_pd->nf);
 		}
 	} else {
 		if (rx_pkt_type != PKT_TYPE_BAR)
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index b896d73..dab7b33 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -77,12 +77,6 @@
 	local_tx_pd->pkt_delay_2ms =
 				mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
 
-	if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
-	    tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
-		local_tx_pd->tx_token_id = tx_info->ack_frame_id;
-		local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
-	}
-
 	if (local_tx_pd->priority <
 	    ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
 		/*
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 22884b4..e294907 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -24,7 +24,6 @@
 #define TDLS_REQ_FIX_LEN      6
 #define TDLS_RESP_FIX_LEN     8
 #define TDLS_CONFIRM_FIX_LEN  6
-#define MWIFIEX_TDLS_WMM_INFO_SIZE 7
 
 static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
 					 const u8 *mac, u8 status)
@@ -368,55 +367,6 @@
 	*pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
 }
 
-static void
-mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb)
-{
-	struct ieee80211_wmm_param_ie *wmm;
-	u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00};
-	u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00};
-	u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00};
-	u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00};
-
-	wmm = (void *)skb_put(skb, sizeof(*wmm));
-	memset(wmm, 0, sizeof(*wmm));
-
-	wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
-	wmm->len = sizeof(*wmm) - 2;
-	wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
-	wmm->oui[1] = 0x50;
-	wmm->oui[2] = 0xf2;
-	wmm->oui_type = 2; /* WME */
-	wmm->oui_subtype = 1; /* WME param */
-	wmm->version = 1; /* WME ver */
-	wmm->qos_info = 0; /* U-APSD not in use */
-
-	/* use default WMM AC parameters for TDLS link*/
-	memcpy(&wmm->ac[0], ac_be, sizeof(ac_be));
-	memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk));
-	memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi));
-	memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo));
-}
-
-static void
-mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb,
-			u8 qosinfo)
-{
-	u8 *buf;
-
-	buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE +
-			      sizeof(struct ieee_types_header));
-
-	*buf++ = WLAN_EID_VENDOR_SPECIFIC;
-	*buf++ = 7; /* len */
-	*buf++ = 0x00; /* Microsoft OUI 00:50:F2 */
-	*buf++ = 0x50;
-	*buf++ = 0xf2;
-	*buf++ = 2; /* WME */
-	*buf++ = 0; /* WME info */
-	*buf++ = 1; /* WME ver */
-	*buf++ = qosinfo; /* U-APSD no in use */
-}
-
 static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
 					const u8 *peer, u8 action_code,
 					u8 dialog_token,
@@ -471,7 +421,6 @@
 
 		mwifiex_tdls_add_ext_capab(priv, skb);
 		mwifiex_tdls_add_qos_capab(skb);
-		mwifiex_add_wmm_info_ie(priv, skb, 0);
 		break;
 
 	case WLAN_TDLS_SETUP_RESPONSE:
@@ -509,7 +458,6 @@
 
 		mwifiex_tdls_add_ext_capab(priv, skb);
 		mwifiex_tdls_add_qos_capab(skb);
-		mwifiex_add_wmm_info_ie(priv, skb, 0);
 		break;
 
 	case WLAN_TDLS_SETUP_CONFIRM:
@@ -518,8 +466,6 @@
 		skb_put(skb, sizeof(tf->u.setup_cfm));
 		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
 		tf->u.setup_cfm.dialog_token = dialog_token;
-
-		mwifiex_tdls_add_wmm_param_ie(priv, skb);
 		if (priv->adapter->is_hw_11ac_capable) {
 			ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
 			if (ret) {
@@ -598,7 +544,6 @@
 		  sizeof(struct ieee_types_bss_co_2040) +
 		  sizeof(struct ieee80211_ht_operation) +
 		  sizeof(struct ieee80211_tdls_lnkie) +
-		  sizeof(struct ieee80211_wmm_param_ie) +
 		  extra_ies_len;
 
 	if (priv->adapter->is_hw_11ac_capable)
@@ -1028,7 +973,6 @@
 	}
 
 	mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
-	mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP);
 	memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
 	tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
 	return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
@@ -1073,8 +1017,6 @@
 
 		memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
 		mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
-		mwifiex_auto_tdls_update_peer_status(priv, peer,
-						     TDLS_SETUP_COMPLETE);
 	} else {
 		dev_dbg(priv->adapter->dev,
 			"tdls: enable link %pM failed\n", peer);
@@ -1088,8 +1030,6 @@
 			mwifiex_del_sta_entry(priv, peer);
 		}
 		mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
-		mwifiex_auto_tdls_update_peer_status(priv, peer,
-						     TDLS_NOT_SETUP);
 
 		return -1;
 	}
@@ -1157,231 +1097,3 @@
 
 	mwifiex_del_all_sta_list(priv);
 }
-
-int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
-{
-	struct mwifiex_auto_tdls_peer *peer;
-	unsigned long flags;
-	u8 mac[ETH_ALEN];
-
-	ether_addr_copy(mac, skb->data);
-
-	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-	list_for_each_entry(peer, &priv->auto_tdls_list, list) {
-		if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {
-			if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
-			    peer->tdls_status == TDLS_NOT_SETUP &&
-			    (peer->failure_count <
-			     MWIFIEX_TDLS_MAX_FAIL_COUNT)) {
-				peer->tdls_status = TDLS_SETUP_INPROGRESS;
-				dev_dbg(priv->adapter->dev,
-					"setup TDLS link, peer=%pM rssi=%d\n",
-					peer->mac_addr, peer->rssi);
-
-				cfg80211_tdls_oper_request(priv->netdev,
-							   peer->mac_addr,
-							   NL80211_TDLS_SETUP,
-							   0, GFP_ATOMIC);
-				peer->do_setup = false;
-				priv->check_tdls_tx = false;
-			} else if (peer->failure_count <
-				   MWIFIEX_TDLS_MAX_FAIL_COUNT &&
-				   peer->do_discover) {
-				mwifiex_send_tdls_data_frame(priv,
-							     peer->mac_addr,
-						    WLAN_TDLS_DISCOVERY_REQUEST,
-							     1, 0, NULL, 0);
-				peer->do_discover = false;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-
-	return 0;
-}
-
-void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)
-{
-	struct mwifiex_auto_tdls_peer *peer, *tmp_node;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-	list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {
-		list_del(&peer->list);
-		kfree(peer);
-	}
-
-	INIT_LIST_HEAD(&priv->auto_tdls_list);
-	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-	priv->check_tdls_tx = false;
-}
-
-void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
-{
-	struct mwifiex_auto_tdls_peer *tdls_peer;
-	unsigned long flags;
-
-	if (!priv->adapter->auto_tdls)
-		return;
-
-	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-	list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
-		if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {
-			tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
-			tdls_peer->rssi_jiffies = jiffies;
-			spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-			return;
-		}
-	}
-
-	/* create new TDLS peer */
-	tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC);
-	if (tdls_peer) {
-		ether_addr_copy(tdls_peer->mac_addr, mac);
-		tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
-		tdls_peer->rssi_jiffies = jiffies;
-		INIT_LIST_HEAD(&tdls_peer->list);
-		list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);
-		dev_dbg(priv->adapter->dev, "Add auto TDLS peer= %pM to list\n",
-			mac);
-	}
-
-	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
-					  const u8 *mac, u8 link_status)
-{
-	struct mwifiex_auto_tdls_peer *peer;
-	unsigned long flags;
-
-	if (!priv->adapter->auto_tdls)
-		return;
-
-	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-	list_for_each_entry(peer, &priv->auto_tdls_list, list) {
-		if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
-			if ((link_status == TDLS_NOT_SETUP) &&
-			    (peer->tdls_status == TDLS_SETUP_INPROGRESS))
-				peer->failure_count++;
-			else if (link_status == TDLS_SETUP_COMPLETE)
-				peer->failure_count = 0;
-
-			peer->tdls_status = link_status;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
-					  u8 *mac, s8 snr, s8 nflr)
-{
-	struct mwifiex_auto_tdls_peer *peer;
-	unsigned long flags;
-
-	if (!priv->adapter->auto_tdls)
-		return;
-
-	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-	list_for_each_entry(peer, &priv->auto_tdls_list, list) {
-		if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
-			peer->rssi = nflr - snr;
-			peer->rssi_jiffies = jiffies;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_check_auto_tdls(unsigned long context)
-{
-	struct mwifiex_private *priv = (struct mwifiex_private *)context;
-	struct mwifiex_auto_tdls_peer *tdls_peer;
-	unsigned long flags;
-	u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
-
-	if (WARN_ON_ONCE(!priv || !priv->adapter)) {
-		pr_err("mwifiex: %s: adapter or private structure is NULL\n",
-		       __func__);
-		return;
-	}
-
-	if (unlikely(!priv->adapter->auto_tdls))
-		return;
-
-	if (!priv->auto_tdls_timer_active) {
-		dev_dbg(priv->adapter->dev,
-			"auto TDLS timer inactive; return");
-		return;
-	}
-
-	priv->check_tdls_tx = false;
-
-	if (list_empty(&priv->auto_tdls_list)) {
-		mod_timer(&priv->auto_tdls_timer,
-			  jiffies +
-			  msecs_to_jiffies(MWIFIEX_TIMER_10S));
-		return;
-	}
-
-	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
-	list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
-		if ((jiffies - tdls_peer->rssi_jiffies) >
-		    (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {
-			tdls_peer->rssi = 0;
-			tdls_peer->do_discover = true;
-			priv->check_tdls_tx = true;
-		}
-
-		if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||
-		     !tdls_peer->rssi) &&
-		    tdls_peer->tdls_status == TDLS_SETUP_COMPLETE) {
-			tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
-			dev_dbg(priv->adapter->dev,
-				"teardown TDLS link,peer=%pM rssi=%d\n",
-				tdls_peer->mac_addr, -tdls_peer->rssi);
-			tdls_peer->do_discover = true;
-			priv->check_tdls_tx = true;
-			cfg80211_tdls_oper_request(priv->netdev,
-						   tdls_peer->mac_addr,
-						   NL80211_TDLS_TEARDOWN,
-						   reason, GFP_ATOMIC);
-		} else if (tdls_peer->rssi &&
-			   tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
-			   tdls_peer->tdls_status == TDLS_NOT_SETUP &&
-			   tdls_peer->failure_count <
-			   MWIFIEX_TDLS_MAX_FAIL_COUNT) {
-				priv->check_tdls_tx = true;
-				tdls_peer->do_setup = true;
-				dev_dbg(priv->adapter->dev,
-					"check TDLS with peer=%pM rssi=%d\n",
-					tdls_peer->mac_addr, -tdls_peer->rssi);
-		}
-	}
-	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-
-	mod_timer(&priv->auto_tdls_timer,
-		  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-}
-
-void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv)
-{
-	init_timer(&priv->auto_tdls_timer);
-	priv->auto_tdls_timer.function = mwifiex_check_auto_tdls;
-	priv->auto_tdls_timer.data = (unsigned long)priv;
-	priv->auto_tdls_timer_active = true;
-	mod_timer(&priv->auto_tdls_timer,
-		  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-}
-
-void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)
-{
-	if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
-	    priv->adapter->auto_tdls &&
-	    priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
-		priv->auto_tdls_timer_active = false;
-		del_timer(&priv->auto_tdls_timer);
-		mwifiex_flush_auto_tdls_list(priv);
-	}
-}
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 6ae1333..96a2126 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -64,6 +64,10 @@
 	else
 		ret = mwifiex_process_sta_rx_packet(priv, skb);
 
+	/* Decrement RX pending counter for each packet */
+	if (adapter->if_ops.data_complete)
+		adapter->if_ops.data_complete(adapter);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
@@ -203,34 +207,3 @@
 }
 EXPORT_SYMBOL_GPL(mwifiex_write_data_complete);
 
-void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
-				   void *event_body)
-{
-	struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
-	struct sk_buff *ack_skb;
-	unsigned long flags;
-	struct mwifiex_txinfo *tx_info;
-
-	if (!tx_status->tx_token_id)
-		return;
-
-	spin_lock_irqsave(&priv->ack_status_lock, flags);
-	ack_skb = idr_find(&priv->ack_status_frames, tx_status->tx_token_id);
-	if (ack_skb)
-		idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
-	spin_unlock_irqrestore(&priv->ack_status_lock, flags);
-
-	if (ack_skb) {
-		tx_info = MWIFIEX_SKB_TXCB(ack_skb);
-
-		if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) {
-			/* consumes ack_skb */
-			skb_complete_wifi_ack(ack_skb, !tx_status->status);
-		} else {
-			cfg80211_mgmt_tx_status(priv->wdev, tx_info->cookie,
-						ack_skb->data, ack_skb->len,
-						!tx_status->status, GFP_ATOMIC);
-			dev_kfree_skb_any(ack_skb);
-		}
-	}
-}
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index 0f347fd..300bab4 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -167,7 +167,7 @@
 	ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
 				 params->beacon.tail_len);
 	if (ht_ie) {
-		memcpy(&bss_cfg->ht_cap, ht_ie,
+		memcpy(&bss_cfg->ht_cap, ht_ie + 2,
 		       sizeof(struct ieee80211_ht_cap));
 		cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info);
 		memset(&bss_cfg->ht_cap.mcs, 0,
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index c54a537..7c2b976 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -110,7 +110,6 @@
 			mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
 			mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
 		}
-		mwifiex_wmm_del_peer_ra_list(priv, deauth_mac);
 		mwifiex_del_sta_entry(priv, deauth_mac);
 		break;
 	case EVENT_UAP_BSS_IDLE:
@@ -173,10 +172,6 @@
 			return mwifiex_handle_event_ext_scan_report(priv,
 						adapter->event_skb->data);
 		break;
-	case EVENT_TX_STATUS_REPORT:
-		dev_dbg(adapter->dev, "event: TX_STATUS Report\n");
-		mwifiex_parse_tx_status_event(priv, adapter->event_body);
-		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
 			eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index be3a203..ec7309d 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -266,7 +266,6 @@
 	struct rx_packet_hdr *rx_pkt_hdr;
 	u16 rx_pkt_type;
 	u8 ta[ETH_ALEN], pkt_type;
-	unsigned long flags;
 	struct mwifiex_sta_node *node;
 
 	uap_rx_pd = (struct uap_rxpd *)(skb->data);
@@ -295,12 +294,10 @@
 	memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
 
 	if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
-		spin_lock_irqsave(&priv->sta_list_spinlock, flags);
 		node = mwifiex_get_sta_entry(priv, ta);
 		if (node)
 			node->rx_seq[uap_rx_pd->priority] =
 						le16_to_cpu(uap_rx_pd->seq_num);
-		spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 	}
 
 	if (!priv->ap_11n_enabled ||
@@ -373,16 +370,10 @@
 	txpd->bss_num = priv->bss_num;
 	txpd->bss_type = priv->bss_type;
 	txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - len));
+
 	txpd->priority = (u8)skb->priority;
-
 	txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
 
-	if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
-	    tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
-		txpd->tx_token_id = tx_info->ack_frame_id;
-		txpd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
-	}
-
 	if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
 		/*
 		 * Set the priority specific tx_control field, setting of 0 will
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 1b56495..4371e12 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -27,11 +27,6 @@
 static struct semaphore add_remove_card_sem;
 
 static struct usb_device_id mwifiex_usb_table[] = {
-	/* 8766 */
-	{USB_DEVICE(USB8XXX_VID, USB8766_PID_1)},
-	{USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8766_PID_2,
-				       USB_CLASS_VENDOR_SPEC,
-				       USB_SUBCLASS_VENDOR_SPEC, 0xff)},
 	/* 8797 */
 	{USB_DEVICE(USB8XXX_VID, USB8797_PID_1)},
 	{USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2,
@@ -130,10 +125,8 @@
 			dev_err(dev, "DATA: skb->len too large\n");
 			return -1;
 		}
-
-		skb_queue_tail(&adapter->rx_data_q, skb);
+		skb_queue_tail(&adapter->usb_rx_data_q, skb);
 		adapter->data_received = true;
-		atomic_inc(&adapter->rx_pending);
 		break;
 	default:
 		dev_err(dev, "%s: unknown endport %#x\n", __func__, ep);
@@ -183,6 +176,7 @@
 		else
 			skb_put(skb, recv_length - skb->len);
 
+		atomic_inc(&adapter->rx_pending);
 		status = mwifiex_usb_recv(adapter, skb, context->ep);
 
 		dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n",
@@ -197,6 +191,7 @@
 			if (card->rx_cmd_ep == context->ep)
 				return;
 		} else {
+			atomic_dec(&adapter->rx_pending);
 			if (status == -1)
 				dev_err(adapter->dev,
 					"received data processing failed!\n");
@@ -227,13 +222,7 @@
 	else
 		size = MWIFIEX_RX_DATA_BUF_SIZE;
 
-	if (card->rx_cmd_ep == context->ep) {
-		mwifiex_usb_submit_rx_urb(context, size);
-	} else {
-		context->skb = NULL;
-		if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING)
-			mwifiex_usb_submit_rx_urb(context, size);
-	}
+	mwifiex_usb_submit_rx_urb(context, size);
 
 	return;
 }
@@ -359,12 +348,10 @@
 
 	/* PID_1 is used for firmware downloading only */
 	switch (id_product) {
-	case USB8766_PID_1:
 	case USB8797_PID_1:
 	case USB8897_PID_1:
 		card->usb_boot_state = USB8XXX_FW_DNLD;
 		break;
-	case USB8766_PID_2:
 	case USB8797_PID_2:
 	case USB8897_PID_2:
 		card->usb_boot_state = USB8XXX_FW_READY;
@@ -793,11 +780,6 @@
 		adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
 		strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME);
 		break;
-	case USB8766_PID_1:
-	case USB8766_PID_2:
-		adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
-		strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME);
-		break;
 	case USB8797_PID_1:
 	case USB8797_PID_2:
 	default:
@@ -980,11 +962,19 @@
 static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter,
 				       struct sk_buff *skb)
 {
+	atomic_dec(&adapter->rx_pending);
 	mwifiex_submit_rx_urb(adapter, MWIFIEX_USB_EP_CMD_EVENT);
 
 	return 0;
 }
 
+static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter)
+{
+	atomic_dec(&adapter->rx_pending);
+
+	return 0;
+}
+
 /* This function wakes up the card. */
 static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 {
@@ -996,20 +986,6 @@
 	return 0;
 }
 
-static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter)
-{
-	struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
-	int i;
-	struct urb_context *ctx;
-
-	for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
-		if (card->rx_data_list[i].skb)
-			continue;
-		ctx = &card->rx_data_list[i];
-		mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE);
-	}
-}
-
 static struct mwifiex_if_ops usb_ops = {
 	.register_dev =		mwifiex_register_dev,
 	.unregister_dev =	mwifiex_unregister_dev,
@@ -1020,8 +996,8 @@
 	.dnld_fw =		mwifiex_usb_dnld_fw,
 	.cmdrsp_complete =	mwifiex_usb_cmd_event_complete,
 	.event_complete =	mwifiex_usb_cmd_event_complete,
+	.data_complete =	mwifiex_usb_data_complete,
 	.host_to_card =		mwifiex_usb_host_to_card,
-	.submit_rem_rx_urbs =	mwifiex_usb_submit_rem_rx_urbs,
 };
 
 /* This function initializes the USB driver module.
@@ -1072,6 +1048,5 @@
 MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION);
 MODULE_VERSION(USB_VERSION);
 MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME);
 MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME);
 MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h
index a7cbba1..4c41c2a 100644
--- a/drivers/net/wireless/mwifiex/usb.h
+++ b/drivers/net/wireless/mwifiex/usb.h
@@ -24,8 +24,6 @@
 
 #define USB8XXX_VID		0x1286
 
-#define USB8766_PID_1		0x2041
-#define USB8766_PID_2		0x2042
 #define USB8797_PID_1		0x2043
 #define USB8797_PID_2		0x2044
 #define USB8897_PID_1		0x2045
@@ -39,7 +37,6 @@
 #define MWIFIEX_RX_DATA_URB	6
 #define MWIFIEX_USB_TIMEOUT	100
 
-#define USB8766_DEFAULT_FW_NAME	"mrvl/usb8766_uapsta.bin"
 #define USB8797_DEFAULT_FW_NAME	"mrvl/usb8797_uapsta.bin"
 #define USB8897_DEFAULT_FW_NAME	"mrvl/usb8897_uapsta.bin"
 
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index b1768fb..ec79c49 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -141,38 +141,6 @@
 	return 0;
 }
 
-static int
-mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
-			  struct rxpd *rx_pd)
-{
-	u16 stype;
-	u8 category, action_code;
-	struct ieee80211_hdr *ieee_hdr = (void *)payload;
-
-	stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE);
-
-	switch (stype) {
-	case IEEE80211_STYPE_ACTION:
-		category = *(payload + sizeof(struct ieee80211_hdr));
-		action_code = *(payload + sizeof(struct ieee80211_hdr) + 1);
-		if (category == WLAN_CATEGORY_PUBLIC &&
-		    action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
-			dev_dbg(priv->adapter->dev,
-				"TDLS discovery response %pM nf=%d, snr=%d\n",
-				ieee_hdr->addr2, rx_pd->nf, rx_pd->snr);
-			mwifiex_auto_tdls_update_peer_signal(priv,
-							     ieee_hdr->addr2,
-							     rx_pd->snr,
-							     rx_pd->nf);
-		}
-		break;
-	default:
-		dev_dbg(priv->adapter->dev,
-			"unknown mgmt frame subytpe %#x\n", stype);
-	}
-
-	return 0;
-}
 /*
  * This function processes the received management packet and send it
  * to the kernel.
@@ -183,7 +151,6 @@
 {
 	struct rxpd *rx_pd;
 	u16 pkt_len;
-	struct ieee80211_hdr *ieee_hdr;
 
 	if (!skb)
 		return -1;
@@ -195,11 +162,6 @@
 
 	pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
 
-	ieee_hdr = (void *)skb->data;
-	if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
-		mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
-					  pkt_len, rx_pd);
-	}
 	/* Remove address4 */
 	memmove(skb->data + sizeof(struct ieee80211_hdr_3addr),
 		skb->data + sizeof(struct ieee80211_hdr),
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index ffffd2c..94c98a8 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -147,6 +147,9 @@
 	struct mwifiex_sta_node *node;
 	unsigned long flags;
 
+	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+	node = mwifiex_get_sta_entry(priv, ra);
+	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 
 	for (i = 0; i < MAX_NUM_TID; ++i) {
 		ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
@@ -167,13 +170,10 @@
 				ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
 			}
 		} else {
-			spin_lock_irqsave(&priv->sta_list_spinlock, flags);
-			node = mwifiex_get_sta_entry(priv, ra);
 			ra_list->is_11n_enabled =
 				      mwifiex_is_sta_11n_enabled(priv, node);
 			if (ra_list->is_11n_enabled)
 				ra_list->max_amsdu = node->max_amsdu;
-			spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 		}
 
 		dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
@@ -523,13 +523,6 @@
 	}
 }
 
-static int mwifiex_free_ack_frame(int id, void *p, void *data)
-{
-	pr_warn("Have pending ack frames!\n");
-	kfree_skb(p);
-	return 0;
-}
-
 /*
  * This function cleans up the Tx and Rx queues.
  *
@@ -565,9 +558,6 @@
 
 	skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
 		mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
-
-	idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
-	idr_destroy(&priv->ack_status_frames);
 }
 
 /*
@@ -611,32 +601,6 @@
 }
 
 /*
- * This function deletes RA list nodes for given mac for all TIDs.
- * Function also decrements TX pending count accordingly.
- */
-void
-mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr)
-{
-	struct mwifiex_ra_list_tbl *ra_list;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
-	for (i = 0; i < MAX_NUM_TID; ++i) {
-		ra_list = mwifiex_wmm_get_ralist_node(priv, i, ra_addr);
-
-		if (!ra_list)
-			continue;
-		mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list);
-		atomic_sub(ra_list->total_pkt_count, &priv->wmm.tx_pkts_queued);
-		list_del(&ra_list->list);
-		kfree(ra_list);
-	}
-	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-}
-
-/*
  * This function checks if a particular RA list node exists in a given TID
  * table index.
  */
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index b8d1e04..ef11044 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -5548,9 +5548,7 @@
 	return rc;
 }
 
-static void mwl8k_sw_scan_start(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif,
-				const u8 *mac_addr)
+static void mwl8k_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	u8 tmp;
@@ -5567,8 +5565,7 @@
 	priv->sw_scan_start = true;
 }
 
-static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif)
+static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	u8 tmp;
diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h
new file mode 100644
index 0000000..aedfaf2
--- /dev/null
+++ b/drivers/net/wireless/p54/net2280.h
@@ -0,0 +1,451 @@
+#ifndef NET2280_H
+#define NET2280_H
+/*
+ * NetChip 2280 high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+ */
+
+/*
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* NET2280 MEMORY MAPPED REGISTERS
+ *
+ * The register layout came from the chip documentation, and the bit
+ * number definitions were extracted from chip specification.
+ *
+ * Use the shift operator ('<<') to build bit masks, with readl/writel
+ * to access the registers through PCI.
+ */
+
+/* main registers, BAR0 + 0x0000 */
+struct net2280_regs {
+	/* offset 0x0000 */
+	__le32			devinit;
+#define LOCAL_CLOCK_FREQUENCY					8
+#define FORCE_PCI_RESET						7
+#define PCI_ID							6
+#define PCI_ENABLE						5
+#define FIFO_SOFT_RESET						4
+#define CFG_SOFT_RESET						3
+#define PCI_SOFT_RESET						2
+#define USB_SOFT_RESET						1
+#define M8051_RESET						0
+	__le32			eectl;
+#define EEPROM_ADDRESS_WIDTH					23
+#define EEPROM_CHIP_SELECT_ACTIVE				22
+#define EEPROM_PRESENT						21
+#define EEPROM_VALID						20
+#define EEPROM_BUSY						19
+#define EEPROM_CHIP_SELECT_ENABLE				18
+#define EEPROM_BYTE_READ_START					17
+#define EEPROM_BYTE_WRITE_START					16
+#define EEPROM_READ_DATA					8
+#define EEPROM_WRITE_DATA					0
+	__le32			eeclkfreq;
+	u32			_unused0;
+	/* offset 0x0010 */
+
+	__le32			pciirqenb0;	/* interrupt PCI master ... */
+#define SETUP_PACKET_INTERRUPT_ENABLE				7
+#define ENDPOINT_F_INTERRUPT_ENABLE				6
+#define ENDPOINT_E_INTERRUPT_ENABLE				5
+#define ENDPOINT_D_INTERRUPT_ENABLE				4
+#define ENDPOINT_C_INTERRUPT_ENABLE				3
+#define ENDPOINT_B_INTERRUPT_ENABLE				2
+#define ENDPOINT_A_INTERRUPT_ENABLE				1
+#define ENDPOINT_0_INTERRUPT_ENABLE				0
+	__le32			pciirqenb1;
+#define PCI_INTERRUPT_ENABLE					31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE			27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE			26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE			25
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE		20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE		19
+#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE		18
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE			17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE			16
+#define GPIO_INTERRUPT_ENABLE					13
+#define DMA_D_INTERRUPT_ENABLE					12
+#define DMA_C_INTERRUPT_ENABLE					11
+#define DMA_B_INTERRUPT_ENABLE					10
+#define DMA_A_INTERRUPT_ENABLE					9
+#define EEPROM_DONE_INTERRUPT_ENABLE				8
+#define VBUS_INTERRUPT_ENABLE					7
+#define CONTROL_STATUS_INTERRUPT_ENABLE				6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE			4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE			3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE			2
+#define RESUME_INTERRUPT_ENABLE					1
+#define SOF_INTERRUPT_ENABLE					0
+	__le32                  cpu_irqenb0;	/* ... or onboard 8051 */
+#define SETUP_PACKET_INTERRUPT_ENABLE				7
+#define ENDPOINT_F_INTERRUPT_ENABLE				6
+#define ENDPOINT_E_INTERRUPT_ENABLE				5
+#define ENDPOINT_D_INTERRUPT_ENABLE				4
+#define ENDPOINT_C_INTERRUPT_ENABLE				3
+#define ENDPOINT_B_INTERRUPT_ENABLE				2
+#define ENDPOINT_A_INTERRUPT_ENABLE				1
+#define ENDPOINT_0_INTERRUPT_ENABLE				0
+	__le32                  cpu_irqenb1;
+#define CPU_INTERRUPT_ENABLE					31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE			27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE			26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE			25
+#define PCI_INTA_INTERRUPT_ENABLE				24
+#define PCI_PME_INTERRUPT_ENABLE				23
+#define PCI_SERR_INTERRUPT_ENABLE				22
+#define PCI_PERR_INTERRUPT_ENABLE				21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE		20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE		19
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE			17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE			16
+#define GPIO_INTERRUPT_ENABLE					13
+#define DMA_D_INTERRUPT_ENABLE					12
+#define DMA_C_INTERRUPT_ENABLE					11
+#define DMA_B_INTERRUPT_ENABLE					10
+#define DMA_A_INTERRUPT_ENABLE					9
+#define EEPROM_DONE_INTERRUPT_ENABLE				8
+#define VBUS_INTERRUPT_ENABLE					7
+#define CONTROL_STATUS_INTERRUPT_ENABLE				6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE			4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE			3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE			2
+#define RESUME_INTERRUPT_ENABLE					1
+#define SOF_INTERRUPT_ENABLE					0
+
+	/* offset 0x0020 */
+	u32			_unused1;
+	__le32			usbirqenb1;
+#define USB_INTERRUPT_ENABLE					31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE			27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE			26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE			25
+#define PCI_INTA_INTERRUPT_ENABLE				24
+#define PCI_PME_INTERRUPT_ENABLE				23
+#define PCI_SERR_INTERRUPT_ENABLE				22
+#define PCI_PERR_INTERRUPT_ENABLE				21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE		20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE		19
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE			17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE			16
+#define GPIO_INTERRUPT_ENABLE					13
+#define DMA_D_INTERRUPT_ENABLE					12
+#define DMA_C_INTERRUPT_ENABLE					11
+#define DMA_B_INTERRUPT_ENABLE					10
+#define DMA_A_INTERRUPT_ENABLE					9
+#define EEPROM_DONE_INTERRUPT_ENABLE				8
+#define VBUS_INTERRUPT_ENABLE					7
+#define CONTROL_STATUS_INTERRUPT_ENABLE				6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE			4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE			3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE			2
+#define RESUME_INTERRUPT_ENABLE					1
+#define SOF_INTERRUPT_ENABLE					0
+	__le32			irqstat0;
+#define INTA_ASSERTED						12
+#define SETUP_PACKET_INTERRUPT					7
+#define ENDPOINT_F_INTERRUPT					6
+#define ENDPOINT_E_INTERRUPT					5
+#define ENDPOINT_D_INTERRUPT					4
+#define ENDPOINT_C_INTERRUPT					3
+#define ENDPOINT_B_INTERRUPT					2
+#define ENDPOINT_A_INTERRUPT					1
+#define ENDPOINT_0_INTERRUPT					0
+	__le32			irqstat1;
+#define POWER_STATE_CHANGE_INTERRUPT				27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT				26
+#define PCI_PARITY_ERROR_INTERRUPT				25
+#define PCI_INTA_INTERRUPT					24
+#define PCI_PME_INTERRUPT					23
+#define PCI_SERR_INTERRUPT					22
+#define PCI_PERR_INTERRUPT					21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT			20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT			19
+#define PCI_RETRY_ABORT_INTERRUPT				17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT				16
+#define GPIO_INTERRUPT						13
+#define DMA_D_INTERRUPT						12
+#define DMA_C_INTERRUPT						11
+#define DMA_B_INTERRUPT						10
+#define DMA_A_INTERRUPT						9
+#define EEPROM_DONE_INTERRUPT					8
+#define VBUS_INTERRUPT						7
+#define CONTROL_STATUS_INTERRUPT				6
+#define ROOT_PORT_RESET_INTERRUPT				4
+#define SUSPEND_REQUEST_INTERRUPT				3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT			2
+#define RESUME_INTERRUPT					1
+#define SOF_INTERRUPT						0
+	/* offset 0x0030 */
+	__le32			idxaddr;
+	__le32			idxdata;
+	__le32			fifoctl;
+#define PCI_BASE2_RANGE						16
+#define IGNORE_FIFO_AVAILABILITY				3
+#define PCI_BASE2_SELECT					2
+#define FIFO_CONFIGURATION_SELECT				0
+	u32			_unused2;
+	/* offset 0x0040 */
+	__le32			memaddr;
+#define START							28
+#define DIRECTION						27
+#define FIFO_DIAGNOSTIC_SELECT					24
+#define MEMORY_ADDRESS						0
+	__le32			memdata0;
+	__le32			memdata1;
+	u32			_unused3;
+	/* offset 0x0050 */
+	__le32			gpioctl;
+#define GPIO3_LED_SELECT					12
+#define GPIO3_INTERRUPT_ENABLE					11
+#define GPIO2_INTERRUPT_ENABLE					10
+#define GPIO1_INTERRUPT_ENABLE					9
+#define GPIO0_INTERRUPT_ENABLE					8
+#define GPIO3_OUTPUT_ENABLE					7
+#define GPIO2_OUTPUT_ENABLE					6
+#define GPIO1_OUTPUT_ENABLE					5
+#define GPIO0_OUTPUT_ENABLE					4
+#define GPIO3_DATA						3
+#define GPIO2_DATA						2
+#define GPIO1_DATA						1
+#define GPIO0_DATA						0
+	__le32			gpiostat;
+#define GPIO3_INTERRUPT						3
+#define GPIO2_INTERRUPT						2
+#define GPIO1_INTERRUPT						1
+#define GPIO0_INTERRUPT						0
+} __packed;
+
+/* usb control, BAR0 + 0x0080 */
+struct net2280_usb_regs {
+	/* offset 0x0080 */
+	__le32			stdrsp;
+#define STALL_UNSUPPORTED_REQUESTS				31
+#define SET_TEST_MODE						16
+#define GET_OTHER_SPEED_CONFIGURATION				15
+#define GET_DEVICE_QUALIFIER					14
+#define SET_ADDRESS						13
+#define ENDPOINT_SET_CLEAR_HALT					12
+#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP			11
+#define GET_STRING_DESCRIPTOR_2					10
+#define GET_STRING_DESCRIPTOR_1					9
+#define GET_STRING_DESCRIPTOR_0					8
+#define GET_SET_INTERFACE					6
+#define GET_SET_CONFIGURATION					5
+#define GET_CONFIGURATION_DESCRIPTOR				4
+#define GET_DEVICE_DESCRIPTOR					3
+#define GET_ENDPOINT_STATUS					2
+#define GET_INTERFACE_STATUS					1
+#define GET_DEVICE_STATUS					0
+	__le32			prodvendid;
+#define     PRODUCT_ID						16
+#define     VENDOR_ID						0
+	__le32			relnum;
+	__le32			usbctl;
+#define SERIAL_NUMBER_INDEX					16
+#define PRODUCT_ID_STRING_ENABLE				13
+#define VENDOR_ID_STRING_ENABLE					12
+#define USB_ROOT_PORT_WAKEUP_ENABLE				11
+#define VBUS_PIN						10
+#define TIMED_DISCONNECT					9
+#define SUSPEND_IMMEDIATELY					7
+#define SELF_POWERED_USB_DEVICE					6
+#define REMOTE_WAKEUP_SUPPORT					5
+#define PME_POLARITY						4
+#define USB_DETECT_ENABLE					3
+#define PME_WAKEUP_ENABLE					2
+#define DEVICE_REMOTE_WAKEUP_ENABLE				1
+#define SELF_POWERED_STATUS					0
+	/* offset 0x0090 */
+	__le32			usbstat;
+#define HIGH_SPEED						7
+#define FULL_SPEED						6
+#define GENERATE_RESUME						5
+#define GENERATE_DEVICE_REMOTE_WAKEUP				4
+	__le32			xcvrdiag;
+#define FORCE_HIGH_SPEED_MODE					31
+#define FORCE_FULL_SPEED_MODE					30
+#define USB_TEST_MODE						24
+#define LINE_STATE						16
+#define TRANSCEIVER_OPERATION_MODE				2
+#define TRANSCEIVER_SELECT					1
+#define TERMINATION_SELECT					0
+	__le32			setup0123;
+	__le32			setup4567;
+	/* offset 0x0090 */
+	u32			_unused0;
+	__le32			ouraddr;
+#define FORCE_IMMEDIATE						7
+#define OUR_USB_ADDRESS						0
+	__le32			ourconfig;
+} __packed;
+
+/* pci control, BAR0 + 0x0100 */
+struct net2280_pci_regs {
+	/* offset 0x0100 */
+	__le32			pcimstctl;
+#define PCI_ARBITER_PARK_SELECT					13
+#define PCI_MULTI LEVEL_ARBITER					12
+#define PCI_RETRY_ABORT_ENABLE					11
+#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE			10
+#define DMA_READ_MULTIPLE_ENABLE				9
+#define DMA_READ_LINE_ENABLE					8
+#define PCI_MASTER_COMMAND_SELECT				6
+#define		MEM_READ_OR_WRITE				0
+#define		IO_READ_OR_WRITE				1
+#define		CFG_READ_OR_WRITE				2
+#define PCI_MASTER_START					5
+#define PCI_MASTER_READ_WRITE					4
+#define		PCI_MASTER_WRITE				0
+#define		PCI_MASTER_READ					1
+#define PCI_MASTER_BYTE_WRITE_ENABLES				0
+	__le32			pcimstaddr;
+	__le32			pcimstdata;
+	__le32			pcimststat;
+#define PCI_ARBITER_CLEAR					2
+#define PCI_EXTERNAL_ARBITER					1
+#define PCI_HOST_MODE						0
+} __packed;
+
+/* dma control, BAR0 + 0x0180 ... array of four structs like this,
+ * for channels 0..3.  see also struct net2280_dma:  descriptor
+ * that can be loaded into some of these registers.
+ */
+struct net2280_dma_regs {	/* [11.7] */
+	/* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */
+	__le32			dmactl;
+#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE		25
+#define DMA_CLEAR_COUNT_ENABLE					21
+#define DESCRIPTOR_POLLING_RATE					19
+#define		POLL_CONTINUOUS					0
+#define		POLL_1_USEC					1
+#define		POLL_100_USEC					2
+#define		POLL_1_MSEC					3
+#define DMA_VALID_BIT_POLLING_ENABLE				18
+#define DMA_VALID_BIT_ENABLE					17
+#define DMA_SCATTER_GATHER_ENABLE				16
+#define DMA_OUT_AUTO_START_ENABLE				4
+#define DMA_PREEMPT_ENABLE					3
+#define DMA_FIFO_VALIDATE					2
+#define DMA_ENABLE						1
+#define DMA_ADDRESS_HOLD					0
+	__le32			dmastat;
+#define DMA_SCATTER_GATHER_DONE_INTERRUPT			25
+#define DMA_TRANSACTION_DONE_INTERRUPT				24
+#define DMA_ABORT						1
+#define DMA_START						0
+	u32			_unused0[2];
+	/* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */
+	__le32                  dmacount;
+#define VALID_BIT						31
+#define DMA_DIRECTION						30
+#define DMA_DONE_INTERRUPT_ENABLE				29
+#define END_OF_CHAIN						28
+#define DMA_BYTE_COUNT_MASK					((1<<24)-1)
+#define DMA_BYTE_COUNT						0
+	__le32			dmaaddr;
+	__le32			dmadesc;
+	u32			_unused1;
+} __packed;
+
+/* dedicated endpoint registers, BAR0 + 0x0200 */
+
+struct net2280_dep_regs {	/* [11.8] */
+	/* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */
+	__le32			dep_cfg;
+	/* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */
+	__le32			dep_rsp;
+	u32			_unused[2];
+} __packed;
+
+/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
+ * like this, for ep0 then the configurable endpoints A..F
+ * ep0 reserved for control; E and F have only 64 bytes of fifo
+ */
+struct net2280_ep_regs {	/* [11.9] */
+	/* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */
+	__le32			ep_cfg;
+#define ENDPOINT_BYTE_COUNT					16
+#define ENDPOINT_ENABLE						10
+#define ENDPOINT_TYPE						8
+#define ENDPOINT_DIRECTION					7
+#define ENDPOINT_NUMBER						0
+	__le32			ep_rsp;
+#define SET_NAK_OUT_PACKETS					15
+#define SET_EP_HIDE_STATUS_PHASE				14
+#define SET_EP_FORCE_CRC_ERROR					13
+#define SET_INTERRUPT_MODE					12
+#define SET_CONTROL_STATUS_PHASE_HANDSHAKE			11
+#define SET_NAK_OUT_PACKETS_MODE				10
+#define SET_ENDPOINT_TOGGLE					9
+#define SET_ENDPOINT_HALT					8
+#define CLEAR_NAK_OUT_PACKETS					7
+#define CLEAR_EP_HIDE_STATUS_PHASE				6
+#define CLEAR_EP_FORCE_CRC_ERROR				5
+#define CLEAR_INTERRUPT_MODE					4
+#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE			3
+#define CLEAR_NAK_OUT_PACKETS_MODE				2
+#define CLEAR_ENDPOINT_TOGGLE					1
+#define CLEAR_ENDPOINT_HALT					0
+	__le32			ep_irqenb;
+#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE			6
+#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE		5
+#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE			3
+#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE		2
+#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE			1
+#define DATA_IN_TOKEN_INTERRUPT_ENABLE				0
+	__le32			ep_stat;
+#define FIFO_VALID_COUNT					24
+#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID			22
+#define TIMEOUT							21
+#define USB_STALL_SENT						20
+#define USB_IN_NAK_SENT						19
+#define USB_IN_ACK_RCVD						18
+#define USB_OUT_PING_NAK_SENT					17
+#define USB_OUT_ACK_SENT					16
+#define FIFO_OVERFLOW						13
+#define FIFO_UNDERFLOW						12
+#define FIFO_FULL						11
+#define FIFO_EMPTY						10
+#define FIFO_FLUSH						9
+#define SHORT_PACKET_OUT_DONE_INTERRUPT				6
+#define SHORT_PACKET_TRANSFERRED_INTERRUPT			5
+#define NAK_OUT_PACKETS						4
+#define DATA_PACKET_RECEIVED_INTERRUPT				3
+#define DATA_PACKET_TRANSMITTED_INTERRUPT			2
+#define DATA_OUT_PING_TOKEN_INTERRUPT				1
+#define DATA_IN_TOKEN_INTERRUPT					0
+	/* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */
+	__le32			ep_avail;
+	__le32			ep_data;
+	u32			_unused0[2];
+} __packed;
+
+struct net2280_reg_write {
+	__le16 port;
+	__le32 addr;
+	__le32 val;
+} __packed;
+
+struct net2280_reg_read {
+	__le16 port;
+	__le32 addr;
+} __packed;
+#endif /* NET2280_H */
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
index a5f5f0f..d273be7 100644
--- a/drivers/net/wireless/p54/p54usb.h
+++ b/drivers/net/wireless/p54/p54usb.h
@@ -16,7 +16,7 @@
 
 /* for isl3886 register definitions used on ver 1 devices */
 #include "p54pci.h"
-#include <linux/usb/net2280.h>
+#include "net2280.h"
 
 /* pci */
 #define NET2280_BASE		0x10000000
@@ -93,17 +93,6 @@
 	NET2280_DEV_CFG_U16	= 0x0883
 };
 
-struct net2280_reg_write {
-	__le16 port;
-	__le32 addr;
-	__le32 val;
-} __packed;
-
-struct net2280_reg_read {
-	__le16 port;
-	__le32 addr;
-} __packed;
-
 #define P54U_FW_BLOCK 2048
 
 #define X2_SIGNATURE "x2  "
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index b6c87b7..7d0df2b 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -256,7 +256,7 @@
 config RT2X00_LIB
 	tristate
 	depends on m
-	select BPAUTO_AVERAGE
+	select BACKPORT_AVERAGE
 
 config RT2X00_LIB_FIRMWARE
 	boolean
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 8f446c1..bcee58c 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -47,7 +47,7 @@
  * BBP and RF register require indirect register access,
  * and use the CSR registers BBPCSR and RFCSR to achieve this.
  * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_USB_BUSY_COUNT times to access
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
  * the register while taking a REGISTER_BUSY_DELAY us delay
  * between each attampt. When the busy bit is still set at that time,
  * the access attempt is considered to have failed,
@@ -62,7 +62,7 @@
 	__le16 reg;
 	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
 				      USB_VENDOR_REQUEST_IN, offset,
-				      &reg, sizeof(reg));
+				      &reg, sizeof(reg), REGISTER_TIMEOUT);
 	*value = le16_to_cpu(reg);
 }
 
@@ -83,7 +83,8 @@
 {
 	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
 				      USB_VENDOR_REQUEST_IN, offset,
-				      value, length);
+				      value, length,
+				      REGISTER_TIMEOUT16(length));
 }
 
 static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
@@ -93,7 +94,7 @@
 	__le16 reg = cpu_to_le16(value);
 	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
 				      USB_VENDOR_REQUEST_OUT, offset,
-				      &reg, sizeof(reg));
+				      &reg, sizeof(reg), REGISTER_TIMEOUT);
 }
 
 static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
@@ -112,7 +113,8 @@
 {
 	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
 				      USB_VENDOR_REQUEST_OUT, offset,
-				      value, length);
+				      value, length,
+				      REGISTER_TIMEOUT16(length));
 }
 
 static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
@@ -122,7 +124,7 @@
 {
 	unsigned int i;
 
-	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 		rt2500usb_register_read_lock(rt2x00dev, offset, reg);
 		if (!rt2x00_get_field16(*reg, field))
 			return 1;
@@ -904,7 +906,7 @@
 	unsigned int i;
 	u8 value;
 
-	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 		rt2500usb_bbp_read(rt2x00dev, 0, &value);
 		if ((value != 0xff) && (value != 0x00))
 			return 0;
@@ -1023,7 +1025,7 @@
 	 * We must wait until the register indicates that the
 	 * device has entered the correct state.
 	 */
-	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 		rt2500usb_register_read(rt2x00dev, MAC_CSR17, &reg2);
 		bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE);
 		rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index b12c863..5ad3899 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4119,20 +4119,7 @@
 	 * expected. We adjust it, based on TSSI reference and boundaries values
 	 * provided in EEPROM.
 	 */
-	switch (rt2x00dev->chip.rt) {
-	case RT2860:
-	case RT2872:
-	case RT2883:
-	case RT3070:
-	case RT3071:
-	case RT3090:
-	case RT3572:
-		delta += rt2800_get_gain_calibration_delta(rt2x00dev);
-		break;
-	default:
-		/* TODO: temperature compensation code for other chips. */
-		break;
-	}
+	delta += rt2800_get_gain_calibration_delta(rt2x00dev);
 
 	/*
 	 * Decrease power according to user settings, on devices with unknown
@@ -4149,19 +4136,25 @@
 	 * TODO: we do not use +6 dBm option to do not increase power beyond
 	 * regulatory limit, however this could be utilized for devices with
 	 * CAPABILITY_POWER_LIMIT.
+	 *
+	 * TODO: add different temperature compensation code for RT3290 & RT5390
+	 * to allow to use BBP_R1 for those chips.
 	 */
-	if (delta <= -12) {
-		power_ctrl = 2;
-		delta += 12;
-	} else if (delta <= -6) {
-		power_ctrl = 1;
-		delta += 6;
-	} else {
-		power_ctrl = 0;
+	if (!rt2x00_rt(rt2x00dev, RT3290) &&
+	    !rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_bbp_read(rt2x00dev, 1, &r1);
+		if (delta <= -12) {
+			power_ctrl = 2;
+			delta += 12;
+		} else if (delta <= -6) {
+			power_ctrl = 1;
+			delta += 6;
+		} else {
+			power_ctrl = 0;
+		}
+		rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
+		rt2800_bbp_write(rt2x00dev, 1, r1);
 	}
-	rt2800_bbp_read(rt2x00dev, 1, &r1);
-	rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
-	rt2800_bbp_write(rt2x00dev, 1, r1);
 
 	offset = TX_PWR_CFG_0;
 
diff --git a/drivers/net/wireless/rt2x00/rt2800soc.c b/drivers/net/wireless/rt2x00/rt2800soc.c
index e6d747f..71ccac7 100644
--- a/drivers/net/wireless/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/rt2x00/rt2800soc.c
@@ -244,6 +244,7 @@
 static struct platform_driver rt2800soc_driver = {
 	.driver		= {
 		.name		= "rt2800_wmac",
+		.owner		= THIS_MODULE,
 		.mod_name	= KBUILD_MODNAME,
 	},
 	.probe		= rt2800soc_probe,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index df74814..7737af9 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1111,7 +1111,6 @@
 	/* Ovislink */
 	{ USB_DEVICE(0x1b75, 0x3071) },
 	{ USB_DEVICE(0x1b75, 0x3072) },
-	{ USB_DEVICE(0x1b75, 0xa200) },
 	/* Para */
 	{ USB_DEVICE(0x20b8, 0x8888) },
 	/* Pegatron */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index caa6400..57b2509 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1019,12 +1019,9 @@
  * Register defines.
  * Some registers require multiple attempts before success,
  * in those cases REGISTER_BUSY_COUNT attempts should be
- * taken with a REGISTER_BUSY_DELAY interval. Due to USB
- * bus delays, we do not have to loop so many times to wait
- * for valid register value on that bus.
+ * taken with a REGISTER_BUSY_DELAY interval.
  */
 #define REGISTER_BUSY_COUNT	100
-#define REGISTER_USB_BUSY_COUNT 20
 #define REGISTER_BUSY_DELAY	100
 
 /*
@@ -1440,11 +1437,8 @@
 		      struct ieee80211_sta *sta);
 int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			 struct ieee80211_sta *sta);
-void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
-			     struct ieee80211_vif *vif,
-			     const u8 *mac_addr);
-void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif);
+void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw);
+void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw);
 int rt2x00mac_get_stats(struct ieee80211_hw *hw,
 			struct ieee80211_low_level_stats *stats);
 void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 7f9e471..9206634 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -568,9 +568,7 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
 
-void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
-			     struct ieee80211_vif *vif,
-			     const u8 *mac_addr)
+void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
@@ -578,8 +576,7 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
 
-void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif)
+void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 66ff364..8e68f87 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -158,29 +158,55 @@
 	skb_trim(skb, frame_length);
 }
 
-/*
- * H/W needs L2 padding between the header and the paylod if header size
- * is not 4 bytes aligned.
- */
-void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len)
+void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
 {
-	unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
+	unsigned int payload_length = skb->len - header_length;
+	unsigned int header_align = ALIGN_SIZE(skb, 0);
+	unsigned int payload_align = ALIGN_SIZE(skb, header_length);
+	unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
 
-	if (!l2pad)
+	/*
+	 * Adjust the header alignment if the payload needs to be moved more
+	 * than the header.
+	 */
+	if (payload_align > header_align)
+		header_align += 4;
+
+	/* There is nothing to do if no alignment is needed */
+	if (!header_align)
 		return;
 
-	skb_push(skb, l2pad);
-	memmove(skb->data, skb->data + l2pad, hdr_len);
+	/* Reserve the amount of space needed in front of the frame */
+	skb_push(skb, header_align);
+
+	/*
+	 * Move the header.
+	 */
+	memmove(skb->data, skb->data + header_align, header_length);
+
+	/* Move the payload, if present and if required */
+	if (payload_length && payload_align)
+		memmove(skb->data + header_length + l2pad,
+			skb->data + header_length + l2pad + payload_align,
+			payload_length);
+
+	/* Trim the skb to the correct size */
+	skb_trim(skb, header_length + l2pad + payload_length);
 }
 
-void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len)
+void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
 {
-	unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
+	/*
+	 * L2 padding is only present if the skb contains more than just the
+	 * IEEE 802.11 header.
+	 */
+	unsigned int l2pad = (skb->len > header_length) ?
+				L2PAD_SIZE(header_length) : 0;
 
 	if (!l2pad)
 		return;
 
-	memmove(skb->data + l2pad, skb->data, hdr_len);
+	memmove(skb->data + l2pad, skb->data, header_length);
 	skb_pull(skb, l2pad);
 }
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 892270d..86c43d1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -42,27 +42,37 @@
 {
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
 	int status;
+	unsigned int i;
 	unsigned int pipe =
 	    (requesttype == USB_VENDOR_REQUEST_IN) ?
 	    usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
-	unsigned long expire = jiffies + msecs_to_jiffies(timeout);
 
 	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
 		return -ENODEV;
 
-	do {
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 		status = usb_control_msg(usb_dev, pipe, request, requesttype,
 					 value, offset, buffer, buffer_length,
-					 timeout / 2);
+					 timeout);
 		if (status >= 0)
 			return 0;
 
-		if (status == -ENODEV) {
-			/* Device has disappeared. */
+		/*
+		 * Check for errors
+		 * -ENODEV: Device has disappeared, no point continuing.
+		 * All other errors: Try again.
+		 */
+		else if (status == -ENODEV) {
 			clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
 			break;
 		}
-	} while (time_before(jiffies, expire));
+	}
+
+	/* If the port is powered down, we get a -EPROTO error, and this
+	 * leads to a endless loop. So just say that the device is gone.
+	 */
+	if (status == -EPROTO)
+		clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
 
 	rt2x00_err(rt2x00dev,
 		   "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
@@ -106,7 +116,7 @@
 int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
 				  const u8 request, const u8 requesttype,
 				  const u16 offset, void *buffer,
-				  const u16 buffer_length)
+				  const u16 buffer_length, const int timeout)
 {
 	int status = 0;
 	unsigned char *tb;
@@ -121,7 +131,7 @@
 		bsize = min_t(u16, CSR_CACHE_SIZE, len);
 		status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
 							requesttype, off, tb,
-							bsize, REGISTER_TIMEOUT);
+							bsize, timeout);
 
 		tb  += bsize;
 		len -= bsize;
@@ -144,7 +154,7 @@
 	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
 		return -ENODEV;
 
-	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 		rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
 		if (!rt2x00_get_field32(*reg, field))
 			return 1;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 8f85fbd..831b65f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -33,14 +33,27 @@
 })
 
 /*
- * For USB vendor requests we need to pass a timeout time in ms, for this we
- * use the REGISTER_TIMEOUT, however when loading firmware or read EEPROM
- * a higher value is required. In that case we use the REGISTER_TIMEOUT_FIRMWARE
- * and EEPROM_TIMEOUT.
+ * For USB vendor requests we need to pass a timeout
+ * time in ms, for this we use the REGISTER_TIMEOUT,
+ * however when loading firmware a higher value is
+ * required. In that case we use the REGISTER_TIMEOUT_FIRMWARE.
  */
-#define REGISTER_TIMEOUT		100
+#define REGISTER_TIMEOUT		500
 #define REGISTER_TIMEOUT_FIRMWARE	1000
-#define EEPROM_TIMEOUT			2000
+
+/**
+ * REGISTER_TIMEOUT16 - Determine the timeout for 16bit register access
+ * @__datalen: Data length
+ */
+#define REGISTER_TIMEOUT16(__datalen)	\
+	( REGISTER_TIMEOUT * ((__datalen) / sizeof(u16)) )
+
+/**
+ * REGISTER_TIMEOUT32 - Determine the timeout for 32bit register access
+ * @__datalen: Data length
+ */
+#define REGISTER_TIMEOUT32(__datalen)	\
+	( REGISTER_TIMEOUT * ((__datalen) / sizeof(u32)) )
 
 /*
  * Cache size
@@ -113,6 +126,7 @@
  * @offset: Register offset to perform action on
  * @buffer: Buffer where information will be read/written to by device
  * @buffer_length: Size of &buffer
+ * @timeout: Operation timeout
  *
  * This function will use a previously with kmalloc allocated cache
  * to communicate with the device. The contents of the buffer pointer
@@ -125,7 +139,7 @@
 int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
 				  const u8 request, const u8 requesttype,
 				  const u16 offset, void *buffer,
-				  const u16 buffer_length);
+				  const u16 buffer_length, const int timeout);
 
 /**
  * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
@@ -183,7 +197,8 @@
 {
 	return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
 					USB_VENDOR_REQUEST_IN, 0, 0,
-					eeprom, length, EEPROM_TIMEOUT);
+					eeprom, length,
+					REGISTER_TIMEOUT16(length));
 }
 
 /**
@@ -202,7 +217,7 @@
 	__le32 reg;
 	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
 				      USB_VENDOR_REQUEST_IN, offset,
-				      &reg, sizeof(reg));
+				      &reg, sizeof(reg), REGISTER_TIMEOUT);
 	*value = le32_to_cpu(reg);
 }
 
@@ -242,7 +257,8 @@
 {
 	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
 				      USB_VENDOR_REQUEST_IN, offset,
-				      value, length);
+				      value, length,
+				      REGISTER_TIMEOUT32(length));
 }
 
 /**
@@ -261,7 +277,7 @@
 	__le32 reg = cpu_to_le32(value);
 	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
 				      USB_VENDOR_REQUEST_OUT, offset,
-				      &reg, sizeof(reg));
+				      &reg, sizeof(reg), REGISTER_TIMEOUT);
 }
 
 /**
@@ -300,7 +316,8 @@
 {
 	rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
 				      USB_VENDOR_REQUEST_OUT, offset,
-				      (void *)value, length);
+				      (void *)value, length,
+				      REGISTER_TIMEOUT32(length));
 }
 
 /**
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index b0a75d9..80d48e9 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1295,7 +1295,7 @@
 	unsigned int i;
 	u8 value;
 
-	for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 		rt73usb_bbp_read(rt2x00dev, 0, &value);
 		if ((value != 0xff) && (value != 0x00))
 			return 0;
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 40b6d1d..58ba718 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -467,7 +467,7 @@
 		    rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
 	/* <2> work queue */
 	rtlpriv->works.hw = hw;
-	rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
+	rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
 	INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
 			  (void *)rtl_watchdog_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index 5fc6f52..f6179bc 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -786,7 +786,6 @@
 				    unsigned int changed_flags,
 				    unsigned int *new_flags, u64 multicast)
 {
-	bool update_rcr = false;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
@@ -807,7 +806,6 @@
 			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 				 "Disable receive multicast frame\n");
 		}
-		update_rcr = true;
 	}
 
 	if (changed_flags & FIF_FCSFAIL) {
@@ -820,8 +818,6 @@
 			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 				 "Disable receive FCS error frame\n");
 		}
-		if (!update_rcr)
-			update_rcr = true;
 	}
 
 	/* if ssid not set to hw don't check bssid
@@ -836,8 +832,6 @@
 				rtlpriv->cfg->ops->set_chk_bssid(hw, false);
 			else
 				rtlpriv->cfg->ops->set_chk_bssid(hw, true);
-			if (update_rcr)
-				update_rcr = false;
 		}
 	}
 
@@ -852,8 +846,6 @@
 			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 				 "Disable receive control frame.\n");
 		}
-		if (!update_rcr)
-			update_rcr = true;
 	}
 
 	if (changed_flags & FIF_OTHER_BSS) {
@@ -866,13 +858,7 @@
 			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 				 "Disable receive other BSS's frame.\n");
 		}
-		if (!update_rcr)
-			update_rcr = true;
 	}
-
-	if (update_rcr)
-		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
-					      (u8 *)(&mac->rx_conf));
 }
 static int rtl_op_sta_add(struct ieee80211_hw *hw,
 			 struct ieee80211_vif *vif,
@@ -1375,9 +1361,7 @@
 	return 0;
 }
 
-static void rtl_op_sw_scan_start(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif,
-				 const u8 *mac_addr)
+static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1412,8 +1396,7 @@
 	rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0);
 }
 
-static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif)
+static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1845,9 +1828,3 @@
 	.flush = rtl_op_flush,
 };
 EXPORT_SYMBOL_GPL(rtl_ops);
-
-bool rtl_btc_status_false(void)
-{
-	return false;
-}
-EXPORT_SYMBOL_GPL(rtl_btc_status_false);
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h
index 624e1dc..59cd3b9 100644
--- a/drivers/net/wireless/rtlwifi/core.h
+++ b/drivers/net/wireless/rtlwifi/core.h
@@ -42,6 +42,5 @@
 		     u32 mask, u32 data);
 void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data);
 bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
-bool rtl_btc_status_false(void);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 846a2e6..667aba8 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -842,8 +842,7 @@
 			break;
 		}
 		/* handle command packet here */
-		if (rtlpriv->cfg->ops->rx_command_packet &&
-		    rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
+		if (rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
 				dev_kfree_skb_any(skb);
 				goto end;
 		}
@@ -1128,14 +1127,9 @@
 
 	__skb_queue_tail(&ring->queue, pskb);
 
-	if (rtlpriv->use_new_trx_flow) {
-		temp_one = 4;
-		rtlpriv->cfg->ops->set_desc(hw, (u8 *)pbuffer_desc, true,
-					    HW_DESC_OWN, (u8 *)&temp_one);
-	} else {
-		rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN,
-					    &temp_one);
-	}
+	rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN,
+				    &temp_one);
+
 	return;
 }
 
@@ -1376,9 +1370,9 @@
 	ring->desc = NULL;
 	if (rtlpriv->use_new_trx_flow) {
 		pci_free_consistent(rtlpci->pdev,
-				    sizeof(*ring->buffer_desc) * ring->entries,
+				    sizeof(*ring->desc) * ring->entries,
 				    ring->buffer_desc, ring->buffer_desc_dma);
-		ring->buffer_desc = NULL;
+		ring->desc = NULL;
 	}
 }
 
@@ -1549,6 +1543,7 @@
 							 true,
 							 HW_DESC_TXBUFF_ADDR),
 						 skb->len, PCI_DMA_TODEVICE);
+				ring->idx = (ring->idx + 1) % ring->entries;
 				kfree_skb(skb);
 				ring->idx = (ring->idx + 1) % ring->entries;
 			}
@@ -1801,8 +1796,7 @@
 	rtl_pci_reset_trx_ring(hw);
 
 	rtlpci->driver_is_goingto_unload = false;
-	if (rtlpriv->cfg->ops->get_btc_status &&
-	    rtlpriv->cfg->ops->get_btc_status()) {
+	if (rtlpriv->cfg->ops->get_btc_status()) {
 		rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv);
 		rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv);
 	}
@@ -2249,16 +2243,6 @@
 	/*like read eeprom and so on */
 	rtlpriv->cfg->ops->read_eeprom_info(hw);
 
-	if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
-		err = -ENODEV;
-		goto fail3;
-	}
-	rtlpriv->cfg->ops->init_sw_leds(hw);
-
-	/*aspm */
-	rtl_pci_init_aspm(hw);
-
 	/* Init mac80211 sw */
 	err = rtl_init_core(hw);
 	if (err) {
@@ -2274,6 +2258,16 @@
 		goto fail3;
 	}
 
+	if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
+		err = -ENODEV;
+		goto fail3;
+	}
+	rtlpriv->cfg->ops->init_sw_leds(hw);
+
+	/*aspm */
+	rtl_pci_init_aspm(hw);
+
 	err = ieee80211_register_hw(hw);
 	if (err) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index 29983bc..a00861b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -656,8 +656,7 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
-	 bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -723,10 +722,7 @@
 	memcpy((u8 *)skb_put(skb, totalpacketlen),
 	       &reserved_page_packet, totalpacketlen);
 
-	if (cmd_send_packet)
-		rtstatus = cmd_send_packet(hw, skb);
-	else
-		rtstatus = rtl_cmd_send_packet(hw, skb);
+	rtstatus = rtl_cmd_send_packet(hw, skb);
 
 	if (rtstatus)
 		b_dlok = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
index b64ae45..a815bd6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
@@ -109,9 +109,7 @@
 			 u32 cmd_len, u8 *p_cmdbuffer);
 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
-void rtl92c_set_fw_rsvdpagepkt
-	(struct ieee80211_hw *hw,
-	 bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *));
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
 void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len);
 void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 9b660df..831df10 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -114,8 +114,6 @@
 	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4)
 #define	GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr)	\
 	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
-#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc)			\
-	SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
 
 #define CHIP_VER_B			BIT(4)
 #define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 5c646d5..8ec0f03 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -459,7 +459,7 @@
 				rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
 					       tmp_reg422 & (~BIT(6)));
 
-				rtl92c_set_fw_rsvdpagepkt(hw, NULL);
+				rtl92c_set_fw_rsvdpagepkt(hw, 0);
 
 				_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
 				_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4));
@@ -955,7 +955,6 @@
 	local_save_flags(flags);
 	local_irq_enable();
 
-	rtlhal->fw_ready = false;
 	rtlpriv->intf_ops->disable_aspm(hw);
 	rtstatus = _rtl92ce_init_mac(hw);
 	if (!rtstatus) {
@@ -972,7 +971,6 @@
 		goto exit;
 	}
 
-	rtlhal->fw_ready = true;
 	rtlhal->last_hmeboxnum = 0;
 	rtl92c_phy_mac_config(hw);
 	/* because last function modify RCR, so we update
@@ -1289,7 +1287,6 @@
 
 	rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
 	rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
-	rtlpci->irq_enabled = true;
 }
 
 void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
@@ -1299,7 +1296,7 @@
 
 	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
 	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
-	rtlpci->irq_enabled = false;
+	synchronize_irq(rtlpci->pdev->irq);
 }
 
 static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index dd5aa08..d86b5b5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -228,7 +228,6 @@
 	.led_control = rtl92ce_led_control,
 	.set_desc = rtl92ce_set_desc,
 	.get_desc = rtl92ce_get_desc,
-	.is_tx_desc_closed = rtl92ce_is_tx_desc_closed,
 	.tx_polling = rtl92ce_tx_polling,
 	.enable_hw_sec = rtl92ce_enable_hw_security_config,
 	.set_key = rtl92ce_set_key,
@@ -245,7 +244,6 @@
 	.phy_lc_calibrate = _rtl92ce_phy_lc_calibrate,
 	.phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback,
 	.dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower,
-	.get_btc_status = rtl_btc_status_false,
 };
 
 static struct rtl_mod_params rtl92ce_mod_params = {
@@ -272,8 +270,6 @@
 	.maps[MAC_RCR_ACRC32] = ACRC32,
 	.maps[MAC_RCR_ACF] = ACF,
 	.maps[MAC_RCR_AAP] = AAP,
-	.maps[MAC_HIMR] = REG_HIMR,
-	.maps[MAC_HIMRE] = REG_HIMRE,
 
 	.maps[EFUSE_TEST] = REG_EFUSE_TEST,
 	.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index e88dcd0..2fb9c7a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -720,15 +720,13 @@
 			break;
 		}
 	} else {
+		struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
 		switch (desc_name) {
 		case HW_DESC_OWN:
-			ret = GET_RX_DESC_OWN(p_desc);
+			ret = GET_RX_DESC_OWN(pdesc);
 			break;
 		case HW_DESC_RXPKT_LEN:
-			ret = GET_RX_DESC_PKT_LEN(p_desc);
-			break;
-		case HW_DESC_RXBUFF_ADDR:
-			ret = GET_RX_DESC_BUFF_ADDR(p_desc);
+			ret = GET_RX_DESC_PKT_LEN(pdesc);
 			break;
 		default:
 			RT_ASSERT(false, "ERR rxdesc :%d not process\n",
@@ -739,23 +737,6 @@
 	return ret;
 }
 
-bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw,
-			       u8 hw_queue, u16 index)
-{
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
-	u8 *entry = (u8 *)(&ring->desc[ring->idx]);
-	u8 own = (u8)rtl92ce_get_desc(entry, true, HW_DESC_OWN);
-
-	/*beacon packet will only use the first
-	 *descriptor defautly,and the own may not
-	 *be cleared by the hardware
-	 */
-	if (own)
-		return false;
-	return true;
-}
-
 void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
index 4bec4b0..9a39ec4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
@@ -723,8 +723,6 @@
 void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
 		      u8 desc_name, u8 *val);
 u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name);
-bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw,
-			       u8 hw_queue, u16 index);
 void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
 void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 			     bool b_firstseg, bool b_lastseg,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 5513217..04aa0b5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -1592,20 +1592,6 @@
 	}
 }
 
-static bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-  /* Currently nothing happens here.
-   * Traffic stops after some seconds in WPA2 802.11n mode.
-   * Maybe because rtl8192cu chip should be set from here?
-   * If I understand correctly, the realtek vendor driver sends some urbs
-   * if its "here".
-   *
-   * This is maybe necessary:
-   * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb);
-   */
-	return true;
-}
-
 void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1953,8 +1939,7 @@
 					recover = true;
 				rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
 					       tmp_reg422 & (~BIT(6)));
-				rtl92c_set_fw_rsvdpagepkt(hw,
-							  &usb_cmd_send_packet);
+				rtl92c_set_fw_rsvdpagepkt(hw, 0);
 				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
 				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
 				if (recover)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
index c1e33b0..0f7812e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
@@ -104,6 +104,7 @@
 void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
 int rtl92c_download_fw(struct ieee80211_hw *hw);
 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished);
 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
 			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index 97f85b7..18933c0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -101,12 +101,6 @@
 	}
 }
 
-/* get bt coexist status */
-static bool rtl92cu_get_btc_status(void)
-{
-	return false;
-}
-
 static struct rtl_hal_ops rtl8192cu_hal_ops = {
 	.init_sw_vars = rtl92cu_init_sw_vars,
 	.deinit_sw_vars = rtl92cu_deinit_sw_vars,
@@ -154,7 +148,6 @@
 	.phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
 	.dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
 	.fill_h2c_cmd = rtl92c_fill_h2c_cmd,
-	.get_btc_status = rtl92cu_get_btc_status,
 };
 
 static struct rtl_mod_params rtl92cu_mod_params = {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
index a0aba08..edab5a5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -251,7 +251,6 @@
 	.get_rfreg = rtl92d_phy_query_rf_reg,
 	.set_rfreg = rtl92d_phy_set_rf_reg,
 	.linked_set_reg = rtl92d_linked_set_reg,
-	.get_btc_status = rtl_btc_status_false,
 };
 
 static struct rtl_mod_params rtl92de_mod_params = {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile b/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile
index c5e6f97..aeea8a9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile
@@ -1,3 +1,6 @@
+obj-m := rtl8192ee.o
+
+
 rtl8192ee-objs :=		\
 		dm.o		\
 		fw.o		\
@@ -11,6 +14,6 @@
 		trx.o		\
 
 
-obj-$(CPTCFG_RTL8192EE) += rtl8192ee.o
+obj-$(CPTCFG_RTL8821AE) += rtl8192ee.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
index 1a87edc..dfdc9b2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
@@ -362,7 +362,7 @@
 		}
 		break;
 	default:
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "switch case not process %x\n", variable);
 		break;
 	}
@@ -591,7 +591,7 @@
 				acm_ctrl &= (~ACMHW_BEQEN);
 				break;
 			default:
-				RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 					 "switch case not process\n");
 				break;
 			}
@@ -710,7 +710,7 @@
 		}
 		break;
 	default:
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 "switch case not process %x\n", variable);
 		break;
 	}
@@ -2424,7 +2424,7 @@
 			enc_algo = CAM_AES;
 			break;
 		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 				 "switch case not process\n");
 			enc_algo = CAM_TKIP;
 			break;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
index 6e7a70b..83c9867 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
@@ -446,8 +446,6 @@
 /* DWORD 6 */
 #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val)	\
 	SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
-#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc)			\
-	SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
 
 #define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
 	(GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||	\
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 5761d5b..00e0670 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -1201,9 +1201,6 @@
 
 	}
 
-	if (type != NL80211_IFTYPE_AP &&
-	    rtlpriv->mac80211.link_state < MAC80211_LINKED)
-		bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK;
 	rtl_write_byte(rtlpriv, (MSR), bt_msr);
 
 	temp = rtl_read_dword(rtlpriv, TCR);
@@ -1265,7 +1262,6 @@
 	rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);
 	/* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */
 	rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F);
-	rtlpci->irq_enabled = true;
 }
 
 void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
@@ -1280,7 +1276,8 @@
 	rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	rtl_write_dword(rtlpriv, INTA_MASK, 0);
 	rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
-	rtlpci->irq_enabled = false;
+
+	synchronize_irq(rtlpci->pdev->irq);
 }
 
 static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index 4b4612f..77c5b5f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -399,8 +399,6 @@
 		case 2:
 			currentcmd = &postcommoncmd[*step];
 			break;
-		default:
-			return true;
 		}
 
 		if (currentcmd->cmdid == CMDID_END) {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index fb00386..1bff2a0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -87,8 +87,11 @@
 static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
 {
 	struct ieee80211_hw *hw = context;
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
 	struct rt_firmware *pfirmware = NULL;
+	int err;
 
 	RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
 			 "Firmware callback routine entered!\n");
@@ -109,6 +112,20 @@
 	memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
 	pfirmware->sz_fw_tmpbufferlen = firmware->size;
 	release_firmware(firmware);
+
+	err = ieee80211_register_hw(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Can't register mac80211 hw\n");
+		return;
+	} else {
+		rtlpriv->mac80211.mac80211_registered = 1;
+	}
+	rtlpci->irq_alloc = 1;
+	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
+
+	/*init rfkill */
+	rtl_init_rfkill(hw);
 }
 
 static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
@@ -209,8 +226,8 @@
 	if (!rtlpriv->rtlhal.pfirmware)
 		return 1;
 
-	rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 +
-			       sizeof(struct fw_hdr);
+	rtlpriv->max_fw_size = RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE;
+
 	pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
 		"Loading firmware %s\n", rtlpriv->cfg->fw_name);
 	/* request fw */
@@ -236,19 +253,6 @@
 	}
 }
 
-static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue,
-				      u16 index)
-{
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
-	u8 *entry = (u8 *)(&ring->desc[ring->idx]);
-	u8 own = (u8)rtl92se_get_desc(entry, true, HW_DESC_OWN);
-
-	if (own)
-		return false;
-	return true;
-}
-
 static struct rtl_hal_ops rtl8192se_hal_ops = {
 	.init_sw_vars = rtl92s_init_sw_vars,
 	.deinit_sw_vars = rtl92s_deinit_sw_vars,
@@ -282,7 +286,6 @@
 	.led_control = rtl92se_led_control,
 	.set_desc = rtl92se_set_desc,
 	.get_desc = rtl92se_get_desc,
-	.is_tx_desc_closed = rtl92se_is_tx_desc_closed,
 	.tx_polling = rtl92se_tx_polling,
 	.enable_hw_sec = rtl92se_enable_hw_security_config,
 	.set_key = rtl92se_set_key,
@@ -291,7 +294,6 @@
 	.set_bbreg = rtl92s_phy_set_bb_reg,
 	.get_rfreg = rtl92s_phy_query_rf_reg,
 	.set_rfreg = rtl92s_phy_set_rf_reg,
-	.get_btc_status = rtl_btc_status_false,
 };
 
 static struct rtl_mod_params rtl92se_mod_params = {
@@ -320,8 +322,6 @@
 	.maps[MAC_RCR_ACRC32] = RCR_ACRC32,
 	.maps[MAC_RCR_ACF] = RCR_ACF,
 	.maps[MAC_RCR_AAP] = RCR_AAP,
-	.maps[MAC_HIMR] = INTA_MASK,
-	.maps[MAC_HIMRE] = INTA_MASK + 4,
 
 	.maps[EFUSE_TEST] = REG_EFUSE_TEST,
 	.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 672fd3b..b358ebc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -640,9 +640,6 @@
 		case HW_DESC_RXPKT_LEN:
 			ret = GET_RX_STATUS_DESC_PKT_LEN(desc);
 			break;
-		case HW_DESC_RXBUFF_ADDR:
-			ret = GET_RX_STATUS_DESC_BUFF_ADDR(desc);
-			break;
 		default:
 			RT_ASSERT(false, "ERR rxdesc :%d not process\n",
 				  desc_name);
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
index e8ce901..e0b1dde 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
@@ -1,3 +1,6 @@
+obj-m := rtl8723ae.o
+
+
 rtl8723ae-objs :=		\
 		dm.o		\
 		fw.o		\
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile b/drivers/net/wireless/rtlwifi/rtl8723be/Makefile
index cd01566..5d18f04 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/Makefile
@@ -1,3 +1,6 @@
+obj-m := rtl8723be.o
+
+
 rtl8723be-objs :=		\
 		dm.o		\
 		fw.o		\
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile b/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile
index 5215004..445930c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile
@@ -1,3 +1,6 @@
+obj-m := rtl8821ae.o
+
+
 rtl8821ae-objs :=		\
 		dm.o		\
 		fw.o		\
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
index ba30b0d..9be1061 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
@@ -2078,7 +2078,8 @@
 	if (rtldm->tx_rate != 0xFF)
 		tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
 
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__);
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
 
 	if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
 		/*CCK*/
@@ -2127,7 +2128,7 @@
 
 	if (method == BBSWING) {
 		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-			 "===>%s\n", __func__);
+			 "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
 		if (rf_path == RF90_PATH_A) {
 			final_swing_idx[RF90_PATH_A] =
 				(rtldm->ofdm_index[RF90_PATH_A] >
@@ -2259,8 +2260,7 @@
 	rtldm->txpower_trackinginit = true;
 
 	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-		 "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
-		 __func__,
+		 "===>rtl8812ae_dm_txpower_tracking_callback_thermalmeter,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
 		 rtldm->swing_idx_cck_base,
 		 rtldm->swing_idx_ofdm_base[RF90_PATH_A],
 		 rtldm->default_ofdm_index);
@@ -2539,7 +2539,8 @@
 		}
 	}
 
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__);
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n");
 }
 
 void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
index 8ec8200..310d316 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
@@ -3672,9 +3672,8 @@
 		mac->opmode == NL80211_IFTYPE_ADHOC)
 		macid = sta->aid + 1;
 	if (wirelessmode == WIRELESS_MODE_N_5G ||
-	    wirelessmode == WIRELESS_MODE_AC_5G ||
-	    wirelessmode == WIRELESS_MODE_A)
-		ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ] << 4;
+	    wirelessmode == WIRELESS_MODE_AC_5G)
+		ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ];
 	else
 		ratr_bitmap = sta->supp_rates[NL80211_BAND_2GHZ];
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
index 9b4d8a6..9786313 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
@@ -800,7 +800,7 @@
 				 "Invalid RateSection %d in Band 2.4G,Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n",
 				 rate_section, path, txnum);
 			break;
-		}
+		};
 	} else if (band == BAND_ON_5G) {
 		switch (rate_section) {
 		case OFDM:
@@ -823,7 +823,7 @@
 				"Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n",
 				rate_section, path, txnum);
 			break;
-		}
+		};
 	} else {
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 			"Invalid Band %d in PHY_SetTxPowerByRateBase()\n", band);
@@ -870,7 +870,7 @@
 				 "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n",
 				 rate_section, path, txnum);
 			break;
-		}
+		};
 	} else if (band == BAND_ON_5G) {
 		switch (rate_section) {
 		case OFDM:
@@ -893,7 +893,7 @@
 				 "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n",
 				 rate_section, path, txnum);
 			break;
-		}
+		};
 	} else {
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 			 "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", band);
@@ -1889,18 +1889,15 @@
 	struct rtl_phy *rtlphy = &rtlpriv->phy;
 	u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr);
 
-	if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
+	if (band != BAND_ON_2_4G && band != BAND_ON_5G)
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band);
-		band = BAND_ON_2_4G;
-	}
-	if (rfpath >= MAX_RF_PATH) {
+
+	if (rfpath >= MAX_RF_PATH)
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath);
-		rfpath = MAX_RF_PATH - 1;
-	}
-	if (txnum >= MAX_RF_PATH) {
+
+	if (txnum >= MAX_RF_PATH)
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum);
-		txnum = MAX_RF_PATH - 1;
-	}
+
 	rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data;
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 		 "TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n",
@@ -3746,7 +3743,7 @@
 		break;
 	default:
 		break;
-	}
+	};
 }
 
 static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw,
@@ -3767,7 +3764,7 @@
 		break;
 	default:
 		break;
-	}
+	};
 }
 
 #define cal_num 10
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 46ee956..10cf69c 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -1117,18 +1117,7 @@
 	}
 	rtlpriv->cfg->ops->init_sw_leds(hw);
 
-	err = ieee80211_register_hw(hw);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 "Can't register mac80211 hw.\n");
-		err = -ENODEV;
-		goto error_out;
-	}
-	rtlpriv->mac80211.mac80211_registered = 1;
-
-	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 	return 0;
-
 error_out:
 	rtl_deinit_core(hw);
 	_rtl_usb_io_handler_release(hw);
diff --git a/drivers/net/wireless/ti/wl1251/Kconfig b/drivers/net/wireless/ti/wl1251/Kconfig
index 1d9ca90..76649c5 100644
--- a/drivers/net/wireless/ti/wl1251/Kconfig
+++ b/drivers/net/wireless/ti/wl1251/Kconfig
@@ -12,7 +12,7 @@
 	  N if unsure.
 
 config WL1251_SPI
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_5
 	tristate "TI wl1251 SPI support"
 	depends on m
 	depends on WL1251 && SPI_MASTER
@@ -25,7 +25,7 @@
 	  Say N if unsure.
 
 config WL1251_SDIO
-	depends on !KERNEL_3_15
+	depends on !BACKPORT_KERNEL_3_15
 	tristate "TI wl1251 SDIO support"
 	depends on m
 	depends on WL1251 && MMC
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 0b30a7b..3823485 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1029,7 +1029,7 @@
 			goto out_sleep;
 	}
 
-	skb = ieee80211_probereq_get(wl->hw, wl->vif->addr, ssid, ssid_len,
+	skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
 				     req->ie_len);
 	if (!skb) {
 		ret = -ENOMEM;
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index d6d0d6d..0bccf12 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1900,6 +1900,7 @@
 	.id_table	= wl12xx_id_table,
 	.driver = {
 		.name	= "wl12xx_driver",
+		.owner	= THIS_MODULE,
 	}
 };
 
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 8e56261..7af1936 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1968,6 +1968,7 @@
 	.id_table	= wl18xx_id_table,
 	.driver = {
 		.name	= "wl18xx_driver",
+		.owner	= THIS_MODULE,
 	}
 };
 
diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig
index 09bb747..4bab094 100644
--- a/drivers/net/wireless/ti/wlcore/Kconfig
+++ b/drivers/net/wireless/ti/wlcore/Kconfig
@@ -26,7 +26,7 @@
 	  Say N if unsure.
 
 config WLCORE_SDIO
-	depends on !KERNEL_3_15
+	depends on !BACKPORT_KERNEL_3_15
 	tristate "TI wlcore SDIO support"
 	depends on m
 	depends on WLCORE && MMC
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index b826619..05604ee 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -64,9 +64,6 @@
 		     id != CMD_STOP_FWLOGGER))
 		return -EIO;
 
-	if (WARN_ON_ONCE(len < sizeof(*cmd)))
-		return -EIO;
-
 	cmd = buf;
 	cmd->id = cpu_to_le16(id);
 	cmd->status = 0;
@@ -131,9 +128,8 @@
  * send command to fw and return cmd status on success
  * valid_rets contains a bitmap of allowed error codes
  */
-static int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf,
-				    size_t len, size_t res_len,
-				    unsigned long valid_rets)
+int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len,
+			     size_t res_len, unsigned long valid_rets)
 {
 	int ret = __wlcore_cmd_send(wl, id, buf, len, res_len);
 
@@ -154,6 +150,7 @@
 	wl12xx_queue_recovery_work(wl);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(wl1271_cmd_send);
 
 /*
  * wrapper for wlcore_cmd_send that accept only CMD_STATUS_SUCCESS
@@ -168,7 +165,6 @@
 		return ret;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(wl1271_cmd_send);
 
 /*
  * Poll the mailbox event field until any of the bits in the mask is set or a
@@ -895,9 +891,6 @@
 
 	wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id);
 
-	if (WARN_ON_ONCE(len < sizeof(*acx)))
-		return -EIO;
-
 	acx->id = cpu_to_le16(id);
 
 	/* payload length, does not include any headers */
@@ -1145,7 +1138,7 @@
 
 	wl1271_debug(DEBUG_SCAN, "build probe request band %d", band);
 
-	skb = ieee80211_probereq_get(wl->hw, vif->addr, ssid, ssid_len,
+	skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
 				     ie0_len + ie1_len);
 	if (!skb) {
 		ret = -ENOMEM;
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index 453684a..ca6a28b 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -31,6 +31,8 @@
 
 int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
 		    size_t res_len);
+int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len,
+			     size_t res_len, unsigned long valid_rets);
 int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type,
 			   u8 *role_id);
 int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 5153640..16d1028 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -259,7 +259,10 @@
 					     &wlvif->connection_loss_work,
 					     msecs_to_jiffies(delay));
 
-		ieee80211_cqm_beacon_loss_notify(vif, GFP_KERNEL);
+		ieee80211_cqm_rssi_notify(
+				vif,
+				NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
+				GFP_KERNEL);
 	}
 }
 EXPORT_SYMBOL_GPL(wlcore_event_beacon_loss);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 6ad3fce..575c8f6 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5177,11 +5177,10 @@
 }
 
 static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
 				     struct ieee80211_channel_switch *ch_switch)
 {
 	struct wl1271 *wl = hw->priv;
-	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+	struct wl12xx_vif *wlvif;
 	int ret;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
@@ -5191,8 +5190,14 @@
 	mutex_lock(&wl->mutex);
 
 	if (unlikely(wl->state == WLCORE_STATE_OFF)) {
-		if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+		wl12xx_for_each_wlvif_sta(wl, wlvif) {
+			struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
+			if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+				continue;
+
 			ieee80211_chswitch_done(vif, false);
+		}
 		goto out;
 	} else if (unlikely(wl->state != WLCORE_STATE_ON)) {
 		goto out;
@@ -5203,10 +5208,12 @@
 		goto out;
 
 	/* TODO: change mac80211 to pass vif as param */
-
-	if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
+	wl12xx_for_each_wlvif_sta(wl, wlvif) {
 		unsigned long delay_usec;
 
+		if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+			continue;
+
 		ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
 		if (ret)
 			goto out_sleep;
@@ -5215,10 +5222,10 @@
 
 		/* indicate failure 5 seconds after channel switch time */
 		delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) *
-			ch_switch->count;
+			     ch_switch->count;
 		ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work,
-					     usecs_to_jiffies(delay_usec) +
-					     msecs_to_jiffies(5000));
+				usecs_to_jiffies(delay_usec) +
+				msecs_to_jiffies(5000));
 	}
 
 out_sleep:
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 07b94ed..73a49b8 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -129,7 +129,7 @@
 	r = zd_ioread16v_locked(chip, v16, a16, count16);
 	if (r) {
 		dev_dbg_f(zd_chip_dev(chip),
-			  "error: %s. Error number %d\n", __func__, r);
+			  "error: zd_ioread16v_locked. Error number %d\n", r);
 		return r;
 	}
 
@@ -256,8 +256,8 @@
 		if (r) {
 			zd_usb_iowrite16v_async_end(&chip->usb, 0);
 			dev_dbg_f(zd_chip_dev(chip),
-				"error _%s. Error number %d\n", __func__,
-				r);
+				"error _zd_iowrite32v_locked."
+				" Error number %d\n", r);
 			return r;
 		}
 	}
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 5d8f3a9..6d0ae8f 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -29,7 +29,7 @@
 	  into the kernel or say M to compile it as module.
 
 config NFC_TRF7970A
-	depends on !KERNEL_3_4
+	depends on !BACKPORT_KERNEL_3_4
 	tristate "Texas Instruments TRF7970a NFC driver"
 	depends on m
 	depends on SPI && NFC_DIGITAL
@@ -43,7 +43,7 @@
 	  trf7970a.ko.
 
 config NFC_MEI_PHY
-	depends on !KERNEL_3_10
+	depends on !BACKPORT_KERNEL_3_10
 	tristate "MEI bus NFC device support"
 	depends on m
 	depends on INTEL_MEI && NFC_HCI
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c
index ce2e2cf..683671a 100644
--- a/drivers/nfc/nfcwilink.c
+++ b/drivers/nfc/nfcwilink.c
@@ -566,6 +566,7 @@
 	.remove = nfcwilink_remove,
 	.driver = {
 		.name = "nfcwilink",
+		.owner = THIS_MODULE,
 	},
 };
 
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
index fc02e8d..440291a 100644
--- a/drivers/nfc/pn544/i2c.c
+++ b/drivers/nfc/pn544/i2c.c
@@ -29,8 +29,8 @@
 #include <linux/delay.h>
 #include <linux/nfc.h>
 #include <linux/firmware.h>
+#include <linux/unaligned/access_ok.h>
 #include <linux/platform_data/pn544.h>
-#include <asm/unaligned.h>
 
 #include <net/nfc/hci.h>
 #include <net/nfc/llc.h>
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 0572208..0ea756b 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -28,8 +28,8 @@
 #include <linux/delay.h>
 #include <linux/nfc.h>
 #include <linux/firmware.h>
+#include <linux/unaligned/access_ok.h>
 #include <linux/platform_data/st21nfca.h>
-#include <asm/unaligned.h>
 
 #include <net/nfc/hci.h>
 #include <net/nfc/llc.h>
@@ -72,6 +72,7 @@
 	struct nfc_hci_dev *hdev;
 
 	unsigned int gpio_ena;
+	unsigned int gpio_irq;
 	unsigned int irq_polarity;
 
 	struct sk_buff *pending_skb;
@@ -530,12 +531,20 @@
 				  "clf_enable");
 	if (r) {
 		nfc_err(&client->dev, "Failed to request enable pin\n");
-		return r;
+		return -ENODEV;
 	}
 
 	phy->gpio_ena = gpio;
 
-	phy->irq_polarity = irq_get_trigger_type(client->irq);
+	/* IRQ */
+	r = irq_of_parse_and_map(pp, 0);
+	if (r < 0) {
+		nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
+		return r;
+	}
+
+	phy->irq_polarity = irq_get_trigger_type(r);
+	client->irq = r;
 
 	return 0;
 }
@@ -551,6 +560,7 @@
 	struct st21nfca_nfc_platform_data *pdata;
 	struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
 	int r;
+	int irq;
 
 	pdata = client->dev.platform_data;
 	if (pdata == NULL) {
@@ -559,18 +569,36 @@
 	}
 
 	/* store for later use */
+	phy->gpio_irq = pdata->gpio_irq;
 	phy->gpio_ena = pdata->gpio_ena;
 	phy->irq_polarity = pdata->irq_polarity;
 
+	r = devm_gpio_request_one(&client->dev, phy->gpio_irq, GPIOF_IN,
+				  "wake_up");
+	if (r) {
+		pr_err("%s : gpio_request failed\n", __FILE__);
+		return -ENODEV;
+	}
+
 	if (phy->gpio_ena > 0) {
 		r = devm_gpio_request_one(&client->dev, phy->gpio_ena,
 					  GPIOF_OUT_INIT_HIGH, "clf_enable");
 		if (r) {
 			pr_err("%s : ena gpio_request failed\n", __FILE__);
-			return r;
+			return -ENODEV;
 		}
 	}
 
+	/* IRQ */
+	irq = gpio_to_irq(phy->gpio_irq);
+	if (irq < 0) {
+		nfc_err(&client->dev,
+				"Unable to get irq number for GPIO %d error %d\n",
+				phy->gpio_irq, r);
+		return -ENODEV;
+	}
+	client->irq = irq;
+
 	return 0;
 }
 
@@ -628,7 +656,7 @@
 	r = st21nfca_hci_platform_init(phy);
 	if (r < 0) {
 		nfc_err(&client->dev, "Unable to reboot st21nfca\n");
-		return r;
+		return -ENODEV;
 	}
 
 	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
@@ -659,13 +687,10 @@
 	return 0;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id of_st21nfca_i2c_match[] = {
 	{ .compatible = "st,st21nfca_i2c", },
 	{}
 };
-MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match);
-#endif
 
 static struct i2c_driver st21nfca_hci_i2c_driver = {
 	.driver = {
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index f2596c8..a89e56c 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -77,6 +77,10 @@
 	((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))
 
 #define ST21NFCA_NFC_MODE			0x03	/* NFC_MODE parameter*/
+#define ST21NFCA_EVT_FIELD_ON			0x11
+#define ST21NFCA_EVT_CARD_DEACTIVATED		0x12
+#define ST21NFCA_EVT_CARD_ACTIVATED		0x13
+#define ST21NFCA_EVT_FIELD_OFF			0x14
 
 static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
 
@@ -837,11 +841,31 @@
 static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
 				       u8 event, struct sk_buff *skb)
 {
-	pr_debug("hci event: %d gate: %x\n", event, gate);
+	int r;
+	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
 
-	switch (gate) {
-	case ST21NFCA_RF_CARD_F_GATE:
-		return st21nfca_dep_event_received(hdev, event, skb);
+	pr_debug("hci event: %d\n", event);
+
+	switch (event) {
+	case ST21NFCA_EVT_CARD_ACTIVATED:
+		if (gate == ST21NFCA_RF_CARD_F_GATE)
+			info->dep_info.curr_nfc_dep_pni = 0;
+		break;
+	case ST21NFCA_EVT_CARD_DEACTIVATED:
+		break;
+	case ST21NFCA_EVT_FIELD_ON:
+		break;
+	case ST21NFCA_EVT_FIELD_OFF:
+		break;
+	case ST21NFCA_EVT_SEND_DATA:
+		if (gate == ST21NFCA_RF_CARD_F_GATE) {
+			r = st21nfca_tm_event_send_data(hdev, skb, gate);
+			if (r < 0)
+				return r;
+			return 0;
+		}
+		info->dep_info.curr_nfc_dep_pni = 0;
+		return 1;
 	default:
 		return 1;
 	}
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 7c2a852..a0b77f1 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -85,4 +85,6 @@
 
 #define ST21NFCA_RF_CARD_F_GATE 0x24
 
+#define ST21NFCA_EVT_SEND_DATA 0x10
+
 #endif /* __LOCAL_ST21NFCA_H_ */
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c
index 8882181..bfb6df5 100644
--- a/drivers/nfc/st21nfca/st21nfca_dep.c
+++ b/drivers/nfc/st21nfca/st21nfca_dep.c
@@ -49,12 +49,6 @@
 #define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30
 #define ST21NFCA_GB_BIT  0x02
 
-#define ST21NFCA_EVT_SEND_DATA		0x10
-#define ST21NFCA_EVT_FIELD_ON           0x11
-#define ST21NFCA_EVT_CARD_DEACTIVATED   0x12
-#define ST21NFCA_EVT_CARD_ACTIVATED     0x13
-#define ST21NFCA_EVT_FIELD_OFF          0x14
-
 #define ST21NFCA_EVT_CARD_F_BITRATE 0x16
 #define ST21NFCA_EVT_READER_F_BITRATE 0x13
 #define	ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38)
@@ -378,8 +372,8 @@
 	return r;
 }
 
-static int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev,
-				struct sk_buff *skb)
+int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
+				u8 gate)
 {
 	u8 cmd0, cmd1;
 	int r;
@@ -406,42 +400,7 @@
 	}
 	return r;
 }
-
-/*
- * Returns:
- * <= 0: driver handled the event, skb consumed
- *    1: driver does not handle the event, please do standard processing
- */
-int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
-				u8 event, struct sk_buff *skb)
-{
-	int r = 0;
-	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	pr_debug("dep event: %d\n", event);
-
-	switch (event) {
-	case ST21NFCA_EVT_CARD_ACTIVATED:
-		info->dep_info.curr_nfc_dep_pni = 0;
-		break;
-	case ST21NFCA_EVT_CARD_DEACTIVATED:
-		break;
-	case ST21NFCA_EVT_FIELD_ON:
-		break;
-	case ST21NFCA_EVT_FIELD_OFF:
-		break;
-	case ST21NFCA_EVT_SEND_DATA:
-		r = st21nfca_tm_event_send_data(hdev, skb);
-		if (r < 0)
-			return r;
-		return 0;
-	default:
-		return 1;
-	}
-	kfree_skb(skb);
-	return r;
-}
-EXPORT_SYMBOL(st21nfca_dep_event_received);
+EXPORT_SYMBOL(st21nfca_tm_event_send_data);
 
 static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
 				     u8 bri, u8 lri)
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.h b/drivers/nfc/st21nfca/st21nfca_dep.h
index baf4664..ca213de 100644
--- a/drivers/nfc/st21nfca/st21nfca_dep.h
+++ b/drivers/nfc/st21nfca/st21nfca_dep.h
@@ -32,8 +32,8 @@
 	u8 lri;
 } __packed;
 
-int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
-				u8 event, struct sk_buff *skb);
+int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
+				u8 gate);
 int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
 
 int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c
index 01ba865..c5d2427 100644
--- a/drivers/nfc/st21nfcb/i2c.c
+++ b/drivers/nfc/st21nfcb/i2c.c
@@ -50,6 +50,7 @@
 	struct i2c_client *i2c_dev;
 	struct llt_ndlc *ndlc;
 
+	unsigned int gpio_irq;
 	unsigned int gpio_reset;
 	unsigned int irq_polarity;
 
@@ -80,6 +81,8 @@
 {
 	struct st21nfcb_i2c_phy *phy = phy_id;
 
+	pr_info("\n");
+
 	phy->powered = 0;
 	/* reset chip in order to flush clf */
 	gpio_set_value(phy->gpio_reset, 0);
@@ -255,11 +258,19 @@
 				GPIOF_OUT_INIT_HIGH, "clf_reset");
 	if (r) {
 		nfc_err(&client->dev, "Failed to request reset pin\n");
-		return r;
+		return -ENODEV;
 	}
 	phy->gpio_reset = gpio;
 
-	phy->irq_polarity = irq_get_trigger_type(client->irq);
+	/* IRQ */
+	r = irq_of_parse_and_map(pp, 0);
+	if (r < 0) {
+		nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
+		return r;
+	}
+
+	phy->irq_polarity = irq_get_trigger_type(r);
+	client->irq = r;
 
 	return 0;
 }
@@ -275,6 +286,7 @@
 	struct st21nfcb_nfc_platform_data *pdata;
 	struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
 	int r;
+	int irq;
 
 	pdata = client->dev.platform_data;
 	if (pdata == NULL) {
@@ -283,16 +295,34 @@
 	}
 
 	/* store for later use */
+	phy->gpio_irq = pdata->gpio_irq;
 	phy->gpio_reset = pdata->gpio_reset;
 	phy->irq_polarity = pdata->irq_polarity;
 
+	r = devm_gpio_request_one(&client->dev, phy->gpio_irq,
+				GPIOF_IN, "clf_irq");
+	if (r) {
+		pr_err("%s : gpio_request failed\n", __FILE__);
+		return -ENODEV;
+	}
+
 	r = devm_gpio_request_one(&client->dev,
 			phy->gpio_reset, GPIOF_OUT_INIT_HIGH, "clf_reset");
 	if (r) {
 		pr_err("%s : reset gpio_request failed\n", __FILE__);
-		return r;
+		return -ENODEV;
 	}
 
+	/* IRQ */
+	irq = gpio_to_irq(phy->gpio_irq);
+	if (irq < 0) {
+		nfc_err(&client->dev,
+			"Unable to get irq number for GPIO %d error %d\n",
+			phy->gpio_irq, r);
+		return -ENODEV;
+	}
+	client->irq = irq;
+
 	return 0;
 }
 
@@ -371,13 +401,10 @@
 	return 0;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id of_st21nfcb_i2c_match[] = {
 	{ .compatible = "st,st21nfcb_i2c", },
 	{}
 };
-MODULE_DEVICE_TABLE(of, of_st21nfcb_i2c_match);
-#endif
 
 static struct i2c_driver st21nfcb_nci_i2c_driver = {
 	.driver = {
diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st21nfcb/ndlc.c
index bac50e8..e7bff89 100644
--- a/drivers/nfc/st21nfcb/ndlc.c
+++ b/drivers/nfc/st21nfcb/ndlc.c
@@ -266,7 +266,7 @@
 
 	*ndlc_id = ndlc;
 
-	/* initialize timers */
+	/* start timers */
 	init_timer(&ndlc->t1_timer);
 	ndlc->t1_timer.data = (unsigned long)ndlc;
 	ndlc->t1_timer.function = ndlc_t1_timeout;
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
index aa6a333..d2ccd28 100644
--- a/drivers/nfc/trf7970a.c
+++ b/drivers/nfc/trf7970a.c
@@ -2154,7 +2154,7 @@
 }
 #endif
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
 static int trf7970a_pm_runtime_suspend(struct device *dev)
 {
 	struct spi_device *spi = container_of(dev, struct spi_device, dev);
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index cc86fa1..4bc1252 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -128,7 +128,7 @@
 	  PCIcore hostmode operation (external PCI bus).
 
 config SSB_DRIVER_MIPS
-	depends on !KERNEL_3_3
+	depends on !BACKPORT_KERNEL_3_3
 	bool "SSB Broadcom MIPS core driver"
 	depends on SSB && MIPS
 	select SSB_SERIAL
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 7b986f9..0907706 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -15,9 +15,6 @@
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/time.h>
-#ifdef CONFIG_BCM47XX
-#include <bcm47xx_nvram.h>
-#endif
 
 #include "ssb_private.h"
 
@@ -213,7 +210,6 @@
 static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
 {
 	struct ssb_bus *bus = mcore->dev->bus;
-	struct ssb_sflash *sflash = &mcore->sflash;
 	struct ssb_pflash *pflash = &mcore->pflash;
 
 	/* When there is no chipcommon on the bus there is 4MB flash */
@@ -246,15 +242,7 @@
 	}
 
 ssb_pflash:
-	if (sflash->present) {
-#ifdef CONFIG_BCM47XX
-		bcm47xx_nvram_init_from_mem(sflash->window, sflash->size);
-#endif
-	} else if (pflash->present) {
-#ifdef CONFIG_BCM47XX
-		bcm47xx_nvram_init_from_mem(pflash->window, pflash->window_size);
-#endif
-
+	if (pflash->present) {
 		ssb_pflash_data.width = pflash->buswidth;
 		ssb_pflash_resource.start = pflash->window;
 		ssb_pflash_resource.end = pflash->window + pflash->window_size;
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
index b9ea3fb..69161bb 100644
--- a/drivers/ssb/pcihost_wrapper.c
+++ b/drivers/ssb/pcihost_wrapper.c
@@ -11,17 +11,15 @@
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
-#include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/ssb/ssb.h>
 
 
-#ifdef CONFIG_PM_SLEEP
-static int ssb_pcihost_suspend(struct device *d)
+#ifdef CONFIG_PM
+static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
 {
-	struct pci_dev *dev = to_pci_dev(d);
 	struct ssb_bus *ssb = pci_get_drvdata(dev);
 	int err;
 
@@ -30,25 +28,17 @@
 		return err;
 	pci_save_state(dev);
 	pci_disable_device(dev);
-
-	/* if there is a wakeup enabled child device on ssb bus,
-	   enable pci wakeup posibility. */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
-	device_set_wakeup_enable(d, d->power.wakeup_path);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) */
-
-	pci_prepare_to_sleep(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
 
 	return 0;
 }
 
-static int ssb_pcihost_resume(struct device *d)
+static int ssb_pcihost_resume(struct pci_dev *dev)
 {
-	struct pci_dev *dev = to_pci_dev(d);
 	struct ssb_bus *ssb = pci_get_drvdata(dev);
 	int err;
 
-	pci_back_from_sleep(dev);
+	pci_set_power_state(dev, PCI_D0);
 	err = pci_enable_device(dev);
 	if (err)
 		return err;
@@ -59,12 +49,10 @@
 
 	return 0;
 }
-
-static const struct dev_pm_ops ssb_pcihost_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(ssb_pcihost_suspend, ssb_pcihost_resume)
-};
-
-#endif /* CONFIG_PM_SLEEP */
+#else /* CONFIG_PM */
+# define ssb_pcihost_suspend	NULL
+# define ssb_pcihost_resume	NULL
+#endif /* CONFIG_PM */
 
 static int ssb_pcihost_probe(struct pci_dev *dev,
 			     const struct pci_device_id *id)
@@ -127,9 +115,8 @@
 {
 	driver->probe = ssb_pcihost_probe;
 	driver->remove = ssb_pcihost_remove;
-#ifdef CONFIG_PM_SLEEP
-	driver->driver.pm = &ssb_pcihost_pm_ops;
-#endif
+	driver->suspend = ssb_pcihost_suspend;
+	driver->resume = ssb_pcihost_resume;
 
 	return pci_register_driver(driver);
 }
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index 33eb274..a495a95 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -31,11 +31,8 @@
 	u32 gpio_mask;
 	u32 gpio_val;
 
-	bool endian_check;
 	bool is_clk_25mhz;
 	bool tx_gain_buffalo;
-	bool disable_2ghz;
-	bool disable_5ghz;
 
 	int (*get_mac_revision)(void);
 	int (*external_reset)(void);
diff --git a/include/linux/average.h b/include/linux/average.h
index e900121..dc5ba21 100644
--- a/include/linux/average.h
+++ b/include/linux/average.h
@@ -1,5 +1,5 @@
 /* Automatically created during backport process */
-#ifndef CPTCFG_BPAUTO_BUILD_AVERAGE
+#ifndef CPTCFG_BACKPORT_BUILD_AVERAGE
 #include_next <linux/average.h>
 #else
 #undef ewma_init
@@ -7,4 +7,4 @@
 #undef ewma_add
 #define ewma_add LINUX_BACKPORT(ewma_add)
 #include <linux/backport-average.h>
-#endif /* CPTCFG_BPAUTO_BUILD_AVERAGE */
+#endif /* CPTCFG_BACKPORT_BUILD_AVERAGE */
diff --git a/include/linux/backport-devcoredump.h b/include/linux/backport-devcoredump.h
deleted file mode 100644
index c1d2d00..0000000
--- a/include/linux/backport-devcoredump.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __DEVCOREDUMP_H
-#define __DEVCOREDUMP_H
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-
-#ifdef CPTCFG_BPAUTO_WANT_DEV_COREDUMP
-void dev_coredumpv(struct device *dev, const void *data, size_t datalen,
-		   gfp_t gfp);
-
-void dev_coredumpm(struct device *dev, struct module *owner,
-		   const void *data, size_t datalen, gfp_t gfp,
-		   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
-				   const void *data, size_t datalen),
-		   void (*free)(const void *data));
-#else
-static inline void dev_coredumpv(struct device *dev, const void *data,
-				 size_t datalen, gfp_t gfp)
-{
-	vfree(data);
-}
-
-static inline void
-dev_coredumpm(struct device *dev, struct module *owner,
-	      const void *data, size_t datalen, gfp_t gfp,
-	      ssize_t (*read)(char *buffer, loff_t offset, size_t count,
-			      const void *data, size_t datalen),
-	      void (*free)(const void *data))
-{
-	free(data);
-}
-#endif /* CPTCFG_BPAUTO_WANT_DEV_COREDUMP */
-
-#endif /* __DEVCOREDUMP_H */
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 2ad74c6..8356303 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -447,6 +447,4 @@
 #define  BCMA_DMA_TRANSLATION_DMA64_CMT	0x80000000 /* Client Mode Translation for 64-bit DMA */
 extern u32 bcma_core_dma_translation(struct bcma_device *core);
 
-extern unsigned int bcma_core_irq(struct bcma_device *core, int num);
-
 #endif /* LINUX_BCMA_H_ */
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h
index 907c48c..73c8a7b 100644
--- a/include/linux/bcma/bcma_driver_mips.h
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -43,12 +43,12 @@
 extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
 extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore);
 
-extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
+extern unsigned int bcma_core_irq(struct bcma_device *core);
 #else
 static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
 static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { }
 
-static inline unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+static inline unsigned int bcma_core_irq(struct bcma_device *core)
 {
 	return 0;
 }
diff --git a/include/linux/devcoredump.h b/include/linux/devcoredump.h
deleted file mode 100644
index 9c215fa..0000000
--- a/include/linux/devcoredump.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* Automatically created during backport process */
-#ifndef CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP
-#include_next <linux/devcoredump.h>
-#else
-#undef dev_coredumpv
-#define dev_coredumpv LINUX_BACKPORT(dev_coredumpv)
-#undef dev_coredumpm
-#define dev_coredumpm LINUX_BACKPORT(dev_coredumpm)
-#include <linux/backport-devcoredump.h>
-#endif /* CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 4f4eea8..b1be39c 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -19,7 +19,6 @@
 #include <linux/types.h>
 #include <linux/if_ether.h>
 #include <asm/byteorder.h>
-#include <asm/unaligned.h>
 
 /*
  * DS bit usage
@@ -1067,12 +1066,6 @@
 
 /* TDLS */
 
-/* Channel switch timing */
-struct ieee80211_ch_switch_timing {
-	__le16 switch_time;
-	__le16 switch_timeout;
-} __packed;
-
 /* Link-id information element */
 struct ieee80211_tdls_lnkie {
 	u8 ie_type; /* Link Identifier IE */
@@ -1114,15 +1107,6 @@
 			u8 dialog_token;
 			u8 variable[0];
 		} __packed discover_req;
-		struct {
-			u8 target_channel;
-			u8 oper_class;
-			u8 variable[0];
-		} __packed chan_switch_req;
-		struct {
-			__le16 status_code;
-			u8 variable[0];
-		} __packed chan_switch_resp;
 	} u;
 } __packed;
 
@@ -1290,7 +1274,7 @@
 #define		IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT	2
 
 /*
- * Maximum length of AMPDU that the STA can receive in high-throughput (HT).
+ * Maximum length of AMPDU that the STA can receive.
  * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
  */
 enum ieee80211_max_ampdu_length_exp {
@@ -1300,21 +1284,6 @@
 	IEEE80211_HT_MAX_AMPDU_64K = 3
 };
 
-/*
- * Maximum length of AMPDU that the STA can receive in VHT.
- * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
- */
-enum ieee80211_vht_max_ampdu_length_exp {
-	IEEE80211_VHT_MAX_AMPDU_8K = 0,
-	IEEE80211_VHT_MAX_AMPDU_16K = 1,
-	IEEE80211_VHT_MAX_AMPDU_32K = 2,
-	IEEE80211_VHT_MAX_AMPDU_64K = 3,
-	IEEE80211_VHT_MAX_AMPDU_128K = 4,
-	IEEE80211_VHT_MAX_AMPDU_256K = 5,
-	IEEE80211_VHT_MAX_AMPDU_512K = 6,
-	IEEE80211_VHT_MAX_AMPDU_1024K = 7
-};
-
 #define IEEE80211_HT_MAX_AMPDU_FACTOR 13
 
 /* Minimum MPDU start spacing */
@@ -2029,16 +1998,6 @@
 	WLAN_TDLS_DISCOVERY_REQUEST = 10,
 };
 
-/* Extended Channel Switching capability to be set in the 1st byte of
- * the @WLAN_EID_EXT_CAPABILITY information element
- */
-#define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING	BIT(2)
-
-/* TDLS capabilities in the the 4th byte of @WLAN_EID_EXT_CAPABILITY */
-#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA		BIT(4)
-#define WLAN_EXT_CAPA4_TDLS_PEER_PSM		BIT(5)
-#define WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH		BIT(6)
-
 /* Interworking capabilities are set in 7th bit of 4th byte of the
  * @WLAN_EID_EXT_CAPABILITY information element
  */
@@ -2050,7 +2009,6 @@
  */
 #define WLAN_EXT_CAPA5_TDLS_ENABLED	BIT(5)
 #define WLAN_EXT_CAPA5_TDLS_PROHIBITED	BIT(6)
-#define WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED	BIT(7)
 
 #define WLAN_EXT_CAPA8_OPMODE_NOTIF	BIT(6)
 #define WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED	BIT(7)
@@ -2058,9 +2016,6 @@
 /* TDLS specific payload type in the LLC/SNAP header */
 #define WLAN_TDLS_SNAP_RFTYPE	0x2
 
-/* BSS Coex IE information field bits */
-#define WLAN_BSS_COEX_INFORMATION_REQUEST	BIT(0)
-
 /**
  * enum - mesh synchronization method identifier
  *
@@ -2443,30 +2398,6 @@
 	return !!(tim->virtual_map[index] & mask);
 }
 
-/**
- * ieee80211_get_tdls_action - get tdls packet action (or -1, if not tdls packet)
- * @skb: the skb containing the frame, length will not be checked
- * @hdr_size: the size of the ieee80211_hdr that starts at skb->data
- *
- * This function assumes the frame is a data frame, and that the network header
- * is in the correct place.
- */
-static inline int ieee80211_get_tdls_action(struct sk_buff *skb, u32 hdr_size)
-{
-	if (!skb_is_nonlinear(skb) &&
-	    skb->len > (skb_network_offset(skb) + 2)) {
-		/* Point to where the indication of TDLS should start */
-		const u8 *tdls_data = skb_network_header(skb) - 2;
-
-		if (get_unaligned_be16(tdls_data) == ETH_P_TDLS &&
-		    tdls_data[2] == WLAN_TDLS_SNAP_RFTYPE &&
-		    tdls_data[3] == WLAN_CATEGORY_TDLS)
-			return tdls_data[4];
-	}
-
-	return -1;
-}
-
 /* convert time units */
 #define TU_TO_JIFFIES(x)	(usecs_to_jiffies((x) * 1024))
 #define TU_TO_EXP_TIME(x)	(jiffies + TU_TO_JIFFIES(x))
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index 167342c..20163b9 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  */
 
 #ifndef NL802154_H
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index e63c02a..1fa99a3 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -522,8 +522,6 @@
 #define PCI_DEVICE_ID_AMD_15H_M10H_F3	0x1403
 #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d
 #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e
-#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F3 0x1573
-#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F4 0x1574
 #define PCI_DEVICE_ID_AMD_15H_NB_F0	0x1600
 #define PCI_DEVICE_ID_AMD_15H_NB_F1	0x1601
 #define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602
@@ -564,7 +562,6 @@
 #define PCI_DEVICE_ID_AMD_8131_BRIDGE	0x7450
 #define PCI_DEVICE_ID_AMD_8131_APIC	0x7451
 #define PCI_DEVICE_ID_AMD_8132_BRIDGE	0x7458
-#define PCI_DEVICE_ID_AMD_NL_USB	0x7912
 #define PCI_DEVICE_ID_AMD_CS5535_IDE    0x208F
 #define PCI_DEVICE_ID_AMD_CS5536_ISA    0x2090
 #define PCI_DEVICE_ID_AMD_CS5536_FLASH  0x2091
diff --git a/include/linux/platform_data/st21nfca.h b/include/linux/platform_data/st21nfca.h
index 5087fff..1730312 100644
--- a/include/linux/platform_data/st21nfca.h
+++ b/include/linux/platform_data/st21nfca.h
@@ -24,6 +24,7 @@
 #define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci"
 
 struct st21nfca_nfc_platform_data {
+	unsigned int gpio_irq;
 	unsigned int gpio_ena;
 	unsigned int irq_polarity;
 };
diff --git a/include/linux/platform_data/st21nfcb.h b/include/linux/platform_data/st21nfcb.h
index c3b432f..2d11f1f 100644
--- a/include/linux/platform_data/st21nfcb.h
+++ b/include/linux/platform_data/st21nfcb.h
@@ -24,6 +24,7 @@
 #define ST21NFCB_NCI_DRIVER_NAME "st21nfcb_nci"
 
 struct st21nfcb_nfc_platform_data {
+	unsigned int gpio_irq;
 	unsigned int gpio_reset;
 	unsigned int irq_polarity;
 };
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index d9a4905..26088fe 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -78,7 +78,6 @@
 #		define EVENT_NO_RUNTIME_PM	9
 #		define EVENT_RX_KILL	10
 #		define EVENT_LINK_CHANGE	11
-#		define EVENT_SET_RX_MODE	12
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -160,9 +159,6 @@
 	/* called by minidriver when receiving indication */
 	void	(*indication)(struct usbnet *dev, void *ind, int indlen);
 
-	/* rx mode change (device changes address list filtering) */
-	void	(*set_rx_mode)(struct usbnet *dev);
-
 	/* for new devices, use the descriptor-reading code instead */
 	int		in;		/* rx endpoint */
 	int		out;		/* tx endpoint */
diff --git a/include/media/davinci/vpbe.h b/include/media/davinci/vpbe.h
index 4376bee..57585c7 100644
--- a/include/media/davinci/vpbe.h
+++ b/include/media/davinci/vpbe.h
@@ -63,7 +63,7 @@
 	 * output basis. If per mode is needed, we may have to move this to
 	 * mode_info structure
 	 */
-	u32 if_params;
+	enum v4l2_mbus_pixelcode if_params;
 };
 
 /* encoder configuration info */
diff --git a/include/media/davinci/vpbe_display.h b/include/media/davinci/vpbe_display.h
index fa0247a..637749a 100644
--- a/include/media/davinci/vpbe_display.h
+++ b/include/media/davinci/vpbe_display.h
@@ -70,6 +70,8 @@
 
 /* vpbe display object structure */
 struct vpbe_layer {
+	/* number of buffers in fbuffers */
+	unsigned int numbuffers;
 	/* Pointer to the vpbe_display */
 	struct vpbe_display *disp_dev;
 	/* Pointer pointing to current v4l2_buffer */
@@ -89,6 +91,10 @@
 	/* V4l2 specific parameters */
 	/* Identifies video device for this layer */
 	struct video_device video_dev;
+	/* This field keeps track of type of buffer exchange mechanism user
+	 * has selected
+	 */
+	enum v4l2_memory memory;
 	/* Used to store pixel format */
 	struct v4l2_pix_format pix_fmt;
 	enum v4l2_field buf_field;
@@ -100,8 +106,12 @@
 	unsigned char window_enable;
 	/* number of open instances of the layer */
 	unsigned int usrs;
+	/* number of users performing IO */
+	unsigned int io_usrs;
 	/* Indicates id of the field which is being displayed */
 	unsigned int field_id;
+	/* Indicates whether streaming started */
+	unsigned char started;
 	/* Identifies device object */
 	enum vpbe_display_device_id device_id;
 	/* facilitation of ioctl ops lock by v4l2*/
@@ -121,6 +131,17 @@
 	struct osd_state *osd_device;
 };
 
+/* File handle structure */
+struct vpbe_fh {
+	struct v4l2_fh fh;
+	/* vpbe device structure */
+	struct vpbe_display *disp_dev;
+	/* pointer to layer object for opened device */
+	struct vpbe_layer *layer;
+	/* Indicates whether this file handle is doing IO */
+	unsigned char io_allowed;
+};
+
 struct buf_config_params {
 	unsigned char min_numbuffers;
 	unsigned char numbuffers[VPBE_DISPLAY_MAX_DEVICES];
diff --git a/include/media/davinci/vpbe_venc.h b/include/media/davinci/vpbe_venc.h
index 3dbd200..476fafc 100644
--- a/include/media/davinci/vpbe_venc.h
+++ b/include/media/davinci/vpbe_venc.h
@@ -30,10 +30,11 @@
 #define VENC_SECOND_FIELD	BIT(2)
 
 struct venc_platform_data {
-	int (*setup_pinmux)(u32 if_type, int field);
+	int (*setup_pinmux)(enum v4l2_mbus_pixelcode if_type,
+			    int field);
 	int (*setup_clock)(enum vpbe_enc_timings_type type,
 			   unsigned int pixclock);
-	int (*setup_if_config)(u32 pixcode);
+	int (*setup_if_config)(enum v4l2_mbus_pixelcode pixcode);
 	/* Number of LCD outputs supported */
 	int num_lcd_outputs;
 	struct vpbe_if_params *lcd_if_params;
diff --git a/include/media/exynos-fimc.h b/include/media/exynos-fimc.h
index 69bcd2a..aa44660 100644
--- a/include/media/exynos-fimc.h
+++ b/include/media/exynos-fimc.h
@@ -101,7 +101,7 @@
  * @flags: flags indicating which operation mode format applies to
  */
 struct fimc_fmt {
-	u32 mbus_code;
+	enum v4l2_mbus_pixelcode mbus_code;
 	char	*name;
 	u32	fourcc;
 	u32	color;
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 05e7ad5..78f0637 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -29,13 +29,14 @@
 	/* Using chunks instead of bytes pretends to simplify boundary checking
 	 * And should allow for some performance fine tunning later */
 	struct kfifo fifo;
+	u8 fifo_initialized;
 };
 
 static inline void lirc_buffer_clear(struct lirc_buffer *buf)
 {
 	unsigned long flags;
 
-	if (kfifo_initialized(&buf->fifo)) {
+	if (buf->fifo_initialized) {
 		spin_lock_irqsave(&buf->fifo_lock, flags);
 		kfifo_reset(&buf->fifo);
 		spin_unlock_irqrestore(&buf->fifo_lock, flags);
@@ -55,14 +56,17 @@
 	buf->chunk_size = chunk_size;
 	buf->size = size;
 	ret = kfifo_alloc(&buf->fifo, size * chunk_size, GFP_KERNEL);
+	if (ret == 0)
+		buf->fifo_initialized = 1;
 
 	return ret;
 }
 
 static inline void lirc_buffer_free(struct lirc_buffer *buf)
 {
-	if (kfifo_initialized(&buf->fifo)) {
+	if (buf->fifo_initialized) {
 		kfifo_free(&buf->fifo);
+		buf->fifo_initialized = 0;
 	} else
 		WARN(1, "calling %s on an uninitialized lirc_buffer\n",
 		     __func__);
diff --git a/include/media/radio-si4713.h b/include/media/radio-si4713.h
new file mode 100644
index 0000000..f6aae29
--- /dev/null
+++ b/include/media/radio-si4713.h
@@ -0,0 +1,30 @@
+/*
+ * include/media/radio-si4713.h
+ *
+ * Board related data definitions for Si4713 radio transmitter chip.
+ *
+ * Copyright (c) 2009 Nokia Corporation
+ * Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef RADIO_SI4713_H
+#define RADIO_SI4713_H
+
+#include <linux/i2c.h>
+
+#define SI4713_NAME "radio-si4713"
+
+/*
+ * Platform dependent definition
+ */
+struct radio_si4713_platform_data {
+	int i2c_bus;
+	struct i2c_board_info *subdev_board_info;
+};
+
+#endif /* ifndef RADIO_SI4713_H*/
diff --git a/include/media/si4713.h b/include/media/si4713.h
index be4f58e..f98a0a7 100644
--- a/include/media/si4713.h
+++ b/include/media/si4713.h
@@ -23,7 +23,9 @@
  * Platform dependent definition
  */
 struct si4713_platform_data {
-	bool is_platform_device;
+	const char * const *supply_names;
+	unsigned supplies;
+	int gpio_reset; /* < 0 if not used */
 };
 
 /*
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 2f6261f..865246b 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -296,7 +296,7 @@
  * format setup.
  */
 struct soc_camera_format_xlate {
-	u32 code;
+	enum v4l2_mbus_pixelcode code;
 	const struct soc_mbus_pixelfmt *host_fmt;
 };
 
diff --git a/include/media/soc_mediabus.h b/include/media/soc_mediabus.h
index 2ff7737..d33f6d0 100644
--- a/include/media/soc_mediabus.h
+++ b/include/media/soc_mediabus.h
@@ -91,16 +91,16 @@
  * @fmt:	pixel format description
  */
 struct soc_mbus_lookup {
-	u32	code;
+	enum v4l2_mbus_pixelcode	code;
 	struct soc_mbus_pixelfmt	fmt;
 };
 
 const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
-	u32 code,
+	enum v4l2_mbus_pixelcode code,
 	const struct soc_mbus_lookup *lookup,
 	int n);
 const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
-	u32 code);
+	enum v4l2_mbus_pixelcode code);
 s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf);
 s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,
 			u32 bytes_per_line, u32 height);
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 1cc0c5b..48f9748 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -80,9 +80,24 @@
 
 /* ------------------------------------------------------------------------- */
 
-/* Control helper function */
+/* Control helper functions */
 
+int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
+		const char * const *menu_items);
+const char *v4l2_ctrl_get_name(u32 id);
+const char * const *v4l2_ctrl_get_menu(u32 id);
+const s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len);
 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def);
+int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu,
+		struct v4l2_queryctrl *qctrl, const char * const *menu_items);
+#define V4L2_CTRL_MENU_IDS_END (0xffffffff)
+int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids);
+
+/* Note: ctrl_classes points to an array of u32 pointers. Each u32 array is a
+   0-terminated array of control IDs. Each array must be sorted low to high
+   and belong to the same control class. The array of u32 pointers must also
+   be sorted, from low class IDs to high class IDs. */
+u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
 
 /* ------------------------------------------------------------------------- */
 
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 911f3e5..b7cd7a6 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -670,31 +670,6 @@
   */
 void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv);
 
-/** v4l2_ctrl_get_name() - Get the name of the control
- * @id:		The control ID.
- *
- * This function returns the name of the given control ID or NULL if it isn't
- * a known control.
- */
-const char *v4l2_ctrl_get_name(u32 id);
-
-/** v4l2_ctrl_get_menu() - Get the menu string array of the control
- * @id:		The control ID.
- *
- * This function returns the NULL-terminated menu string array name of the
- * given control ID or NULL if it isn't a known menu control.
- */
-const char * const *v4l2_ctrl_get_menu(u32 id);
-
-/** v4l2_ctrl_get_int_menu() - Get the integer menu array of the control
- * @id:		The control ID.
- * @len:	The size of the integer array.
- *
- * This function returns the integer array of the given control ID or NULL if it
- * if it isn't a known integer menu control.
- */
-const s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len);
-
 /** v4l2_ctrl_g_ctrl() - Helper function to get the control's value from within a driver.
   * @ctrl:	The control.
   *
diff --git a/include/media/v4l2-image-sizes.h b/include/media/v4l2-image-sizes.h
index a07d7a6..10daf92 100644
--- a/include/media/v4l2-image-sizes.h
+++ b/include/media/v4l2-image-sizes.h
@@ -25,19 +25,10 @@
 #define QVGA_WIDTH	320
 #define QVGA_HEIGHT	240
 
-#define SVGA_WIDTH	800
-#define SVGA_HEIGHT	600
-
 #define SXGA_WIDTH	1280
 #define SXGA_HEIGHT	1024
 
 #define VGA_WIDTH	640
 #define VGA_HEIGHT	480
 
-#define UXGA_WIDTH	1600
-#define UXGA_HEIGHT	1200
-
-#define XGA_WIDTH	1024
-#define XGA_HEIGHT	768
-
 #endif /* _IMAGE_SIZES_H */
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
index 38d960d..395c4a9 100644
--- a/include/media/v4l2-mediabus.h
+++ b/include/media/v4l2-mediabus.h
@@ -94,20 +94,16 @@
 	pix_fmt->height = mbus_fmt->height;
 	pix_fmt->field = mbus_fmt->field;
 	pix_fmt->colorspace = mbus_fmt->colorspace;
-	pix_fmt->ycbcr_enc = mbus_fmt->ycbcr_enc;
-	pix_fmt->quantization = mbus_fmt->quantization;
 }
 
 static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt,
 			   const struct v4l2_pix_format *pix_fmt,
-			   u32 code)
+			   enum v4l2_mbus_pixelcode code)
 {
 	mbus_fmt->width = pix_fmt->width;
 	mbus_fmt->height = pix_fmt->height;
 	mbus_fmt->field = pix_fmt->field;
 	mbus_fmt->colorspace = pix_fmt->colorspace;
-	mbus_fmt->ycbcr_enc = pix_fmt->ycbcr_enc;
-	mbus_fmt->quantization = pix_fmt->quantization;
 	mbus_fmt->code = code;
 }
 
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 063a83e..8e95674 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -341,7 +341,7 @@
 	int (*query_dv_timings)(struct v4l2_subdev *sd,
 			struct v4l2_dv_timings *timings);
 	int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
-			     u32 *code);
+			     enum v4l2_mbus_pixelcode *code);
 	int (*enum_mbus_fsizes)(struct v4l2_subdev *sd,
 			     struct v4l2_frmsizeenum *fsize);
 	int (*g_mbus_fmt)(struct v4l2_subdev *sd,
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index e320202..69a9595 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -82,17 +82,14 @@
  *				  unmap_dmabuf.
  */
 struct vb2_mem_ops {
-	void		*(*alloc)(void *alloc_ctx, unsigned long size,
-				  enum dma_data_direction dma_dir,
-				  gfp_t gfp_flags);
+	void		*(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
 	void		(*put)(void *buf_priv);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
 	struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) */
 
 	void		*(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
-					unsigned long size,
-					enum dma_data_direction dma_dir);
+					unsigned long size, int write);
 	void		(*put_userptr)(void *buf_priv);
 
 	void		(*prepare)(void *buf_priv);
@@ -100,8 +97,7 @@
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
 	void		*(*attach_dmabuf)(void *alloc_ctx, struct dma_buf *dbuf,
-					  unsigned long size,
-					  enum dma_data_direction dma_dir);
+				unsigned long size, int write);
 	void		(*detach_dmabuf)(void *buf_priv);
 	int		(*map_dmabuf)(void *buf_priv);
 	void		(*unmap_dmabuf)(void *buf_priv);
@@ -278,24 +274,22 @@
  *			queue setup from completing successfully; optional.
  * @buf_prepare:	called every time the buffer is queued from userspace
  *			and from the VIDIOC_PREPARE_BUF ioctl; drivers may
- *			perform any initialization required before each
- *			hardware operation in this callback; drivers can
- *			access/modify the buffer here as it is still synced for
- *			the CPU; drivers that support VIDIOC_CREATE_BUFS must
- *			also validate the buffer size; if an error is returned,
- *			the buffer will not be queued in driver; optional.
+ *			perform any initialization required before each hardware
+ *			operation in this callback; drivers that support
+ *			VIDIOC_CREATE_BUFS must also validate the buffer size;
+ *			if an error is returned, the buffer will not be queued
+ *			in driver; optional.
  * @buf_finish:		called before every dequeue of the buffer back to
- *			userspace; the buffer is synced for the CPU, so drivers
- *			can access/modify the buffer contents; drivers may
- *			perform any operations required before userspace
- *			accesses the buffer; optional. The buffer state can be
- *			one of the following: DONE and ERROR occur while
- *			streaming is in progress, and the PREPARED state occurs
- *			when the queue has been canceled and all pending
- *			buffers are being returned to their default DEQUEUED
- *			state. Typically you only have to do something if the
- *			state is VB2_BUF_STATE_DONE, since in all other cases
- *			the buffer contents will be ignored anyway.
+ *			userspace; drivers may perform any operations required
+ *			before userspace accesses the buffer; optional. The
+ *			buffer state can be one of the following: DONE and
+ *			ERROR occur while streaming is in progress, and the
+ *			PREPARED state occurs when the queue has been canceled
+ *			and all pending buffers are being returned to their
+ *			default DEQUEUED state. Typically you only have to do
+ *			something if the state is VB2_BUF_STATE_DONE, since in
+ *			all other cases the buffer contents will be ignored
+ *			anyway.
  * @buf_cleanup:	called once before the buffer is freed; drivers may
  *			perform any additional cleanup; optional.
  * @start_streaming:	called once to enter 'streaming' state; the driver may
diff --git a/include/media/videobuf2-dma-sg.h b/include/media/videobuf2-dma-sg.h
index 14ce306..7b89852 100644
--- a/include/media/videobuf2-dma-sg.h
+++ b/include/media/videobuf2-dma-sg.h
@@ -21,9 +21,6 @@
 	return (struct sg_table *)vb2_plane_cookie(vb, plane_no);
 }
 
-void *vb2_dma_sg_init_ctx(struct device *dev);
-void vb2_dma_sg_cleanup_ctx(void *alloc_ctx);
-
 extern const struct vb2_mem_ops vb2_dma_sg_memops;
 
 #endif
diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index dc03d77..d184df1 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -372,12 +372,12 @@
 	return skb->len + uncomp_header - ret;
 }
 
-int
-lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
-			 const u8 *saddr, const u8 saddr_type,
-			 const u8 saddr_len, const u8 *daddr,
-			 const u8 daddr_type, const u8 daddr_len,
-			 u8 iphc0, u8 iphc1);
+typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
+
+int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
+		const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
+		const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
+		u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type, const void *_daddr,
 			const void *_saddr, unsigned int len);
diff --git a/include/net/af_ieee802154.h b/include/net/af_ieee802154.h
index 7d38e2f..085940f 100644
--- a/include/net/af_ieee802154.h
+++ b/include/net/af_ieee802154.h
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 40129b3..6e8f249 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -129,15 +129,6 @@
 	 * during the hdev->setup vendor callback.
 	 */
 	HCI_QUIRK_INVALID_BDADDR,
-
-	/* When this quirk is set, the duplicate filtering during
-	 * scanning is based on Bluetooth devices addresses. To allow
-	 * RSSI based updates, restart scanning if needed.
-	 *
-	 * This quirk can be set before hci_register_dev is called or
-	 * during the hdev->setup vendor callback.
-	 */
-	HCI_QUIRK_STRICT_DUPLICATE_FILTER,
 };
 
 /* HCI device flags */
@@ -163,7 +154,6 @@
 enum {
 	HCI_DUT_MODE,
 	HCI_FORCE_SC,
-	HCI_FORCE_LESC,
 	HCI_FORCE_STATIC_ADDR,
 };
 
@@ -275,7 +265,6 @@
 /* Low Energy links do not have defined link type. Use invented one */
 #define LE_LINK		0x80
 #define AMP_LINK	0x81
-#define INVALID_LINK	0xff
 
 /* LMP features */
 #define LMP_3SLOT	0x01
@@ -343,7 +332,6 @@
 #define HCI_LE_ENCRYPTION		0x01
 #define HCI_LE_CONN_PARAM_REQ_PROC	0x02
 #define HCI_LE_PING			0x10
-#define HCI_LE_EXT_SCAN_POLICY		0x80
 
 /* Connection modes */
 #define HCI_CM_ACTIVE	0x0000
@@ -413,7 +401,6 @@
 
 /* The core spec defines 127 as the "not available" value */
 #define HCI_TX_POWER_INVALID	127
-#define HCI_RSSI_INVALID	127
 
 #define HCI_ROLE_MASTER		0x00
 #define HCI_ROLE_SLAVE		0x01
@@ -642,7 +629,7 @@
 struct hci_cp_remote_oob_data_reply {
 	bdaddr_t bdaddr;
 	__u8     hash[16];
-	__u8     rand[16];
+	__u8     randomizer[16];
 } __packed;
 
 #define HCI_OP_REMOTE_OOB_DATA_NEG_REPLY	0x0433
@@ -734,9 +721,9 @@
 struct hci_cp_remote_oob_ext_data_reply {
 	bdaddr_t bdaddr;
 	__u8     hash192[16];
-	__u8     rand192[16];
+	__u8     randomizer192[16];
 	__u8     hash256[16];
-	__u8     rand256[16];
+	__u8     randomizer256[16];
 } __packed;
 
 #define HCI_OP_SNIFF_MODE		0x0803
@@ -943,7 +930,7 @@
 struct hci_rp_read_local_oob_data {
 	__u8     status;
 	__u8     hash[16];
-	__u8     rand[16];
+	__u8     randomizer[16];
 } __packed;
 
 #define HCI_OP_READ_INQ_RSP_TX_POWER	0x0c58
@@ -1027,9 +1014,9 @@
 struct hci_rp_read_local_oob_ext_data {
 	__u8     status;
 	__u8     hash192[16];
-	__u8     rand192[16];
+	__u8     randomizer192[16];
 	__u8     hash256[16];
-	__u8     rand256[16];
+	__u8     randomizer256[16];
 } __packed;
 
 #define HCI_OP_READ_LOCAL_VERSION	0x1001
@@ -1476,11 +1463,6 @@
 	__le16   opcode;
 } __packed;
 
-#define HCI_EV_HARDWARE_ERROR		0x10
-struct hci_ev_hardware_error {
-	__u8     code;
-} __packed;
-
 #define HCI_EV_ROLE_CHANGE		0x12
 struct hci_ev_role_change {
 	__u8     status;
@@ -1752,25 +1734,6 @@
 	__u8     clk_accurancy;
 } __packed;
 
-/* Advertising report event types */
-#define LE_ADV_IND		0x00
-#define LE_ADV_DIRECT_IND	0x01
-#define LE_ADV_SCAN_IND		0x02
-#define LE_ADV_NONCONN_IND	0x03
-#define LE_ADV_SCAN_RSP		0x04
-
-#define ADDR_LE_DEV_PUBLIC	0x00
-#define ADDR_LE_DEV_RANDOM	0x01
-
-#define HCI_EV_LE_ADVERTISING_REPORT	0x02
-struct hci_ev_le_advertising_info {
-	__u8	 evt_type;
-	__u8	 bdaddr_type;
-	bdaddr_t bdaddr;
-	__u8	 length;
-	__u8	 data[0];
-} __packed;
-
 #define HCI_EV_LE_CONN_UPDATE_COMPLETE	0x03
 struct hci_ev_le_conn_update_complete {
 	__u8     status;
@@ -1796,14 +1759,23 @@
 	__le16 timeout;
 } __packed;
 
-#define HCI_EV_LE_DIRECT_ADV_REPORT	0x0B
-struct hci_ev_le_direct_adv_info {
+/* Advertising report event types */
+#define LE_ADV_IND		0x00
+#define LE_ADV_DIRECT_IND	0x01
+#define LE_ADV_SCAN_IND		0x02
+#define LE_ADV_NONCONN_IND	0x03
+#define LE_ADV_SCAN_RSP		0x04
+
+#define ADDR_LE_DEV_PUBLIC	0x00
+#define ADDR_LE_DEV_RANDOM	0x01
+
+#define HCI_EV_LE_ADVERTISING_REPORT	0x02
+struct hci_ev_le_advertising_info {
 	__u8	 evt_type;
 	__u8	 bdaddr_type;
 	bdaddr_t bdaddr;
-	__u8	 direct_addr_type;
-	bdaddr_t direct_addr;
-	__s8	 rssi;
+	__u8	 length;
+	__u8	 data[0];
 } __packed;
 
 /* Internal events generated by Bluetooth stack */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3c78270..37ff1ae 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -75,10 +75,6 @@
 	u32			last_adv_flags;
 	u8			last_adv_data[HCI_MAX_AD_LENGTH];
 	u8			last_adv_data_len;
-	bool			report_invalid_rssi;
-	s8			rssi;
-	u16			uuid_count;
-	u8			(*uuids)[16];
 };
 
 struct hci_conn_hash {
@@ -112,7 +108,6 @@
 
 struct smp_ltk {
 	struct list_head list;
-	struct rcu_head rcu;
 	bdaddr_t bdaddr;
 	u8 bdaddr_type;
 	u8 authenticated;
@@ -125,7 +120,6 @@
 
 struct smp_irk {
 	struct list_head list;
-	struct rcu_head rcu;
 	bdaddr_t rpa;
 	bdaddr_t bdaddr;
 	u8 addr_type;
@@ -134,7 +128,6 @@
 
 struct link_key {
 	struct list_head list;
-	struct rcu_head rcu;
 	bdaddr_t bdaddr;
 	u8 type;
 	u8 val[HCI_LINK_KEY_SIZE];
@@ -144,11 +137,10 @@
 struct oob_data {
 	struct list_head list;
 	bdaddr_t bdaddr;
-	u8 bdaddr_type;
 	u8 hash192[16];
-	u8 rand192[16];
+	u8 randomizer192[16];
 	u8 hash256[16];
-	u8 rand256[16];
+	u8 randomizer256[16];
 };
 
 #define HCI_MAX_SHORT_NAME_LENGTH	10
@@ -311,7 +303,6 @@
 	__u32			req_result;
 
 	void			*smp_data;
-	void			*smp_bredr_data;
 
 	struct discovery_state	discovery;
 	struct hci_conn_hash	conn_hash;
@@ -407,8 +398,6 @@
 	__u16		le_conn_interval;
 	__u16		le_conn_latency;
 	__u16		le_supv_timeout;
-	__u8		le_adv_data[HCI_MAX_AD_LENGTH];
-	__u8		le_adv_data_len;
 	__s8		rssi;
 	__s8		tx_power;
 	__s8		max_tx_power;
@@ -507,17 +496,6 @@
 	INIT_LIST_HEAD(&hdev->discovery.all);
 	INIT_LIST_HEAD(&hdev->discovery.unknown);
 	INIT_LIST_HEAD(&hdev->discovery.resolve);
-	hdev->discovery.report_invalid_rssi = true;
-	hdev->discovery.rssi = HCI_RSSI_INVALID;
-}
-
-static inline void hci_discovery_filter_clear(struct hci_dev *hdev)
-{
-	hdev->discovery.report_invalid_rssi = true;
-	hdev->discovery.rssi = HCI_RSSI_INVALID;
-	hdev->discovery.uuid_count = 0;
-	kfree(hdev->discovery.uuids);
-	hdev->discovery.uuids = NULL;
 }
 
 bool hci_discovery_active(struct hci_dev *hdev);
@@ -575,8 +553,6 @@
 	HCI_CONN_STK_ENCRYPT,
 	HCI_CONN_AUTH_INITIATOR,
 	HCI_CONN_DROP,
-	HCI_CONN_PARAM_REMOVAL_PEND,
-	HCI_CONN_NEW_LINK_KEY,
 };
 
 static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -667,26 +643,6 @@
 	return c->acl_num + c->amp_num + c->sco_num + c->le_num;
 }
 
-static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle)
-{
-	struct hci_conn_hash *h = &hdev->conn_hash;
-	struct hci_conn *c;
-	__u8 type = INVALID_LINK;
-
-	rcu_read_lock();
-
-	list_for_each_entry_rcu(c, &h->list, list) {
-		if (c->handle == handle) {
-			type = c->type;
-			break;
-		}
-	}
-
-	rcu_read_unlock();
-
-	return type;
-}
-
 static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
 								__u16 handle)
 {
@@ -897,7 +853,6 @@
 void hci_unregister_dev(struct hci_dev *hdev);
 int hci_suspend_dev(struct hci_dev *hdev);
 int hci_resume_dev(struct hci_dev *hdev);
-int hci_reset_dev(struct hci_dev *hdev);
 int hci_dev_open(__u16 dev);
 int hci_dev_close(__u16 dev);
 int hci_dev_reset(__u16 dev);
@@ -939,11 +894,13 @@
 struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
 				  bdaddr_t *bdaddr, u8 *val, u8 type,
 				  u8 pin_len, bool *persistent);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
+			     u8 role);
 struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
 			    u8 addr_type, u8 type, u8 authenticated,
 			    u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand);
-struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
-			     u8 addr_type, u8 role);
+struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				     u8 addr_type, u8 role);
 int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type);
 void hci_smp_ltks_clear(struct hci_dev *hdev);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
@@ -958,12 +915,13 @@
 
 void hci_remote_oob_data_clear(struct hci_dev *hdev);
 struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
-					  bdaddr_t *bdaddr, u8 bdaddr_type);
+					  bdaddr_t *bdaddr);
 int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
-			    u8 bdaddr_type, u8 *hash192, u8 *rand192,
-			    u8 *hash256, u8 *rand256);
-int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
-			       u8 bdaddr_type);
+			    u8 *hash, u8 *randomizer);
+int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				u8 *hash192, u8 *randomizer192,
+				u8 *hash256, u8 *randomizer256);
+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
@@ -1014,9 +972,6 @@
 
 #define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
 				!test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
-#define bredr_sc_enabled(dev) ((lmp_sc_capable(dev) || \
-				test_bit(HCI_FORCE_SC, &(dev)->dbg_flags)) && \
-			       test_bit(HCI_SC_ENABLED, &(dev)->dev_flags))
 
 /* ----- HCI protocols ----- */
 #define HCI_PROTO_DEFER             0x01
@@ -1355,8 +1310,9 @@
 void mgmt_discoverable_timeout(struct hci_dev *hdev);
 void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
 		       bool persistent);
-void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
-			   u32 flags, u8 *name, u8 name_len);
+void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+			   u8 addr_type, u32 flags, u8 *name, u8 name_len,
+			   u8 *dev_class);
 void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
 			      u8 link_type, u8 addr_type, u8 reason,
 			      bool mgmt_connected);
@@ -1393,8 +1349,8 @@
 				    u8 status);
 void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
 void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
-				       u8 *rand192, u8 *hash256, u8 *rand256,
-				       u8 status);
+				       u8 *randomizer192, u8 *hash256,
+				       u8 *randomizer256, u8 status);
 void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		       u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
 		       u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index eee3ef5..ead99f0 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -28,7 +28,6 @@
 #define __L2CAP_H
 
 #include <asm/unaligned.h>
-#include <linux/atomic.h>
 
 /* L2CAP defaults */
 #define L2CAP_DEFAULT_MTU		672
@@ -141,7 +140,6 @@
 #define L2CAP_FC_ATT		0x10
 #define L2CAP_FC_SIG_LE		0x20
 #define L2CAP_FC_SMP_LE		0x40
-#define L2CAP_FC_SMP_BREDR	0x80
 
 /* L2CAP Control Field bit masks */
 #define L2CAP_CTRL_SAR			0xC000
@@ -256,7 +254,6 @@
 #define L2CAP_CID_ATT		0x0004
 #define L2CAP_CID_LE_SIGNALING	0x0005
 #define L2CAP_CID_SMP		0x0006
-#define L2CAP_CID_SMP_BREDR	0x0007
 #define L2CAP_CID_DYN_START	0x0040
 #define L2CAP_CID_DYN_END	0xffff
 #define L2CAP_CID_LE_DYN_END	0x007f
@@ -484,7 +481,6 @@
 	struct hci_conn		*hs_hcon;
 	struct hci_chan		*hs_hchan;
 	struct kref	kref;
-	atomic_t	nesting;
 
 	__u8		state;
 
@@ -621,8 +617,8 @@
 	unsigned int		mtu;
 
 	__u32			feat_mask;
-	__u8			remote_fixed_chan;
-	__u8			local_fixed_chan;
+	__u8			fixed_chan_mask;
+	bool			hs_enabled;
 
 	__u8			info_state;
 	__u8			info_ident;
@@ -717,17 +713,6 @@
 	FLAG_HOLD_HCI_CONN,
 };
 
-/* Lock nesting levels for L2CAP channels. We need these because lockdep
- * otherwise considers all channels equal and will e.g. complain about a
- * connection oriented channel triggering SMP procedures or a listening
- * channel creating and locking a child channel.
- */
-enum {
-	L2CAP_NESTING_SMP,
-	L2CAP_NESTING_NORMAL,
-	L2CAP_NESTING_PARENT,
-};
-
 enum {
 	L2CAP_TX_STATE_XMIT,
 	L2CAP_TX_STATE_WAIT_F,
@@ -793,7 +778,7 @@
 
 static inline void l2cap_chan_lock(struct l2cap_chan *chan)
 {
-	mutex_lock_nested(&chan->lock, atomic_read(&chan->nesting));
+	mutex_lock(&chan->lock);
 }
 
 static inline void l2cap_chan_unlock(struct l2cap_chan *chan)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 95c34d5..414cd2f 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -184,9 +184,6 @@
 
 #define MGMT_LTK_UNAUTHENTICATED	0x00
 #define MGMT_LTK_AUTHENTICATED		0x01
-#define MGMT_LTK_P256_UNAUTH		0x02
-#define MGMT_LTK_P256_AUTH		0x03
-#define MGMT_LTK_P256_DEBUG		0x04
 
 struct mgmt_ltk_info {
 	struct mgmt_addr_info addr;
@@ -302,28 +299,28 @@
 #define MGMT_READ_LOCAL_OOB_DATA_SIZE	0
 struct mgmt_rp_read_local_oob_data {
 	__u8	hash[16];
-	__u8	rand[16];
+	__u8	randomizer[16];
 } __packed;
 struct mgmt_rp_read_local_oob_ext_data {
 	__u8	hash192[16];
-	__u8	rand192[16];
+	__u8	randomizer192[16];
 	__u8	hash256[16];
-	__u8	rand256[16];
+	__u8	randomizer256[16];
 } __packed;
 
 #define MGMT_OP_ADD_REMOTE_OOB_DATA	0x0021
 struct mgmt_cp_add_remote_oob_data {
 	struct mgmt_addr_info addr;
 	__u8	hash[16];
-	__u8	rand[16];
+	__u8	randomizer[16];
 } __packed;
 #define MGMT_ADD_REMOTE_OOB_DATA_SIZE	(MGMT_ADDR_INFO_SIZE + 32)
 struct mgmt_cp_add_remote_oob_ext_data {
 	struct mgmt_addr_info addr;
 	__u8	hash192[16];
-	__u8	rand192[16];
+	__u8	randomizer192[16];
 	__u8	hash256[16];
-	__u8	rand256[16];
+	__u8	randomizer256[16];
 } __packed;
 #define MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 64)
 
@@ -498,15 +495,6 @@
 } __packed;
 #define MGMT_SET_PUBLIC_ADDRESS_SIZE	6
 
-#define MGMT_OP_START_SERVICE_DISCOVERY	0x003A
-struct mgmt_cp_start_service_discovery {
-	__u8 type;
-	__s8 rssi;
-	__le16 uuid_count;
-	__u8 uuids[0][16];
-} __packed;
-#define MGMT_START_SERVICE_DISCOVERY_SIZE 4
-
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16	opcode;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 66fc97a..87362c1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -319,12 +319,9 @@
 /**
  * struct vif_params - describes virtual interface parameters
  * @use_4addr: use 4-address frames
- * @macaddr: address to use for this virtual interface.
- *	If this parameter is set to zero address the driver may
- *	determine the address as needed.
- *	This feature is only fully supported by drivers that enable the
- *	%NL80211_FEATURE_MAC_ON_CREATE flag.  Others may support creating
- **	only p2p devices with specified MAC.
+ * @macaddr: address to use for this virtual interface. This will only
+ * 	be used for non-netdevice interfaces. If this parameter is set
+ * 	to zero address the driver may determine the address as needed.
  */
 struct vif_params {
        int use_4addr;
@@ -802,22 +799,6 @@
 };
 
 /**
- * struct station_del_parameters - station deletion parameters
- *
- * Used to delete a station entry (or all stations).
- *
- * @mac: MAC address of the station to remove or NULL to remove all stations
- * @subtype: Management frame subtype to use for indicating removal
- *	(10 = Disassociation, 12 = Deauthentication)
- * @reason_code: Reason code for the Disassociation/Deauthentication frame
- */
-struct station_del_parameters {
-	const u8 *mac;
-	u8 subtype;
-	u16 reason_code;
-};
-
-/**
  * enum cfg80211_station_type - the type of station being modified
  * @CFG80211_STA_AP_CLIENT: client of an AP interface
  * @CFG80211_STA_AP_MLME_CLIENT: client of an AP interface that has
@@ -1359,16 +1340,6 @@
 };
 
 /**
- * struct ocb_setup - 802.11p OCB mode setup configuration
- * @chandef: defines the channel to use
- *
- * These parameters are fixed when connecting to the network
- */
-struct ocb_setup {
-	struct cfg80211_chan_def chandef;
-};
-
-/**
  * struct ieee80211_txq_params - TX queue parameters
  * @ac: AC identifier
  * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled
@@ -1437,10 +1408,6 @@
  * @aborted: (internal) scan request was notified as aborted
  * @notified: (internal) scan request was notified as done or aborted
  * @no_cck: used to send probe requests at non CCK rate in 2GHz band
- * @mac_addr: MAC address used with randomisation
- * @mac_addr_mask: MAC address mask used with randomisation, bits that
- *	are 0 in the mask should be randomised, bits that are 1 should
- *	be taken from the @mac_addr
  */
 struct cfg80211_scan_request {
 	struct cfg80211_ssid *ssids;
@@ -1455,9 +1422,6 @@
 
 	struct wireless_dev *wdev;
 
-	u8 mac_addr[ETH_ALEN] __aligned(2);
-	u8 mac_addr_mask[ETH_ALEN] __aligned(2);
-
 	/* internal */
 	struct wiphy *wiphy;
 	unsigned long scan_start;
@@ -1468,17 +1432,6 @@
 	struct ieee80211_channel *channels[0];
 };
 
-static inline void get_random_mask_addr(u8 *buf, const u8 *addr, const u8 *mask)
-{
-	int i;
-
-	get_random_bytes(buf, ETH_ALEN);
-	for (i = 0; i < ETH_ALEN; i++) {
-		buf[i] &= ~mask[i];
-		buf[i] |= addr[i] & mask[i];
-	}
-}
-
 /**
  * struct cfg80211_match_set - sets of attributes to match
  *
@@ -1512,10 +1465,6 @@
  * @channels: channels to scan
  * @min_rssi_thold: for drivers only supporting a single threshold, this
  *	contains the minimum over all matchsets
- * @mac_addr: MAC address used with randomisation
- * @mac_addr_mask: MAC address mask used with randomisation, bits that
- *	are 0 in the mask should be randomised, bits that are 1 should
- *	be taken from the @mac_addr
  */
 struct cfg80211_sched_scan_request {
 	struct cfg80211_ssid *ssids;
@@ -1530,9 +1479,6 @@
 	int n_match_sets;
 	s32 min_rssi_thold;
 
-	u8 mac_addr[ETH_ALEN] __aligned(2);
-	u8 mac_addr_mask[ETH_ALEN] __aligned(2);
-
 	/* internal */
 	struct wiphy *wiphy;
 	struct net_device *dev;
@@ -1965,7 +1911,6 @@
  * @rfkill_release: wake up when rfkill is released
  * @tcp: TCP connection establishment/wakeup parameters, see nl80211.h.
  *	NULL if not configured.
- * @nd_config: configuration for the scan to be used for net detect wake.
  */
 struct cfg80211_wowlan {
 	bool any, disconnect, magic_pkt, gtk_rekey_failure,
@@ -1974,7 +1919,6 @@
 	struct cfg80211_pkt_pattern *patterns;
 	struct cfg80211_wowlan_tcp *tcp;
 	int n_patterns;
-	struct cfg80211_sched_scan_request *nd_config;
 };
 
 /**
@@ -2007,35 +1951,6 @@
 };
 
 /**
- * struct cfg80211_wowlan_nd_match - information about the match
- *
- * @ssid: SSID of the match that triggered the wake up
- * @n_channels: Number of channels where the match occurred.  This
- *	value may be zero if the driver can't report the channels.
- * @channels: center frequencies of the channels where a match
- *	occurred (in MHz)
- */
-struct cfg80211_wowlan_nd_match {
-	struct cfg80211_ssid ssid;
-	int n_channels;
-	u32 channels[];
-};
-
-/**
- * struct cfg80211_wowlan_nd_info - net detect wake up information
- *
- * @n_matches: Number of match information instances provided in
- *	@matches.  This value may be zero if the driver can't provide
- *	match information.
- * @matches: Array of pointers to matches containing information about
- *	the matches that triggered the wake up.
- */
-struct cfg80211_wowlan_nd_info {
-	int n_matches;
-	struct cfg80211_wowlan_nd_match *matches[];
-};
-
-/**
  * struct cfg80211_wowlan_wakeup - wakeup report
  * @disconnect: woke up by getting disconnected
  * @magic_pkt: woke up by receiving magic packet
@@ -2054,7 +1969,6 @@
  * @tcp_match: TCP wakeup packet received
  * @tcp_connlost: TCP connection lost or failed to establish
  * @tcp_nomoretokens: TCP data ran out of tokens
- * @net_detect: if not %NULL, woke up because of net detect
  */
 struct cfg80211_wowlan_wakeup {
 	bool disconnect, magic_pkt, gtk_rekey_failure,
@@ -2064,7 +1978,6 @@
 	s32 pattern_idx;
 	u32 packet_present_len, packet_len;
 	const void *packet;
-	struct cfg80211_wowlan_nd_info *net_detect;
 };
 
 /**
@@ -2219,7 +2132,7 @@
  * @stop_ap: Stop being an AP, including stopping beaconing.
  *
  * @add_station: Add a new station.
- * @del_station: Remove a station
+ * @del_station: Remove a station; @mac may be NULL to remove all stations.
  * @change_station: Modify a given station. Note that flags changes are not much
  *	validated in cfg80211, in particular the auth/assoc/authorized flags
  *	might come to the driver in invalid combinations -- make sure to check
@@ -2233,8 +2146,6 @@
  * @change_mpath: change a given mesh path
  * @get_mpath: get a mesh path for the given parameters
  * @dump_mpath: dump mesh path callback -- resume dump at index @idx
- * @get_mpp: get a mesh proxy path for the given parameters
- * @dump_mpp: dump mesh proxy path callback -- resume dump at index @idx
  * @join_mesh: join the mesh network with the specified parameters
  *	(invoked with the wireless_dev mutex held)
  * @leave_mesh: leave the current mesh network
@@ -2420,17 +2331,6 @@
  *	with the peer followed by immediate teardown when the addition is later
  *	rejected)
  * @del_tx_ts: remove an existing TX TS
- *
- * @join_ocb: join the OCB network with the specified parameters
- *	(invoked with the wireless_dev mutex held)
- * @leave_ocb: leave the current OCB network
- *	(invoked with the wireless_dev mutex held)
- *
- * @tdls_channel_switch: Start channel-switching with a TDLS peer. The driver
- *	is responsible for continually initiating channel-switching operations
- *	and returning to the base channel for communication with the AP.
- * @tdls_cancel_channel_switch: Stop channel-switching with a TDLS peer. Both
- *	peers must be on the base channel when the call completes.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2476,7 +2376,7 @@
 			       const u8 *mac,
 			       struct station_parameters *params);
 	int	(*del_station)(struct wiphy *wiphy, struct net_device *dev,
-			       struct station_del_parameters *params);
+			       const u8 *mac);
 	int	(*change_station)(struct wiphy *wiphy, struct net_device *dev,
 				  const u8 *mac,
 				  struct station_parameters *params);
@@ -2496,11 +2396,6 @@
 	int	(*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
 			      int idx, u8 *dst, u8 *next_hop,
 			      struct mpath_info *pinfo);
-	int	(*get_mpp)(struct wiphy *wiphy, struct net_device *dev,
-			   u8 *dst, u8 *mpp, struct mpath_info *pinfo);
-	int	(*dump_mpp)(struct wiphy *wiphy, struct net_device *dev,
-			    int idx, u8 *dst, u8 *mpp,
-			    struct mpath_info *pinfo);
 	int	(*get_mesh_config)(struct wiphy *wiphy,
 				struct net_device *dev,
 				struct mesh_config *conf);
@@ -2512,10 +2407,6 @@
 			     const struct mesh_setup *setup);
 	int	(*leave_mesh)(struct wiphy *wiphy, struct net_device *dev);
 
-	int	(*join_ocb)(struct wiphy *wiphy, struct net_device *dev,
-			    struct ocb_setup *setup);
-	int	(*leave_ocb)(struct wiphy *wiphy, struct net_device *dev);
-
 	int	(*change_bss)(struct wiphy *wiphy, struct net_device *dev,
 			      struct bss_parameters *params);
 
@@ -2686,14 +2577,6 @@
 			     u16 admitted_time);
 	int	(*del_tx_ts)(struct wiphy *wiphy, struct net_device *dev,
 			     u8 tsid, const u8 *peer);
-
-	int	(*tdls_channel_switch)(struct wiphy *wiphy,
-				       struct net_device *dev,
-				       const u8 *addr, u8 oper_class,
-				       struct cfg80211_chan_def *chandef);
-	void	(*tdls_cancel_channel_switch)(struct wiphy *wiphy,
-					      struct net_device *dev,
-					      const u8 *addr);
 };
 
 /*
@@ -2740,9 +2623,13 @@
  * @WIPHY_FLAG_SUPPORTS_5_10_MHZ: Device supports 5 MHz and 10 MHz channels.
  * @WIPHY_FLAG_HAS_CHANNEL_SWITCH: Device supports channel switch in
  *	beaconing mode (AP, IBSS, Mesh, ...).
+ * @WIPHY_FLAG_SUPPORTS_WMM_ADMISSION: the device supports setting up WMM
+ *	TSPEC sessions (TID aka TSID 0-7) with the NL80211_CMD_ADD_TX_TS
+ *	command. Standard IEEE 802.11 TSPEC setup is not yet supported, it
+ *	needs to be able to handle Block-Ack agreements and other things.
  */
 enum wiphy_flags {
-	/* use hole at 0 */
+	WIPHY_FLAG_SUPPORTS_WMM_ADMISSION	= BIT(0),
 	/* use hole at 1 */
 	/* use hole at 2 */
 	WIPHY_FLAG_NETNS_OK			= BIT(3),
@@ -2868,7 +2755,6 @@
  * @WIPHY_WOWLAN_EAP_IDENTITY_REQ: supports wakeup on EAP identity request
  * @WIPHY_WOWLAN_4WAY_HANDSHAKE: supports wakeup on 4-way handshake failure
  * @WIPHY_WOWLAN_RFKILL_RELEASE: supports wakeup on RF-kill release
- * @WIPHY_WOWLAN_NET_DETECT: supports wakeup on network detection
  */
 enum wiphy_wowlan_support_flags {
 	WIPHY_WOWLAN_ANY		= BIT(0),
@@ -2879,7 +2765,6 @@
 	WIPHY_WOWLAN_EAP_IDENTITY_REQ	= BIT(5),
 	WIPHY_WOWLAN_4WAY_HANDSHAKE	= BIT(6),
 	WIPHY_WOWLAN_RFKILL_RELEASE	= BIT(7),
-	WIPHY_WOWLAN_NET_DETECT		= BIT(8),
 };
 
 struct wiphy_wowlan_tcp_support {
@@ -2898,11 +2783,6 @@
  * @pattern_max_len: maximum length of each pattern
  * @pattern_min_len: minimum length of each pattern
  * @max_pkt_offset: maximum Rx packet offset
- * @max_nd_match_sets: maximum number of matchsets for net-detect,
- *	similar, but not necessarily identical, to max_match_sets for
- *	scheduled scans.
- *	See &struct cfg80211_sched_scan_request.@match_sets for more
- *	details.
  * @tcp: TCP wakeup support information
  */
 struct wiphy_wowlan_support {
@@ -2911,7 +2791,6 @@
 	int pattern_max_len;
 	int pattern_min_len;
 	int max_pkt_offset;
-	int max_nd_match_sets;
 	const struct wiphy_wowlan_tcp_support *tcp;
 };
 
@@ -3290,23 +3169,6 @@
 }
 
 /**
- * wiphy_new_nm - create a new wiphy for use with cfg80211
- *
- * @ops: The configuration operations for this device
- * @sizeof_priv: The size of the private area to allocate
- * @requested_name: Request a particular name.
- *	NULL is valid value, and means use the default phy%d naming.
- *
- * Create a new wiphy and associate the given operations with it.
- * @sizeof_priv bytes are allocated for private use.
- *
- * Return: A pointer to the new wiphy. This pointer must be
- * assigned to each netdev's ieee80211_ptr for proper operation.
- */
-struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
-			   const char *requested_name);
-
-/**
  * wiphy_new - create a new wiphy for use with cfg80211
  *
  * @ops: The configuration operations for this device
@@ -3318,11 +3180,7 @@
  * Return: A pointer to the new wiphy. This pointer must be
  * assigned to each netdev's ieee80211_ptr for proper operation.
  */
-static inline struct wiphy *wiphy_new(const struct cfg80211_ops *ops,
-				      int sizeof_priv)
-{
-	return wiphy_new_nm(ops, sizeof_priv, NULL);
-}
+struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv);
 
 /**
  * wiphy_register - register a wiphy with cfg80211
@@ -4646,42 +4504,6 @@
 			      gfp_t gfp);
 
 /**
- * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
- * @dev: network device
- * @peer: peer's MAC address
- * @num_packets: how many packets were lost -- should be a fixed threshold
- *	but probably no less than maybe 50, or maybe a throughput dependent
- *	threshold (to account for temporary interference)
- * @gfp: context flags
- */
-void cfg80211_cqm_pktloss_notify(struct net_device *dev,
-				 const u8 *peer, u32 num_packets, gfp_t gfp);
-
-/**
- * cfg80211_cqm_txe_notify - TX error rate event
- * @dev: network device
- * @peer: peer's MAC address
- * @num_packets: how many packets were lost
- * @rate: % of packets which failed transmission
- * @intvl: interval (in s) over which the TX failure threshold was breached.
- * @gfp: context flags
- *
- * Notify userspace when configured % TX failures over number of packets in a
- * given interval is exceeded.
- */
-void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer,
-			     u32 num_packets, u32 rate, u32 intvl, gfp_t gfp);
-
-/**
- * cfg80211_cqm_beacon_loss_notify - beacon loss event
- * @dev: network device
- * @gfp: context flags
- *
- * Notify userspace about beacon loss from the connected AP.
- */
-void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp);
-
-/**
  * cfg80211_radar_event - radar detection event
  * @wiphy: the wiphy
  * @chandef: chandef for the current channel
@@ -4709,6 +4531,33 @@
 
 
 /**
+ * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @num_packets: how many packets were lost -- should be a fixed threshold
+ *	but probably no less than maybe 50, or maybe a throughput dependent
+ *	threshold (to account for temporary interference)
+ * @gfp: context flags
+ */
+void cfg80211_cqm_pktloss_notify(struct net_device *dev,
+				 const u8 *peer, u32 num_packets, gfp_t gfp);
+
+/**
+ * cfg80211_cqm_txe_notify - TX error rate event
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @num_packets: how many packets were lost
+ * @rate: % of packets which failed transmission
+ * @intvl: interval (in s) over which the TX failure threshold was breached.
+ * @gfp: context flags
+ *
+ * Notify userspace when configured % TX failures over number of packets in a
+ * given interval is exceeded.
+ */
+void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer,
+			     u32 num_packets, u32 rate, u32 intvl, gfp_t gfp);
+
+/**
  * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
  * @dev: network device
  * @bssid: BSSID of AP (to avoid races)
@@ -4811,20 +4660,6 @@
 void cfg80211_ch_switch_notify(struct net_device *dev,
 			       struct cfg80211_chan_def *chandef);
 
-/*
- * cfg80211_ch_switch_started_notify - notify channel switch start
- * @dev: the device on which the channel switch started
- * @chandef: the future channel definition
- * @count: the number of TBTTs until the channel switch happens
- *
- * Inform the userspace about the channel switch that has just
- * started, so that it can take appropriate actions (eg. starting
- * channel switch on other vifs), if necessary.
- */
-void cfg80211_ch_switch_started_notify(struct net_device *dev,
-				       struct cfg80211_chan_def *chandef,
-				       u8 count);
-
 /**
  * ieee80211_operating_class_to_band - convert operating class to band
  *
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
deleted file mode 100644
index 7f713ac..0000000
--- a/include/net/cfg802154.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2007, 2008, 2009 Siemens AG
- *
- * 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.
- *
- * Written by:
- * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
- */
-
-#ifndef __NET_CFG802154_H
-#define __NET_CFG802154_H
-
-#include <linux/ieee802154.h>
-#include <linux/netdevice.h>
-#include <linux/mutex.h>
-#include <linux/bug.h>
-
-#include <net/nl802154.h>
-
-struct wpan_phy;
-
-struct cfg802154_ops {
-	struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
-							   const char *name,
-							   int type);
-	void	(*del_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
-					       struct net_device *dev);
-	int	(*add_virtual_intf)(struct wpan_phy *wpan_phy,
-				    const char *name,
-				    enum nl802154_iftype type,
-				    __le64 extended_addr);
-	int	(*del_virtual_intf)(struct wpan_phy *wpan_phy,
-				    struct wpan_dev *wpan_dev);
-	int	(*set_channel)(struct wpan_phy *wpan_phy, u8 page, u8 channel);
-	int	(*set_pan_id)(struct wpan_phy *wpan_phy,
-			      struct wpan_dev *wpan_dev, __le16 pan_id);
-	int	(*set_short_addr)(struct wpan_phy *wpan_phy,
-				  struct wpan_dev *wpan_dev, __le16 short_addr);
-	int	(*set_backoff_exponent)(struct wpan_phy *wpan_phy,
-					struct wpan_dev *wpan_dev, u8 min_be,
-					u8 max_be);
-	int	(*set_max_csma_backoffs)(struct wpan_phy *wpan_phy,
-					 struct wpan_dev *wpan_dev,
-					 u8 max_csma_backoffs);
-	int	(*set_max_frame_retries)(struct wpan_phy *wpan_phy,
-					 struct wpan_dev *wpan_dev,
-					 s8 max_frame_retries);
-	int	(*set_lbt_mode)(struct wpan_phy *wpan_phy,
-				struct wpan_dev *wpan_dev, bool mode);
-};
-
-struct wpan_phy {
-	struct mutex pib_lock;
-
-	/* If multiple wpan_phys are registered and you're handed e.g.
-	 * a regular netdev with assigned ieee802154_ptr, you won't
-	 * know whether it points to a wpan_phy your driver has registered
-	 * or not. Assign this to something global to your driver to
-	 * help determine whether you own this wpan_phy or not.
-	 */
-	const void *privid;
-
-	/*
-	 * This is a PIB according to 802.15.4-2011.
-	 * We do not provide timing-related variables, as they
-	 * aren't used outside of driver
-	 */
-	u8 current_channel;
-	u8 current_page;
-	u32 channels_supported[IEEE802154_MAX_PAGE + 1];
-	s8 transmit_power;
-	u8 cca_mode;
-
-	__le64 perm_extended_addr;
-
-	s32 cca_ed_level;
-
-	/* PHY depended MAC PIB values */
-
-	/* 802.15.4 acronym: Tdsym in usec */
-	u8 symbol_duration;
-	/* lifs and sifs periods timing */
-	u16 lifs_period;
-	u16 sifs_period;
-
-	struct device dev;
-
-	char priv[0] __aligned(NETDEV_ALIGN);
-};
-
-struct wpan_dev {
-	struct wpan_phy *wpan_phy;
-	int iftype;
-
-	/* the remainder of this struct should be private to cfg802154 */
-	struct list_head list;
-	struct net_device *netdev;
-
-	u32 identifier;
-
-	/* MAC PIB */
-	__le16 pan_id;
-	__le16 short_addr;
-	__le64 extended_addr;
-
-	/* MAC BSN field */
-	u8 bsn;
-	/* MAC DSN field */
-	u8 dsn;
-
-	u8 min_be;
-	u8 max_be;
-	u8 csma_retries;
-	s8 frame_retries;
-
-	bool lbt;
-
-	bool promiscuous_mode;
-};
-
-#define to_phy(_dev)	container_of(_dev, struct wpan_phy, dev)
-
-struct wpan_phy *
-wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size);
-static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
-{
-	phy->dev.parent = dev;
-}
-
-int wpan_phy_register(struct wpan_phy *phy);
-void wpan_phy_unregister(struct wpan_phy *phy);
-void wpan_phy_free(struct wpan_phy *phy);
-/* Same semantics as for class_for_each_device */
-int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), void *data);
-
-static inline void *wpan_phy_priv(struct wpan_phy *phy)
-{
-	BUG_ON(!phy);
-	return &phy->priv;
-}
-
-struct wpan_phy *wpan_phy_find(const char *str);
-
-static inline void wpan_phy_put(struct wpan_phy *phy)
-{
-	put_device(&phy->dev);
-}
-
-static inline const char *wpan_phy_name(struct wpan_phy *phy)
-{
-	return dev_name(&phy->dev);
-}
-
-#endif /* __NET_CFG802154_H */
diff --git a/include/linux/ieee802154.h b/include/net/ieee802154.h
similarity index 79%
rename from include/linux/ieee802154.h
rename to include/net/ieee802154.h
index 6e82d88..0aa7122 100644
--- a/include/linux/ieee802154.h
+++ b/include/net/ieee802154.h
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
@@ -20,27 +24,10 @@
  * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
  */
 
-#ifndef LINUX_IEEE802154_H
-#define LINUX_IEEE802154_H
-
-#include <linux/types.h>
-#include <linux/random.h>
-#include <asm/byteorder.h>
+#ifndef NET_IEEE802154_H
+#define NET_IEEE802154_H
 
 #define IEEE802154_MTU			127
-#define IEEE802154_MIN_PSDU_LEN		5
-
-#define IEEE802154_PAN_ID_BROADCAST	0xffff
-#define IEEE802154_ADDR_SHORT_BROADCAST	0xffff
-#define IEEE802154_ADDR_SHORT_UNSPEC	0xfffe
-
-#define IEEE802154_EXTENDED_ADDR_LEN	8
-
-#define IEEE802154_LIFS_PERIOD		40
-#define IEEE802154_SIFS_PERIOD		12
-
-#define IEEE802154_MAX_CHANNEL		26
-#define IEEE802154_MAX_PAGE		31
 
 #define IEEE802154_FC_TYPE_BEACON	0x0	/* Frame is beacon */
 #define	IEEE802154_FC_TYPE_DATA		0x1	/* Frame is data */
@@ -202,41 +189,7 @@
 	IEEE802154_SCAN_IN_PROGRESS = 0xfc,
 };
 
-/**
- * ieee802154_is_valid_psdu_len - check if psdu len is valid
- * @len: psdu len with (MHR + payload + MFR)
- */
-static inline bool ieee802154_is_valid_psdu_len(const u8 len)
-{
-	return (len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU);
-}
 
-/**
- * ieee802154_is_valid_psdu_len - check if extended addr is valid
- * @addr: extended addr to check
- */
-static inline bool ieee802154_is_valid_extended_addr(const __le64 addr)
-{
-	/* These EUI-64 addresses are reserved by IEEE. 0xffffffffffffffff
-	 * is used internally as extended to short address broadcast mapping.
-	 * This is currently a workaround because neighbor discovery can't
-	 * deal with short addresses types right now.
-	 */
-	return ((addr != cpu_to_le64(0x0000000000000000ULL)) &&
-		(addr != cpu_to_le64(0xffffffffffffffffULL)));
-}
+#endif
 
-/**
- * ieee802154_random_extended_addr - generates a random extended address
- * @addr: extended addr pointer to place the random address
- */
-static inline void ieee802154_random_extended_addr(__le64 *addr)
-{
-	get_random_bytes(addr, IEEE802154_EXTENDED_ADDR_LEN);
 
-	/* toggle some bit if we hit an invalid extended addr */
-	if (!ieee802154_is_valid_extended_addr(*addr))
-		((u8 *)addr)[IEEE802154_EXTENDED_ADDR_LEN - 1] ^= 0x01;
-}
-
-#endif /* LINUX_IEEE802154_H */
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 83bb8a7..3b53c8e 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
@@ -23,10 +27,10 @@
 #ifndef IEEE802154_NETDEVICE_H
 #define IEEE802154_NETDEVICE_H
 
+#include <net/ieee802154.h>
 #include <net/af_ieee802154.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
-#include <linux/ieee802154.h>
 
 struct ieee802154_sechdr {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
@@ -423,6 +427,8 @@
 
 	/* The fields below are required. */
 
+	struct wpan_phy *(*get_phy)(const struct net_device *dev);
+
 	/*
 	 * FIXME: these should become the part of PIB/MIB interface.
 	 * However we still don't have IB interface of any kind
@@ -432,6 +438,16 @@
 	u8 (*get_dsn)(const struct net_device *dev);
 };
 
+/* The IEEE 802.15.4 standard defines 2 type of the devices:
+ * - FFD - full functionality device
+ * - RFD - reduce functionality device
+ *
+ * So 2 sets of mlme operations are needed
+ */
+struct ieee802154_reduced_mlme_ops {
+	struct wpan_phy *(*get_phy)(const struct net_device *dev);
+};
+
 static inline struct ieee802154_mlme_ops *
 ieee802154_mlme_ops(const struct net_device *dev)
 {
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 96323df..c5ba507 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -263,7 +263,6 @@
  * @BSS_CHANGED_BANDWIDTH: The bandwidth used by this interface changed,
  *	note that this is only called when it changes after the channel
  *	context had been assigned.
- * @BSS_CHANGED_OCB: OCB join status changed
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -288,7 +287,6 @@
 	BSS_CHANGED_P2P_PS		= 1<<19,
 	BSS_CHANGED_BEACON_INFO		= 1<<20,
 	BSS_CHANGED_BANDWIDTH		= 1<<21,
-	BSS_CHANGED_OCB                 = 1<<22,
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -741,8 +739,7 @@
 			u8 ampdu_ack_len;
 			u8 ampdu_len;
 			u8 antenna;
-			u16 tx_time;
-			void *status_driver_data[19 / sizeof(void *)];
+			void *status_driver_data[21 / sizeof(void *)];
 		} status;
 		struct {
 			struct ieee80211_tx_rate driver_rates[
@@ -882,9 +879,6 @@
  *	subframes share the same sequence number. Reported subframes can be
  *	either regular MSDU or singly A-MSDUs. Subframes must not be
  *	interleaved with other frames.
- * @RX_FLAG_RADIOTAP_VENDOR_DATA: This frame contains vendor-specific
- *	radiotap data in the skb->data (before the frame) as described by
- *	the &struct ieee80211_vendor_radiotap.
  */
 enum mac80211_rx_flags {
 	RX_FLAG_MMIC_ERROR		= BIT(0),
@@ -914,7 +908,6 @@
 	RX_FLAG_10MHZ			= BIT(28),
 	RX_FLAG_5MHZ			= BIT(29),
 	RX_FLAG_AMSDU_MORE		= BIT(30),
-	RX_FLAG_RADIOTAP_VENDOR_DATA	= BIT(31),
 };
 
 #define RX_FLAG_STBC_SHIFT		26
@@ -986,39 +979,6 @@
 };
 
 /**
- * struct ieee80211_vendor_radiotap - vendor radiotap data information
- * @present: presence bitmap for this vendor namespace
- *	(this could be extended in the future if any vendor needs more
- *	 bits, the radiotap spec does allow for that)
- * @align: radiotap vendor namespace alignment. This defines the needed
- *	alignment for the @data field below, not for the vendor namespace
- *	description itself (which has a fixed 2-byte alignment)
- *	Must be a power of two, and be set to at least 1!
- * @oui: radiotap vendor namespace OUI
- * @subns: radiotap vendor sub namespace
- * @len: radiotap vendor sub namespace skip length, if alignment is done
- *	then that's added to this, i.e. this is only the length of the
- *	@data field.
- * @pad: number of bytes of padding after the @data, this exists so that
- *	the skb data alignment can be preserved even if the data has odd
- *	length
- * @data: the actual vendor namespace data
- *
- * This struct, including the vendor data, goes into the skb->data before
- * the 802.11 header. It's split up in mac80211 using the align/oui/subns
- * data.
- */
-struct ieee80211_vendor_radiotap {
-	u32 present;
-	u8 align;
-	u8 oui[3];
-	u8 subns;
-	u8 pad;
-	u16 len;
-	u8 data[];
-} __packed;
-
-/**
  * enum ieee80211_conf_flags - configuration flags
  *
  * Flags to define PHY configuration options
@@ -1157,8 +1117,6 @@
  *	Function (TSF) timer when the frame containing the channel switch
  *	announcement was received. This is simply the rx.mactime parameter
  *	the driver passed into mac80211.
- * @device_timestamp: arbitrary timestamp for the device, this is the
- *	rx.device_timestamp parameter the driver passed to mac80211.
  * @block_tx: Indicates whether transmission must be blocked before the
  *	scheduled channel switch, as indicated by the AP.
  * @chandef: the new channel to switch to
@@ -1166,7 +1124,6 @@
  */
 struct ieee80211_channel_switch {
 	u64 timestamp;
-	u32 device_timestamp;
 	bool block_tx;
 	struct cfg80211_chan_def chandef;
 	u8 count;
@@ -1466,8 +1423,6 @@
  * @smps_mode: current SMPS mode (off, static or dynamic)
  * @rates: rate control selection table
  * @tdls: indicates whether the STA is a TDLS peer
- * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only
- *	valid if the STA is a TDLS peer in the first place.
  */
 struct ieee80211_sta {
 	u32 supp_rates[IEEE80211_NUM_BANDS];
@@ -1483,7 +1438,6 @@
 	enum ieee80211_smps_mode smps_mode;
 	struct ieee80211_sta_rates __rcu *rates;
 	bool tdls;
-	bool tdls_initiator;
 
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
@@ -1622,10 +1576,6 @@
  *	a virtual monitor interface when monitor interfaces are the only
  *	active interfaces.
  *
- * @IEEE80211_HW_NO_AUTO_VIF: The driver would like for no wlanX to
- *	be created.  It is expected user-space will create vifs as
- *	desired (and thus have them named as desired).
- *
  * @IEEE80211_HW_QUEUE_CONTROL: The driver wants to control per-interface
  *	queue mapping in order to use different queues (not just one per AC)
  *	for different virtual interfaces. See the doc section on HW queue
@@ -1672,8 +1622,7 @@
 	IEEE80211_HW_SUPPORTS_DYNAMIC_PS		= 1<<12,
 	IEEE80211_HW_MFP_CAPABLE			= 1<<13,
 	IEEE80211_HW_WANT_MONITOR_VIF			= 1<<14,
-	IEEE80211_HW_NO_AUTO_VIF			= 1<<15,
-	/* free slot */
+	/* free slots */
 	IEEE80211_HW_SUPPORTS_UAPSD			= 1<<17,
 	IEEE80211_HW_REPORTS_TX_ACK_STATUS		= 1<<18,
 	IEEE80211_HW_CONNECTION_MONITOR			= 1<<19,
@@ -1827,31 +1776,6 @@
 };
 
 /**
- * struct ieee80211_tdls_ch_sw_params - TDLS channel switch parameters
- *
- * @sta: peer this TDLS channel-switch request/response came from
- * @chandef: channel referenced in a TDLS channel-switch request
- * @action_code: see &enum ieee80211_tdls_actioncode
- * @status: channel-switch response status
- * @timestamp: time at which the frame was received
- * @switch_time: switch-timing parameter received in the frame
- * @switch_timeout: switch-timing parameter received in the frame
- * @tmpl_skb: TDLS switch-channel response template
- * @ch_sw_tm_ie: offset of the channel-switch timing IE inside @tmpl_skb
- */
-struct ieee80211_tdls_ch_sw_params {
-	struct ieee80211_sta *sta;
-	struct cfg80211_chan_def *chandef;
-	u8 action_code;
-	u32 status;
-	u32 timestamp;
-	u16 switch_time;
-	u16 switch_timeout;
-	struct sk_buff *tmpl_skb;
-	u32 ch_sw_tm_ie;
-};
-
-/**
  * wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy
  *
  * @wiphy: the &struct wiphy which we want to query
@@ -2451,22 +2375,6 @@
 };
 
 /**
- * enum ieee80211_reconfig_complete_type - reconfig type
- *
- * This enum is used by the reconfig_complete() callback to indicate what
- * reconfiguration type was completed.
- *
- * @IEEE80211_RECONFIG_TYPE_RESTART: hw restart type
- *	(also due to resume() callback returning 1)
- * @IEEE80211_RECONFIG_TYPE_SUSPEND: suspend type (regardless
- *	of wowlan configuration)
- */
-enum ieee80211_reconfig_type {
-	IEEE80211_RECONFIG_TYPE_RESTART,
-	IEEE80211_RECONFIG_TYPE_SUSPEND,
-};
-
-/**
  * struct ieee80211_ops - callbacks from mac80211 to the driver
  *
  * This structure contains various callbacks that the driver may
@@ -2622,9 +2530,7 @@
  *
  * @sw_scan_start: Notifier function that is called just before a software scan
  *	is started. Can be NULL, if the driver doesn't need this notification.
- *	The mac_addr parameter allows supporting NL80211_SCAN_FLAG_RANDOM_ADDR,
- *	the driver may set the NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR flag if it
- *	can use this parameter. The callback can sleep.
+ *	The callback can sleep.
  *
  * @sw_scan_complete: Notifier function that is called just after a
  *	software scan finished. Can be NULL, if the driver doesn't need
@@ -2695,9 +2601,6 @@
  *	uses hardware rate control (%IEEE80211_HW_HAS_RATE_CONTROL) since
  *	otherwise the rate control algorithm is notified directly.
  *	Must be atomic.
- * @sta_rate_tbl_update: Notifies the driver that the rate table changed. This
- *	is only used if the configured rate control algorithm actually uses
- *	the new rate table API, and is therefore optional. Must be atomic.
  *
  * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
  *	bursting) for a hardware TX queue.
@@ -2906,11 +2809,11 @@
  *	disabled/enabled via @bss_info_changed.
  * @stop_ap: Stop operation on the AP interface.
  *
- * @reconfig_complete: Called after a call to ieee80211_restart_hw() and
- *	during resume, when the reconfiguration has completed.
- *	This can help the driver implement the reconfiguration step (and
- *	indicate mac80211 is ready to receive frames).
- *	This callback may sleep.
+ * @restart_complete: Called after a call to ieee80211_restart_hw(), when the
+ *	reconfiguration has completed. This can help the driver implement the
+ *	reconfiguration step. Also called when reconfiguring because the
+ *	driver's resume function returned 1, as this is just like an "inline"
+ *	hardware restart. This callback may sleep.
  *
  * @ipv6_addr_change: IPv6 address assignment on the given interface changed.
  *	Currently, this is only called for managed or P2P client interfaces.
@@ -2926,13 +2829,6 @@
  *	transmitted and then call ieee80211_csa_finish().
  *	If the CSA count starts as zero or 1, this function will not be called,
  *	since there won't be any time to beacon before the switch anyway.
- * @pre_channel_switch: This is an optional callback that is called
- *	before a channel switch procedure is started (ie. when a STA
- *	gets a CSA or an userspace initiated channel-switch), allowing
- *	the driver to prepare for the channel switch.
- * @post_channel_switch: This is an optional callback that is called
- *	after a channel switch procedure is completed, allowing the
- *	driver to go back to a normal configuration.
  *
  * @join_ibss: Join an IBSS (on an IBSS interface); this is called after all
  *	information in bss_conf is set up and the beacon can be retrieved. A
@@ -2942,26 +2838,6 @@
  * @get_expected_throughput: extract the expected throughput towards the
  *	specified station. The returned value is expressed in Kbps. It returns 0
  *	if the RC algorithm does not have proper data to provide.
- *
- * @get_txpower: get current maximum tx power (in dBm) based on configuration
- *	and hardware limits.
- *
- * @tdls_channel_switch: Start channel-switching with a TDLS peer. The driver
- *	is responsible for continually initiating channel-switching operations
- *	and returning to the base channel for communication with the AP. The
- *	driver receives a channel-switch request template and the location of
- *	the switch-timing IE within the template as part of the invocation.
- *	The template is valid only within the call, and the driver can
- *	optionally copy the skb for further re-use.
- * @tdls_cancel_channel_switch: Stop channel-switching with a TDLS peer. Both
- *	peers must be on the base channel when the call completes.
- * @tdls_recv_channel_switch: a TDLS channel-switch related frame (request or
- *	response) has been received from a remote peer. The driver gets
- *	parameters parsed from the incoming frame and may use them to continue
- *	an ongoing channel-switch operation. In addition, a channel-switch
- *	response template is provided, together with the location of the
- *	switch-timing IE within the template. The skb can only be used within
- *	the function call.
  */
 struct ieee80211_ops {
 	void (*tx)(struct ieee80211_hw *hw,
@@ -3021,11 +2897,8 @@
 				struct ieee80211_scan_ies *ies);
 	int (*sched_scan_stop)(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif);
-	void (*sw_scan_start)(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif,
-			      const u8 *mac_addr);
-	void (*sw_scan_complete)(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif);
+	void (*sw_scan_start)(struct ieee80211_hw *hw);
+	void (*sw_scan_complete)(struct ieee80211_hw *hw);
 	int (*get_stats)(struct ieee80211_hw *hw,
 			 struct ieee80211_low_level_stats *stats);
 	void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
@@ -3059,9 +2932,6 @@
 			      struct ieee80211_vif *vif,
 			      struct ieee80211_sta *sta,
 			      u32 changed);
-	void (*sta_rate_tbl_update)(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_sta *sta);
 	int (*conf_tx)(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif, u16 ac,
 		       const struct ieee80211_tx_queue_params *params);
@@ -3089,7 +2959,6 @@
 	void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		      u32 queues, bool drop);
 	void (*channel_switch)(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
 			       struct ieee80211_channel_switch *ch_switch);
 	int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
 	int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
@@ -3156,8 +3025,7 @@
 				  int n_vifs,
 				  enum ieee80211_chanctx_switch_mode mode);
 
-	void (*reconfig_complete)(struct ieee80211_hw *hw,
-				  enum ieee80211_reconfig_type reconfig_type);
+	void (*restart_complete)(struct ieee80211_hw *hw);
 
 #if IS_ENABLED(CONFIG_IPV6)
 	void (*ipv6_addr_change)(struct ieee80211_hw *hw,
@@ -3167,54 +3035,14 @@
 	void (*channel_switch_beacon)(struct ieee80211_hw *hw,
 				      struct ieee80211_vif *vif,
 				      struct cfg80211_chan_def *chandef);
-	int (*pre_channel_switch)(struct ieee80211_hw *hw,
-				  struct ieee80211_vif *vif,
-				  struct ieee80211_channel_switch *ch_switch);
-
-	int (*post_channel_switch)(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif);
 
 	int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 	void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 	u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
-	int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			   int *dbm);
-
-	int (*tdls_channel_switch)(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif,
-				   struct ieee80211_sta *sta, u8 oper_class,
-				   struct cfg80211_chan_def *chandef,
-				   struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie);
-	void (*tdls_cancel_channel_switch)(struct ieee80211_hw *hw,
-					   struct ieee80211_vif *vif,
-					   struct ieee80211_sta *sta);
-	void (*tdls_recv_channel_switch)(struct ieee80211_hw *hw,
-					 struct ieee80211_vif *vif,
-					 struct ieee80211_tdls_ch_sw_params *params);
 };
 
 /**
- * ieee80211_alloc_hw_nm - Allocate a new hardware device
- *
- * This must be called once for each hardware device. The returned pointer
- * must be used to refer to this device when calling other functions.
- * mac80211 allocates a private data area for the driver pointed to by
- * @priv in &struct ieee80211_hw, the size of this area is given as
- * @priv_data_len.
- *
- * @priv_data_len: length of private data
- * @ops: callbacks for this device
- * @requested_name: Requested name for this device.
- *	NULL is valid value, and means use the default naming (phy%d)
- *
- * Return: A pointer to the new hardware device, or %NULL on error.
- */
-struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
-					   const struct ieee80211_ops *ops,
-					   const char *requested_name);
-
-/**
- * ieee80211_alloc_hw - Allocate a new hardware device
+ * ieee80211_alloc_hw -  Allocate a new hardware device
  *
  * This must be called once for each hardware device. The returned pointer
  * must be used to refer to this device when calling other functions.
@@ -3227,12 +3055,8 @@
  *
  * Return: A pointer to the new hardware device, or %NULL on error.
  */
-static inline
 struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
-					const struct ieee80211_ops *ops)
-{
-	return ieee80211_alloc_hw_nm(priv_data_len, ops, NULL);
-}
+					const struct ieee80211_ops *ops);
 
 /**
  * ieee80211_register_hw - Register hardware device
@@ -3619,26 +3443,6 @@
 			 struct sk_buff *skb);
 
 /**
- * ieee80211_tx_status_noskb - transmit status callback without skb
- *
- * This function can be used as a replacement for ieee80211_tx_status
- * in drivers that cannot reliably map tx status information back to
- * specific skbs.
- *
- * Calls to this function for a single hardware must be synchronized
- * against each other. Calls to this function, ieee80211_tx_status_ni()
- * and ieee80211_tx_status_irqsafe() may not be mixed for a single hardware.
- *
- * @hw: the hardware the frame was transmitted by
- * @sta: the receiver station to which this packet is sent
- *	(NULL for multicast packets)
- * @info: tx status information
- */
-void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
-			       struct ieee80211_sta *sta,
-			       struct ieee80211_tx_info *info);
-
-/**
  * ieee80211_tx_status_ni - transmit status callback (in process context)
  *
  * Like ieee80211_tx_status() but can be called in process context.
@@ -3851,7 +3655,7 @@
 /**
  * ieee80211_probereq_get - retrieve a Probe Request template
  * @hw: pointer obtained from ieee80211_alloc_hw().
- * @src_addr: source MAC address
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  * @ssid: SSID buffer
  * @ssid_len: length of SSID
  * @tailroom: tailroom to reserve at end of SKB for IEs
@@ -3862,7 +3666,7 @@
  * Return: The Probe Request template. %NULL on error.
  */
 struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
-				       const u8 *src_addr,
+				       struct ieee80211_vif *vif,
 				       const u8 *ssid, size_t ssid_len,
 				       size_t tailroom);
 
@@ -4368,22 +4172,6 @@
 					      void *data);
 
 /**
- * ieee80211_iterate_stations_atomic - iterate stations
- *
- * This function iterates over all stations associated with a given
- * hardware that are currently uploaded to the driver and calls the callback
- * function for them.
- * This function requires the iterator callback function to be atomic,
- *
- * @hw: the hardware struct of which the interfaces should be iterated over
- * @iterator: the iterator function to call, cannot sleep
- * @data: first argument of the iterator function
- */
-void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
-				       void (*iterator)(void *data,
-						struct ieee80211_sta *sta),
-				       void *data);
-/**
  * ieee80211_queue_work - add work onto the mac80211 workqueue
  *
  * Drivers and mac80211 use this to add work onto the mac80211 workqueue.
@@ -4692,14 +4480,6 @@
 			       gfp_t gfp);
 
 /**
- * ieee80211_cqm_beacon_loss_notify - inform CQM of beacon loss
- *
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
- * @gfp: context flags
- */
-void ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp);
-
-/**
  * ieee80211_radar_detected - inform that a radar was detected
  *
  * @hw: pointer as obtained from ieee80211_alloc_hw()
@@ -4857,10 +4637,6 @@
 	void (*free_sta)(void *priv, struct ieee80211_sta *sta,
 			 void *priv_sta);
 
-	void (*tx_status_noskb)(void *priv,
-				struct ieee80211_supported_band *sband,
-				struct ieee80211_sta *sta, void *priv_sta,
-				struct ieee80211_tx_info *info);
 	void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
 			  struct ieee80211_sta *sta, void *priv_sta,
 			  struct sk_buff *skb);
@@ -5112,69 +4888,4 @@
 void ieee80211_tdls_oper_request(struct ieee80211_vif *vif, const u8 *peer,
 				 enum nl80211_tdls_operation oper,
 				 u16 reason_code, gfp_t gfp);
-
-/**
- * ieee80211_reserve_tid - request to reserve a specific TID
- *
- * There is sometimes a need (such as in TDLS) for blocking the driver from
- * using a specific TID so that the FW can use it for certain operations such
- * as sending PTI requests. To make sure that the driver doesn't use that TID,
- * this function must be called as it flushes out packets on this TID and marks
- * it as blocked, so that any transmit for the station on this TID will be
- * redirected to the alternative TID in the same AC.
- *
- * Note that this function blocks and may call back into the driver, so it
- * should be called without driver locks held. Also note this function should
- * only be called from the driver's @sta_state callback.
- *
- * @sta: the station to reserve the TID for
- * @tid: the TID to reserve
- *
- * Returns: 0 on success, else on failure
- */
-int ieee80211_reserve_tid(struct ieee80211_sta *sta, u8 tid);
-
-/**
- * ieee80211_unreserve_tid - request to unreserve a specific TID
- *
- * Once there is no longer any need for reserving a certain TID, this function
- * should be called, and no longer will packets have their TID modified for
- * preventing use of this TID in the driver.
- *
- * Note that this function blocks and acquires a lock, so it should be called
- * without driver locks held. Also note this function should only be called
- * from the driver's @sta_state callback.
- *
- * @sta: the station
- * @tid: the TID to unreserve
- */
-void ieee80211_unreserve_tid(struct ieee80211_sta *sta, u8 tid);
-
-/**
- * ieee80211_ie_split - split an IE buffer according to ordering
- *
- * @ies: the IE buffer
- * @ielen: the length of the IE buffer
- * @ids: an array with element IDs that are allowed before
- *	the split
- * @n_ids: the size of the element ID array
- * @offset: offset where to start splitting in the buffer
- *
- * This function splits an IE buffer by updating the @offset
- * variable to point to the location where the buffer should be
- * split.
- *
- * It assumes that the given IE buffer is well-formed, this
- * has to be guaranteed by the caller!
- *
- * It also assumes that the IEs in the buffer are ordered
- * correctly, if not the result of using this function will not
- * be ordered correctly either, i.e. it does no reordering.
- *
- * The function returns the offset where the next part of the
- * buffer starts, which may be @ielen if the entire (remainder)
- * of the buffer should be used.
- */
-size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
-			  const u8 *ids, int n_ids, size_t offset);
 #endif /* MAC80211_H */
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index c823d91..2e67cdd 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -12,12 +12,14 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 #ifndef NET_MAC802154_H
 #define NET_MAC802154_H
 
 #include <net/af_ieee802154.h>
-#include <linux/ieee802154.h>
 #include <linux/skbuff.h>
 
 /* General MAC frame format:
@@ -33,13 +35,13 @@
  */
 
 /* indicates that the Short Address changed */
-#define IEEE802154_AFILT_SADDR_CHANGED		0x00000001
+#define IEEE802515_AFILT_SADDR_CHANGED		0x00000001
 /* indicates that the IEEE Address changed */
-#define IEEE802154_AFILT_IEEEADDR_CHANGED	0x00000002
+#define IEEE802515_AFILT_IEEEADDR_CHANGED	0x00000002
 /* indicates that the PAN ID changed */
-#define IEEE802154_AFILT_PANID_CHANGED		0x00000004
+#define IEEE802515_AFILT_PANID_CHANGED		0x00000004
 /* indicates that PAN Coordinator status changed */
-#define IEEE802154_AFILT_PANC_CHANGED		0x00000008
+#define	IEEE802515_AFILT_PANC_CHANGED		0x00000008
 
 struct ieee802154_hw_addr_filt {
 	__le16	pan_id;		/* Each independent PAN selects a unique
@@ -53,14 +55,7 @@
 	u8	pan_coord;
 };
 
-struct ieee802154_vif {
-	int type;
-
-	/* must be last */
-	u8 drv_priv[0] __aligned(sizeof(void *));
-};
-
-struct ieee802154_hw {
+struct ieee802154_dev {
 	/* filled by the driver */
 	int	extra_tx_headroom;
 	u32	flags;
@@ -70,7 +65,6 @@
 	struct	ieee802154_hw_addr_filt hw_filt;
 	void	*priv;
 	struct	wpan_phy *phy;
-	size_t vif_data_size;
 };
 
 /* Checksum is in hardware and is omitted from a packet
@@ -82,43 +76,28 @@
  * however, so you are advised to review these flags carefully.
  */
 
-/* Indicates that xmitter will add FCS on it's own. */
-#define IEEE802154_HW_TX_OMIT_CKSUM	0x00000001
+/* Indicates that receiver omits FCS and xmitter will add FCS on it's own. */
+#define	IEEE802154_HW_OMIT_CKSUM	0x00000001
 /* Indicates that receiver will autorespond with ACK frames. */
-#define IEEE802154_HW_AACK		0x00000002
+#define	IEEE802154_HW_AACK		0x00000002
 /* Indicates that transceiver will support transmit power setting. */
-#define IEEE802154_HW_TXPOWER		0x00000004
+#define	IEEE802154_HW_TXPOWER		0x00000004
 /* Indicates that transceiver will support listen before transmit. */
-#define IEEE802154_HW_LBT		0x00000008
+#define	IEEE802154_HW_LBT		0x00000008
 /* Indicates that transceiver will support cca mode setting. */
-#define IEEE802154_HW_CCA_MODE		0x00000010
+#define	IEEE802154_HW_CCA_MODE		0x00000010
 /* Indicates that transceiver will support cca ed level setting. */
-#define IEEE802154_HW_CCA_ED_LEVEL	0x00000020
+#define	IEEE802154_HW_CCA_ED_LEVEL	0x00000020
 /* Indicates that transceiver will support csma (max_be, min_be, csma retries)
  * settings. */
-#define IEEE802154_HW_CSMA_PARAMS	0x00000040
+#define	IEEE802154_HW_CSMA_PARAMS	0x00000040
 /* Indicates that transceiver will support ARET frame retries setting. */
-#define IEEE802154_HW_FRAME_RETRIES	0x00000080
-/* Indicates that transceiver will support hardware address filter setting. */
-#define IEEE802154_HW_AFILT		0x00000100
-/* Indicates that transceiver will support promiscuous mode setting. */
-#define IEEE802154_HW_PROMISCUOUS	0x00000200
-/* Indicates that receiver omits FCS. */
-#define IEEE802154_HW_RX_OMIT_CKSUM	0x00000400
-/* Indicates that receiver will not filter frames with bad checksum. */
-#define IEEE802154_HW_RX_DROP_BAD_CKSUM	0x00000800
-
-/* Indicates that receiver omits FCS and xmitter will add FCS on it's own. */
-#define IEEE802154_HW_OMIT_CKSUM	(IEEE802154_HW_TX_OMIT_CKSUM | \
-					 IEEE802154_HW_RX_OMIT_CKSUM)
+#define	IEEE802154_HW_FRAME_RETRIES	0x00000080
 
 /* This groups the most common CSMA support fields into one. */
 #define IEEE802154_HW_CSMA		(IEEE802154_HW_CCA_MODE | \
 					 IEEE802154_HW_CCA_ED_LEVEL | \
-					 IEEE802154_HW_CSMA_PARAMS)
-
-/* This groups the most common ARET support fields into one. */
-#define IEEE802154_HW_ARET		(IEEE802154_HW_CSMA | \
+					 IEEE802154_HW_CSMA_PARAMS | \
 					 IEEE802154_HW_FRAME_RETRIES)
 
 /* struct ieee802154_ops - callbacks from mac802154 to the driver
@@ -133,24 +112,12 @@
  * stop:  Handler that 802.15.4 module calls for device cleanup.
  *	  This function is called after the last interface is removed.
  *
- * xmit_sync:
- *	  Handler that 802.15.4 module calls for each transmitted frame.
- *	  skb cntains the buffer starting from the IEEE 802.15.4 header.
- *	  The low-level driver should send the frame based on available
- *	  configuration. This is called by a workqueue and useful for
- *	  synchronous 802.15.4 drivers.
- *	  This function should return zero or negative errno.
- *
- *	  WARNING:
- *	  This will be deprecated soon. We don't accept synced xmit callbacks
- *	  drivers anymore.
- *
- * xmit_async:
- *	  Handler that 802.15.4 module calls for each transmitted frame.
+ * xmit:  Handler that 802.15.4 module calls for each transmitted frame.
  *	  skb cntains the buffer starting from the IEEE 802.15.4 header.
  *	  The low-level driver should send the frame based on available
  *	  configuration.
- *	  This function should return zero or negative errno.
+ *	  This function should return zero or negative errno. Called with
+ *	  pib_lock held.
  *
  * ed:    Handler that 802.15.4 module calls for Energy Detection.
  *	  This function should place the value for detected energy
@@ -192,75 +159,40 @@
  * set_frame_retries
  *	  Sets the retransmission attempt limit. Called with pib_lock held.
  *	  Returns either zero, or negative errno.
- *
- * set_promiscuous_mode
- *	  Enables or disable promiscuous mode.
  */
 struct ieee802154_ops {
 	struct module	*owner;
-	int		(*start)(struct ieee802154_hw *hw);
-	void		(*stop)(struct ieee802154_hw *hw);
-	int		(*xmit_sync)(struct ieee802154_hw *hw,
-				     struct sk_buff *skb);
-	int		(*xmit_async)(struct ieee802154_hw *hw,
-				      struct sk_buff *skb);
-	int		(*ed)(struct ieee802154_hw *hw, u8 *level);
-	int		(*set_channel)(struct ieee802154_hw *hw, u8 page,
-				       u8 channel);
-	int		(*set_hw_addr_filt)(struct ieee802154_hw *hw,
-					    struct ieee802154_hw_addr_filt *filt,
+	int		(*start)(struct ieee802154_dev *dev);
+	void		(*stop)(struct ieee802154_dev *dev);
+	int		(*xmit)(struct ieee802154_dev *dev,
+				struct sk_buff *skb);
+	int		(*ed)(struct ieee802154_dev *dev, u8 *level);
+	int		(*set_channel)(struct ieee802154_dev *dev,
+				       int page,
+				       int channel);
+	int		(*set_hw_addr_filt)(struct ieee802154_dev *dev,
+					  struct ieee802154_hw_addr_filt *filt,
 					    unsigned long changed);
-	int		(*set_txpower)(struct ieee802154_hw *hw, int db);
-	int		(*set_lbt)(struct ieee802154_hw *hw, bool on);
-	int		(*set_cca_mode)(struct ieee802154_hw *hw, u8 mode);
-	int		(*set_cca_ed_level)(struct ieee802154_hw *hw,
+	int		(*ieee_addr)(struct ieee802154_dev *dev, __le64 addr);
+	int		(*set_txpower)(struct ieee802154_dev *dev, int db);
+	int		(*set_lbt)(struct ieee802154_dev *dev, bool on);
+	int		(*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
+	int		(*set_cca_ed_level)(struct ieee802154_dev *dev,
 					    s32 level);
-	int		(*set_csma_params)(struct ieee802154_hw *hw,
+	int		(*set_csma_params)(struct ieee802154_dev *dev,
 					   u8 min_be, u8 max_be, u8 retries);
-	int		(*set_frame_retries)(struct ieee802154_hw *hw,
+	int		(*set_frame_retries)(struct ieee802154_dev *dev,
 					     s8 retries);
-	int             (*set_promiscuous_mode)(struct ieee802154_hw *hw,
-						const bool on);
 };
 
-/**
- * ieee802154_be64_to_le64 - copies and convert be64 to le64
- * @le64_dst: le64 destination pointer
- * @be64_src: be64 source pointer
- */
-static inline void ieee802154_be64_to_le64(void *le64_dst, const void *be64_src)
-{
-	__le64 tmp = (__force __le64)swab64p(be64_src);
+/* Basic interface to register ieee802154 device */
+struct ieee802154_dev *
+ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops);
+void ieee802154_free_device(struct ieee802154_dev *dev);
+int ieee802154_register_device(struct ieee802154_dev *dev);
+void ieee802154_unregister_device(struct ieee802154_dev *dev);
 
-	memcpy(le64_dst, &tmp, IEEE802154_EXTENDED_ADDR_LEN);
-}
-
-/**
- * ieee802154_le64_to_be64 - copies and convert le64 to be64
- * @be64_dst: be64 destination pointer
- * @le64_src: le64 source pointer
- */
-static inline void ieee802154_le64_to_be64(void *be64_dst, const void *le64_src)
-{
-	__be64 tmp = (__force __be64)swab64p(le64_src);
-
-	memcpy(be64_dst, &tmp, IEEE802154_EXTENDED_ADDR_LEN);
-}
-
-/* Basic interface to register ieee802154 hwice */
-struct ieee802154_hw *
-ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops);
-void ieee802154_free_hw(struct ieee802154_hw *hw);
-int ieee802154_register_hw(struct ieee802154_hw *hw);
-void ieee802154_unregister_hw(struct ieee802154_hw *hw);
-
-void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb);
-void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
+void ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb,
 			   u8 lqi);
 
-void ieee802154_wake_queue(struct ieee802154_hw *hw);
-void ieee802154_stop_queue(struct ieee802154_hw *hw);
-void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
-			      bool ifs_handling);
-
 #endif /* NET_MAC802154_H */
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h
index 0ae101e..d9a5cf7 100644
--- a/include/net/nfc/digital.h
+++ b/include/net/nfc/digital.h
@@ -225,19 +225,6 @@
 	u8 curr_protocol;
 	u8 curr_rf_tech;
 	u8 curr_nfc_dep_pni;
-	u8 did;
-
-	u8 local_payload_max;
-	u8 remote_payload_max;
-
-	struct sk_buff *chaining_skb;
-	struct digital_data_exch *data_exch;
-
-	int atn_count;
-	int nack_count;
-
-	struct sk_buff *saved_skb;
-	unsigned int saved_skb_len;
 
 	u16 target_fsc;
 
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index 14bd0e1..7ee8f4c 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -57,14 +57,10 @@
 	int (*discover_se)(struct nfc_hci_dev *dev);
 	int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx);
 	int (*disable_se)(struct nfc_hci_dev *dev, u32 se_idx);
-	int (*se_io)(struct nfc_hci_dev *dev, u32 se_idx,
-		      u8 *apdu, size_t apdu_length,
-		      se_io_cb_t cb, void *cb_context);
 };
 
 /* Pipes */
 #define NFC_HCI_INVALID_PIPE	0x80
-#define NFC_HCI_DO_NOT_CREATE_PIPE	0x81
 #define NFC_HCI_LINK_MGMT_PIPE	0x00
 #define NFC_HCI_ADMIN_PIPE	0x01
 
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index e7257a4..9eca9ae 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -28,8 +28,6 @@
 #ifndef __NCI_H
 #define __NCI_H
 
-#include <net/nfc/nfc.h>
-
 /* NCI constants */
 #define NCI_MAX_NUM_MAPPING_CONFIGS				10
 #define NCI_MAX_NUM_RF_CONFIGS					10
@@ -75,8 +73,6 @@
 #define NCI_NFC_A_ACTIVE_LISTEN_MODE				0x83
 #define NCI_NFC_F_ACTIVE_LISTEN_MODE				0x85
 
-#define NCI_RF_TECH_MODE_LISTEN_MASK				0x80
-
 /* NCI RF Technologies */
 #define NCI_NFC_RF_TECHNOLOGY_A					0x00
 #define NCI_NFC_RF_TECHNOLOGY_B					0x01
@@ -110,17 +106,6 @@
 
 /* NCI Configuration Parameter Tags */
 #define NCI_PN_ATR_REQ_GEN_BYTES				0x29
-#define NCI_LN_ATR_RES_GEN_BYTES				0x61
-#define NCI_LA_SEL_INFO						0x32
-#define NCI_LF_PROTOCOL_TYPE					0x50
-#define NCI_LF_CON_BITR_F					0x54
-
-/* NCI Configuration Parameters masks */
-#define NCI_LA_SEL_INFO_ISO_DEP_MASK				0x20
-#define NCI_LA_SEL_INFO_NFC_DEP_MASK				0x40
-#define NCI_LF_PROTOCOL_TYPE_NFC_DEP_MASK			0x02
-#define NCI_LF_CON_BITR_F_212					0x02
-#define NCI_LF_CON_BITR_F_424					0x04
 
 /* NCI Reset types */
 #define NCI_RESET_TYPE_KEEP_CONFIG				0x00
@@ -329,31 +314,26 @@
 struct rf_tech_specific_params_nfca_poll {
 	__u16	sens_res;
 	__u8	nfcid1_len;	/* 0, 4, 7, or 10 Bytes */
-	__u8	nfcid1[NFC_NFCID1_MAXSIZE];
+	__u8	nfcid1[10];
 	__u8	sel_res_len;	/* 0 or 1 Bytes */
 	__u8	sel_res;
 } __packed;
 
 struct rf_tech_specific_params_nfcb_poll {
 	__u8	sensb_res_len;
-	__u8	sensb_res[NFC_SENSB_RES_MAXSIZE];	/* 11 or 12 Bytes */
+	__u8	sensb_res[12];	/* 11 or 12 Bytes */
 } __packed;
 
 struct rf_tech_specific_params_nfcf_poll {
 	__u8	bit_rate;
 	__u8	sensf_res_len;
-	__u8	sensf_res[NFC_SENSF_RES_MAXSIZE];	/* 16 or 18 Bytes */
+	__u8	sensf_res[18];	/* 16 or 18 Bytes */
 } __packed;
 
 struct rf_tech_specific_params_nfcv_poll {
 	__u8	res_flags;
 	__u8	dsfid;
-	__u8	uid[NFC_ISO15693_UID_MAXSIZE];	/* 8 Bytes */
-} __packed;
-
-struct rf_tech_specific_params_nfcf_listen {
-	__u8	local_nfcid2_len;
-	__u8	local_nfcid2[NFC_NFCID2_MAXSIZE];	/* 0 or 8 Bytes */
+	__u8	uid[8];	/* 8 Bytes */
 } __packed;
 
 struct nci_rf_discover_ntf {
@@ -385,12 +365,7 @@
 
 struct activation_params_poll_nfc_dep {
 	__u8	atr_res_len;
-	__u8	atr_res[NFC_ATR_RES_MAXSIZE - 2]; /* ATR_RES from byte 3 */
-};
-
-struct activation_params_listen_nfc_dep {
-	__u8	atr_req_len;
-	__u8	atr_req[NFC_ATR_REQ_MAXSIZE - 2]; /* ATR_REQ from byte 3 */
+	__u8	atr_res[63];
 };
 
 struct nci_rf_intf_activated_ntf {
@@ -407,7 +382,6 @@
 		struct rf_tech_specific_params_nfcb_poll nfcb_poll;
 		struct rf_tech_specific_params_nfcf_poll nfcf_poll;
 		struct rf_tech_specific_params_nfcv_poll nfcv_poll;
-		struct rf_tech_specific_params_nfcf_listen nfcf_listen;
 	} rf_tech_specific_params;
 
 	__u8	data_exch_rf_tech_and_mode;
@@ -419,7 +393,6 @@
 		struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep;
 		struct activation_params_nfcb_poll_iso_dep nfcb_poll_iso_dep;
 		struct activation_params_poll_nfc_dep poll_nfc_dep;
-		struct activation_params_listen_nfc_dep listen_nfc_dep;
 	} activation_params;
 
 } __packed;
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 9e51bb4..75d10e6 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -4,7 +4,6 @@
  *
  *  Copyright (C) 2011 Texas Instruments, Inc.
  *  Copyright (C) 2013 Intel Corporation. All rights reserved.
- *  Copyright (C) 2014 Marvell International Ltd.
  *
  *  Written by Ilan Elias <ilane@ti.com>
  *
@@ -50,8 +49,6 @@
 	NCI_W4_ALL_DISCOVERIES,
 	NCI_W4_HOST_SELECT,
 	NCI_POLL_ACTIVE,
-	NCI_LISTEN_ACTIVE,
-	NCI_LISTEN_SLEEP,
 };
 
 /* NCI timeouts */
@@ -72,12 +69,6 @@
 	int   (*send)(struct nci_dev *ndev, struct sk_buff *skb);
 	int   (*setup)(struct nci_dev *ndev);
 	__u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol);
-	int   (*discover_se)(struct nci_dev *ndev);
-	int   (*disable_se)(struct nci_dev *ndev, u32 se_idx);
-	int   (*enable_se)(struct nci_dev *ndev, u32 se_idx);
-	int   (*se_io)(struct nci_dev *ndev, u32 se_idx,
-				u8 *apdu, size_t apdu_length,
-				se_io_cb_t cb, void *cb_context);
 };
 
 #define NCI_MAX_SUPPORTED_RF_INTERFACES		4
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 12adb81..6c583e2 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -1,6 +1,5 @@
 /*
  * Copyright (C) 2011 Instituto Nokia de Tecnologia
- * Copyright (C) 2014 Marvell International Ltd.
  *
  * Authors:
  *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
@@ -88,7 +87,6 @@
 #define NFC_TARGET_IDX_ANY -1
 #define NFC_MAX_GT_LEN 48
 #define NFC_ATR_RES_GT_OFFSET 15
-#define NFC_ATR_REQ_GT_OFFSET 14
 
 /**
  * struct nfc_target - NFC target descriptiom
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 6dbd406..b23548e 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -1,122 +1,126 @@
-#ifndef __NL802154_H
-#define __NL802154_H
 /*
- * 802.15.4 netlink interface public header
+ * nl802154.h
  *
- * Copyright 2014 Alexander Aring <aar@pengutronix.de>
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
  *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
+ * 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.
  *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
 
-#define NL802154_GENL_NAME "nl802154"
+#ifndef IEEE802154_NL_H
+#define IEEE802154_NL_H
 
-enum nl802154_commands {
-/* don't change the order or add anything between, this is ABI! */
-/* currently we don't shipping this file via uapi, ignore the above one */
-	NL802154_CMD_UNSPEC,
+struct net_device;
+struct ieee802154_addr;
 
-	NL802154_CMD_GET_WPAN_PHY,		/* can dump */
-	NL802154_CMD_SET_WPAN_PHY,
-	NL802154_CMD_NEW_WPAN_PHY,
-	NL802154_CMD_DEL_WPAN_PHY,
+/**
+ * ieee802154_nl_assoc_indic - Notify userland of an association request.
+ * @dev: The network device on which this association request was
+ *       received.
+ * @addr: The address of the device requesting association.
+ * @cap: The capability information field from the device.
+ *
+ * This informs a userland coordinator of a device requesting to
+ * associate with the PAN controlled by the coordinator.
+ *
+ * Note: This is in section 7.3.1 of the IEEE 802.15.4-2006 document.
+ */
+int ieee802154_nl_assoc_indic(struct net_device *dev,
+		struct ieee802154_addr *addr, u8 cap);
 
-	NL802154_CMD_GET_INTERFACE,		/* can dump */
-	NL802154_CMD_SET_INTERFACE,
-	NL802154_CMD_NEW_INTERFACE,
-	NL802154_CMD_DEL_INTERFACE,
+/**
+ * ieee802154_nl_assoc_confirm - Notify userland of association.
+ * @dev: The device which has completed association.
+ * @short_addr: The short address assigned to the device.
+ * @status: The status of the association.
+ *
+ * Inform userland of the result of an association request. If the
+ * association request included asking the coordinator to allocate
+ * a short address then it is returned in @short_addr.
+ *
+ * Note: This is in section 7.3.2 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_assoc_confirm(struct net_device *dev,
+		__le16 short_addr, u8 status);
 
-	NL802154_CMD_SET_CHANNEL,
+/**
+ * ieee802154_nl_disassoc_indic - Notify userland of disassociation.
+ * @dev: The device on which disassociation was indicated.
+ * @addr: The device which is disassociating.
+ * @reason: The reason for the disassociation.
+ *
+ * Inform userland that a device has disassociated from the network.
+ *
+ * Note: This is in section 7.3.3 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_disassoc_indic(struct net_device *dev,
+		struct ieee802154_addr *addr, u8 reason);
 
-	NL802154_CMD_SET_PAN_ID,
-	NL802154_CMD_SET_SHORT_ADDR,
+/**
+ * ieee802154_nl_disassoc_confirm - Notify userland of disassociation
+ * completion.
+ * @dev: The device on which disassociation was ordered.
+ * @status: The result of the disassociation.
+ *
+ * Inform userland of the result of requesting that a device
+ * disassociate, or the result of requesting that we disassociate from
+ * a PAN managed by another coordinator.
+ *
+ * Note: This is in section 7.1.4.3 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_disassoc_confirm(struct net_device *dev,
+		u8 status);
 
-	NL802154_CMD_SET_TX_POWER,
-	NL802154_CMD_SET_CCA_MODE,
-	NL802154_CMD_SET_CCA_ED_LEVEL,
+/**
+ * ieee802154_nl_scan_confirm - Notify userland of completion of scan.
+ * @dev: The device which was instructed to scan.
+ * @status: The status of the scan operation.
+ * @scan_type: What type of scan was performed.
+ * @unscanned: Any channels that the device was unable to scan.
+ * @edl: The energy levels (if a passive scan).
+ *
+ *
+ * Note: This is in section 7.1.11 of the IEEE 802.15.4 document.
+ * Note: This API does not permit the return of an active scan result.
+ */
+int ieee802154_nl_scan_confirm(struct net_device *dev,
+		u8 status, u8 scan_type, u32 unscanned, u8 page,
+		u8 *edl/*, struct list_head *pan_desc_list */);
 
-	NL802154_CMD_SET_MAX_FRAME_RETRIES,
+/**
+ * ieee802154_nl_beacon_indic - Notify userland of a received beacon.
+ * @dev: The device on which a beacon was received.
+ * @panid: The PAN of the coordinator.
+ * @coord_addr: The short address of the coordinator on that PAN.
+ *
+ * Note: This is in section 7.1.5 of the IEEE 802.15.4 document.
+ * Note: This API does not provide extended information such as what
+ * channel the PAN is on or what the LQI of the beacon frame was on
+ * receipt.
+ * Note: This API cannot indicate a beacon frame for a coordinator
+ *       operating in long addressing mode.
+ */
+int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
+		__le16 coord_addr);
 
-	NL802154_CMD_SET_BACKOFF_EXPONENT,
-	NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
+/**
+ * ieee802154_nl_start_confirm - Notify userland of completion of start.
+ * @dev: The device which was instructed to scan.
+ * @status: The status of the scan operation.
+ *
+ * Note: This is in section 7.1.14 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_start_confirm(struct net_device *dev, u8 status);
 
-	NL802154_CMD_SET_LBT_MODE,
-
-	/* add new commands above here */
-
-	/* used to define NL802154_CMD_MAX below */
-	__NL802154_CMD_AFTER_LAST,
-	NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1
-};
-
-enum nl802154_attrs {
-/* don't change the order or add anything between, this is ABI! */
-/* currently we don't shipping this file via uapi, ignore the above one */
-	NL802154_ATTR_UNSPEC,
-
-	NL802154_ATTR_WPAN_PHY,
-	NL802154_ATTR_WPAN_PHY_NAME,
-
-	NL802154_ATTR_IFINDEX,
-	NL802154_ATTR_IFNAME,
-	NL802154_ATTR_IFTYPE,
-
-	NL802154_ATTR_WPAN_DEV,
-
-	NL802154_ATTR_PAGE,
-	NL802154_ATTR_CHANNEL,
-
-	NL802154_ATTR_PAN_ID,
-	NL802154_ATTR_SHORT_ADDR,
-
-	NL802154_ATTR_TX_POWER,
-
-	NL802154_ATTR_CCA_MODE,
-	NL802154_ATTR_CCA_MODE3_AND,
-	NL802154_ATTR_CCA_ED_LEVEL,
-
-	NL802154_ATTR_MAX_FRAME_RETRIES,
-
-	NL802154_ATTR_MAX_BE,
-	NL802154_ATTR_MIN_BE,
-	NL802154_ATTR_MAX_CSMA_BACKOFFS,
-
-	NL802154_ATTR_LBT_MODE,
-
-	NL802154_ATTR_GENERATION,
-
-	NL802154_ATTR_CHANNELS_SUPPORTED,
-	NL802154_ATTR_SUPPORTED_CHANNEL,
-
-	NL802154_ATTR_EXTENDED_ADDR,
-
-	/* add attributes here, update the policy in nl802154.c */
-
-	__NL802154_ATTR_AFTER_LAST,
-	NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1
-};
-
-enum nl802154_iftype {
-	/* for backwards compatibility TODO */
-	NL802154_IFTYPE_UNSPEC = -1,
-
-	NL802154_IFTYPE_NODE,
-	NL802154_IFTYPE_MONITOR,
-	NL802154_IFTYPE_COORD,
-
-	/* keep last */
-	NUM_NL802154_IFTYPES,
-	NL802154_IFTYPE_MAX = NUM_NL802154_IFTYPES - 1
-};
-
-#endif /* __NL802154_H */
+#endif
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index b776d72..dad7ab2 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -136,17 +136,6 @@
  *      otherwise initiating radiation is not allowed. This will enable the
  *      relaxations enabled under the CFG80211_REG_RELAX_NO_IR configuration
  *      option
- * @REGULATORY_IGNORE_STALE_KICKOFF: the regulatory core will _not_ make sure
- *	all interfaces on this wiphy reside on allowed channels. If this flag
- *	is not set, upon a regdomain change, the interfaces are given a grace
- *	period (currently 60 seconds) to disconnect or move to an allowed
- *	channel. Interfaces on forbidden channels are forcibly disconnected.
- *	Currently these types of interfaces are supported for enforcement:
- *	NL80211_IFTYPE_ADHOC, NL80211_IFTYPE_STATION, NL80211_IFTYPE_AP,
- *	NL80211_IFTYPE_AP_VLAN, NL80211_IFTYPE_MONITOR,
- *	NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_P2P_GO,
- *	NL80211_IFTYPE_P2P_DEVICE. The flag will be set by default if a device
- *	includes any modes unsupported for enforcement checking.
  */
 enum ieee80211_regulatory_flags {
 	REGULATORY_CUSTOM_REG			= BIT(0),
@@ -155,7 +144,6 @@
 	REGULATORY_COUNTRY_IE_FOLLOW_POWER	= BIT(3),
 	REGULATORY_COUNTRY_IE_IGNORE		= BIT(4),
 	REGULATORY_ENABLE_RELAX_NO_IR           = BIT(5),
-	REGULATORY_IGNORE_STALE_KICKOFF         = BIT(6),
 };
 
 struct ieee80211_freq_range {
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
new file mode 100644
index 0000000..10ab0fc
--- /dev/null
+++ b/include/net/wpan-phy.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ */
+
+#ifndef WPAN_PHY_H
+#define WPAN_PHY_H
+
+#include <linux/netdevice.h>
+#include <linux/mutex.h>
+#include <linux/bug.h>
+
+/* According to the IEEE 802.15.4 stadard the upper most significant bits of
+ * the 32-bit channel bitmaps shall be used as an integer value to specify 32
+ * possible channel pages. The lower 27 bits of the channel bit map shall be
+ * used as a bit mask to specify channel numbers within a channel page.
+ */
+#define WPAN_NUM_CHANNELS	27
+#define WPAN_NUM_PAGES		32
+
+struct wpan_phy {
+	struct mutex pib_lock;
+
+	/*
+	 * This is a PIB according to 802.15.4-2011.
+	 * We do not provide timing-related variables, as they
+	 * aren't used outside of driver
+	 */
+	u8 current_channel;
+	u8 current_page;
+	u32 channels_supported[32];
+	s8 transmit_power;
+	u8 cca_mode;
+	u8 min_be;
+	u8 max_be;
+	u8 csma_retries;
+	s8 frame_retries;
+
+	bool lbt;
+	s32 cca_ed_level;
+
+	struct device dev;
+	int idx;
+
+	struct net_device *(*add_iface)(struct wpan_phy *phy,
+					const char *name, int type);
+	void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
+
+	int (*set_txpower)(struct wpan_phy *phy, int db);
+	int (*set_lbt)(struct wpan_phy *phy, bool on);
+	int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode);
+	int (*set_cca_ed_level)(struct wpan_phy *phy, int level);
+	int (*set_csma_params)(struct wpan_phy *phy, u8 min_be, u8 max_be,
+			       u8 retries);
+	int (*set_frame_retries)(struct wpan_phy *phy, s8 retries);
+
+	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
+};
+
+#define to_phy(_dev)	container_of(_dev, struct wpan_phy, dev)
+
+struct wpan_phy *wpan_phy_alloc(size_t priv_size);
+static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
+{
+	phy->dev.parent = dev;
+}
+int wpan_phy_register(struct wpan_phy *phy);
+void wpan_phy_unregister(struct wpan_phy *phy);
+void wpan_phy_free(struct wpan_phy *phy);
+/* Same semantics as for class_for_each_device */
+int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), void *data);
+
+static inline void *wpan_phy_priv(struct wpan_phy *phy)
+{
+	BUG_ON(!phy);
+	return &phy->priv;
+}
+
+struct wpan_phy *wpan_phy_find(const char *str);
+
+static inline void wpan_phy_put(struct wpan_phy *phy)
+{
+	put_device(&phy->dev);
+}
+
+static inline const char *wpan_phy_name(struct wpan_phy *phy)
+{
+	return dev_name(&phy->dev);
+}
+#endif
diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h
deleted file mode 100644
index 23b4090..0000000
--- a/include/uapi/linux/media-bus-format.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Media Bus API header
- *
- * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * 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 __LINUX_MEDIA_BUS_FORMAT_H
-#define __LINUX_MEDIA_BUS_FORMAT_H
-
-/*
- * These bus formats uniquely identify data formats on the data bus. Format 0
- * is reserved, MEDIA_BUS_FMT_FIXED shall be used by host-client pairs, where
- * the data format is fixed. Additionally, "2X8" means that one pixel is
- * transferred in two 8-bit samples, "BE" or "LE" specify in which order those
- * samples are transferred over the bus: "LE" means that the least significant
- * bits are transferred first, "BE" means that the most significant bits are
- * transferred first, and "PADHI" and "PADLO" define which bits - low or high,
- * in the incomplete high byte, are filled with padding bits.
- *
- * The bus formats are grouped by type, bus_width, bits per component, samples
- * per pixel and order of subsamples. Numerical values are sorted using generic
- * numerical sort order (8 thus comes before 10).
- *
- * As their value can't change when a new bus format is inserted in the
- * enumeration, the bus formats are explicitly given a numerical value. The next
- * free values for each category are listed below, update them when inserting
- * new pixel codes.
- */
-
-#define MEDIA_BUS_FMT_FIXED			0x0001
-
-/* RGB - next is	0x100e */
-#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE	0x1001
-#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE	0x1002
-#define MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE	0x1003
-#define MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE	0x1004
-#define MEDIA_BUS_FMT_BGR565_2X8_BE		0x1005
-#define MEDIA_BUS_FMT_BGR565_2X8_LE		0x1006
-#define MEDIA_BUS_FMT_RGB565_2X8_BE		0x1007
-#define MEDIA_BUS_FMT_RGB565_2X8_LE		0x1008
-#define MEDIA_BUS_FMT_RGB666_1X18		0x1009
-#define MEDIA_BUS_FMT_RGB888_1X24		0x100a
-#define MEDIA_BUS_FMT_RGB888_2X12_BE		0x100b
-#define MEDIA_BUS_FMT_RGB888_2X12_LE		0x100c
-#define MEDIA_BUS_FMT_ARGB8888_1X32		0x100d
-
-/* YUV (including grey) - next is	0x2024 */
-#define MEDIA_BUS_FMT_Y8_1X8			0x2001
-#define MEDIA_BUS_FMT_UV8_1X8			0x2015
-#define MEDIA_BUS_FMT_UYVY8_1_5X8		0x2002
-#define MEDIA_BUS_FMT_VYUY8_1_5X8		0x2003
-#define MEDIA_BUS_FMT_YUYV8_1_5X8		0x2004
-#define MEDIA_BUS_FMT_YVYU8_1_5X8		0x2005
-#define MEDIA_BUS_FMT_UYVY8_2X8			0x2006
-#define MEDIA_BUS_FMT_VYUY8_2X8			0x2007
-#define MEDIA_BUS_FMT_YUYV8_2X8			0x2008
-#define MEDIA_BUS_FMT_YVYU8_2X8			0x2009
-#define MEDIA_BUS_FMT_Y10_1X10			0x200a
-#define MEDIA_BUS_FMT_UYVY10_2X10		0x2018
-#define MEDIA_BUS_FMT_VYUY10_2X10		0x2019
-#define MEDIA_BUS_FMT_YUYV10_2X10		0x200b
-#define MEDIA_BUS_FMT_YVYU10_2X10		0x200c
-#define MEDIA_BUS_FMT_Y12_1X12			0x2013
-#define MEDIA_BUS_FMT_UYVY8_1X16		0x200f
-#define MEDIA_BUS_FMT_VYUY8_1X16		0x2010
-#define MEDIA_BUS_FMT_YUYV8_1X16		0x2011
-#define MEDIA_BUS_FMT_YVYU8_1X16		0x2012
-#define MEDIA_BUS_FMT_YDYUYDYV8_1X16		0x2014
-#define MEDIA_BUS_FMT_UYVY10_1X20		0x201a
-#define MEDIA_BUS_FMT_VYUY10_1X20		0x201b
-#define MEDIA_BUS_FMT_YUYV10_1X20		0x200d
-#define MEDIA_BUS_FMT_YVYU10_1X20		0x200e
-#define MEDIA_BUS_FMT_YUV10_1X30		0x2016
-#define MEDIA_BUS_FMT_AYUV8_1X32		0x2017
-#define MEDIA_BUS_FMT_UYVY12_2X12		0x201c
-#define MEDIA_BUS_FMT_VYUY12_2X12		0x201d
-#define MEDIA_BUS_FMT_YUYV12_2X12		0x201e
-#define MEDIA_BUS_FMT_YVYU12_2X12		0x201f
-#define MEDIA_BUS_FMT_UYVY12_1X24		0x2020
-#define MEDIA_BUS_FMT_VYUY12_1X24		0x2021
-#define MEDIA_BUS_FMT_YUYV12_1X24		0x2022
-#define MEDIA_BUS_FMT_YVYU12_1X24		0x2023
-
-/* Bayer - next is	0x3019 */
-#define MEDIA_BUS_FMT_SBGGR8_1X8		0x3001
-#define MEDIA_BUS_FMT_SGBRG8_1X8		0x3013
-#define MEDIA_BUS_FMT_SGRBG8_1X8		0x3002
-#define MEDIA_BUS_FMT_SRGGB8_1X8		0x3014
-#define MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8		0x3015
-#define MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8		0x3016
-#define MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8		0x3017
-#define MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8		0x3018
-#define MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8		0x300b
-#define MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8		0x300c
-#define MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8		0x3009
-#define MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8		0x300d
-#define MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE	0x3003
-#define MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE	0x3004
-#define MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE	0x3005
-#define MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE	0x3006
-#define MEDIA_BUS_FMT_SBGGR10_1X10		0x3007
-#define MEDIA_BUS_FMT_SGBRG10_1X10		0x300e
-#define MEDIA_BUS_FMT_SGRBG10_1X10		0x300a
-#define MEDIA_BUS_FMT_SRGGB10_1X10		0x300f
-#define MEDIA_BUS_FMT_SBGGR12_1X12		0x3008
-#define MEDIA_BUS_FMT_SGBRG12_1X12		0x3010
-#define MEDIA_BUS_FMT_SGRBG12_1X12		0x3011
-#define MEDIA_BUS_FMT_SRGGB12_1X12		0x3012
-
-/* JPEG compressed formats - next is	0x4002 */
-#define MEDIA_BUS_FMT_JPEG_1X8			0x4001
-
-/* Vendor specific formats - next is	0x5002 */
-
-/* S5C73M3 sensor specific interleaved UYVY and JPEG */
-#define MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8		0x5001
-
-/* HSV - next is	0x6002 */
-#define MEDIA_BUS_FMT_AHSV8888_1X32		0x6001
-
-#endif /* __LINUX_MEDIA_BUS_FORMAT_H */
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index 8119255..9b19b44 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -116,7 +116,6 @@
 	NFC_EVENT_SE_TRANSACTION,
 	NFC_CMD_GET_SE,
 	NFC_CMD_SE_IO,
-	NFC_CMD_ACTIVATE_TARGET,
 /* private: internal use only */
 	__NFC_CMD_AFTER_LAST
 };
@@ -197,19 +196,15 @@
 };
 #define NFC_SDP_ATTR_MAX (__NFC_SDP_ATTR_AFTER_LAST - 1)
 
-#define NFC_DEVICE_NAME_MAXSIZE		8
-#define NFC_NFCID1_MAXSIZE		10
-#define NFC_NFCID2_MAXSIZE		8
-#define NFC_NFCID3_MAXSIZE		10
-#define NFC_SENSB_RES_MAXSIZE		12
-#define NFC_SENSF_RES_MAXSIZE		18
-#define NFC_ATR_REQ_MAXSIZE		64
-#define NFC_ATR_RES_MAXSIZE		64
-#define NFC_ATR_REQ_GB_MAXSIZE		48
-#define NFC_ATR_RES_GB_MAXSIZE		47
-#define NFC_GB_MAXSIZE			48
-#define NFC_FIRMWARE_NAME_MAXSIZE	32
-#define NFC_ISO15693_UID_MAXSIZE	8
+#define NFC_DEVICE_NAME_MAXSIZE 8
+#define NFC_NFCID1_MAXSIZE 10
+#define NFC_NFCID2_MAXSIZE 8
+#define NFC_NFCID3_MAXSIZE 10
+#define NFC_SENSB_RES_MAXSIZE 12
+#define NFC_SENSF_RES_MAXSIZE 18
+#define NFC_GB_MAXSIZE        48
+#define NFC_FIRMWARE_NAME_MAXSIZE 32
+#define NFC_ISO15693_UID_MAXSIZE 8
 
 /* NFC protocols */
 #define NFC_PROTO_JEWEL		1
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index b37bd5a..4b28dc0 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -227,11 +227,7 @@
  *	the interface identified by %NL80211_ATTR_IFINDEX.
  * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC
  *	or, if no MAC address given, all stations, on the interface identified
- *	by %NL80211_ATTR_IFINDEX. %NL80211_ATTR_MGMT_SUBTYPE and
- *	%NL80211_ATTR_REASON_CODE can optionally be used to specify which type
- *	of disconnection indication should be sent to the station
- *	(Deauthentication or Disassociation frame and reason code for that
- *	frame).
+ *	by %NL80211_ATTR_IFINDEX.
  *
  * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
  * 	destination %NL80211_ATTR_MAC on the interface identified by
@@ -643,18 +639,7 @@
  * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels
  *	independently of the userspace SME, send this event indicating
  *	%NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the
- *	attributes determining channel width.  This indication may also be
- *	sent when a remotely-initiated switch (e.g., when a STA receives a CSA
- *	from the remote AP) is completed;
- *
- * @NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: Notify that a channel switch
- *	has been started on an interface, regardless of the initiator
- *	(ie. whether it was requested from a remote device or
- *	initiated on our own).  It indicates that
- *	%NL80211_ATTR_IFINDEX will be on %NL80211_ATTR_WIPHY_FREQ
- *	after %NL80211_ATTR_CH_SWITCH_COUNT TBTT's.  The userspace may
- *	decide to react to this indication by requesting other
- *	interfaces to change channel as well.
+ *	attributes determining channel width.
  *
  * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
  *	its %NL80211_ATTR_WDEV identifier. It must have been created with
@@ -753,27 +738,6 @@
  *	before removing a station entry entirely, or before disassociating
  *	or similar, cleanup will happen in the driver/device in this case.
  *
- * @NL80211_CMD_GET_MPP: Get mesh path attributes for mesh proxy path to
- *	destination %NL80211_ATTR_MAC on the interface identified by
- *	%NL80211_ATTR_IFINDEX.
- *
- * @NL80211_CMD_JOIN_OCB: Join the OCB network. The center frequency and
- *	bandwidth of a channel must be given.
- * @NL80211_CMD_LEAVE_OCB: Leave the OCB network -- no special arguments, the
- *	network is determined by the network interface.
- *
- * @NL80211_CMD_TDLS_CHANNEL_SWITCH: Start channel-switching with a TDLS peer,
- *	identified by the %NL80211_ATTR_MAC parameter. A target channel is
- *	provided via %NL80211_ATTR_WIPHY_FREQ and other attributes determining
- *	channel width/type. The target operating class is given via
- *	%NL80211_ATTR_OPER_CLASS.
- *	The driver is responsible for continually initiating channel-switching
- *	operations and returning to the base channel for communication with the
- *	AP.
- * @NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH: Stop channel-switching with a TDLS
- *	peer given by %NL80211_ATTR_MAC. Both peers must be on the base channel
- *	when this command completes.
- *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -948,16 +912,6 @@
 	NL80211_CMD_ADD_TX_TS,
 	NL80211_CMD_DEL_TX_TS,
 
-	NL80211_CMD_GET_MPP,
-
-	NL80211_CMD_JOIN_OCB,
-	NL80211_CMD_LEAVE_OCB,
-
-	NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
-
-	NL80211_CMD_TDLS_CHANNEL_SWITCH,
-	NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
-
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1652,9 +1606,9 @@
  * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32.
  *	As specified in the &enum nl80211_tdls_peer_capability.
  *
- * @NL80211_ATTR_SOCKET_OWNER: Flag attribute, if set during interface
+ * @NL80211_ATTR_IFACE_SOCKET_OWNER: flag attribute, if set during interface
  *	creation then the new interface will be owned by the netlink socket
- *	that created it and will be destroyed when the socket is closed.
+ *	that created it and will be destroyed when the socket is closed
  *
  * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
  *	the TDLS link initiator.
@@ -1684,11 +1638,6 @@
  * @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see
  *	&enum nl80211_smps_mode.
  *
- * @NL80211_ATTR_OPER_CLASS: operating class
- *
- * @NL80211_ATTR_MAC_MASK: MAC address mask
- *
- * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -2024,7 +1973,7 @@
 
 	NL80211_ATTR_TDLS_PEER_CAPABILITY,
 
-	NL80211_ATTR_SOCKET_OWNER,
+	NL80211_ATTR_IFACE_SOCKET_OWNER,
 
 	NL80211_ATTR_CSA_C_OFFSETS_TX,
 	NL80211_ATTR_MAX_CSA_COUNTERS,
@@ -2041,21 +1990,15 @@
 
 	NL80211_ATTR_SMPS_MODE,
 
-	NL80211_ATTR_OPER_CLASS,
-
-	NL80211_ATTR_MAC_MASK,
-
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
-	NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
 	NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
 };
 
 /* source-level API compatibility */
 #define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
 #define	NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
-#define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER
 
 /*
  * Allow user space programs to use #ifdef on new attributes by defining them
@@ -2121,8 +2064,6 @@
  *	and therefore can't be created in the normal ways, use the
  *	%NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
  *	commands to create and destroy one
- * @NL80211_IF_TYPE_OCB: Outside Context of a BSS
- *	This mode corresponds to the MIB variable dot11OCBActivated=true
  * @NL80211_IFTYPE_MAX: highest interface type number currently defined
  * @NUM_NL80211_IFTYPES: number of defined interface types
  *
@@ -2142,7 +2083,6 @@
 	NL80211_IFTYPE_P2P_CLIENT,
 	NL80211_IFTYPE_P2P_GO,
 	NL80211_IFTYPE_P2P_DEVICE,
-	NL80211_IFTYPE_OCB,
 
 	/* keep last */
 	NUM_NL80211_IFTYPES,
@@ -2691,11 +2631,6 @@
  * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated
  *	base on contiguous rules and wider channels will be allowed to cross
  *	multiple contiguous/overlapping frequency ranges.
- * @NL80211_RRF_GO_CONCURRENT: See &NL80211_FREQUENCY_ATTR_GO_CONCURRENT
- * @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation
- * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation
- * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
- * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
  */
 enum nl80211_reg_rule_flags {
 	NL80211_RRF_NO_OFDM		= 1<<0,
@@ -2708,18 +2643,11 @@
 	NL80211_RRF_NO_IR		= 1<<7,
 	__NL80211_RRF_NO_IBSS		= 1<<8,
 	NL80211_RRF_AUTO_BW		= 1<<11,
-	NL80211_RRF_GO_CONCURRENT	= 1<<12,
-	NL80211_RRF_NO_HT40MINUS	= 1<<13,
-	NL80211_RRF_NO_HT40PLUS		= 1<<14,
-	NL80211_RRF_NO_80MHZ		= 1<<15,
-	NL80211_RRF_NO_160MHZ		= 1<<16,
 };
 
 #define NL80211_RRF_PASSIVE_SCAN	NL80211_RRF_NO_IR
 #define NL80211_RRF_NO_IBSS		NL80211_RRF_NO_IR
 #define NL80211_RRF_NO_IR		NL80211_RRF_NO_IR
-#define NL80211_RRF_NO_HT40		(NL80211_RRF_NO_HT40MINUS |\
-					 NL80211_RRF_NO_HT40PLUS)
 
 /* For backport compatibility with older userspace */
 #define NL80211_RRF_NO_IR_ALL		(NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
@@ -3451,8 +3379,6 @@
  *	interval in which %NL80211_ATTR_CQM_TXE_PKTS and
  *	%NL80211_ATTR_CQM_TXE_RATE must be satisfied before generating an
  *	%NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting.
- * @NL80211_ATTR_CQM_BEACON_LOSS_EVENT: flag attribute that's set in a beacon
- *	loss event
  * @__NL80211_ATTR_CQM_AFTER_LAST: internal
  * @NL80211_ATTR_CQM_MAX: highest key attribute
  */
@@ -3465,7 +3391,6 @@
 	NL80211_ATTR_CQM_TXE_RATE,
 	NL80211_ATTR_CQM_TXE_PKTS,
 	NL80211_ATTR_CQM_TXE_INTVL,
-	NL80211_ATTR_CQM_BEACON_LOSS_EVENT,
 
 	/* keep last */
 	__NL80211_ATTR_CQM_AFTER_LAST,
@@ -3478,7 +3403,9 @@
  *      configured threshold
  * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the
  *      configured threshold
- * @NL80211_CQM_RSSI_BEACON_LOSS_EVENT: (reserved, never sent)
+ * @NL80211_CQM_RSSI_BEACON_LOSS_EVENT: The device experienced beacon loss.
+ *	(Note that deauth/disassoc will still follow if the AP is not
+ *	available. This event might get used as roaming event, etc.)
  */
 enum nl80211_cqm_rssi_threshold_event {
 	NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
@@ -3618,25 +3545,6 @@
  * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: For wakeup reporting only,
  *	the TCP connection ran out of tokens to use for data to send to the
  *	service
- * @NL80211_WOWLAN_TRIG_NET_DETECT: wake up when a configured network
- *	is detected.  This is a nested attribute that contains the
- *	same attributes used with @NL80211_CMD_START_SCHED_SCAN.  It
- *	specifies how the scan is performed (e.g. the interval and the
- *	channels to scan) as well as the scan results that will
- *	trigger a wake (i.e. the matchsets).
- * @NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS: nested attribute
- *	containing an array with information about what triggered the
- *	wake up.  If no elements are present in the array, it means
- *	that the information is not available.  If more than one
- *	element is present, it means that more than one match
- *	occurred.
- *	Each element in the array is a nested attribute that contains
- *	one optional %NL80211_ATTR_SSID attribute and one optional
- *	%NL80211_ATTR_SCAN_FREQUENCIES attribute.  At least one of
- *	these attributes must be present.  If
- *	%NL80211_ATTR_SCAN_FREQUENCIES contains more than one
- *	frequency, it means that the match occurred in more than one
- *	channel.
  * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
  * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
  *
@@ -3662,8 +3570,6 @@
 	NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH,
 	NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST,
 	NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS,
-	NL80211_WOWLAN_TRIG_NET_DETECT,
-	NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS,
 
 	/* keep last */
 	NUM_NL80211_WOWLAN_TRIG,
@@ -4136,27 +4042,6 @@
  *	multiplexing powersave, ie. can turn off all but one chain
  *	and then wake the rest up as required after, for example,
  *	rts/cts handshake.
- * @NL80211_FEATURE_SUPPORTS_WMM_ADMISSION: the device supports setting up WMM
- *	TSPEC sessions (TID aka TSID 0-7) with the %NL80211_CMD_ADD_TX_TS
- *	command. Standard IEEE 802.11 TSPEC setup is not yet supported, it
- *	needs to be able to handle Block-Ack agreements and other things.
- * @NL80211_FEATURE_MAC_ON_CREATE: Device supports configuring
- *	the vif's MAC address upon creation.
- *	See 'macaddr' field in the vif_params (cfg80211.h).
- * @NL80211_FEATURE_TDLS_CHANNEL_SWITCH: Driver supports channel switching when
- *	operating as a TDLS peer.
- * @NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports using a
- *	random MAC address during scan (if the device is unassociated); the
- *	%NL80211_SCAN_FLAG_RANDOM_ADDR flag may be set for scans and the MAC
- *	address mask/value will be used.
- * @NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR: This device/driver supports
- *	using a random MAC address for every scan iteration during scheduled
- *	scan (while not associated), the %NL80211_SCAN_FLAG_RANDOM_ADDR may
- *	be set for scheduled scan and the MAC address mask/value will be used.
- * @NL80211_FEATURE_ND_RANDOM_MAC_ADDR: This device/driver supports using a
- *	random MAC address for every scan iteration during "net detect", i.e.
- *	scan in unassociated WoWLAN, the %NL80211_SCAN_FLAG_RANDOM_ADDR may
- *	be set for scheduled scan and the MAC address mask/value will be used.
  */
 enum nl80211_feature_flags {
 	NL80211_FEATURE_SK_TX_STATUS			= 1 << 0,
@@ -4185,12 +4070,6 @@
 	NL80211_FEATURE_ACKTO_ESTIMATION		= 1 << 23,
 	NL80211_FEATURE_STATIC_SMPS			= 1 << 24,
 	NL80211_FEATURE_DYNAMIC_SMPS			= 1 << 25,
-	NL80211_FEATURE_SUPPORTS_WMM_ADMISSION		= 1 << 26,
-	NL80211_FEATURE_MAC_ON_CREATE			= 1 << 27,
-	NL80211_FEATURE_TDLS_CHANNEL_SWITCH		= 1 << 28,
-	NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR		= 1 << 29,
-	NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR	= 1 << 30,
-	NL80211_FEATURE_ND_RANDOM_MAC_ADDR		= 1 << 31,
 };
 
 /**
@@ -4239,21 +4118,11 @@
  *	dangerous because will destroy stations performance as a lot of frames
  *	will be lost while scanning off-channel, therefore it must be used only
  *	when really needed
- * @NL80211_SCAN_FLAG_RANDOM_ADDR: use a random MAC address for this scan (or
- *	for scheduled scan: a different one for every scan iteration). When the
- *	flag is set, depending on device capabilities the @NL80211_ATTR_MAC and
- *	@NL80211_ATTR_MAC_MASK attributes may also be given in which case only
- *	the masked bits will be preserved from the MAC address and the remainder
- *	randomised. If the attributes are not given full randomisation (46 bits,
- *	locally administered 1, multicast 0) is assumed.
- *	This flag must not be requested when the feature isn't supported, check
- *	the nl80211 feature flags for the device.
  */
 enum nl80211_scan_flags {
 	NL80211_SCAN_FLAG_LOW_PRIORITY			= 1<<0,
 	NL80211_SCAN_FLAG_FLUSH				= 1<<1,
 	NL80211_SCAN_FLAG_AP				= 1<<2,
-	NL80211_SCAN_FLAG_RANDOM_ADDR			= 1<<3,
 };
 
 /**
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
deleted file mode 100644
index 4a1d0cc..0000000
--- a/include/uapi/linux/pci_regs.h
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- *	pci_regs.h
- *
- *	PCI standard defines
- *	Copyright 1994, Drew Eckhardt
- *	Copyright 1997--1999 Martin Mares <mj@ucw.cz>
- *
- *	For more information, please consult the following manuals (look at
- *	http://www.pcisig.com/ for how to get them):
- *
- *	PCI BIOS Specification
- *	PCI Local Bus Specification
- *	PCI to PCI Bridge Specification
- *	PCI System Design Guide
- *
- *	For HyperTransport information, please consult the following manuals
- *	from http://www.hypertransport.org
- *
- *	The HyperTransport I/O Link Specification
- */
-
-#ifndef LINUX_PCI_REGS_H
-#define LINUX_PCI_REGS_H
-
-/*
- * Under PCI, each device has 256 bytes of configuration address space,
- * of which the first 64 bytes are standardized as follows:
- */
-#define PCI_STD_HEADER_SIZEOF	64
-#define PCI_VENDOR_ID		0x00	/* 16 bits */
-#define PCI_DEVICE_ID		0x02	/* 16 bits */
-#define PCI_COMMAND		0x04	/* 16 bits */
-#define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
-#define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
-#define  PCI_COMMAND_MASTER	0x4	/* Enable bus mastering */
-#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
-#define  PCI_COMMAND_INVALIDATE	0x10	/* Use memory write and invalidate */
-#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
-#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
-#define  PCI_COMMAND_WAIT	0x80	/* Enable address/data stepping */
-#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
-#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
-#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
-
-#define PCI_STATUS		0x06	/* 16 bits */
-#define  PCI_STATUS_INTERRUPT	0x08	/* Interrupt status */
-#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
-#define  PCI_STATUS_66MHZ	0x20	/* Support 66 MHz PCI 2.1 bus */
-#define  PCI_STATUS_UDF		0x40	/* Support User Definable Features [obsolete] */
-#define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
-#define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
-#define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
-#define  PCI_STATUS_DEVSEL_FAST		0x000
-#define  PCI_STATUS_DEVSEL_MEDIUM	0x200
-#define  PCI_STATUS_DEVSEL_SLOW		0x400
-#define  PCI_STATUS_SIG_TARGET_ABORT	0x800 /* Set on target abort */
-#define  PCI_STATUS_REC_TARGET_ABORT	0x1000 /* Master ack of " */
-#define  PCI_STATUS_REC_MASTER_ABORT	0x2000 /* Set on master abort */
-#define  PCI_STATUS_SIG_SYSTEM_ERROR	0x4000 /* Set when we drive SERR */
-#define  PCI_STATUS_DETECTED_PARITY	0x8000 /* Set on parity error */
-
-#define PCI_CLASS_REVISION	0x08	/* High 24 bits are class, low 8 revision */
-#define PCI_REVISION_ID		0x08	/* Revision ID */
-#define PCI_CLASS_PROG		0x09	/* Reg. Level Programming Interface */
-#define PCI_CLASS_DEVICE	0x0a	/* Device class */
-
-#define PCI_CACHE_LINE_SIZE	0x0c	/* 8 bits */
-#define PCI_LATENCY_TIMER	0x0d	/* 8 bits */
-#define PCI_HEADER_TYPE		0x0e	/* 8 bits */
-#define  PCI_HEADER_TYPE_NORMAL		0
-#define  PCI_HEADER_TYPE_BRIDGE		1
-#define  PCI_HEADER_TYPE_CARDBUS	2
-
-#define PCI_BIST		0x0f	/* 8 bits */
-#define  PCI_BIST_CODE_MASK	0x0f	/* Return result */
-#define  PCI_BIST_START		0x40	/* 1 to start BIST, 2 secs or less */
-#define  PCI_BIST_CAPABLE	0x80	/* 1 if BIST capable */
-
-/*
- * Base addresses specify locations in memory or I/O space.
- * Decoded size can be determined by writing a value of
- * 0xffffffff to the register, and reading it back.  Only
- * 1 bits are decoded.
- */
-#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
-#define PCI_BASE_ADDRESS_1	0x14	/* 32 bits [htype 0,1 only] */
-#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits [htype 0 only] */
-#define PCI_BASE_ADDRESS_3	0x1c	/* 32 bits */
-#define PCI_BASE_ADDRESS_4	0x20	/* 32 bits */
-#define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
-#define  PCI_BASE_ADDRESS_SPACE		0x01	/* 0 = memory, 1 = I/O */
-#define  PCI_BASE_ADDRESS_SPACE_IO	0x01
-#define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
-#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK	0x06
-#define  PCI_BASE_ADDRESS_MEM_TYPE_32	0x00	/* 32 bit address */
-#define  PCI_BASE_ADDRESS_MEM_TYPE_1M	0x02	/* Below 1M [obsolete] */
-#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
-#define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
-#define  PCI_BASE_ADDRESS_MEM_MASK	(~0x0fUL)
-#define  PCI_BASE_ADDRESS_IO_MASK	(~0x03UL)
-/* bit 1 is reserved if address_space = 1 */
-
-/* Header type 0 (normal devices) */
-#define PCI_CARDBUS_CIS		0x28
-#define PCI_SUBSYSTEM_VENDOR_ID	0x2c
-#define PCI_SUBSYSTEM_ID	0x2e
-#define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
-#define  PCI_ROM_ADDRESS_ENABLE	0x01
-#define PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
-
-#define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
-
-/* 0x35-0x3b are reserved */
-#define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
-#define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
-#define PCI_MIN_GNT		0x3e	/* 8 bits */
-#define PCI_MAX_LAT		0x3f	/* 8 bits */
-
-/* Header type 1 (PCI-to-PCI bridges) */
-#define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
-#define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
-#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
-#define PCI_SEC_LATENCY_TIMER	0x1b	/* Latency timer for secondary interface */
-#define PCI_IO_BASE		0x1c	/* I/O range behind the bridge */
-#define PCI_IO_LIMIT		0x1d
-#define  PCI_IO_RANGE_TYPE_MASK	0x0fUL	/* I/O bridging type */
-#define  PCI_IO_RANGE_TYPE_16	0x00
-#define  PCI_IO_RANGE_TYPE_32	0x01
-#define  PCI_IO_RANGE_MASK	(~0x0fUL) /* Standard 4K I/O windows */
-#define  PCI_IO_1K_RANGE_MASK	(~0x03UL) /* Intel 1K I/O windows */
-#define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
-#define PCI_MEMORY_BASE		0x20	/* Memory range behind */
-#define PCI_MEMORY_LIMIT	0x22
-#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
-#define  PCI_MEMORY_RANGE_MASK	(~0x0fUL)
-#define PCI_PREF_MEMORY_BASE	0x24	/* Prefetchable memory range behind */
-#define PCI_PREF_MEMORY_LIMIT	0x26
-#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
-#define  PCI_PREF_RANGE_TYPE_32	0x00
-#define  PCI_PREF_RANGE_TYPE_64	0x01
-#define  PCI_PREF_RANGE_MASK	(~0x0fUL)
-#define PCI_PREF_BASE_UPPER32	0x28	/* Upper half of prefetchable memory range */
-#define PCI_PREF_LIMIT_UPPER32	0x2c
-#define PCI_IO_BASE_UPPER16	0x30	/* Upper half of I/O addresses */
-#define PCI_IO_LIMIT_UPPER16	0x32
-/* 0x34 same as for htype 0 */
-/* 0x35-0x3b is reserved */
-#define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_BRIDGE_CONTROL	0x3e
-#define  PCI_BRIDGE_CTL_PARITY	0x01	/* Enable parity detection on secondary interface */
-#define  PCI_BRIDGE_CTL_SERR	0x02	/* The same for SERR forwarding */
-#define  PCI_BRIDGE_CTL_ISA	0x04	/* Enable ISA mode */
-#define  PCI_BRIDGE_CTL_VGA	0x08	/* Forward VGA addresses */
-#define  PCI_BRIDGE_CTL_MASTER_ABORT	0x20  /* Report master aborts */
-#define  PCI_BRIDGE_CTL_BUS_RESET	0x40	/* Secondary bus reset */
-#define  PCI_BRIDGE_CTL_FAST_BACK	0x80	/* Fast Back2Back enabled on secondary interface */
-
-/* Header type 2 (CardBus bridges) */
-#define PCI_CB_CAPABILITY_LIST	0x14
-/* 0x15 reserved */
-#define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
-#define PCI_CB_PRIMARY_BUS	0x18	/* PCI bus number */
-#define PCI_CB_CARD_BUS		0x19	/* CardBus bus number */
-#define PCI_CB_SUBORDINATE_BUS	0x1a	/* Subordinate bus number */
-#define PCI_CB_LATENCY_TIMER	0x1b	/* CardBus latency timer */
-#define PCI_CB_MEMORY_BASE_0	0x1c
-#define PCI_CB_MEMORY_LIMIT_0	0x20
-#define PCI_CB_MEMORY_BASE_1	0x24
-#define PCI_CB_MEMORY_LIMIT_1	0x28
-#define PCI_CB_IO_BASE_0	0x2c
-#define PCI_CB_IO_BASE_0_HI	0x2e
-#define PCI_CB_IO_LIMIT_0	0x30
-#define PCI_CB_IO_LIMIT_0_HI	0x32
-#define PCI_CB_IO_BASE_1	0x34
-#define PCI_CB_IO_BASE_1_HI	0x36
-#define PCI_CB_IO_LIMIT_1	0x38
-#define PCI_CB_IO_LIMIT_1_HI	0x3a
-#define  PCI_CB_IO_RANGE_MASK	(~0x03UL)
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_CB_BRIDGE_CONTROL	0x3e
-#define  PCI_CB_BRIDGE_CTL_PARITY	0x01	/* Similar to standard bridge control register */
-#define  PCI_CB_BRIDGE_CTL_SERR		0x02
-#define  PCI_CB_BRIDGE_CTL_ISA		0x04
-#define  PCI_CB_BRIDGE_CTL_VGA		0x08
-#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT	0x20
-#define  PCI_CB_BRIDGE_CTL_CB_RESET	0x40	/* CardBus reset */
-#define  PCI_CB_BRIDGE_CTL_16BIT_INT	0x80	/* Enable interrupt for 16-bit cards */
-#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100	/* Prefetch enable for both memory regions */
-#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
-#define  PCI_CB_BRIDGE_CTL_POST_WRITES	0x400
-#define PCI_CB_SUBSYSTEM_VENDOR_ID	0x40
-#define PCI_CB_SUBSYSTEM_ID		0x42
-#define PCI_CB_LEGACY_MODE_BASE		0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
-/* 0x48-0x7f reserved */
-
-/* Capability lists */
-
-#define PCI_CAP_LIST_ID		0	/* Capability ID */
-#define  PCI_CAP_ID_PM		0x01	/* Power Management */
-#define  PCI_CAP_ID_AGP		0x02	/* Accelerated Graphics Port */
-#define  PCI_CAP_ID_VPD		0x03	/* Vital Product Data */
-#define  PCI_CAP_ID_SLOTID	0x04	/* Slot Identification */
-#define  PCI_CAP_ID_MSI		0x05	/* Message Signalled Interrupts */
-#define  PCI_CAP_ID_CHSWP	0x06	/* CompactPCI HotSwap */
-#define  PCI_CAP_ID_PCIX	0x07	/* PCI-X */
-#define  PCI_CAP_ID_HT		0x08	/* HyperTransport */
-#define  PCI_CAP_ID_VNDR	0x09	/* Vendor-Specific */
-#define  PCI_CAP_ID_DBG		0x0A	/* Debug port */
-#define  PCI_CAP_ID_CCRC	0x0B	/* CompactPCI Central Resource Control */
-#define  PCI_CAP_ID_SHPC	0x0C	/* PCI Standard Hot-Plug Controller */
-#define  PCI_CAP_ID_SSVID	0x0D	/* Bridge subsystem vendor/device ID */
-#define  PCI_CAP_ID_AGP3	0x0E	/* AGP Target PCI-PCI bridge */
-#define  PCI_CAP_ID_SECDEV	0x0F	/* Secure Device */
-#define  PCI_CAP_ID_EXP		0x10	/* PCI Express */
-#define  PCI_CAP_ID_MSIX	0x11	/* MSI-X */
-#define  PCI_CAP_ID_SATA	0x12	/* SATA Data/Index Conf. */
-#define  PCI_CAP_ID_AF		0x13	/* PCI Advanced Features */
-#define  PCI_CAP_ID_MAX		PCI_CAP_ID_AF
-#define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
-#define PCI_CAP_FLAGS		2	/* Capability defined flags (16 bits) */
-#define PCI_CAP_SIZEOF		4
-
-/* Power Management Registers */
-
-#define PCI_PM_PMC		2	/* PM Capabilities Register */
-#define  PCI_PM_CAP_VER_MASK	0x0007	/* Version */
-#define  PCI_PM_CAP_PME_CLOCK	0x0008	/* PME clock required */
-#define  PCI_PM_CAP_RESERVED    0x0010  /* Reserved field */
-#define  PCI_PM_CAP_DSI		0x0020	/* Device specific initialization */
-#define  PCI_PM_CAP_AUX_POWER	0x01C0	/* Auxiliary power support mask */
-#define  PCI_PM_CAP_D1		0x0200	/* D1 power state support */
-#define  PCI_PM_CAP_D2		0x0400	/* D2 power state support */
-#define  PCI_PM_CAP_PME		0x0800	/* PME pin supported */
-#define  PCI_PM_CAP_PME_MASK	0xF800	/* PME Mask of all supported states */
-#define  PCI_PM_CAP_PME_D0	0x0800	/* PME# from D0 */
-#define  PCI_PM_CAP_PME_D1	0x1000	/* PME# from D1 */
-#define  PCI_PM_CAP_PME_D2	0x2000	/* PME# from D2 */
-#define  PCI_PM_CAP_PME_D3	0x4000	/* PME# from D3 (hot) */
-#define  PCI_PM_CAP_PME_D3cold	0x8000	/* PME# from D3 (cold) */
-#define  PCI_PM_CAP_PME_SHIFT	11	/* Start of the PME Mask in PMC */
-#define PCI_PM_CTRL		4	/* PM control and status register */
-#define  PCI_PM_CTRL_STATE_MASK	0x0003	/* Current power state (D0 to D3) */
-#define  PCI_PM_CTRL_NO_SOFT_RESET	0x0008	/* No reset for D3hot->D0 */
-#define  PCI_PM_CTRL_PME_ENABLE	0x0100	/* PME pin enable */
-#define  PCI_PM_CTRL_DATA_SEL_MASK	0x1e00	/* Data select (??) */
-#define  PCI_PM_CTRL_DATA_SCALE_MASK	0x6000	/* Data scale (??) */
-#define  PCI_PM_CTRL_PME_STATUS	0x8000	/* PME pin status */
-#define PCI_PM_PPB_EXTENSIONS	6	/* PPB support extensions (??) */
-#define  PCI_PM_PPB_B2_B3	0x40	/* Stop clock when in D3hot (??) */
-#define  PCI_PM_BPCC_ENABLE	0x80	/* Bus power/clock control enable (??) */
-#define PCI_PM_DATA_REGISTER	7	/* (??) */
-#define PCI_PM_SIZEOF		8
-
-/* AGP registers */
-
-#define PCI_AGP_VERSION		2	/* BCD version number */
-#define PCI_AGP_RFU		3	/* Rest of capability flags */
-#define PCI_AGP_STATUS		4	/* Status register */
-#define  PCI_AGP_STATUS_RQ_MASK	0xff000000	/* Maximum number of requests - 1 */
-#define  PCI_AGP_STATUS_SBA	0x0200	/* Sideband addressing supported */
-#define  PCI_AGP_STATUS_64BIT	0x0020	/* 64-bit addressing supported */
-#define  PCI_AGP_STATUS_FW	0x0010	/* FW transfers supported */
-#define  PCI_AGP_STATUS_RATE4	0x0004	/* 4x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE2	0x0002	/* 2x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE1	0x0001	/* 1x transfer rate supported */
-#define PCI_AGP_COMMAND		8	/* Control register */
-#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
-#define  PCI_AGP_COMMAND_SBA	0x0200	/* Sideband addressing enabled */
-#define  PCI_AGP_COMMAND_AGP	0x0100	/* Allow processing of AGP transactions */
-#define  PCI_AGP_COMMAND_64BIT	0x0020	/* Allow processing of 64-bit addresses */
-#define  PCI_AGP_COMMAND_FW	0x0010	/* Force FW transfers */
-#define  PCI_AGP_COMMAND_RATE4	0x0004	/* Use 4x rate */
-#define  PCI_AGP_COMMAND_RATE2	0x0002	/* Use 2x rate */
-#define  PCI_AGP_COMMAND_RATE1	0x0001	/* Use 1x rate */
-#define PCI_AGP_SIZEOF		12
-
-/* Vital Product Data */
-
-#define PCI_VPD_ADDR		2	/* Address to access (15 bits!) */
-#define  PCI_VPD_ADDR_MASK	0x7fff	/* Address mask */
-#define  PCI_VPD_ADDR_F		0x8000	/* Write 0, 1 indicates completion */
-#define PCI_VPD_DATA		4	/* 32-bits of data returned here */
-#define PCI_CAP_VPD_SIZEOF	8
-
-/* Slot Identification */
-
-#define PCI_SID_ESR		2	/* Expansion Slot Register */
-#define  PCI_SID_ESR_NSLOTS	0x1f	/* Number of expansion slots available */
-#define  PCI_SID_ESR_FIC	0x20	/* First In Chassis Flag */
-#define PCI_SID_CHASSIS_NR	3	/* Chassis Number */
-
-/* Message Signalled Interrupts registers */
-
-#define PCI_MSI_FLAGS		2	/* Message Control */
-#define  PCI_MSI_FLAGS_ENABLE	0x0001	/* MSI feature enabled */
-#define  PCI_MSI_FLAGS_QMASK	0x000e	/* Maximum queue size available */
-#define  PCI_MSI_FLAGS_QSIZE	0x0070	/* Message queue size configured */
-#define  PCI_MSI_FLAGS_64BIT	0x0080	/* 64-bit addresses allowed */
-#define  PCI_MSI_FLAGS_MASKBIT	0x0100	/* Per-vector masking capable */
-#define PCI_MSI_RFU		3	/* Rest of capability flags */
-#define PCI_MSI_ADDRESS_LO	4	/* Lower 32 bits */
-#define PCI_MSI_ADDRESS_HI	8	/* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
-#define PCI_MSI_DATA_32		8	/* 16 bits of data for 32-bit devices */
-#define PCI_MSI_MASK_32		12	/* Mask bits register for 32-bit devices */
-#define PCI_MSI_PENDING_32	16	/* Pending intrs for 32-bit devices */
-#define PCI_MSI_DATA_64		12	/* 16 bits of data for 64-bit devices */
-#define PCI_MSI_MASK_64		16	/* Mask bits register for 64-bit devices */
-#define PCI_MSI_PENDING_64	20	/* Pending intrs for 64-bit devices */
-
-/* MSI-X registers */
-#define PCI_MSIX_FLAGS		2	/* Message Control */
-#define  PCI_MSIX_FLAGS_QSIZE	0x07FF	/* Table size */
-#define  PCI_MSIX_FLAGS_MASKALL	0x4000	/* Mask all vectors for this function */
-#define  PCI_MSIX_FLAGS_ENABLE	0x8000	/* MSI-X enable */
-#define PCI_MSIX_TABLE		4	/* Table offset */
-#define  PCI_MSIX_TABLE_BIR	0x00000007 /* BAR index */
-#define  PCI_MSIX_TABLE_OFFSET	0xfffffff8 /* Offset into specified BAR */
-#define PCI_MSIX_PBA		8	/* Pending Bit Array offset */
-#define  PCI_MSIX_PBA_BIR	0x00000007 /* BAR index */
-#define  PCI_MSIX_PBA_OFFSET	0xfffffff8 /* Offset into specified BAR */
-#define PCI_CAP_MSIX_SIZEOF	12	/* size of MSIX registers */
-
-/* MSI-X Table entry format */
-#define PCI_MSIX_ENTRY_SIZE		16
-#define  PCI_MSIX_ENTRY_LOWER_ADDR	0
-#define  PCI_MSIX_ENTRY_UPPER_ADDR	4
-#define  PCI_MSIX_ENTRY_DATA		8
-#define  PCI_MSIX_ENTRY_VECTOR_CTRL	12
-#define   PCI_MSIX_ENTRY_CTRL_MASKBIT	1
-
-/* CompactPCI Hotswap Register */
-
-#define PCI_CHSWP_CSR		2	/* Control and Status Register */
-#define  PCI_CHSWP_DHA		0x01	/* Device Hiding Arm */
-#define  PCI_CHSWP_EIM		0x02	/* ENUM# Signal Mask */
-#define  PCI_CHSWP_PIE		0x04	/* Pending Insert or Extract */
-#define  PCI_CHSWP_LOO		0x08	/* LED On / Off */
-#define  PCI_CHSWP_PI		0x30	/* Programming Interface */
-#define  PCI_CHSWP_EXT		0x40	/* ENUM# status - extraction */
-#define  PCI_CHSWP_INS		0x80	/* ENUM# status - insertion */
-
-/* PCI Advanced Feature registers */
-
-#define PCI_AF_LENGTH		2
-#define PCI_AF_CAP		3
-#define  PCI_AF_CAP_TP		0x01
-#define  PCI_AF_CAP_FLR		0x02
-#define PCI_AF_CTRL		4
-#define  PCI_AF_CTRL_FLR	0x01
-#define PCI_AF_STATUS		5
-#define  PCI_AF_STATUS_TP	0x01
-#define PCI_CAP_AF_SIZEOF	6	/* size of AF registers */
-
-/* PCI-X registers (Type 0 (non-bridge) devices) */
-
-#define PCI_X_CMD		2	/* Modes & Features */
-#define  PCI_X_CMD_DPERR_E	0x0001	/* Data Parity Error Recovery Enable */
-#define  PCI_X_CMD_ERO		0x0002	/* Enable Relaxed Ordering */
-#define  PCI_X_CMD_READ_512	0x0000	/* 512 byte maximum read byte count */
-#define  PCI_X_CMD_READ_1K	0x0004	/* 1Kbyte maximum read byte count */
-#define  PCI_X_CMD_READ_2K	0x0008	/* 2Kbyte maximum read byte count */
-#define  PCI_X_CMD_READ_4K	0x000c	/* 4Kbyte maximum read byte count */
-#define  PCI_X_CMD_MAX_READ	0x000c	/* Max Memory Read Byte Count */
-				/* Max # of outstanding split transactions */
-#define  PCI_X_CMD_SPLIT_1	0x0000	/* Max 1 */
-#define  PCI_X_CMD_SPLIT_2	0x0010	/* Max 2 */
-#define  PCI_X_CMD_SPLIT_3	0x0020	/* Max 3 */
-#define  PCI_X_CMD_SPLIT_4	0x0030	/* Max 4 */
-#define  PCI_X_CMD_SPLIT_8	0x0040	/* Max 8 */
-#define  PCI_X_CMD_SPLIT_12	0x0050	/* Max 12 */
-#define  PCI_X_CMD_SPLIT_16	0x0060	/* Max 16 */
-#define  PCI_X_CMD_SPLIT_32	0x0070	/* Max 32 */
-#define  PCI_X_CMD_MAX_SPLIT	0x0070	/* Max Outstanding Split Transactions */
-#define  PCI_X_CMD_VERSION(x)	(((x) >> 12) & 3) /* Version */
-#define PCI_X_STATUS		4	/* PCI-X capabilities */
-#define  PCI_X_STATUS_DEVFN	0x000000ff	/* A copy of devfn */
-#define  PCI_X_STATUS_BUS	0x0000ff00	/* A copy of bus nr */
-#define  PCI_X_STATUS_64BIT	0x00010000	/* 64-bit device */
-#define  PCI_X_STATUS_133MHZ	0x00020000	/* 133 MHz capable */
-#define  PCI_X_STATUS_SPL_DISC	0x00040000	/* Split Completion Discarded */
-#define  PCI_X_STATUS_UNX_SPL	0x00080000	/* Unexpected Split Completion */
-#define  PCI_X_STATUS_COMPLEX	0x00100000	/* Device Complexity */
-#define  PCI_X_STATUS_MAX_READ	0x00600000	/* Designed Max Memory Read Count */
-#define  PCI_X_STATUS_MAX_SPLIT	0x03800000	/* Designed Max Outstanding Split Transactions */
-#define  PCI_X_STATUS_MAX_CUM	0x1c000000	/* Designed Max Cumulative Read Size */
-#define  PCI_X_STATUS_SPL_ERR	0x20000000	/* Rcvd Split Completion Error Msg */
-#define  PCI_X_STATUS_266MHZ	0x40000000	/* 266 MHz capable */
-#define  PCI_X_STATUS_533MHZ	0x80000000	/* 533 MHz capable */
-#define PCI_X_ECC_CSR		8	/* ECC control and status */
-#define PCI_CAP_PCIX_SIZEOF_V0	8	/* size of registers for Version 0 */
-#define PCI_CAP_PCIX_SIZEOF_V1	24	/* size for Version 1 */
-#define PCI_CAP_PCIX_SIZEOF_V2	PCI_CAP_PCIX_SIZEOF_V1	/* Same for v2 */
-
-/* PCI-X registers (Type 1 (bridge) devices) */
-
-#define PCI_X_BRIDGE_SSTATUS	2	/* Secondary Status */
-#define  PCI_X_SSTATUS_64BIT	0x0001	/* Secondary AD interface is 64 bits */
-#define  PCI_X_SSTATUS_133MHZ	0x0002	/* 133 MHz capable */
-#define  PCI_X_SSTATUS_FREQ	0x03c0	/* Secondary Bus Mode and Frequency */
-#define  PCI_X_SSTATUS_VERS	0x3000	/* PCI-X Capability Version */
-#define  PCI_X_SSTATUS_V1	0x1000	/* Mode 2, not Mode 1 */
-#define  PCI_X_SSTATUS_V2	0x2000	/* Mode 1 or Modes 1 and 2 */
-#define  PCI_X_SSTATUS_266MHZ	0x4000	/* 266 MHz capable */
-#define  PCI_X_SSTATUS_533MHZ	0x8000	/* 533 MHz capable */
-#define PCI_X_BRIDGE_STATUS	4	/* Bridge Status */
-
-/* PCI Bridge Subsystem ID registers */
-
-#define PCI_SSVID_VENDOR_ID     4	/* PCI Bridge subsystem vendor ID */
-#define PCI_SSVID_DEVICE_ID     6	/* PCI Bridge subsystem device ID */
-
-/* PCI Express capability registers */
-
-#define PCI_EXP_FLAGS		2	/* Capabilities register */
-#define PCI_EXP_FLAGS_VERS	0x000f	/* Capability version */
-#define PCI_EXP_FLAGS_TYPE	0x00f0	/* Device/Port type */
-#define  PCI_EXP_TYPE_ENDPOINT	0x0	/* Express Endpoint */
-#define  PCI_EXP_TYPE_LEG_END	0x1	/* Legacy Endpoint */
-#define  PCI_EXP_TYPE_ROOT_PORT 0x4	/* Root Port */
-#define  PCI_EXP_TYPE_UPSTREAM	0x5	/* Upstream Port */
-#define  PCI_EXP_TYPE_DOWNSTREAM 0x6	/* Downstream Port */
-#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7	/* PCIe to PCI/PCI-X Bridge */
-#define  PCI_EXP_TYPE_PCIE_BRIDGE 0x8	/* PCI/PCI-X to PCIe Bridge */
-#define  PCI_EXP_TYPE_RC_END	0x9	/* Root Complex Integrated Endpoint */
-#define  PCI_EXP_TYPE_RC_EC	0xa	/* Root Complex Event Collector */
-#define PCI_EXP_FLAGS_SLOT	0x0100	/* Slot implemented */
-#define PCI_EXP_FLAGS_IRQ	0x3e00	/* Interrupt message number */
-#define PCI_EXP_DEVCAP		4	/* Device capabilities */
-#define  PCI_EXP_DEVCAP_PAYLOAD	0x00000007 /* Max_Payload_Size */
-#define  PCI_EXP_DEVCAP_PHANTOM	0x00000018 /* Phantom functions */
-#define  PCI_EXP_DEVCAP_EXT_TAG	0x00000020 /* Extended tags */
-#define  PCI_EXP_DEVCAP_L0S	0x000001c0 /* L0s Acceptable Latency */
-#define  PCI_EXP_DEVCAP_L1	0x00000e00 /* L1 Acceptable Latency */
-#define  PCI_EXP_DEVCAP_ATN_BUT	0x00001000 /* Attention Button Present */
-#define  PCI_EXP_DEVCAP_ATN_IND	0x00002000 /* Attention Indicator Present */
-#define  PCI_EXP_DEVCAP_PWR_IND	0x00004000 /* Power Indicator Present */
-#define  PCI_EXP_DEVCAP_RBER	0x00008000 /* Role-Based Error Reporting */
-#define  PCI_EXP_DEVCAP_PWR_VAL	0x03fc0000 /* Slot Power Limit Value */
-#define  PCI_EXP_DEVCAP_PWR_SCL	0x0c000000 /* Slot Power Limit Scale */
-#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
-#define PCI_EXP_DEVCTL		8	/* Device Control */
-#define  PCI_EXP_DEVCTL_CERE	0x0001	/* Correctable Error Reporting En. */
-#define  PCI_EXP_DEVCTL_NFERE	0x0002	/* Non-Fatal Error Reporting Enable */
-#define  PCI_EXP_DEVCTL_FERE	0x0004	/* Fatal Error Reporting Enable */
-#define  PCI_EXP_DEVCTL_URRE	0x0008	/* Unsupported Request Reporting En. */
-#define  PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
-#define  PCI_EXP_DEVCTL_PAYLOAD	0x00e0	/* Max_Payload_Size */
-#define  PCI_EXP_DEVCTL_EXT_TAG	0x0100	/* Extended Tag Field Enable */
-#define  PCI_EXP_DEVCTL_PHANTOM	0x0200	/* Phantom Functions Enable */
-#define  PCI_EXP_DEVCTL_AUX_PME	0x0400	/* Auxiliary Power PM Enable */
-#define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
-#define  PCI_EXP_DEVCTL_READRQ	0x7000	/* Max_Read_Request_Size */
-#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
-#define PCI_EXP_DEVSTA		10	/* Device Status */
-#define  PCI_EXP_DEVSTA_CED	0x0001	/* Correctable Error Detected */
-#define  PCI_EXP_DEVSTA_NFED	0x0002	/* Non-Fatal Error Detected */
-#define  PCI_EXP_DEVSTA_FED	0x0004	/* Fatal Error Detected */
-#define  PCI_EXP_DEVSTA_URD	0x0008	/* Unsupported Request Detected */
-#define  PCI_EXP_DEVSTA_AUXPD	0x0010	/* AUX Power Detected */
-#define  PCI_EXP_DEVSTA_TRPND	0x0020	/* Transactions Pending */
-#define PCI_EXP_LNKCAP		12	/* Link Capabilities */
-#define  PCI_EXP_LNKCAP_SLS	0x0000000f /* Supported Link Speeds */
-#define  PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */
-#define  PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */
-#define  PCI_EXP_LNKCAP_MLW	0x000003f0 /* Maximum Link Width */
-#define  PCI_EXP_LNKCAP_ASPMS	0x00000c00 /* ASPM Support */
-#define  PCI_EXP_LNKCAP_L0SEL	0x00007000 /* L0s Exit Latency */
-#define  PCI_EXP_LNKCAP_L1EL	0x00038000 /* L1 Exit Latency */
-#define  PCI_EXP_LNKCAP_CLKPM	0x00040000 /* Clock Power Management */
-#define  PCI_EXP_LNKCAP_SDERC	0x00080000 /* Surprise Down Error Reporting Capable */
-#define  PCI_EXP_LNKCAP_DLLLARC	0x00100000 /* Data Link Layer Link Active Reporting Capable */
-#define  PCI_EXP_LNKCAP_LBNC	0x00200000 /* Link Bandwidth Notification Capability */
-#define  PCI_EXP_LNKCAP_PN	0xff000000 /* Port Number */
-#define PCI_EXP_LNKCTL		16	/* Link Control */
-#define  PCI_EXP_LNKCTL_ASPMC	0x0003	/* ASPM Control */
-#define  PCI_EXP_LNKCTL_ASPM_L0S 0x0001	/* L0s Enable */
-#define  PCI_EXP_LNKCTL_ASPM_L1  0x0002	/* L1 Enable */
-#define  PCI_EXP_LNKCTL_RCB	0x0008	/* Read Completion Boundary */
-#define  PCI_EXP_LNKCTL_LD	0x0010	/* Link Disable */
-#define  PCI_EXP_LNKCTL_RL	0x0020	/* Retrain Link */
-#define  PCI_EXP_LNKCTL_CCC	0x0040	/* Common Clock Configuration */
-#define  PCI_EXP_LNKCTL_ES	0x0080	/* Extended Synch */
-#define  PCI_EXP_LNKCTL_CLKREQ_EN 0x0100 /* Enable clkreq */
-#define  PCI_EXP_LNKCTL_HAWD	0x0200	/* Hardware Autonomous Width Disable */
-#define  PCI_EXP_LNKCTL_LBMIE	0x0400	/* Link Bandwidth Management Interrupt Enable */
-#define  PCI_EXP_LNKCTL_LABIE	0x0800	/* Link Autonomous Bandwidth Interrupt Enable */
-#define PCI_EXP_LNKSTA		18	/* Link Status */
-#define  PCI_EXP_LNKSTA_CLS	0x000f	/* Current Link Speed */
-#define  PCI_EXP_LNKSTA_CLS_2_5GB 0x0001 /* Current Link Speed 2.5GT/s */
-#define  PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */
-#define  PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */
-#define  PCI_EXP_LNKSTA_NLW	0x03f0	/* Negotiated Link Width */
-#define  PCI_EXP_LNKSTA_NLW_X1	0x0010	/* Current Link Width x1 */
-#define  PCI_EXP_LNKSTA_NLW_X2	0x0020	/* Current Link Width x2 */
-#define  PCI_EXP_LNKSTA_NLW_X4	0x0040	/* Current Link Width x4 */
-#define  PCI_EXP_LNKSTA_NLW_X8	0x0080	/* Current Link Width x8 */
-#define  PCI_EXP_LNKSTA_NLW_SHIFT 4	/* start of NLW mask in link status */
-#define  PCI_EXP_LNKSTA_LT	0x0800	/* Link Training */
-#define  PCI_EXP_LNKSTA_SLC	0x1000	/* Slot Clock Configuration */
-#define  PCI_EXP_LNKSTA_DLLLA	0x2000	/* Data Link Layer Link Active */
-#define  PCI_EXP_LNKSTA_LBMS	0x4000	/* Link Bandwidth Management Status */
-#define  PCI_EXP_LNKSTA_LABS	0x8000	/* Link Autonomous Bandwidth Status */
-#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V1	20	/* v1 endpoints end here */
-#define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
-#define  PCI_EXP_SLTCAP_ABP	0x00000001 /* Attention Button Present */
-#define  PCI_EXP_SLTCAP_PCP	0x00000002 /* Power Controller Present */
-#define  PCI_EXP_SLTCAP_MRLSP	0x00000004 /* MRL Sensor Present */
-#define  PCI_EXP_SLTCAP_AIP	0x00000008 /* Attention Indicator Present */
-#define  PCI_EXP_SLTCAP_PIP	0x00000010 /* Power Indicator Present */
-#define  PCI_EXP_SLTCAP_HPS	0x00000020 /* Hot-Plug Surprise */
-#define  PCI_EXP_SLTCAP_HPC	0x00000040 /* Hot-Plug Capable */
-#define  PCI_EXP_SLTCAP_SPLV	0x00007f80 /* Slot Power Limit Value */
-#define  PCI_EXP_SLTCAP_SPLS	0x00018000 /* Slot Power Limit Scale */
-#define  PCI_EXP_SLTCAP_EIP	0x00020000 /* Electromechanical Interlock Present */
-#define  PCI_EXP_SLTCAP_NCCS	0x00040000 /* No Command Completed Support */
-#define  PCI_EXP_SLTCAP_PSN	0xfff80000 /* Physical Slot Number */
-#define PCI_EXP_SLTCTL		24	/* Slot Control */
-#define  PCI_EXP_SLTCTL_ABPE	0x0001	/* Attention Button Pressed Enable */
-#define  PCI_EXP_SLTCTL_PFDE	0x0002	/* Power Fault Detected Enable */
-#define  PCI_EXP_SLTCTL_MRLSCE	0x0004	/* MRL Sensor Changed Enable */
-#define  PCI_EXP_SLTCTL_PDCE	0x0008	/* Presence Detect Changed Enable */
-#define  PCI_EXP_SLTCTL_CCIE	0x0010	/* Command Completed Interrupt Enable */
-#define  PCI_EXP_SLTCTL_HPIE	0x0020	/* Hot-Plug Interrupt Enable */
-#define  PCI_EXP_SLTCTL_AIC	0x00c0	/* Attention Indicator Control */
-#define  PCI_EXP_SLTCTL_ATTN_IND_ON    0x0040 /* Attention Indicator on */
-#define  PCI_EXP_SLTCTL_ATTN_IND_BLINK 0x0080 /* Attention Indicator blinking */
-#define  PCI_EXP_SLTCTL_ATTN_IND_OFF   0x00c0 /* Attention Indicator off */
-#define  PCI_EXP_SLTCTL_PIC	0x0300	/* Power Indicator Control */
-#define  PCI_EXP_SLTCTL_PWR_IND_ON     0x0100 /* Power Indicator on */
-#define  PCI_EXP_SLTCTL_PWR_IND_BLINK  0x0200 /* Power Indicator blinking */
-#define  PCI_EXP_SLTCTL_PWR_IND_OFF    0x0300 /* Power Indicator off */
-#define  PCI_EXP_SLTCTL_PCC	0x0400	/* Power Controller Control */
-#define  PCI_EXP_SLTCTL_PWR_ON         0x0000 /* Power On */
-#define  PCI_EXP_SLTCTL_PWR_OFF        0x0400 /* Power Off */
-#define  PCI_EXP_SLTCTL_EIC	0x0800	/* Electromechanical Interlock Control */
-#define  PCI_EXP_SLTCTL_DLLSCE	0x1000	/* Data Link Layer State Changed Enable */
-#define PCI_EXP_SLTSTA		26	/* Slot Status */
-#define  PCI_EXP_SLTSTA_ABP	0x0001	/* Attention Button Pressed */
-#define  PCI_EXP_SLTSTA_PFD	0x0002	/* Power Fault Detected */
-#define  PCI_EXP_SLTSTA_MRLSC	0x0004	/* MRL Sensor Changed */
-#define  PCI_EXP_SLTSTA_PDC	0x0008	/* Presence Detect Changed */
-#define  PCI_EXP_SLTSTA_CC	0x0010	/* Command Completed */
-#define  PCI_EXP_SLTSTA_MRLSS	0x0020	/* MRL Sensor State */
-#define  PCI_EXP_SLTSTA_PDS	0x0040	/* Presence Detect State */
-#define  PCI_EXP_SLTSTA_EIS	0x0080	/* Electromechanical Interlock Status */
-#define  PCI_EXP_SLTSTA_DLLSC	0x0100	/* Data Link Layer State Changed */
-#define PCI_EXP_RTCTL		28	/* Root Control */
-#define  PCI_EXP_RTCTL_SECEE	0x0001	/* System Error on Correctable Error */
-#define  PCI_EXP_RTCTL_SENFEE	0x0002	/* System Error on Non-Fatal Error */
-#define  PCI_EXP_RTCTL_SEFEE	0x0004	/* System Error on Fatal Error */
-#define  PCI_EXP_RTCTL_PMEIE	0x0008	/* PME Interrupt Enable */
-#define  PCI_EXP_RTCTL_CRSSVE	0x0010	/* CRS Software Visibility Enable */
-#define PCI_EXP_RTCAP		30	/* Root Capabilities */
-#define  PCI_EXP_RTCAP_CRSVIS	0x0001	/* CRS Software Visibility capability */
-#define PCI_EXP_RTSTA		32	/* Root Status */
-#define PCI_EXP_RTSTA_PME	0x00010000 /* PME status */
-#define PCI_EXP_RTSTA_PENDING	0x00020000 /* PME pending */
-/*
- * The Device Capabilities 2, Device Status 2, Device Control 2,
- * Link Capabilities 2, Link Status 2, Link Control 2,
- * Slot Capabilities 2, Slot Status 2, and Slot Control 2 registers
- * are only present on devices with PCIe Capability version 2.
- * Use pcie_capability_read_word() and similar interfaces to use them
- * safely.
- */
-#define PCI_EXP_DEVCAP2		36	/* Device Capabilities 2 */
-#define  PCI_EXP_DEVCAP2_ARI		0x00000020 /* Alternative Routing-ID */
-#define  PCI_EXP_DEVCAP2_LTR		0x00000800 /* Latency tolerance reporting */
-#define  PCI_EXP_DEVCAP2_OBFF_MASK	0x000c0000 /* OBFF support mechanism */
-#define  PCI_EXP_DEVCAP2_OBFF_MSG	0x00040000 /* New message signaling */
-#define  PCI_EXP_DEVCAP2_OBFF_WAKE	0x00080000 /* Re-use WAKE# for OBFF */
-#define PCI_EXP_DEVCTL2		40	/* Device Control 2 */
-#define  PCI_EXP_DEVCTL2_COMP_TIMEOUT	0x000f	/* Completion Timeout Value */
-#define  PCI_EXP_DEVCTL2_ARI		0x0020	/* Alternative Routing-ID */
-#define  PCI_EXP_DEVCTL2_IDO_REQ_EN	0x0100	/* Allow IDO for requests */
-#define  PCI_EXP_DEVCTL2_IDO_CMP_EN	0x0200	/* Allow IDO for completions */
-#define  PCI_EXP_DEVCTL2_LTR_EN		0x0400	/* Enable LTR mechanism */
-#define  PCI_EXP_DEVCTL2_OBFF_MSGA_EN	0x2000	/* Enable OBFF Message type A */
-#define  PCI_EXP_DEVCTL2_OBFF_MSGB_EN	0x4000	/* Enable OBFF Message type B */
-#define  PCI_EXP_DEVCTL2_OBFF_WAKE_EN	0x6000	/* OBFF using WAKE# signaling */
-#define PCI_EXP_DEVSTA2		42	/* Device Status 2 */
-#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2	44	/* v2 endpoints end here */
-#define PCI_EXP_LNKCAP2		44	/* Link Capabilities 2 */
-#define  PCI_EXP_LNKCAP2_SLS_2_5GB	0x00000002 /* Supported Speed 2.5GT/s */
-#define  PCI_EXP_LNKCAP2_SLS_5_0GB	0x00000004 /* Supported Speed 5.0GT/s */
-#define  PCI_EXP_LNKCAP2_SLS_8_0GB	0x00000008 /* Supported Speed 8.0GT/s */
-#define  PCI_EXP_LNKCAP2_CROSSLINK	0x00000100 /* Crosslink supported */
-#define PCI_EXP_LNKCTL2		48	/* Link Control 2 */
-#define PCI_EXP_LNKSTA2		50	/* Link Status 2 */
-#define PCI_EXP_SLTCAP2		52	/* Slot Capabilities 2 */
-#define PCI_EXP_SLTCTL2		56	/* Slot Control 2 */
-#define PCI_EXP_SLTSTA2		58	/* Slot Status 2 */
-
-/* Extended Capabilities (PCI-X 2.0 and Express) */
-#define PCI_EXT_CAP_ID(header)		(header & 0x0000ffff)
-#define PCI_EXT_CAP_VER(header)		((header >> 16) & 0xf)
-#define PCI_EXT_CAP_NEXT(header)	((header >> 20) & 0xffc)
-
-#define PCI_EXT_CAP_ID_ERR	0x01	/* Advanced Error Reporting */
-#define PCI_EXT_CAP_ID_VC	0x02	/* Virtual Channel Capability */
-#define PCI_EXT_CAP_ID_DSN	0x03	/* Device Serial Number */
-#define PCI_EXT_CAP_ID_PWR	0x04	/* Power Budgeting */
-#define PCI_EXT_CAP_ID_RCLD	0x05	/* Root Complex Link Declaration */
-#define PCI_EXT_CAP_ID_RCILC	0x06	/* Root Complex Internal Link Control */
-#define PCI_EXT_CAP_ID_RCEC	0x07	/* Root Complex Event Collector */
-#define PCI_EXT_CAP_ID_MFVC	0x08	/* Multi-Function VC Capability */
-#define PCI_EXT_CAP_ID_VC9	0x09	/* same as _VC */
-#define PCI_EXT_CAP_ID_RCRB	0x0A	/* Root Complex RB? */
-#define PCI_EXT_CAP_ID_VNDR	0x0B	/* Vendor-Specific */
-#define PCI_EXT_CAP_ID_CAC	0x0C	/* Config Access - obsolete */
-#define PCI_EXT_CAP_ID_ACS	0x0D	/* Access Control Services */
-#define PCI_EXT_CAP_ID_ARI	0x0E	/* Alternate Routing ID */
-#define PCI_EXT_CAP_ID_ATS	0x0F	/* Address Translation Services */
-#define PCI_EXT_CAP_ID_SRIOV	0x10	/* Single Root I/O Virtualization */
-#define PCI_EXT_CAP_ID_MRIOV	0x11	/* Multi Root I/O Virtualization */
-#define PCI_EXT_CAP_ID_MCAST	0x12	/* Multicast */
-#define PCI_EXT_CAP_ID_PRI	0x13	/* Page Request Interface */
-#define PCI_EXT_CAP_ID_AMD_XXX	0x14	/* Reserved for AMD */
-#define PCI_EXT_CAP_ID_REBAR	0x15	/* Resizable BAR */
-#define PCI_EXT_CAP_ID_DPA	0x16	/* Dynamic Power Allocation */
-#define PCI_EXT_CAP_ID_TPH	0x17	/* TPH Requester */
-#define PCI_EXT_CAP_ID_LTR	0x18	/* Latency Tolerance Reporting */
-#define PCI_EXT_CAP_ID_SECPCI	0x19	/* Secondary PCIe Capability */
-#define PCI_EXT_CAP_ID_PMUX	0x1A	/* Protocol Multiplexing */
-#define PCI_EXT_CAP_ID_PASID	0x1B	/* Process Address Space ID */
-#define PCI_EXT_CAP_ID_MAX	PCI_EXT_CAP_ID_PASID
-
-#define PCI_EXT_CAP_DSN_SIZEOF	12
-#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
-
-/* Advanced Error Reporting */
-#define PCI_ERR_UNCOR_STATUS	4	/* Uncorrectable Error Status */
-#define  PCI_ERR_UNC_UND	0x00000001	/* Undefined */
-#define  PCI_ERR_UNC_DLP	0x00000010	/* Data Link Protocol */
-#define  PCI_ERR_UNC_SURPDN	0x00000020	/* Surprise Down */
-#define  PCI_ERR_UNC_POISON_TLP	0x00001000	/* Poisoned TLP */
-#define  PCI_ERR_UNC_FCP	0x00002000	/* Flow Control Protocol */
-#define  PCI_ERR_UNC_COMP_TIME	0x00004000	/* Completion Timeout */
-#define  PCI_ERR_UNC_COMP_ABORT	0x00008000	/* Completer Abort */
-#define  PCI_ERR_UNC_UNX_COMP	0x00010000	/* Unexpected Completion */
-#define  PCI_ERR_UNC_RX_OVER	0x00020000	/* Receiver Overflow */
-#define  PCI_ERR_UNC_MALF_TLP	0x00040000	/* Malformed TLP */
-#define  PCI_ERR_UNC_ECRC	0x00080000	/* ECRC Error Status */
-#define  PCI_ERR_UNC_UNSUP	0x00100000	/* Unsupported Request */
-#define  PCI_ERR_UNC_ACSV	0x00200000	/* ACS Violation */
-#define  PCI_ERR_UNC_INTN	0x00400000	/* internal error */
-#define  PCI_ERR_UNC_MCBTLP	0x00800000	/* MC blocked TLP */
-#define  PCI_ERR_UNC_ATOMEG	0x01000000	/* Atomic egress blocked */
-#define  PCI_ERR_UNC_TLPPRE	0x02000000	/* TLP prefix blocked */
-#define PCI_ERR_UNCOR_MASK	8	/* Uncorrectable Error Mask */
-	/* Same bits as above */
-#define PCI_ERR_UNCOR_SEVER	12	/* Uncorrectable Error Severity */
-	/* Same bits as above */
-#define PCI_ERR_COR_STATUS	16	/* Correctable Error Status */
-#define  PCI_ERR_COR_RCVR	0x00000001	/* Receiver Error Status */
-#define  PCI_ERR_COR_BAD_TLP	0x00000040	/* Bad TLP Status */
-#define  PCI_ERR_COR_BAD_DLLP	0x00000080	/* Bad DLLP Status */
-#define  PCI_ERR_COR_REP_ROLL	0x00000100	/* REPLAY_NUM Rollover */
-#define  PCI_ERR_COR_REP_TIMER	0x00001000	/* Replay Timer Timeout */
-#define  PCI_ERR_COR_ADV_NFAT	0x00002000	/* Advisory Non-Fatal */
-#define  PCI_ERR_COR_INTERNAL	0x00004000	/* Corrected Internal */
-#define  PCI_ERR_COR_LOG_OVER	0x00008000	/* Header Log Overflow */
-#define PCI_ERR_COR_MASK	20	/* Correctable Error Mask */
-	/* Same bits as above */
-#define PCI_ERR_CAP		24	/* Advanced Error Capabilities */
-#define  PCI_ERR_CAP_FEP(x)	((x) & 31)	/* First Error Pointer */
-#define  PCI_ERR_CAP_ECRC_GENC	0x00000020	/* ECRC Generation Capable */
-#define  PCI_ERR_CAP_ECRC_GENE	0x00000040	/* ECRC Generation Enable */
-#define  PCI_ERR_CAP_ECRC_CHKC	0x00000080	/* ECRC Check Capable */
-#define  PCI_ERR_CAP_ECRC_CHKE	0x00000100	/* ECRC Check Enable */
-#define PCI_ERR_HEADER_LOG	28	/* Header Log Register (16 bytes) */
-#define PCI_ERR_ROOT_COMMAND	44	/* Root Error Command */
-/* Correctable Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_COR_EN		0x00000001
-/* Non-fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_NONFATAL_EN	0x00000002
-/* Fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_FATAL_EN	0x00000004
-#define PCI_ERR_ROOT_STATUS	48
-#define PCI_ERR_ROOT_COR_RCV		0x00000001	/* ERR_COR Received */
-/* Multi ERR_COR Received */
-#define PCI_ERR_ROOT_MULTI_COR_RCV	0x00000002
-/* ERR_FATAL/NONFATAL Received */
-#define PCI_ERR_ROOT_UNCOR_RCV		0x00000004
-/* Multi ERR_FATAL/NONFATAL Received */
-#define PCI_ERR_ROOT_MULTI_UNCOR_RCV	0x00000008
-#define PCI_ERR_ROOT_FIRST_FATAL	0x00000010	/* First Fatal */
-#define PCI_ERR_ROOT_NONFATAL_RCV	0x00000020	/* Non-Fatal Received */
-#define PCI_ERR_ROOT_FATAL_RCV		0x00000040	/* Fatal Received */
-#define PCI_ERR_ROOT_ERR_SRC	52	/* Error Source Identification */
-
-/* Virtual Channel */
-#define PCI_VC_PORT_CAP1	4
-#define  PCI_VC_CAP1_EVCC	0x00000007	/* extended VC count */
-#define  PCI_VC_CAP1_LPEVCC	0x00000070	/* low prio extended VC count */
-#define  PCI_VC_CAP1_ARB_SIZE	0x00000c00
-#define PCI_VC_PORT_CAP2	8
-#define  PCI_VC_CAP2_32_PHASE		0x00000002
-#define  PCI_VC_CAP2_64_PHASE		0x00000004
-#define  PCI_VC_CAP2_128_PHASE		0x00000008
-#define  PCI_VC_CAP2_ARB_OFF		0xff000000
-#define PCI_VC_PORT_CTRL	12
-#define  PCI_VC_PORT_CTRL_LOAD_TABLE	0x00000001
-#define PCI_VC_PORT_STATUS	14
-#define  PCI_VC_PORT_STATUS_TABLE	0x00000001
-#define PCI_VC_RES_CAP		16
-#define  PCI_VC_RES_CAP_32_PHASE	0x00000002
-#define  PCI_VC_RES_CAP_64_PHASE	0x00000004
-#define  PCI_VC_RES_CAP_128_PHASE	0x00000008
-#define  PCI_VC_RES_CAP_128_PHASE_TB	0x00000010
-#define  PCI_VC_RES_CAP_256_PHASE	0x00000020
-#define  PCI_VC_RES_CAP_ARB_OFF		0xff000000
-#define PCI_VC_RES_CTRL		20
-#define  PCI_VC_RES_CTRL_LOAD_TABLE	0x00010000
-#define  PCI_VC_RES_CTRL_ARB_SELECT	0x000e0000
-#define  PCI_VC_RES_CTRL_ID		0x07000000
-#define  PCI_VC_RES_CTRL_ENABLE		0x80000000
-#define PCI_VC_RES_STATUS	26
-#define  PCI_VC_RES_STATUS_TABLE	0x00000001
-#define  PCI_VC_RES_STATUS_NEGO		0x00000002
-#define PCI_CAP_VC_BASE_SIZEOF		0x10
-#define PCI_CAP_VC_PER_VC_SIZEOF	0x0C
-
-/* Power Budgeting */
-#define PCI_PWR_DSR		4	/* Data Select Register */
-#define PCI_PWR_DATA		8	/* Data Register */
-#define  PCI_PWR_DATA_BASE(x)	((x) & 0xff)	    /* Base Power */
-#define  PCI_PWR_DATA_SCALE(x)	(((x) >> 8) & 3)    /* Data Scale */
-#define  PCI_PWR_DATA_PM_SUB(x)	(((x) >> 10) & 7)   /* PM Sub State */
-#define  PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
-#define  PCI_PWR_DATA_TYPE(x)	(((x) >> 15) & 7)   /* Type */
-#define  PCI_PWR_DATA_RAIL(x)	(((x) >> 18) & 7)   /* Power Rail */
-#define PCI_PWR_CAP		12	/* Capability */
-#define  PCI_PWR_CAP_BUDGET(x)	((x) & 1)	/* Included in system budget */
-#define PCI_EXT_CAP_PWR_SIZEOF	16
-
-/* Vendor-Specific (VSEC, PCI_EXT_CAP_ID_VNDR) */
-#define PCI_VNDR_HEADER		4	/* Vendor-Specific Header */
-#define  PCI_VNDR_HEADER_ID(x)	((x) & 0xffff)
-#define  PCI_VNDR_HEADER_REV(x)	(((x) >> 16) & 0xf)
-#define  PCI_VNDR_HEADER_LEN(x)	(((x) >> 20) & 0xfff)
-
-/*
- * HyperTransport sub capability types
- *
- * Unfortunately there are both 3 bit and 5 bit capability types defined
- * in the HT spec, catering for that is a little messy. You probably don't
- * want to use these directly, just use pci_find_ht_capability() and it
- * will do the right thing for you.
- */
-#define HT_3BIT_CAP_MASK	0xE0
-#define HT_CAPTYPE_SLAVE	0x00	/* Slave/Primary link configuration */
-#define HT_CAPTYPE_HOST		0x20	/* Host/Secondary link configuration */
-
-#define HT_5BIT_CAP_MASK	0xF8
-#define HT_CAPTYPE_IRQ		0x80	/* IRQ Configuration */
-#define HT_CAPTYPE_REMAPPING_40	0xA0	/* 40 bit address remapping */
-#define HT_CAPTYPE_REMAPPING_64 0xA2	/* 64 bit address remapping */
-#define HT_CAPTYPE_UNITID_CLUMP	0x90	/* Unit ID clumping */
-#define HT_CAPTYPE_EXTCONF	0x98	/* Extended Configuration Space Access */
-#define HT_CAPTYPE_MSI_MAPPING	0xA8	/* MSI Mapping Capability */
-#define  HT_MSI_FLAGS		0x02		/* Offset to flags */
-#define  HT_MSI_FLAGS_ENABLE	0x1		/* Mapping enable */
-#define  HT_MSI_FLAGS_FIXED	0x2		/* Fixed mapping only */
-#define  HT_MSI_FIXED_ADDR	0x00000000FEE00000ULL	/* Fixed addr */
-#define  HT_MSI_ADDR_LO		0x04		/* Offset to low addr bits */
-#define  HT_MSI_ADDR_LO_MASK	0xFFF00000	/* Low address bit mask */
-#define  HT_MSI_ADDR_HI		0x08		/* Offset to high addr bits */
-#define HT_CAPTYPE_DIRECT_ROUTE	0xB0	/* Direct routing configuration */
-#define HT_CAPTYPE_VCSET	0xB8	/* Virtual Channel configuration */
-#define HT_CAPTYPE_ERROR_RETRY	0xC0	/* Retry on error configuration */
-#define HT_CAPTYPE_GEN3		0xD0	/* Generation 3 HyperTransport configuration */
-#define HT_CAPTYPE_PM		0xE0	/* HyperTransport power management configuration */
-#define HT_CAP_SIZEOF_LONG	28	/* slave & primary */
-#define HT_CAP_SIZEOF_SHORT	24	/* host & secondary */
-
-/* Alternative Routing-ID Interpretation */
-#define PCI_ARI_CAP		0x04	/* ARI Capability Register */
-#define  PCI_ARI_CAP_MFVC	0x0001	/* MFVC Function Groups Capability */
-#define  PCI_ARI_CAP_ACS	0x0002	/* ACS Function Groups Capability */
-#define  PCI_ARI_CAP_NFN(x)	(((x) >> 8) & 0xff) /* Next Function Number */
-#define PCI_ARI_CTRL		0x06	/* ARI Control Register */
-#define  PCI_ARI_CTRL_MFVC	0x0001	/* MFVC Function Groups Enable */
-#define  PCI_ARI_CTRL_ACS	0x0002	/* ACS Function Groups Enable */
-#define  PCI_ARI_CTRL_FG(x)	(((x) >> 4) & 7) /* Function Group */
-#define PCI_EXT_CAP_ARI_SIZEOF	8
-
-/* Address Translation Service */
-#define PCI_ATS_CAP		0x04	/* ATS Capability Register */
-#define  PCI_ATS_CAP_QDEP(x)	((x) & 0x1f)	/* Invalidate Queue Depth */
-#define  PCI_ATS_MAX_QDEP	32	/* Max Invalidate Queue Depth */
-#define PCI_ATS_CTRL		0x06	/* ATS Control Register */
-#define  PCI_ATS_CTRL_ENABLE	0x8000	/* ATS Enable */
-#define  PCI_ATS_CTRL_STU(x)	((x) & 0x1f)	/* Smallest Translation Unit */
-#define  PCI_ATS_MIN_STU	12	/* shift of minimum STU block */
-#define PCI_EXT_CAP_ATS_SIZEOF	8
-
-/* Page Request Interface */
-#define PCI_PRI_CTRL		0x04	/* PRI control register */
-#define  PCI_PRI_CTRL_ENABLE	0x01	/* Enable */
-#define  PCI_PRI_CTRL_RESET	0x02	/* Reset */
-#define PCI_PRI_STATUS		0x06	/* PRI status register */
-#define  PCI_PRI_STATUS_RF	0x001	/* Response Failure */
-#define  PCI_PRI_STATUS_UPRGI	0x002	/* Unexpected PRG index */
-#define  PCI_PRI_STATUS_STOPPED	0x100	/* PRI Stopped */
-#define PCI_PRI_MAX_REQ		0x08	/* PRI max reqs supported */
-#define PCI_PRI_ALLOC_REQ	0x0c	/* PRI max reqs allowed */
-#define PCI_EXT_CAP_PRI_SIZEOF	16
-
-/* Process Address Space ID */
-#define PCI_PASID_CAP		0x04    /* PASID feature register */
-#define  PCI_PASID_CAP_EXEC	0x02	/* Exec permissions Supported */
-#define  PCI_PASID_CAP_PRIV	0x04	/* Privilege Mode Supported */
-#define PCI_PASID_CTRL		0x06    /* PASID control register */
-#define  PCI_PASID_CTRL_ENABLE	0x01	/* Enable bit */
-#define  PCI_PASID_CTRL_EXEC	0x02	/* Exec permissions Enable */
-#define  PCI_PASID_CTRL_PRIV	0x04	/* Privilege Mode Enable */
-#define PCI_EXT_CAP_PASID_SIZEOF	8
-
-/* Single Root I/O Virtualization */
-#define PCI_SRIOV_CAP		0x04	/* SR-IOV Capabilities */
-#define  PCI_SRIOV_CAP_VFM	0x01	/* VF Migration Capable */
-#define  PCI_SRIOV_CAP_INTR(x)	((x) >> 21) /* Interrupt Message Number */
-#define PCI_SRIOV_CTRL		0x08	/* SR-IOV Control */
-#define  PCI_SRIOV_CTRL_VFE	0x01	/* VF Enable */
-#define  PCI_SRIOV_CTRL_VFM	0x02	/* VF Migration Enable */
-#define  PCI_SRIOV_CTRL_INTR	0x04	/* VF Migration Interrupt Enable */
-#define  PCI_SRIOV_CTRL_MSE	0x08	/* VF Memory Space Enable */
-#define  PCI_SRIOV_CTRL_ARI	0x10	/* ARI Capable Hierarchy */
-#define PCI_SRIOV_STATUS	0x0a	/* SR-IOV Status */
-#define  PCI_SRIOV_STATUS_VFM	0x01	/* VF Migration Status */
-#define PCI_SRIOV_INITIAL_VF	0x0c	/* Initial VFs */
-#define PCI_SRIOV_TOTAL_VF	0x0e	/* Total VFs */
-#define PCI_SRIOV_NUM_VF	0x10	/* Number of VFs */
-#define PCI_SRIOV_FUNC_LINK	0x12	/* Function Dependency Link */
-#define PCI_SRIOV_VF_OFFSET	0x14	/* First VF Offset */
-#define PCI_SRIOV_VF_STRIDE	0x16	/* Following VF Stride */
-#define PCI_SRIOV_VF_DID	0x1a	/* VF Device ID */
-#define PCI_SRIOV_SUP_PGSIZE	0x1c	/* Supported Page Sizes */
-#define PCI_SRIOV_SYS_PGSIZE	0x20	/* System Page Size */
-#define PCI_SRIOV_BAR		0x24	/* VF BAR0 */
-#define  PCI_SRIOV_NUM_BARS	6	/* Number of VF BARs */
-#define PCI_SRIOV_VFM		0x3c	/* VF Migration State Array Offset*/
-#define  PCI_SRIOV_VFM_BIR(x)	((x) & 7)	/* State BIR */
-#define  PCI_SRIOV_VFM_OFFSET(x) ((x) & ~7)	/* State Offset */
-#define  PCI_SRIOV_VFM_UA	0x0	/* Inactive.Unavailable */
-#define  PCI_SRIOV_VFM_MI	0x1	/* Dormant.MigrateIn */
-#define  PCI_SRIOV_VFM_MO	0x2	/* Active.MigrateOut */
-#define  PCI_SRIOV_VFM_AV	0x3	/* Active.Available */
-#define PCI_EXT_CAP_SRIOV_SIZEOF 64
-
-#define PCI_LTR_MAX_SNOOP_LAT	0x4
-#define PCI_LTR_MAX_NOSNOOP_LAT	0x6
-#define  PCI_LTR_VALUE_MASK	0x000003ff
-#define  PCI_LTR_SCALE_MASK	0x00001c00
-#define  PCI_LTR_SCALE_SHIFT	10
-#define PCI_EXT_CAP_LTR_SIZEOF	8
-
-/* Access Control Service */
-#define PCI_ACS_CAP		0x04	/* ACS Capability Register */
-#define  PCI_ACS_SV		0x01	/* Source Validation */
-#define  PCI_ACS_TB		0x02	/* Translation Blocking */
-#define  PCI_ACS_RR		0x04	/* P2P Request Redirect */
-#define  PCI_ACS_CR		0x08	/* P2P Completion Redirect */
-#define  PCI_ACS_UF		0x10	/* Upstream Forwarding */
-#define  PCI_ACS_EC		0x20	/* P2P Egress Control */
-#define  PCI_ACS_DT		0x40	/* Direct Translated P2P */
-#define PCI_ACS_EGRESS_BITS	0x05	/* ACS Egress Control Vector Size */
-#define PCI_ACS_CTRL		0x06	/* ACS Control Register */
-#define PCI_ACS_EGRESS_CTL_V	0x08	/* ACS Egress Control Vector */
-
-#define PCI_VSEC_HDR		4	/* extended cap - vendor-specific */
-#define  PCI_VSEC_HDR_LEN_SHIFT	20	/* shift for length field */
-
-/* SATA capability */
-#define PCI_SATA_REGS		4	/* SATA REGs specifier */
-#define  PCI_SATA_REGS_MASK	0xF	/* location - BAR#/inline */
-#define  PCI_SATA_REGS_INLINE	0xF	/* REGS in config space */
-#define PCI_SATA_SIZEOF_SHORT	8
-#define PCI_SATA_SIZEOF_LONG	16
-
-/* Resizable BARs */
-#define PCI_REBAR_CTRL		8	/* control register */
-#define  PCI_REBAR_CTRL_NBAR_MASK	(7 << 5)	/* mask for # bars */
-#define  PCI_REBAR_CTRL_NBAR_SHIFT	5	/* shift for # bars */
-
-/* Dynamic Power Allocation */
-#define PCI_DPA_CAP		4	/* capability register */
-#define  PCI_DPA_CAP_SUBSTATE_MASK	0x1F	/* # substates - 1 */
-#define PCI_DPA_BASE_SIZEOF	16	/* size with 0 substates */
-
-/* TPH Requester */
-#define PCI_TPH_CAP		4	/* capability register */
-#define  PCI_TPH_CAP_LOC_MASK	0x600	/* location mask */
-#define   PCI_TPH_LOC_NONE	0x000	/* no location */
-#define   PCI_TPH_LOC_CAP	0x200	/* in capability */
-#define   PCI_TPH_LOC_MSIX	0x400	/* in MSI-X */
-#define PCI_TPH_CAP_ST_MASK	0x07FF0000	/* st table mask */
-#define PCI_TPH_CAP_ST_SHIFT	16	/* st table shift */
-#define PCI_TPH_BASE_SIZEOF	12	/* size with no st table */
-
-#endif /* LINUX_PCI_REGS_H */
diff --git a/include/uapi/linux/v4l2-common.h b/include/uapi/linux/v4l2-common.h
index 1527398..2f6f8ca 100644
--- a/include/uapi/linux/v4l2-common.h
+++ b/include/uapi/linux/v4l2-common.h
@@ -43,8 +43,6 @@
 #define V4L2_SEL_TGT_CROP_DEFAULT	0x0001
 /* Cropping bounds */
 #define V4L2_SEL_TGT_CROP_BOUNDS	0x0002
-/* Native frame size */
-#define V4L2_SEL_TGT_NATIVE_SIZE	0x0003
 /* Current composing area */
 #define V4L2_SEL_TGT_COMPOSE		0x0100
 /* Default composing area */
diff --git a/include/uapi/linux/v4l2-dv-timings.h b/include/uapi/linux/v4l2-dv-timings.h
index 6c8f159..6a0764c 100644
--- a/include/uapi/linux/v4l2-dv-timings.h
+++ b/include/uapi/linux/v4l2-dv-timings.h
@@ -21,17 +21,8 @@
 #ifndef _V4L2_DV_TIMINGS_H
 #define _V4L2_DV_TIMINGS_H
 
-#if __GNUC__ < 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ < 6))
-/* Sadly gcc versions older than 4.6 have a bug in how they initialize
-   anonymous unions where they require additional curly brackets.
-   This violates the C1x standard. This workaround adds the curly brackets
-   if needed. */
 #define V4L2_INIT_BT_TIMINGS(_width, args...) \
 	{ .bt = { _width , ## args } }
-#else
-#define V4L2_INIT_BT_TIMINGS(_width, args...) \
-	.bt = { _width , ## args }
-#endif
 
 /* CEA-861-E timings (i.e. standard HDTV timings) */
 
diff --git a/include/uapi/linux/v4l2-mediabus.h b/include/uapi/linux/v4l2-mediabus.h
index 26db206..1445e85 100644
--- a/include/uapi/linux/v4l2-mediabus.h
+++ b/include/uapi/linux/v4l2-mediabus.h
@@ -11,10 +11,122 @@
 #ifndef __LINUX_V4L2_MEDIABUS_H
 #define __LINUX_V4L2_MEDIABUS_H
 
-#include <linux/media-bus-format.h>
 #include <linux/types.h>
 #include <linux/videodev2.h>
 
+/*
+ * These pixel codes uniquely identify data formats on the media bus. Mostly
+ * they correspond to similarly named V4L2_PIX_FMT_* formats, format 0 is
+ * reserved, V4L2_MBUS_FMT_FIXED shall be used by host-client pairs, where the
+ * data format is fixed. Additionally, "2X8" means that one pixel is transferred
+ * in two 8-bit samples, "BE" or "LE" specify in which order those samples are
+ * transferred over the bus: "LE" means that the least significant bits are
+ * transferred first, "BE" means that the most significant bits are transferred
+ * first, and "PADHI" and "PADLO" define which bits - low or high, in the
+ * incomplete high byte, are filled with padding bits.
+ *
+ * The pixel codes are grouped by type, bus_width, bits per component, samples
+ * per pixel and order of subsamples. Numerical values are sorted using generic
+ * numerical sort order (8 thus comes before 10).
+ *
+ * As their value can't change when a new pixel code is inserted in the
+ * enumeration, the pixel codes are explicitly given a numerical value. The next
+ * free values for each category are listed below, update them when inserting
+ * new pixel codes.
+ */
+enum v4l2_mbus_pixelcode {
+	V4L2_MBUS_FMT_FIXED = 0x0001,
+
+	/* RGB - next is 0x100e */
+	V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE = 0x1001,
+	V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE = 0x1002,
+	V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE = 0x1003,
+	V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE = 0x1004,
+	V4L2_MBUS_FMT_BGR565_2X8_BE = 0x1005,
+	V4L2_MBUS_FMT_BGR565_2X8_LE = 0x1006,
+	V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
+	V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
+	V4L2_MBUS_FMT_RGB666_1X18 = 0x1009,
+	V4L2_MBUS_FMT_RGB888_1X24 = 0x100a,
+	V4L2_MBUS_FMT_RGB888_2X12_BE = 0x100b,
+	V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c,
+	V4L2_MBUS_FMT_ARGB8888_1X32 = 0x100d,
+
+	/* YUV (including grey) - next is 0x2024 */
+	V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
+	V4L2_MBUS_FMT_UV8_1X8 = 0x2015,
+	V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
+	V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
+	V4L2_MBUS_FMT_YUYV8_1_5X8 = 0x2004,
+	V4L2_MBUS_FMT_YVYU8_1_5X8 = 0x2005,
+	V4L2_MBUS_FMT_UYVY8_2X8 = 0x2006,
+	V4L2_MBUS_FMT_VYUY8_2X8 = 0x2007,
+	V4L2_MBUS_FMT_YUYV8_2X8 = 0x2008,
+	V4L2_MBUS_FMT_YVYU8_2X8 = 0x2009,
+	V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
+	V4L2_MBUS_FMT_UYVY10_2X10 = 0x2018,
+	V4L2_MBUS_FMT_VYUY10_2X10 = 0x2019,
+	V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
+	V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
+	V4L2_MBUS_FMT_Y12_1X12 = 0x2013,
+	V4L2_MBUS_FMT_UYVY8_1X16 = 0x200f,
+	V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010,
+	V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
+	V4L2_MBUS_FMT_YVYU8_1X16 = 0x2012,
+	V4L2_MBUS_FMT_YDYUYDYV8_1X16 = 0x2014,
+	V4L2_MBUS_FMT_UYVY10_1X20 = 0x201a,
+	V4L2_MBUS_FMT_VYUY10_1X20 = 0x201b,
+	V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
+	V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
+	V4L2_MBUS_FMT_YUV10_1X30 = 0x2016,
+	V4L2_MBUS_FMT_AYUV8_1X32 = 0x2017,
+	V4L2_MBUS_FMT_UYVY12_2X12 = 0x201c,
+	V4L2_MBUS_FMT_VYUY12_2X12 = 0x201d,
+	V4L2_MBUS_FMT_YUYV12_2X12 = 0x201e,
+	V4L2_MBUS_FMT_YVYU12_2X12 = 0x201f,
+	V4L2_MBUS_FMT_UYVY12_1X24 = 0x2020,
+	V4L2_MBUS_FMT_VYUY12_1X24 = 0x2021,
+	V4L2_MBUS_FMT_YUYV12_1X24 = 0x2022,
+	V4L2_MBUS_FMT_YVYU12_1X24 = 0x2023,
+
+	/* Bayer - next is 0x3019 */
+	V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
+	V4L2_MBUS_FMT_SGBRG8_1X8 = 0x3013,
+	V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
+	V4L2_MBUS_FMT_SRGGB8_1X8 = 0x3014,
+	V4L2_MBUS_FMT_SBGGR10_ALAW8_1X8 = 0x3015,
+	V4L2_MBUS_FMT_SGBRG10_ALAW8_1X8 = 0x3016,
+	V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8 = 0x3017,
+	V4L2_MBUS_FMT_SRGGB10_ALAW8_1X8 = 0x3018,
+	V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
+	V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c,
+	V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
+	V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 = 0x300d,
+	V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE = 0x3003,
+	V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE = 0x3004,
+	V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE = 0x3005,
+	V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE = 0x3006,
+	V4L2_MBUS_FMT_SBGGR10_1X10 = 0x3007,
+	V4L2_MBUS_FMT_SGBRG10_1X10 = 0x300e,
+	V4L2_MBUS_FMT_SGRBG10_1X10 = 0x300a,
+	V4L2_MBUS_FMT_SRGGB10_1X10 = 0x300f,
+	V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008,
+	V4L2_MBUS_FMT_SGBRG12_1X12 = 0x3010,
+	V4L2_MBUS_FMT_SGRBG12_1X12 = 0x3011,
+	V4L2_MBUS_FMT_SRGGB12_1X12 = 0x3012,
+
+	/* JPEG compressed formats - next is 0x4002 */
+	V4L2_MBUS_FMT_JPEG_1X8 = 0x4001,
+
+	/* Vendor specific formats - next is 0x5002 */
+
+	/* S5C73M3 sensor specific interleaved UYVY and JPEG */
+	V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8 = 0x5001,
+
+	/* HSV - next is 0x6002 */
+	V4L2_MBUS_FMT_AHSV8888_1X32 = 0x6001,
+};
+
 /**
  * struct v4l2_mbus_framefmt - frame format on the media bus
  * @width:	frame width
@@ -22,8 +134,6 @@
  * @code:	data format code (from enum v4l2_mbus_pixelcode)
  * @field:	used interlacing type (from enum v4l2_field)
  * @colorspace:	colorspace of the data (from enum v4l2_colorspace)
- * @ycbcr_enc:	YCbCr encoding of the data (from enum v4l2_ycbcr_encoding)
- * @quantization: quantization of the data (from enum v4l2_quantization)
  */
 struct v4l2_mbus_framefmt {
 	__u32			width;
@@ -31,108 +141,7 @@
 	__u32			code;
 	__u32			field;
 	__u32			colorspace;
-	__u16			ycbcr_enc;
-	__u16			quantization;
-	__u32			reserved[6];
+	__u32			reserved[7];
 };
 
-#ifndef __KERNEL__
-/*
- * enum v4l2_mbus_pixelcode and its definitions are now deprecated, and
- * MEDIA_BUS_FMT_ definitions (defined in media-bus-format.h) should be
- * used instead.
- *
- * New defines should only be added to media-bus-format.h. The
- * v4l2_mbus_pixelcode enum is frozen.
- */
-
-#define V4L2_MBUS_FROM_MEDIA_BUS_FMT(name)	\
-	V4L2_MBUS_FMT_ ## name = MEDIA_BUS_FMT_ ## name
-
-enum v4l2_mbus_pixelcode {
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(FIXED),
-
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB444_2X8_PADHI_BE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB444_2X8_PADHI_LE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB555_2X8_PADHI_BE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB555_2X8_PADHI_LE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(BGR565_2X8_BE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(BGR565_2X8_LE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB565_2X8_BE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB565_2X8_LE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB666_1X18),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB888_1X24),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB888_2X12_BE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB888_2X12_LE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(ARGB8888_1X32),
-
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(Y8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(UV8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY8_1_5X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY8_1_5X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV8_1_5X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU8_1_5X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY8_2X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY8_2X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV8_2X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU8_2X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(Y10_1X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY10_2X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY10_2X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV10_2X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU10_2X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(Y12_1X12),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY8_1X16),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY8_1X16),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV8_1X16),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU8_1X16),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YDYUYDYV8_1X16),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY10_1X20),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY10_1X20),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV10_1X20),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU10_1X20),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUV10_1X30),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(AYUV8_1X32),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY12_2X12),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY12_2X12),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV12_2X12),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU12_2X12),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY12_1X24),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY12_1X24),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV12_1X24),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU12_1X24),
-
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_ALAW8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG10_ALAW8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG10_ALAW8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB10_ALAW8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_DPCM8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG10_DPCM8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG10_DPCM8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB10_DPCM8_1X8),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_2X8_PADHI_BE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_2X8_PADHI_LE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_2X8_PADLO_BE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_2X8_PADLO_LE),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_1X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG10_1X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG10_1X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB10_1X10),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR12_1X12),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG12_1X12),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG12_1X12),
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB12_1X12),
-
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(JPEG_1X8),
-
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(S5C_UYVY_JPEG_1X8),
-
-	V4L2_MBUS_FROM_MEDIA_BUS_FMT(AHSV8888_1X32),
-};
-#endif /* __KERNEL__ */
-
 #endif
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index e0a7e3d..a619cdd 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -68,7 +68,7 @@
  * struct v4l2_subdev_mbus_code_enum - Media bus format enumeration
  * @pad: pad number, as reported by the media API
  * @index: format index during enumeration
- * @code: format code (MEDIA_BUS_FMT_ definitions)
+ * @code: format code (from enum v4l2_mbus_pixelcode)
  */
 struct v4l2_subdev_mbus_code_enum {
 	__u32 pad;
@@ -81,7 +81,7 @@
  * struct v4l2_subdev_frame_size_enum - Media bus format enumeration
  * @pad: pad number, as reported by the media API
  * @index: format index during enumeration
- * @code: format code (MEDIA_BUS_FMT_ definitions)
+ * @code: format code (from enum v4l2_mbus_pixelcode)
  */
 struct v4l2_subdev_frame_size_enum {
 	__u32 index;
@@ -109,7 +109,7 @@
  * struct v4l2_subdev_frame_interval_enum - Frame interval enumeration
  * @pad: pad number, as reported by the media API
  * @index: frame interval index during enumeration
- * @code: format code (MEDIA_BUS_FMT_ definitions)
+ * @code: format code (from enum v4l2_mbus_pixelcode)
  * @width: frame width in pixels
  * @height: frame height in pixels
  * @interval: frame interval in seconds
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 7a26b65..accc4ef 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -178,103 +178,30 @@
 
 /* see also http://vektor.theorem.ca/graphics/ycbcr/ */
 enum v4l2_colorspace {
-	/* SMPTE 170M: used for broadcast NTSC/PAL SDTV */
+	/* ITU-R 601 -- broadcast NTSC/PAL */
 	V4L2_COLORSPACE_SMPTE170M     = 1,
 
-	/* Obsolete pre-1998 SMPTE 240M HDTV standard, superseded by Rec 709 */
+	/* 1125-Line (US) HDTV */
 	V4L2_COLORSPACE_SMPTE240M     = 2,
 
-	/* Rec.709: used for HDTV */
+	/* HD and modern captures. */
 	V4L2_COLORSPACE_REC709        = 3,
 
-	/*
-	 * Deprecated, do not use. No driver will ever return this. This was
-	 * based on a misunderstanding of the bt878 datasheet.
-	 */
+	/* broken BT878 extents (601, luma range 16-253 instead of 16-235) */
 	V4L2_COLORSPACE_BT878         = 4,
 
-	/*
-	 * NTSC 1953 colorspace. This only makes sense when dealing with
-	 * really, really old NTSC recordings. Superseded by SMPTE 170M.
-	 */
+	/* These should be useful.  Assume 601 extents. */
 	V4L2_COLORSPACE_470_SYSTEM_M  = 5,
-
-	/*
-	 * EBU Tech 3213 PAL/SECAM colorspace. This only makes sense when
-	 * dealing with really old PAL/SECAM recordings. Superseded by
-	 * SMPTE 170M.
-	 */
 	V4L2_COLORSPACE_470_SYSTEM_BG = 6,
 
-	/*
-	 * Effectively shorthand for V4L2_COLORSPACE_SRGB, V4L2_YCBCR_ENC_601
-	 * and V4L2_QUANTIZATION_FULL_RANGE. To be used for (Motion-)JPEG.
+	/* I know there will be cameras that send this.  So, this is
+	 * unspecified chromaticities and full 0-255 on each of the
+	 * Y'CbCr components
 	 */
 	V4L2_COLORSPACE_JPEG          = 7,
 
-	/* For RGB colorspaces such as produces by most webcams. */
+	/* For RGB colourspaces, this is probably a good start. */
 	V4L2_COLORSPACE_SRGB          = 8,
-
-	/* AdobeRGB colorspace */
-	V4L2_COLORSPACE_ADOBERGB      = 9,
-
-	/* BT.2020 colorspace, used for UHDTV. */
-	V4L2_COLORSPACE_BT2020        = 10,
-};
-
-enum v4l2_ycbcr_encoding {
-	/*
-	 * Mapping of V4L2_YCBCR_ENC_DEFAULT to actual encodings for the
-	 * various colorspaces:
-	 *
-	 * V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M,
-	 * V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_ADOBERGB and
-	 * V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601
-	 *
-	 * V4L2_COLORSPACE_REC709: V4L2_YCBCR_ENC_709
-	 *
-	 * V4L2_COLORSPACE_SRGB: V4L2_YCBCR_ENC_SYCC
-	 *
-	 * V4L2_COLORSPACE_BT2020: V4L2_YCBCR_ENC_BT2020
-	 *
-	 * V4L2_COLORSPACE_SMPTE240M: V4L2_YCBCR_ENC_SMPTE240M
-	 */
-	V4L2_YCBCR_ENC_DEFAULT        = 0,
-
-	/* ITU-R 601 -- SDTV */
-	V4L2_YCBCR_ENC_601            = 1,
-
-	/* Rec. 709 -- HDTV */
-	V4L2_YCBCR_ENC_709            = 2,
-
-	/* ITU-R 601/EN 61966-2-4 Extended Gamut -- SDTV */
-	V4L2_YCBCR_ENC_XV601          = 3,
-
-	/* Rec. 709/EN 61966-2-4 Extended Gamut -- HDTV */
-	V4L2_YCBCR_ENC_XV709          = 4,
-
-	/* sYCC (Y'CbCr encoding of sRGB) */
-	V4L2_YCBCR_ENC_SYCC           = 5,
-
-	/* BT.2020 Non-constant Luminance Y'CbCr */
-	V4L2_YCBCR_ENC_BT2020         = 6,
-
-	/* BT.2020 Constant Luminance Y'CbcCrc */
-	V4L2_YCBCR_ENC_BT2020_CONST_LUM = 7,
-
-	/* SMPTE 240M -- Obsolete HDTV */
-	V4L2_YCBCR_ENC_SMPTE240M      = 8,
-};
-
-enum v4l2_quantization {
-	/*
-	 * The default for R'G'B' quantization is always full range. For
-	 * Y'CbCr the quantization is always limited range, except for
-	 * SYCC, XV601, XV709 or JPEG: those are full range.
-	 */
-	V4L2_QUANTIZATION_DEFAULT     = 0,
-	V4L2_QUANTIZATION_FULL_RANGE  = 1,
-	V4L2_QUANTIZATION_LIM_RANGE   = 2,
 };
 
 enum v4l2_priority {
@@ -367,8 +294,6 @@
 	__u32			colorspace;	/* enum v4l2_colorspace */
 	__u32			priv;		/* private data, depends on pixelformat */
 	__u32			flags;		/* format flags (V4L2_PIX_FMT_FLAG_*) */
-	__u32			ycbcr_enc;	/* enum v4l2_ycbcr_encoding */
-	__u32			quantization;	/* enum v4l2_quantization */
 };
 
 /*      Pixel format         FOURCC                          depth  Description  */
@@ -1324,7 +1249,6 @@
 #define V4L2_IN_CAP_DV_TIMINGS		0x00000002 /* Supports S_DV_TIMINGS */
 #define V4L2_IN_CAP_CUSTOM_TIMINGS	V4L2_IN_CAP_DV_TIMINGS /* For compatibility */
 #define V4L2_IN_CAP_STD			0x00000004 /* Supports S_STD */
-#define V4L2_IN_CAP_NATIVE_SIZE		0x00000008 /* Supports setting native size */
 
 /*
  *	V I D E O   O U T P U T S
@@ -1348,7 +1272,6 @@
 #define V4L2_OUT_CAP_DV_TIMINGS		0x00000002 /* Supports S_DV_TIMINGS */
 #define V4L2_OUT_CAP_CUSTOM_TIMINGS	V4L2_OUT_CAP_DV_TIMINGS /* For compatibility */
 #define V4L2_OUT_CAP_STD		0x00000004 /* Supports S_STD */
-#define V4L2_OUT_CAP_NATIVE_SIZE	0x00000008 /* Supports setting native size */
 
 /*
  *	C O N T R O L S
@@ -1854,8 +1777,6 @@
  * @plane_fmt:		per-plane information
  * @num_planes:		number of planes for this format
  * @flags:		format flags (V4L2_PIX_FMT_FLAG_*)
- * @ycbcr_enc:		enum v4l2_ycbcr_encoding, Y'CbCr encoding
- * @quantization:	enum v4l2_quantization, colorspace quantization
  */
 struct v4l2_pix_format_mplane {
 	__u32				width;
@@ -1867,9 +1788,7 @@
 	struct v4l2_plane_pix_format	plane_fmt[VIDEO_MAX_PLANES];
 	__u8				num_planes;
 	__u8				flags;
-	__u8				ycbcr_enc;
-	__u8				quantization;
-	__u8				reserved[8];
+	__u8				reserved[10];
 } __attribute__ ((packed));
 
 /**
diff --git a/kconf/Makefile b/kconf/Makefile
index 9edd957..b307c65 100644
--- a/kconf/Makefile
+++ b/kconf/Makefile
@@ -3,12 +3,9 @@
 LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
 
 conf: conf.o zconf.tab.o
-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
-mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
-mconf: CFLAGS += $(mconf_CFLAGS)
-
+mconf: LDFLAGS = -Wl,--add-needed $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
+mconf: CFLAGS += -DCURSES_LOC="<ncurses.h>" -DLOCALE
 mconf: mconf.o zconf.tab.o $(LXDIALOG)
-	$(CC) -o mconf $^ $(mconf_LDFLAGS)
 
 .PHONY: clean
 clean:
diff --git a/net/6lowpan/Kconfig b/net/6lowpan/Kconfig
deleted file mode 100644
index cb540f5..0000000
--- a/net/6lowpan/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config 6LOWPAN
-	tristate "6LoWPAN Support"
-	depends on m
-	depends on IPV6
-	---help---
-	  This enables IPv6 over Low power Wireless Personal Area Network -
-	  "6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks.
diff --git a/net/6lowpan/Makefile b/net/6lowpan/Makefile
deleted file mode 100644
index 0f2fd34..0000000
--- a/net/6lowpan/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CPTCFG_6LOWPAN) := 6lowpan.o
-
-6lowpan-y := iphc.o
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
deleted file mode 100644
index 32ffec6..0000000
--- a/net/6lowpan/iphc.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright 2011, Siemens AG
- * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
- */
-
-/* Based on patches from Jon Smirl <jonsmirl@gmail.com>
- * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.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.
- *
- */
-
-/* Jon's code is based on 6lowpan implementation for Contiki which is:
- * Copyright (c) 2008, Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the Institute nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <linux/bitops.h>
-#include <linux/if_arp.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <net/6lowpan.h>
-#include <net/ipv6.h>
-#include <net/af_ieee802154.h>
-
-/* Uncompress address function for source and
- * destination address(non-multicast).
- *
- * address_mode is sam value or dam value.
- */
-static int uncompress_addr(struct sk_buff *skb,
-			   struct in6_addr *ipaddr, const u8 address_mode,
-			   const u8 *lladdr, const u8 addr_type,
-			   const u8 addr_len)
-{
-	bool fail;
-
-	switch (address_mode) {
-	case LOWPAN_IPHC_ADDR_00:
-		/* for global link addresses */
-		fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
-		break;
-	case LOWPAN_IPHC_ADDR_01:
-		/* fe:80::XXXX:XXXX:XXXX:XXXX */
-		ipaddr->s6_addr[0] = 0xFE;
-		ipaddr->s6_addr[1] = 0x80;
-		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
-		break;
-	case LOWPAN_IPHC_ADDR_02:
-		/* fe:80::ff:fe00:XXXX */
-		ipaddr->s6_addr[0] = 0xFE;
-		ipaddr->s6_addr[1] = 0x80;
-		ipaddr->s6_addr[11] = 0xFF;
-		ipaddr->s6_addr[12] = 0xFE;
-		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
-		break;
-	case LOWPAN_IPHC_ADDR_03:
-		fail = false;
-		switch (addr_type) {
-		case IEEE802154_ADDR_LONG:
-			/* fe:80::XXXX:XXXX:XXXX:XXXX
-			 *        \_________________/
-			 *              hwaddr
-			 */
-			ipaddr->s6_addr[0] = 0xFE;
-			ipaddr->s6_addr[1] = 0x80;
-			memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
-			/* second bit-flip (Universe/Local)
-			 * is done according RFC2464
-			 */
-			ipaddr->s6_addr[8] ^= 0x02;
-			break;
-		case IEEE802154_ADDR_SHORT:
-			/* fe:80::ff:fe00:XXXX
-			 *		  \__/
-			 *	       short_addr
-			 *
-			 * Universe/Local bit is zero.
-			 */
-			ipaddr->s6_addr[0] = 0xFE;
-			ipaddr->s6_addr[1] = 0x80;
-			ipaddr->s6_addr[11] = 0xFF;
-			ipaddr->s6_addr[12] = 0xFE;
-			ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
-			break;
-		default:
-			pr_debug("Invalid addr_type set\n");
-			return -EINVAL;
-		}
-		break;
-	default:
-		pr_debug("Invalid address mode value: 0x%x\n", address_mode);
-		return -EINVAL;
-	}
-
-	if (fail) {
-		pr_debug("Failed to fetch skb data\n");
-		return -EIO;
-	}
-
-	raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
-			ipaddr->s6_addr, 16);
-
-	return 0;
-}
-
-/* Uncompress address function for source context
- * based address(non-multicast).
- */
-static int uncompress_context_based_src_addr(struct sk_buff *skb,
-					     struct in6_addr *ipaddr,
-					     const u8 sam)
-{
-	switch (sam) {
-	case LOWPAN_IPHC_ADDR_00:
-		/* unspec address ::
-		 * Do nothing, address is already ::
-		 */
-		break;
-	case LOWPAN_IPHC_ADDR_01:
-		/* TODO */
-	case LOWPAN_IPHC_ADDR_02:
-		/* TODO */
-	case LOWPAN_IPHC_ADDR_03:
-		/* TODO */
-		netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
-		return -EINVAL;
-	default:
-		pr_debug("Invalid sam value: 0x%x\n", sam);
-		return -EINVAL;
-	}
-
-	raw_dump_inline(NULL,
-			"Reconstructed context based ipv6 src addr is",
-			ipaddr->s6_addr, 16);
-
-	return 0;
-}
-
-/* Uncompress function for multicast destination address,
- * when M bit is set.
- */
-static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
-					     struct in6_addr *ipaddr,
-					     const u8 dam)
-{
-	bool fail;
-
-	switch (dam) {
-	case LOWPAN_IPHC_DAM_00:
-		/* 00:  128 bits.  The full address
-		 * is carried in-line.
-		 */
-		fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
-		break;
-	case LOWPAN_IPHC_DAM_01:
-		/* 01:  48 bits.  The address takes
-		 * the form ffXX::00XX:XXXX:XXXX.
-		 */
-		ipaddr->s6_addr[0] = 0xFF;
-		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
-		fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
-		break;
-	case LOWPAN_IPHC_DAM_10:
-		/* 10:  32 bits.  The address takes
-		 * the form ffXX::00XX:XXXX.
-		 */
-		ipaddr->s6_addr[0] = 0xFF;
-		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
-		fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
-		break;
-	case LOWPAN_IPHC_DAM_11:
-		/* 11:  8 bits.  The address takes
-		 * the form ff02::00XX.
-		 */
-		ipaddr->s6_addr[0] = 0xFF;
-		ipaddr->s6_addr[1] = 0x02;
-		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
-		break;
-	default:
-		pr_debug("DAM value has a wrong value: 0x%x\n", dam);
-		return -EINVAL;
-	}
-
-	if (fail) {
-		pr_debug("Failed to fetch skb data\n");
-		return -EIO;
-	}
-
-	raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
-			ipaddr->s6_addr, 16);
-
-	return 0;
-}
-
-static int uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
-{
-	bool fail;
-	u8 tmp = 0, val = 0;
-
-	fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp));
-
-	if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
-		pr_debug("UDP header uncompression\n");
-		switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
-		case LOWPAN_NHC_UDP_CS_P_00:
-			fail |= lowpan_fetch_skb(skb, &uh->source,
-						 sizeof(uh->source));
-			fail |= lowpan_fetch_skb(skb, &uh->dest,
-						 sizeof(uh->dest));
-			break;
-		case LOWPAN_NHC_UDP_CS_P_01:
-			fail |= lowpan_fetch_skb(skb, &uh->source,
-						 sizeof(uh->source));
-			fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
-			uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
-			break;
-		case LOWPAN_NHC_UDP_CS_P_10:
-			fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
-			uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
-			fail |= lowpan_fetch_skb(skb, &uh->dest,
-						 sizeof(uh->dest));
-			break;
-		case LOWPAN_NHC_UDP_CS_P_11:
-			fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
-			uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT +
-					   (val >> 4));
-			uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT +
-					 (val & 0x0f));
-			break;
-		default:
-			pr_debug("ERROR: unknown UDP format\n");
-			goto err;
-		}
-
-		pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
-			 ntohs(uh->source), ntohs(uh->dest));
-
-		/* checksum */
-		if (tmp & LOWPAN_NHC_UDP_CS_C) {
-			pr_debug_ratelimited("checksum elided currently not supported\n");
-			goto err;
-		} else {
-			fail |= lowpan_fetch_skb(skb, &uh->check,
-						 sizeof(uh->check));
-		}
-
-		/* UDP length needs to be infered from the lower layers
-		 * here, we obtain the hint from the remaining size of the
-		 * frame
-		 */
-		uh->len = htons(skb->len + sizeof(struct udphdr));
-		pr_debug("uncompressed UDP length: src = %d", ntohs(uh->len));
-	} else {
-		pr_debug("ERROR: unsupported NH format\n");
-		goto err;
-	}
-
-	if (fail)
-		goto err;
-
-	return 0;
-err:
-	return -EINVAL;
-}
-
-/* TTL uncompression values */
-static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
-
-int
-lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
-			 const u8 *saddr, const u8 saddr_type,
-			 const u8 saddr_len, const u8 *daddr,
-			 const u8 daddr_type, const u8 daddr_len,
-			 u8 iphc0, u8 iphc1)
-{
-	struct ipv6hdr hdr = {};
-	u8 tmp, num_context = 0;
-	int err;
-
-	raw_dump_table(__func__, "raw skb data dump uncompressed",
-		       skb->data, skb->len);
-
-	/* another if the CID flag is set */
-	if (iphc1 & LOWPAN_IPHC_CID) {
-		pr_debug("CID flag is set, increase header with one\n");
-		if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context)))
-			return -EINVAL;
-	}
-
-	hdr.version = 6;
-
-	/* Traffic Class and Flow Label */
-	switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
-	/* Traffic Class and FLow Label carried in-line
-	 * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
-	 */
-	case 0: /* 00b */
-		if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
-			return -EINVAL;
-
-		memcpy(&hdr.flow_lbl, &skb->data[0], 3);
-		skb_pull(skb, 3);
-		hdr.priority = ((tmp >> 2) & 0x0f);
-		hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
-					(hdr.flow_lbl[0] & 0x0f);
-		break;
-	/* Traffic class carried in-line
-	 * ECN + DSCP (1 byte), Flow Label is elided
-	 */
-	case 2: /* 10b */
-		if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
-			return -EINVAL;
-
-		hdr.priority = ((tmp >> 2) & 0x0f);
-		hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
-		break;
-	/* Flow Label carried in-line
-	 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
-	 */
-	case 1: /* 01b */
-		if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
-			return -EINVAL;
-
-		hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
-		memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
-		skb_pull(skb, 2);
-		break;
-	/* Traffic Class and Flow Label are elided */
-	case 3: /* 11b */
-		break;
-	default:
-		break;
-	}
-
-	/* Next Header */
-	if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
-		/* Next header is carried inline */
-		if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr)))
-			return -EINVAL;
-
-		pr_debug("NH flag is set, next header carried inline: %02x\n",
-			 hdr.nexthdr);
-	}
-
-	/* Hop Limit */
-	if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) {
-		hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
-	} else {
-		if (lowpan_fetch_skb(skb, &hdr.hop_limit,
-				     sizeof(hdr.hop_limit)))
-			return -EINVAL;
-	}
-
-	/* Extract SAM to the tmp variable */
-	tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
-
-	if (iphc1 & LOWPAN_IPHC_SAC) {
-		/* Source address context based uncompression */
-		pr_debug("SAC bit is set. Handle context based source address.\n");
-		err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp);
-	} else {
-		/* Source address uncompression */
-		pr_debug("source address stateless compression\n");
-		err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
-				      saddr_type, saddr_len);
-	}
-
-	/* Check on error of previous branch */
-	if (err)
-		return -EINVAL;
-
-	/* Extract DAM to the tmp variable */
-	tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
-
-	/* check for Multicast Compression */
-	if (iphc1 & LOWPAN_IPHC_M) {
-		if (iphc1 & LOWPAN_IPHC_DAC) {
-			pr_debug("dest: context-based mcast compression\n");
-			/* TODO: implement this */
-		} else {
-			err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr,
-								tmp);
-
-			if (err)
-				return -EINVAL;
-		}
-	} else {
-		err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
-				      daddr_type, daddr_len);
-		pr_debug("dest: stateless compression mode %d dest %pI6c\n",
-			 tmp, &hdr.daddr);
-		if (err)
-			return -EINVAL;
-	}
-
-	/* UDP data uncompression */
-	if (iphc0 & LOWPAN_IPHC_NH_C) {
-		struct udphdr uh;
-		const int needed = sizeof(struct udphdr) + sizeof(hdr);
-
-		if (uncompress_udp_header(skb, &uh))
-			return -EINVAL;
-
-		/* replace the compressed UDP head by the uncompressed UDP
-		 * header
-		 */
-		err = skb_cow(skb, needed);
-		if (unlikely(err))
-			return err;
-
-		skb_push(skb, sizeof(struct udphdr));
-		skb_reset_transport_header(skb);
-		skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
-
-		raw_dump_table(__func__, "raw UDP header dump",
-			       (u8 *)&uh, sizeof(uh));
-
-		hdr.nexthdr = UIP_PROTO_UDP;
-	} else {
-		err = skb_cow(skb, sizeof(hdr));
-		if (unlikely(err))
-			return err;
-	}
-
-	hdr.payload_len = htons(skb->len);
-
-	pr_debug("skb headroom size = %d, data length = %d\n",
-		 skb_headroom(skb), skb->len);
-
-	pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n\t"
-		 "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
-		hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
-		hdr.hop_limit, &hdr.daddr);
-
-	skb_push(skb, sizeof(hdr));
-	skb_reset_network_header(skb);
-	skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
-
-	raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(lowpan_header_decompress);
-
-static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
-				  const struct in6_addr *ipaddr,
-				  const unsigned char *lladdr)
-{
-	u8 val = 0;
-
-	if (is_addr_mac_addr_based(ipaddr, lladdr)) {
-		val = 3; /* 0-bits */
-		pr_debug("address compression 0 bits\n");
-	} else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
-		/* compress IID to 16 bits xxxx::XXXX */
-		lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2);
-		val = 2; /* 16-bits */
-		raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
-				*hc_ptr - 2, 2);
-	} else {
-		/* do not compress IID => xxxx::IID */
-		lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8);
-		val = 1; /* 64-bits */
-		raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
-				*hc_ptr - 8, 8);
-	}
-
-	return rol8(val, shift);
-}
-
-static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb)
-{
-	struct udphdr *uh;
-	u8 tmp;
-
-	/* In the case of RAW sockets the transport header is not set by
-	 * the ip6 stack so we must set it ourselves
-	 */
-	if (skb->transport_header == skb->network_header)
-		skb_set_transport_header(skb, sizeof(struct ipv6hdr));
-
-	uh = udp_hdr(skb);
-
-	if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) ==
-	     LOWPAN_NHC_UDP_4BIT_PORT) &&
-	    ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
-	     LOWPAN_NHC_UDP_4BIT_PORT)) {
-		pr_debug("UDP header: both ports compression to 4 bits\n");
-		/* compression value */
-		tmp = LOWPAN_NHC_UDP_CS_P_11;
-		lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
-		/* source and destination port */
-		tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT +
-		      ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4);
-		lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
-	} else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
-			LOWPAN_NHC_UDP_8BIT_PORT) {
-		pr_debug("UDP header: remove 8 bits of dest\n");
-		/* compression value */
-		tmp = LOWPAN_NHC_UDP_CS_P_01;
-		lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
-		/* source port */
-		lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
-		/* destination port */
-		tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT;
-		lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
-	} else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
-			LOWPAN_NHC_UDP_8BIT_PORT) {
-		pr_debug("UDP header: remove 8 bits of source\n");
-		/* compression value */
-		tmp = LOWPAN_NHC_UDP_CS_P_10;
-		lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
-		/* source port */
-		tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT;
-		lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
-		/* destination port */
-		lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
-	} else {
-		pr_debug("UDP header: can't compress\n");
-		/* compression value */
-		tmp = LOWPAN_NHC_UDP_CS_P_00;
-		lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
-		/* source port */
-		lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
-		/* destination port */
-		lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
-	}
-
-	/* checksum is always inline */
-	lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check));
-
-	/* skip the UDP header */
-	skb_pull(skb, sizeof(struct udphdr));
-}
-
-int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
-			   unsigned short type, const void *_daddr,
-			   const void *_saddr, unsigned int len)
-{
-	u8 tmp, iphc0, iphc1, *hc_ptr;
-	struct ipv6hdr *hdr;
-	u8 head[100] = {};
-	int addr_type;
-
-	if (type != ETH_P_IPV6)
-		return -EINVAL;
-
-	hdr = ipv6_hdr(skb);
-	hc_ptr = head + 2;
-
-	pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n"
-		 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
-		 hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
-		 hdr->hop_limit, &hdr->daddr);
-
-	raw_dump_table(__func__, "raw skb network header dump",
-		       skb_network_header(skb), sizeof(struct ipv6hdr));
-
-	/* As we copy some bit-length fields, in the IPHC encoding bytes,
-	 * we sometimes use |=
-	 * If the field is 0, and the current bit value in memory is 1,
-	 * this does not work. We therefore reset the IPHC encoding here
-	 */
-	iphc0 = LOWPAN_DISPATCH_IPHC;
-	iphc1 = 0;
-
-	/* TODO: context lookup */
-
-	raw_dump_inline(__func__, "saddr",
-			(unsigned char *)_saddr, IEEE802154_ADDR_LEN);
-	raw_dump_inline(__func__, "daddr",
-			(unsigned char *)_daddr, IEEE802154_ADDR_LEN);
-
-	raw_dump_table(__func__, "sending raw skb network uncompressed packet",
-		       skb->data, skb->len);
-
-	/* Traffic class, flow label
-	 * If flow label is 0, compress it. If traffic class is 0, compress it
-	 * We have to process both in the same time as the offset of traffic
-	 * class depends on the presence of version and flow label
-	 */
-
-	/* hc format of TC is ECN | DSCP , original one is DSCP | ECN */
-	tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
-	tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
-
-	if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
-	    (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
-		/* flow label can be compressed */
-		iphc0 |= LOWPAN_IPHC_FL_C;
-		if ((hdr->priority == 0) &&
-		    ((hdr->flow_lbl[0] & 0xF0) == 0)) {
-			/* compress (elide) all */
-			iphc0 |= LOWPAN_IPHC_TC_C;
-		} else {
-			/* compress only the flow label */
-			*hc_ptr = tmp;
-			hc_ptr += 1;
-		}
-	} else {
-		/* Flow label cannot be compressed */
-		if ((hdr->priority == 0) &&
-		    ((hdr->flow_lbl[0] & 0xF0) == 0)) {
-			/* compress only traffic class */
-			iphc0 |= LOWPAN_IPHC_TC_C;
-			*hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
-			memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2);
-			hc_ptr += 3;
-		} else {
-			/* compress nothing */
-			memcpy(hc_ptr, hdr, 4);
-			/* replace the top byte with new ECN | DSCP format */
-			*hc_ptr = tmp;
-			hc_ptr += 4;
-		}
-	}
-
-	/* NOTE: payload length is always compressed */
-
-	/* Next Header is compress if UDP */
-	if (hdr->nexthdr == UIP_PROTO_UDP)
-		iphc0 |= LOWPAN_IPHC_NH_C;
-
-	if ((iphc0 & LOWPAN_IPHC_NH_C) == 0)
-		lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr,
-				    sizeof(hdr->nexthdr));
-
-	/* Hop limit
-	 * if 1:   compress, encoding is 01
-	 * if 64:  compress, encoding is 10
-	 * if 255: compress, encoding is 11
-	 * else do not compress
-	 */
-	switch (hdr->hop_limit) {
-	case 1:
-		iphc0 |= LOWPAN_IPHC_TTL_1;
-		break;
-	case 64:
-		iphc0 |= LOWPAN_IPHC_TTL_64;
-		break;
-	case 255:
-		iphc0 |= LOWPAN_IPHC_TTL_255;
-		break;
-	default:
-		lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit,
-				    sizeof(hdr->hop_limit));
-	}
-
-	addr_type = ipv6_addr_type(&hdr->saddr);
-	/* source address compression */
-	if (addr_type == IPV6_ADDR_ANY) {
-		pr_debug("source address is unspecified, setting SAC\n");
-		iphc1 |= LOWPAN_IPHC_SAC;
-	} else {
-		if (addr_type & IPV6_ADDR_LINKLOCAL) {
-			iphc1 |= lowpan_compress_addr_64(&hc_ptr,
-							 LOWPAN_IPHC_SAM_BIT,
-							 &hdr->saddr, _saddr);
-			pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
-				 &hdr->saddr, iphc1);
-		} else {
-			pr_debug("send the full source address\n");
-			lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16);
-		}
-	}
-
-	addr_type = ipv6_addr_type(&hdr->daddr);
-	/* destination address compression */
-	if (addr_type & IPV6_ADDR_MULTICAST) {
-		pr_debug("destination address is multicast: ");
-		iphc1 |= LOWPAN_IPHC_M;
-		if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
-			pr_debug("compressed to 1 octet\n");
-			iphc1 |= LOWPAN_IPHC_DAM_11;
-			/* use last byte */
-			lowpan_push_hc_data(&hc_ptr,
-					    &hdr->daddr.s6_addr[15], 1);
-		} else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
-			pr_debug("compressed to 4 octets\n");
-			iphc1 |= LOWPAN_IPHC_DAM_10;
-			/* second byte + the last three */
-			lowpan_push_hc_data(&hc_ptr,
-					    &hdr->daddr.s6_addr[1], 1);
-			lowpan_push_hc_data(&hc_ptr,
-					    &hdr->daddr.s6_addr[13], 3);
-		} else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
-			pr_debug("compressed to 6 octets\n");
-			iphc1 |= LOWPAN_IPHC_DAM_01;
-			/* second byte + the last five */
-			lowpan_push_hc_data(&hc_ptr,
-					    &hdr->daddr.s6_addr[1], 1);
-			lowpan_push_hc_data(&hc_ptr,
-					    &hdr->daddr.s6_addr[11], 5);
-		} else {
-			pr_debug("using full address\n");
-			iphc1 |= LOWPAN_IPHC_DAM_00;
-			lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
-		}
-	} else {
-		if (addr_type & IPV6_ADDR_LINKLOCAL) {
-			/* TODO: context lookup */
-			iphc1 |= lowpan_compress_addr_64(&hc_ptr,
-				LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
-			pr_debug("dest address unicast link-local %pI6c "
-				 "iphc1 0x%02x\n", &hdr->daddr, iphc1);
-		} else {
-			pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
-			lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
-		}
-	}
-
-	/* UDP header compression */
-	if (hdr->nexthdr == UIP_PROTO_UDP)
-		compress_udp_header(&hc_ptr, skb);
-
-	head[0] = iphc0;
-	head[1] = iphc1;
-
-	skb_pull(skb, sizeof(struct ipv6hdr));
-	skb_reset_transport_header(skb);
-	memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head);
-	skb_reset_network_header(skb);
-
-	pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len);
-
-	raw_dump_table(__func__, "raw skb data dump compressed",
-		       skb->data, skb->len);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(lowpan_header_compress);
-
-MODULE_LICENSE("GPL");
diff --git a/net/Kconfig b/net/Kconfig
index ff9ffc1..6272420 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -6,7 +6,7 @@
 	bool "Networking support"
 	select NLATTR
 	select GENERIC_NET_UTILS
-	select BPF
+	select ANON_INODES
 	---help---
 	  Unless you really know what you are doing, you should say Y here.
 	  The reason is that some programs need kernel networking support even
@@ -228,7 +228,6 @@
 source "net/netlink/Kconfig"
 source "net/mpls/Kconfig"
 source "net/hsr/Kconfig"
-source "net/switchdev/Kconfig"
 
 config RPS
 	boolean
diff --git a/net/Makefile b/net/Makefile
index 76f0349..23a0b60 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -5,6 +5,8 @@
 # Rewritten to use lists instead of if-statements.
 #
 
+obj-y	:= nonet.o
+
 obj-$(CONFIG_NET)		:= socket.o core/
 
 tmp-$(CONFIG_COMPAT) 		:= compat.o
@@ -55,7 +57,7 @@
 ifneq ($(CONFIG_DCB),)
 obj-y				+= dcb/
 endif
-obj-$(CPTCFG_6LOWPAN)		+= 6lowpan/
+obj-$(CONFIG_6LOWPAN)		+= 6lowpan/
 obj-$(CPTCFG_IEEE802154)	+= ieee802154/
 obj-$(CPTCFG_MAC802154)		+= mac802154/
 
@@ -71,6 +73,3 @@
 obj-$(CONFIG_VSOCKETS)	+= vmw_vsock/
 obj-$(CONFIG_NET_MPLS_GSO)	+= mpls/
 obj-$(CONFIG_HSR)		+= hsr/
-ifneq ($(CONFIG_NET_SWITCHDEV),)
-obj-y				+= switchdev/
-endif
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 8ea2d68..c2e0d14 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -18,7 +18,6 @@
 #include <linux/debugfs.h>
 
 #include <net/ipv6.h>
-#include <net/ip6_fib.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
 
@@ -54,7 +53,7 @@
  * The list contains struct lowpan_dev elements.
  */
 static LIST_HEAD(bt_6lowpan_devices);
-static DEFINE_SPINLOCK(devices_lock);
+static DEFINE_RWLOCK(devices_lock);
 
 /* If psm is set to 0 (default value), then 6lowpan is disabled.
  * Other values are used to indicate a Protocol Service Multiplexer
@@ -68,7 +67,6 @@
 
 struct lowpan_peer {
 	struct list_head list;
-	struct rcu_head rcu;
 	struct l2cap_chan *chan;
 
 	/* peer addresses in various formats */
@@ -95,14 +93,13 @@
 
 static inline void peer_add(struct lowpan_dev *dev, struct lowpan_peer *peer)
 {
-	list_add_rcu(&peer->list, &dev->peers);
+	list_add(&peer->list, &dev->peers);
 	atomic_inc(&dev->peer_count);
 }
 
 static inline bool peer_del(struct lowpan_dev *dev, struct lowpan_peer *peer)
 {
-	list_del_rcu(&peer->list);
-	kfree_rcu(peer, rcu);
+	list_del(&peer->list);
 
 	module_put(THIS_MODULE);
 
@@ -117,37 +114,31 @@
 static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_dev *dev,
 						 bdaddr_t *ba, __u8 type)
 {
-	struct lowpan_peer *peer;
+	struct lowpan_peer *peer, *tmp;
 
 	BT_DBG("peers %d addr %pMR type %d", atomic_read(&dev->peer_count),
 	       ba, type);
 
-	rcu_read_lock();
-
-	list_for_each_entry_rcu(peer, &dev->peers, list) {
+	list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
 		BT_DBG("dst addr %pMR dst type %d",
 		       &peer->chan->dst, peer->chan->dst_type);
 
 		if (bacmp(&peer->chan->dst, ba))
 			continue;
 
-		if (type == peer->chan->dst_type) {
-			rcu_read_unlock();
+		if (type == peer->chan->dst_type)
 			return peer;
-		}
 	}
 
-	rcu_read_unlock();
-
 	return NULL;
 }
 
-static inline struct lowpan_peer *__peer_lookup_chan(struct lowpan_dev *dev,
-						     struct l2cap_chan *chan)
+static inline struct lowpan_peer *peer_lookup_chan(struct lowpan_dev *dev,
+						   struct l2cap_chan *chan)
 {
-	struct lowpan_peer *peer;
+	struct lowpan_peer *peer, *tmp;
 
-	list_for_each_entry_rcu(peer, &dev->peers, list) {
+	list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
 		if (peer->chan == chan)
 			return peer;
 	}
@@ -155,12 +146,12 @@
 	return NULL;
 }
 
-static inline struct lowpan_peer *__peer_lookup_conn(struct lowpan_dev *dev,
-						     struct l2cap_conn *conn)
+static inline struct lowpan_peer *peer_lookup_conn(struct lowpan_dev *dev,
+						   struct l2cap_conn *conn)
 {
-	struct lowpan_peer *peer;
+	struct lowpan_peer *peer, *tmp;
 
-	list_for_each_entry_rcu(peer, &dev->peers, list) {
+	list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
 		if (peer->chan->conn == conn)
 			return peer;
 	}
@@ -172,7 +163,7 @@
 						  struct in6_addr *daddr,
 						  struct sk_buff *skb)
 {
-	struct lowpan_peer *peer;
+	struct lowpan_peer *peer, *tmp;
 	struct in6_addr *nexthop;
 	struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
 	int count = atomic_read(&dev->peer_count);
@@ -183,13 +174,9 @@
 	 * send the packet. If only one peer exists, then we can send the
 	 * packet right away.
 	 */
-	if (count == 1) {
-		rcu_read_lock();
-		peer = list_first_or_null_rcu(&dev->peers, struct lowpan_peer,
-					      list);
-		rcu_read_unlock();
-		return peer;
-	}
+	if (count == 1)
+		return list_first_entry(&dev->peers, struct lowpan_peer,
+					list);
 
 	if (!rt) {
 		nexthop = &lowpan_cb(skb)->gw;
@@ -208,57 +195,53 @@
 
 	BT_DBG("gw %pI6c", nexthop);
 
-	rcu_read_lock();
-
-	list_for_each_entry_rcu(peer, &dev->peers, list) {
+	list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
 		BT_DBG("dst addr %pMR dst type %d ip %pI6c",
 		       &peer->chan->dst, peer->chan->dst_type,
 		       &peer->peer_addr);
 
-		if (!ipv6_addr_cmp(&peer->peer_addr, nexthop)) {
-			rcu_read_unlock();
+		if (!ipv6_addr_cmp(&peer->peer_addr, nexthop))
 			return peer;
-		}
 	}
 
-	rcu_read_unlock();
-
 	return NULL;
 }
 
 static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn)
 {
-	struct lowpan_dev *entry;
+	struct lowpan_dev *entry, *tmp;
 	struct lowpan_peer *peer = NULL;
+	unsigned long flags;
 
-	rcu_read_lock();
+	read_lock_irqsave(&devices_lock, flags);
 
-	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
-		peer = __peer_lookup_conn(entry, conn);
+	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+		peer = peer_lookup_conn(entry, conn);
 		if (peer)
 			break;
 	}
 
-	rcu_read_unlock();
+	read_unlock_irqrestore(&devices_lock, flags);
 
 	return peer;
 }
 
 static struct lowpan_dev *lookup_dev(struct l2cap_conn *conn)
 {
-	struct lowpan_dev *entry;
+	struct lowpan_dev *entry, *tmp;
 	struct lowpan_dev *dev = NULL;
+	unsigned long flags;
 
-	rcu_read_lock();
+	read_lock_irqsave(&devices_lock, flags);
 
-	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
+	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
 		if (conn->hcon->hdev == entry->hdev) {
 			dev = entry;
 			break;
 		}
 	}
 
-	rcu_read_unlock();
+	read_unlock_irqrestore(&devices_lock, flags);
 
 	return dev;
 }
@@ -266,49 +249,59 @@
 static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sk_buff *skb_cp;
+	int ret;
 
 	skb_cp = skb_copy(skb, GFP_ATOMIC);
 	if (!skb_cp)
-		return NET_RX_DROP;
+		return -ENOMEM;
 
-	return netif_rx(skb_cp);
+	ret = netif_rx(skb_cp);
+	if (ret < 0) {
+		BT_DBG("receive skb %d", ret);
+		return NET_RX_DROP;
+	}
+
+	return ret;
 }
 
-static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
-			   struct l2cap_chan *chan)
+static int process_data(struct sk_buff *skb, struct net_device *netdev,
+			struct l2cap_chan *chan)
 {
 	const u8 *saddr, *daddr;
 	u8 iphc0, iphc1;
 	struct lowpan_dev *dev;
 	struct lowpan_peer *peer;
+	unsigned long flags;
 
 	dev = lowpan_dev(netdev);
 
-	rcu_read_lock();
-	peer = __peer_lookup_chan(dev, chan);
-	rcu_read_unlock();
+	read_lock_irqsave(&devices_lock, flags);
+	peer = peer_lookup_chan(dev, chan);
+	read_unlock_irqrestore(&devices_lock, flags);
 	if (!peer)
-		return -EINVAL;
+		goto drop;
 
 	saddr = peer->eui64_addr;
 	daddr = dev->netdev->dev_addr;
 
 	/* at least two bytes will be used for the encoding */
 	if (skb->len < 2)
-		return -EINVAL;
+		goto drop;
 
 	if (lowpan_fetch_skb_u8(skb, &iphc0))
-		return -EINVAL;
+		goto drop;
 
 	if (lowpan_fetch_skb_u8(skb, &iphc1))
-		return -EINVAL;
+		goto drop;
 
-	return lowpan_header_decompress(skb, netdev,
-					saddr, IEEE802154_ADDR_LONG,
-					EUI64_ADDR_LEN, daddr,
-					IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
-					iphc0, iphc1);
+	return lowpan_process_data(skb, netdev,
+				   saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+				   daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+				   iphc0, iphc1, give_skb_to_upper);
 
+drop:
+	kfree_skb(skb);
+	return -EINVAL;
 }
 
 static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
@@ -323,10 +316,6 @@
 	if (dev->type != ARPHRD_6LOWPAN)
 		goto drop;
 
-	skb = skb_share_check(skb, GFP_ATOMIC);
-	if (!skb)
-		goto drop;
-
 	/* check that it's our buffer */
 	if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
 		/* Copy the packet so that the IPv6 header is
@@ -351,8 +340,8 @@
 		dev->stats.rx_bytes += skb->len;
 		dev->stats.rx_packets++;
 
-		consume_skb(local_skb);
-		consume_skb(skb);
+		kfree_skb(local_skb);
+		kfree_skb(skb);
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
@@ -360,27 +349,14 @@
 			if (!local_skb)
 				goto drop;
 
-			ret = iphc_decompress(local_skb, dev, chan);
-			if (ret < 0) {
-				kfree_skb(local_skb);
+			ret = process_data(local_skb, dev, chan);
+			if (ret != NET_RX_SUCCESS)
 				goto drop;
-			}
-
-			local_skb->protocol = htons(ETH_P_IPV6);
-			local_skb->pkt_type = PACKET_HOST;
-			local_skb->dev = dev;
-
-			if (give_skb_to_upper(local_skb, dev)
-					!= NET_RX_SUCCESS) {
-				kfree_skb(local_skb);
-				goto drop;
-			}
 
 			dev->stats.rx_bytes += skb->len;
 			dev->stats.rx_packets++;
 
-			consume_skb(local_skb);
-			consume_skb(skb);
+			kfree_skb(skb);
 			break;
 		default:
 			break;
@@ -467,6 +443,7 @@
 	if (ipv6_addr_is_multicast(&ipv6_daddr)) {
 		lowpan_cb(skb)->chan = NULL;
 	} else {
+		unsigned long flags;
 		u8 addr_type;
 
 		/* Get destination BT device from skb.
@@ -477,14 +454,19 @@
 		BT_DBG("dest addr %pMR type %d IP %pI6c", &addr,
 		       addr_type, &ipv6_daddr);
 
+		read_lock_irqsave(&devices_lock, flags);
 		peer = peer_lookup_ba(dev, &addr, addr_type);
+		read_unlock_irqrestore(&devices_lock, flags);
+
 		if (!peer) {
 			/* The packet might be sent to 6lowpan interface
 			 * because of routing (either via default route
 			 * or user set route) so get peer according to
 			 * the destination address.
 			 */
+			read_lock_irqsave(&devices_lock, flags);
 			peer = peer_lookup_dst(dev, &ipv6_daddr, skb);
+			read_unlock_irqrestore(&devices_lock, flags);
 			if (!peer) {
 				BT_DBG("no such peer %pMR found", &addr);
 				return -ENOENT;
@@ -538,19 +520,12 @@
 	 */
 	chan->data = skb;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
 	memset(&msg, 0, sizeof(msg));
 	msg.msg_iov = (struct iovec *) &iv;
 	msg.msg_iovlen = 1;
-#endif
 	iv.iov_base = skb->data;
 	iv.iov_len = skb->len;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-	memset(&msg, 0, sizeof(msg));
-	iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, skb->len);
-#endif
-
 	err = l2cap_chan_send(chan, &msg, skb->len);
 	if (err > 0) {
 		netdev->stats.tx_bytes += err;
@@ -574,13 +549,14 @@
 static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct sk_buff *local_skb;
-	struct lowpan_dev *entry;
+	struct lowpan_dev *entry, *tmp;
+	unsigned long flags;
 	int err = 0;
 
-	rcu_read_lock();
+	read_lock_irqsave(&devices_lock, flags);
 
-	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
-		struct lowpan_peer *pentry;
+	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+		struct lowpan_peer *pentry, *ptmp;
 		struct lowpan_dev *dev;
 
 		if (entry->netdev != netdev)
@@ -588,7 +564,7 @@
 
 		dev = lowpan_dev(entry->netdev);
 
-		list_for_each_entry_rcu(pentry, &dev->peers, list) {
+		list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) {
 			int ret;
 
 			local_skb = skb_clone(skb, GFP_ATOMIC);
@@ -605,7 +581,7 @@
 		}
 	}
 
-	rcu_read_unlock();
+	read_unlock_irqrestore(&devices_lock, flags);
 
 	return err;
 }
@@ -615,13 +591,17 @@
 	int err = 0;
 	bdaddr_t addr;
 	u8 addr_type;
+	struct sk_buff *tmpskb;
 
 	/* We must take a copy of the skb before we modify/replace the ipv6
 	 * header as the header could be used elsewhere
 	 */
-	skb = skb_unshare(skb, GFP_ATOMIC);
-	if (!skb)
+	tmpskb = skb_unshare(skb, GFP_ATOMIC);
+	if (!tmpskb) {
+		kfree_skb(skb);
 		return NET_XMIT_DROP;
+	}
+	skb = tmpskb;
 
 	/* Return values from setup_header()
 	 *  <0 - error, packet is dropped
@@ -658,28 +638,7 @@
 	return err < 0 ? NET_XMIT_DROP : err;
 }
 
-static struct lock_class_key bt_tx_busylock;
-static struct lock_class_key bt_netdev_xmit_lock_key;
-
-static void bt_set_lockdep_class_one(struct net_device *dev,
-				     struct netdev_queue *txq,
-				     void *_unused)
-{
-	lockdep_set_class(&txq->_xmit_lock, &bt_netdev_xmit_lock_key);
-}
-
-static int bt_dev_init(struct net_device *dev)
-{
-	netdev_for_each_tx_queue(dev, bt_set_lockdep_class_one, NULL);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
-	dev->qdisc_tx_busylock = &bt_tx_busylock;
-#endif
-
-	return 0;
-}
-
 static const struct net_device_ops netdev_ops = {
-	.ndo_init		= bt_dev_init,
 	.ndo_start_xmit		= bt_xmit,
 };
 
@@ -824,6 +783,7 @@
 					struct lowpan_dev *dev)
 {
 	struct lowpan_peer *peer;
+	unsigned long flags;
 
 	peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
 	if (!peer)
@@ -846,10 +806,10 @@
 	 */
 	set_ip_addr_bits(chan->dst_type, (u8 *)&peer->peer_addr.s6_addr + 8);
 
-	spin_lock(&devices_lock);
+	write_lock_irqsave(&devices_lock, flags);
 	INIT_LIST_HEAD(&peer->list);
 	peer_add(dev, peer);
-	spin_unlock(&devices_lock);
+	write_unlock_irqrestore(&devices_lock, flags);
 
 	/* Notifying peers about us needs to be done without locks held */
 	INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers);
@@ -862,6 +822,7 @@
 {
 	struct net_device *netdev;
 	int err = 0;
+	unsigned long flags;
 
 	netdev = alloc_netdev(sizeof(struct lowpan_dev), IFACE_NAME_TEMPLATE,
 			      NET_NAME_UNKNOWN, netdev_setup);
@@ -891,10 +852,10 @@
 	(*dev)->hdev = chan->conn->hcon->hdev;
 	INIT_LIST_HEAD(&(*dev)->peers);
 
-	spin_lock(&devices_lock);
+	write_lock_irqsave(&devices_lock, flags);
 	INIT_LIST_HEAD(&(*dev)->list);
-	list_add_rcu(&(*dev)->list, &bt_6lowpan_devices);
-	spin_unlock(&devices_lock);
+	list_add(&(*dev)->list, &bt_6lowpan_devices);
+	write_unlock_irqrestore(&devices_lock, flags);
 
 	return 0;
 
@@ -948,10 +909,11 @@
 
 static void chan_close_cb(struct l2cap_chan *chan)
 {
-	struct lowpan_dev *entry;
+	struct lowpan_dev *entry, *tmp;
 	struct lowpan_dev *dev = NULL;
 	struct lowpan_peer *peer;
 	int err = -ENOENT;
+	unsigned long flags;
 	bool last = false, removed = true;
 
 	BT_DBG("chan %p conn %p", chan, chan->conn);
@@ -966,11 +928,11 @@
 		removed = false;
 	}
 
-	spin_lock(&devices_lock);
+	write_lock_irqsave(&devices_lock, flags);
 
-	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
+	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
 		dev = lowpan_dev(entry->netdev);
-		peer = __peer_lookup_chan(dev, chan);
+		peer = peer_lookup_chan(dev, chan);
 		if (peer) {
 			last = peer_del(dev, peer);
 			err = 0;
@@ -981,12 +943,13 @@
 			       atomic_read(&chan->kref.refcount));
 
 			l2cap_chan_put(chan);
+			kfree(peer);
 			break;
 		}
 	}
 
 	if (!err && last && dev && !atomic_read(&dev->peer_count)) {
-		spin_unlock(&devices_lock);
+		write_unlock_irqrestore(&devices_lock, flags);
 
 		cancel_delayed_work_sync(&dev->notify_peers);
 
@@ -997,7 +960,7 @@
 			schedule_work(&entry->delete_netdev);
 		}
 	} else {
-		spin_unlock(&devices_lock);
+		write_unlock_irqrestore(&devices_lock, flags);
 	}
 
 	return;
@@ -1140,8 +1103,6 @@
 	pchan->state = BT_LISTEN;
 	pchan->src_type = BDADDR_LE_PUBLIC;
 
-	atomic_set(&pchan->nesting, L2CAP_NESTING_PARENT);
-
 	BT_DBG("psm 0x%04x chan %p src type %d", psm_6lowpan, pchan,
 	       pchan->src_type);
 
@@ -1191,9 +1152,10 @@
 
 static void disconnect_all_peers(void)
 {
-	struct lowpan_dev *entry;
+	struct lowpan_dev *entry, *tmp_dev;
 	struct lowpan_peer *peer, *tmp_peer, *new_peer;
 	struct list_head peers;
+	unsigned long flags;
 
 	INIT_LIST_HEAD(&peers);
 
@@ -1202,10 +1164,10 @@
 	 * with the same list at the same time.
 	 */
 
-	rcu_read_lock();
+	read_lock_irqsave(&devices_lock, flags);
 
-	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
-		list_for_each_entry_rcu(peer, &entry->peers, list) {
+	list_for_each_entry_safe(entry, tmp_dev, &bt_6lowpan_devices, list) {
+		list_for_each_entry_safe(peer, tmp_peer, &entry->peers, list) {
 			new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC);
 			if (!new_peer)
 				break;
@@ -1217,36 +1179,26 @@
 		}
 	}
 
-	rcu_read_unlock();
+	read_unlock_irqrestore(&devices_lock, flags);
 
-	spin_lock(&devices_lock);
 	list_for_each_entry_safe(peer, tmp_peer, &peers, list) {
 		l2cap_chan_close(peer->chan, ENOENT);
-
-		list_del_rcu(&peer->list);
-		kfree_rcu(peer, rcu);
-
-		module_put(THIS_MODULE);
+		kfree(peer);
 	}
-	spin_unlock(&devices_lock);
 }
 
-struct set_psm {
-	struct work_struct work;
-	u16 psm;
-};
-
-static void do_psm_set(struct work_struct *work)
+static int lowpan_psm_set(void *data, u64 val)
 {
-	struct set_psm *set_psm = container_of(work, struct set_psm, work);
+	u16 psm;
 
-	if (set_psm->psm == 0 || psm_6lowpan != set_psm->psm)
+	psm = val;
+	if (psm == 0 || psm_6lowpan != psm)
 		/* Disconnect existing connections if 6lowpan is
 		 * disabled (psm = 0), or if psm changes.
 		 */
 		disconnect_all_peers();
 
-	psm_6lowpan = set_psm->psm;
+	psm_6lowpan = psm;
 
 	if (listen_chan) {
 		l2cap_chan_close(listen_chan, 0);
@@ -1255,22 +1207,6 @@
 
 	listen_chan = bt_6lowpan_listen();
 
-	kfree(set_psm);
-}
-
-static int lowpan_psm_set(void *data, u64 val)
-{
-	struct set_psm *set_psm;
-
-	set_psm = kzalloc(sizeof(*set_psm), GFP_KERNEL);
-	if (!set_psm)
-		return -ENOMEM;
-
-	set_psm->psm = val;
-	INIT_WORK(&set_psm->work, do_psm_set);
-
-	schedule_work(&set_psm->work);
-
 	return 0;
 }
 
@@ -1352,18 +1288,19 @@
 
 static int lowpan_control_show(struct seq_file *f, void *ptr)
 {
-	struct lowpan_dev *entry;
-	struct lowpan_peer *peer;
+	struct lowpan_dev *entry, *tmp_dev;
+	struct lowpan_peer *peer, *tmp_peer;
+	unsigned long flags;
 
-	spin_lock(&devices_lock);
+	read_lock_irqsave(&devices_lock, flags);
 
-	list_for_each_entry(entry, &bt_6lowpan_devices, list) {
-		list_for_each_entry(peer, &entry->peers, list)
+	list_for_each_entry_safe(entry, tmp_dev, &bt_6lowpan_devices, list) {
+		list_for_each_entry_safe(peer, tmp_peer, &entry->peers, list)
 			seq_printf(f, "%pMR (type %u)\n",
 				   &peer->chan->dst, peer->chan->dst_type);
 	}
 
-	spin_unlock(&devices_lock);
+	read_unlock_irqrestore(&devices_lock, flags);
 
 	return 0;
 }
@@ -1385,6 +1322,7 @@
 {
 	struct lowpan_dev *entry, *tmp, *new_dev;
 	struct list_head devices;
+	unsigned long flags;
 
 	INIT_LIST_HEAD(&devices);
 
@@ -1393,9 +1331,9 @@
 	 * devices list.
 	 */
 
-	rcu_read_lock();
+	read_lock_irqsave(&devices_lock, flags);
 
-	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
+	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
 		new_dev = kmalloc(sizeof(*new_dev), GFP_ATOMIC);
 		if (!new_dev)
 			break;
@@ -1403,10 +1341,10 @@
 		new_dev->netdev = entry->netdev;
 		INIT_LIST_HEAD(&new_dev->list);
 
-		list_add_rcu(&new_dev->list, &devices);
+		list_add(&new_dev->list, &devices);
 	}
 
-	rcu_read_unlock();
+	read_unlock_irqrestore(&devices_lock, flags);
 
 	list_for_each_entry_safe(entry, tmp, &devices, list) {
 		ifdown(entry->netdev);
@@ -1421,15 +1359,17 @@
 			unsigned long event, void *ptr)
 {
 	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
-	struct lowpan_dev *entry;
+	struct lowpan_dev *entry, *tmp;
+	unsigned long flags;
 
 	if (netdev->type != ARPHRD_6LOWPAN)
 		return NOTIFY_DONE;
 
 	switch (event) {
 	case NETDEV_UNREGISTER:
-		spin_lock(&devices_lock);
-		list_for_each_entry(entry, &bt_6lowpan_devices, list) {
+		write_lock_irqsave(&devices_lock, flags);
+		list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
+					 list) {
 			if (entry->netdev == netdev) {
 				BT_DBG("Unregistered netdev %s %p",
 				       netdev->name, netdev);
@@ -1438,7 +1378,7 @@
 				break;
 			}
 		}
-		spin_unlock(&devices_lock);
+		write_unlock_irqrestore(&devices_lock, flags);
 		break;
 	}
 
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index a68caf3..b5df2e3 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -11,7 +11,6 @@
 	depends on CRYPTO
 	depends on CRYPTO_BLKCIPHER
 	depends on CRYPTO_AES
-	depends on CRYPTO_CMAC
 	depends on CRYPTO_ECB
 	depends on CRYPTO_SHA256
 	help
@@ -41,10 +40,12 @@
 	  to Bluetooth kernel modules are provided in the BlueZ packages.  For
 	  more information, see <http://www.bluez.org/>.
 
-config BT_BREDR
-	bool "Bluetooth Classic (BR/EDR) features"
-	depends on BT
-	default y
+config BT_6LOWPAN
+	tristate "Bluetooth 6LoWPAN support"
+	depends on m
+	depends on BT && 6LOWPAN
+	help
+	  IPv6 compression over Bluetooth Low Energy.
 
 source "net/bluetooth/rfcomm/Kconfig"
 
@@ -54,16 +55,4 @@
 
 source "net/bluetooth/hidp/Kconfig"
 
-config BT_LE
-	bool "Bluetooth Low Energy (LE) features"
-	depends on BT
-	default y
-
-config BT_6LOWPAN
-	tristate "Bluetooth 6LoWPAN support"
-	depends on m
-	depends on BT_LE && 6LOWPAN
-	help
-	  IPv6 compression over Bluetooth Low Energy.
-
 source "drivers/bluetooth/Kconfig"
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index e3474dd..cb87c99 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -13,6 +13,6 @@
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
 	hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
-	a2mp.o amp.o ecc.o
+	a2mp.o amp.o
 
 subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 6fcb9bf..5dcade5 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -60,12 +60,8 @@
 
 	memset(&msg, 0, sizeof(msg));
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-	iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, total_len);
-#else
 	msg.msg_iov = (struct iovec *) &iv;
 	msg.msg_iovlen = 1;
-#endif
 
 	l2cap_chan_send(chan, &msg, total_len);
 
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 012e3b0..339c74a 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -31,7 +31,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <linux/proc_fs.h>
 
-#define VERSION "2.20"
+#define VERSION "2.19"
 
 /* Bluetooth sockets */
 #define BT_MAX_PROTO	8
@@ -237,7 +237,7 @@
 	}
 
 	skb_reset_transport_header(skb);
-	err = skb_copy_datagram_msg(skb, 0, msg, copied);
+	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 	if (err == 0) {
 		sock_recv_ts_and_drops(msg, sk, skb);
 
@@ -328,7 +328,7 @@
 		}
 
 		chunk = min_t(unsigned int, skb->len, size);
-		if (skb_copy_datagram_msg(skb, 0, msg, chunk)) {
+		if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
 			skb_queue_head(&sk->sk_receive_queue, skb);
 			if (!copied)
 				copied = -EFAULT;
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index ee016f0..2640d78 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -134,7 +134,6 @@
 static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
 {
 	struct crypto_shash *tfm;
-	struct shash_desc *shash;
 	int ret;
 
 	if (!ksize)
@@ -149,24 +148,18 @@
 	ret = crypto_shash_setkey(tfm, key, ksize);
 	if (ret) {
 		BT_DBG("crypto_ahash_setkey failed: err %d", ret);
-		goto failed;
+	} else {
+		char desc[sizeof(struct shash_desc) +
+			crypto_shash_descsize(tfm)] CRYPTO_MINALIGN_ATTR;
+		struct shash_desc *shash = (struct shash_desc *)desc;
+
+		shash->tfm = tfm;
+		shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+		ret = crypto_shash_digest(shash, plaintext, psize,
+					  output);
 	}
 
-	shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
-			GFP_KERNEL);
-	if (!shash) {
-		ret = -ENOMEM;
-		goto failed;
-	}
-
-	shash->tfm = tfm;
-	shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-
-	ret = crypto_shash_digest(shash, plaintext, psize, output);
-
-	kfree(shash);
-
-failed:
 	crypto_free_shash(tfm);
 	return ret;
 }
diff --git a/net/bluetooth/bnep/Kconfig b/net/bluetooth/bnep/Kconfig
index 64ffb40..7ca2e1c 100644
--- a/net/bluetooth/bnep/Kconfig
+++ b/net/bluetooth/bnep/Kconfig
@@ -1,7 +1,7 @@
 config BT_BNEP
 	tristate "BNEP protocol support"
 	depends on m
-	depends on BT_BREDR
+	depends on BT
 	depends on CRC32
 	help
 	  BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet
diff --git a/net/bluetooth/cmtp/Kconfig b/net/bluetooth/cmtp/Kconfig
index 7acd7ea..accf52d 100644
--- a/net/bluetooth/cmtp/Kconfig
+++ b/net/bluetooth/cmtp/Kconfig
@@ -1,7 +1,7 @@
 config BT_CMTP
 	tristate "CMTP protocol support"
 	depends on m
-	depends on BT_BREDR && ISDN_CAPI
+	depends on BT && ISDN_CAPI
 	help
 	  CMTP (CAPI Message Transport Protocol) is a transport layer
 	  for CAPI messages.  CMTP is required for the Bluetooth Common
diff --git a/net/bluetooth/ecc.c b/net/bluetooth/ecc.c
deleted file mode 100644
index e1709f8..0000000
--- a/net/bluetooth/ecc.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
- * Copyright (c) 2013, Kenneth MacKay
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *  * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/random.h>
-
-#include "ecc.h"
-
-/* 256-bit curve */
-#define ECC_BYTES 32
-
-#define MAX_TRIES 16
-
-/* Number of u64's needed */
-#define NUM_ECC_DIGITS (ECC_BYTES / 8)
-
-struct ecc_point {
-	u64 x[NUM_ECC_DIGITS];
-	u64 y[NUM_ECC_DIGITS];
-};
-
-typedef struct {
-	u64 m_low;
-	u64 m_high;
-} uint128_t;
-
-#define CURVE_P_32 {	0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull, \
-			0x0000000000000000ull, 0xFFFFFFFF00000001ull }
-
-#define CURVE_G_32 { \
-		{	0xF4A13945D898C296ull, 0x77037D812DEB33A0ull,	\
-			0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull }, \
-		{	0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull,	\
-			0x8EE7EB4A7C0F9E16ull, 0x4FE342E2FE1A7F9Bull }	\
-}
-
-#define CURVE_N_32 {	0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull,	\
-			0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull }
-
-static u64 curve_p[NUM_ECC_DIGITS] = CURVE_P_32;
-static struct ecc_point curve_g = CURVE_G_32;
-static u64 curve_n[NUM_ECC_DIGITS] = CURVE_N_32;
-
-static void vli_clear(u64 *vli)
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++)
-		vli[i] = 0;
-}
-
-/* Returns true if vli == 0, false otherwise. */
-static bool vli_is_zero(const u64 *vli)
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		if (vli[i])
-			return false;
-	}
-
-	return true;
-}
-
-/* Returns nonzero if bit bit of vli is set. */
-static u64 vli_test_bit(const u64 *vli, unsigned int bit)
-{
-	return (vli[bit / 64] & ((u64) 1 << (bit % 64)));
-}
-
-/* Counts the number of 64-bit "digits" in vli. */
-static unsigned int vli_num_digits(const u64 *vli)
-{
-	int i;
-
-	/* Search from the end until we find a non-zero digit.
-	 * We do it in reverse because we expect that most digits will
-	 * be nonzero.
-	 */
-	for (i = NUM_ECC_DIGITS - 1; i >= 0 && vli[i] == 0; i--);
-
-	return (i + 1);
-}
-
-/* Counts the number of bits required for vli. */
-static unsigned int vli_num_bits(const u64 *vli)
-{
-	unsigned int i, num_digits;
-	u64 digit;
-
-	num_digits = vli_num_digits(vli);
-	if (num_digits == 0)
-		return 0;
-
-	digit = vli[num_digits - 1];
-	for (i = 0; digit; i++)
-		digit >>= 1;
-
-	return ((num_digits - 1) * 64 + i);
-}
-
-/* Sets dest = src. */
-static void vli_set(u64 *dest, const u64 *src)
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++)
-		dest[i] = src[i];
-}
-
-/* Returns sign of left - right. */
-static int vli_cmp(const u64 *left, const u64 *right)
-{
-    int i;
-
-    for (i = NUM_ECC_DIGITS - 1; i >= 0; i--) {
-	    if (left[i] > right[i])
-		    return 1;
-	    else if (left[i] < right[i])
-		    return -1;
-    }
-
-    return 0;
-}
-
-/* Computes result = in << c, returning carry. Can modify in place
- * (if result == in). 0 < shift < 64.
- */
-static u64 vli_lshift(u64 *result, const u64 *in,
-			   unsigned int shift)
-{
-	u64 carry = 0;
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		u64 temp = in[i];
-
-		result[i] = (temp << shift) | carry;
-		carry = temp >> (64 - shift);
-	}
-
-	return carry;
-}
-
-/* Computes vli = vli >> 1. */
-static void vli_rshift1(u64 *vli)
-{
-	u64 *end = vli;
-	u64 carry = 0;
-
-	vli += NUM_ECC_DIGITS;
-
-	while (vli-- > end) {
-		u64 temp = *vli;
-		*vli = (temp >> 1) | carry;
-		carry = temp << 63;
-	}
-}
-
-/* Computes result = left + right, returning carry. Can modify in place. */
-static u64 vli_add(u64 *result, const u64 *left,
-			const u64 *right)
-{
-	u64 carry = 0;
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		u64 sum;
-
-		sum = left[i] + right[i] + carry;
-		if (sum != left[i])
-			carry = (sum < left[i]);
-
-		result[i] = sum;
-	}
-
-	return carry;
-}
-
-/* Computes result = left - right, returning borrow. Can modify in place. */
-static u64 vli_sub(u64 *result, const u64 *left, const u64 *right)
-{
-	u64 borrow = 0;
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		u64 diff;
-
-		diff = left[i] - right[i] - borrow;
-		if (diff != left[i])
-			borrow = (diff > left[i]);
-
-		result[i] = diff;
-	}
-
-	return borrow;
-}
-
-static uint128_t mul_64_64(u64 left, u64 right)
-{
-	u64 a0 = left & 0xffffffffull;
-	u64 a1 = left >> 32;
-	u64 b0 = right & 0xffffffffull;
-	u64 b1 = right >> 32;
-	u64 m0 = a0 * b0;
-	u64 m1 = a0 * b1;
-	u64 m2 = a1 * b0;
-	u64 m3 = a1 * b1;
-	uint128_t result;
-
-	m2 += (m0 >> 32);
-	m2 += m1;
-
-	/* Overflow */
-	if (m2 < m1)
-		m3 += 0x100000000ull;
-
-	result.m_low = (m0 & 0xffffffffull) | (m2 << 32);
-	result.m_high = m3 + (m2 >> 32);
-
-	return result;
-}
-
-static uint128_t add_128_128(uint128_t a, uint128_t b)
-{
-	uint128_t result;
-
-	result.m_low = a.m_low + b.m_low;
-	result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low);
-
-	return result;
-}
-
-static void vli_mult(u64 *result, const u64 *left, const u64 *right)
-{
-	uint128_t r01 = { 0, 0 };
-	u64 r2 = 0;
-	unsigned int i, k;
-
-	/* Compute each digit of result in sequence, maintaining the
-	 * carries.
-	 */
-	for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
-		unsigned int min;
-
-		if (k < NUM_ECC_DIGITS)
-			min = 0;
-		else
-			min = (k + 1) - NUM_ECC_DIGITS;
-
-		for (i = min; i <= k && i < NUM_ECC_DIGITS; i++) {
-			uint128_t product;
-
-			product = mul_64_64(left[i], right[k - i]);
-
-			r01 = add_128_128(r01, product);
-			r2 += (r01.m_high < product.m_high);
-		}
-
-		result[k] = r01.m_low;
-		r01.m_low = r01.m_high;
-		r01.m_high = r2;
-		r2 = 0;
-	}
-
-	result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
-}
-
-static void vli_square(u64 *result, const u64 *left)
-{
-	uint128_t r01 = { 0, 0 };
-	u64 r2 = 0;
-	int i, k;
-
-	for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
-		unsigned int min;
-
-		if (k < NUM_ECC_DIGITS)
-			min = 0;
-		else
-			min = (k + 1) - NUM_ECC_DIGITS;
-
-		for (i = min; i <= k && i <= k - i; i++) {
-			uint128_t product;
-
-			product = mul_64_64(left[i], left[k - i]);
-
-			if (i < k - i) {
-				r2 += product.m_high >> 63;
-				product.m_high = (product.m_high << 1) |
-						 (product.m_low >> 63);
-				product.m_low <<= 1;
-			}
-
-			r01 = add_128_128(r01, product);
-			r2 += (r01.m_high < product.m_high);
-		}
-
-		result[k] = r01.m_low;
-		r01.m_low = r01.m_high;
-		r01.m_high = r2;
-		r2 = 0;
-	}
-
-	result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
-}
-
-/* Computes result = (left + right) % mod.
- * Assumes that left < mod and right < mod, result != mod.
- */
-static void vli_mod_add(u64 *result, const u64 *left, const u64 *right,
-			const u64 *mod)
-{
-	u64 carry;
-
-	carry = vli_add(result, left, right);
-
-	/* result > mod (result = mod + remainder), so subtract mod to
-	 * get remainder.
-	 */
-	if (carry || vli_cmp(result, mod) >= 0)
-		vli_sub(result, result, mod);
-}
-
-/* Computes result = (left - right) % mod.
- * Assumes that left < mod and right < mod, result != mod.
- */
-static void vli_mod_sub(u64 *result, const u64 *left, const u64 *right,
-			const u64 *mod)
-{
-	u64 borrow = vli_sub(result, left, right);
-
-	/* In this case, p_result == -diff == (max int) - diff.
-	 * Since -x % d == d - x, we can get the correct result from
-	 * result + mod (with overflow).
-	 */
-	if (borrow)
-		vli_add(result, result, mod);
-}
-
-/* Computes result = product % curve_p
-   from http://www.nsa.gov/ia/_files/nist-routines.pdf */
-static void vli_mmod_fast(u64 *result, const u64 *product)
-{
-	u64 tmp[NUM_ECC_DIGITS];
-	int carry;
-
-	/* t */
-	vli_set(result, product);
-
-	/* s1 */
-	tmp[0] = 0;
-	tmp[1] = product[5] & 0xffffffff00000000ull;
-	tmp[2] = product[6];
-	tmp[3] = product[7];
-	carry = vli_lshift(tmp, tmp, 1);
-	carry += vli_add(result, result, tmp);
-
-	/* s2 */
-	tmp[1] = product[6] << 32;
-	tmp[2] = (product[6] >> 32) | (product[7] << 32);
-	tmp[3] = product[7] >> 32;
-	carry += vli_lshift(tmp, tmp, 1);
-	carry += vli_add(result, result, tmp);
-
-	/* s3 */
-	tmp[0] = product[4];
-	tmp[1] = product[5] & 0xffffffff;
-	tmp[2] = 0;
-	tmp[3] = product[7];
-	carry += vli_add(result, result, tmp);
-
-	/* s4 */
-	tmp[0] = (product[4] >> 32) | (product[5] << 32);
-	tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
-	tmp[2] = product[7];
-	tmp[3] = (product[6] >> 32) | (product[4] << 32);
-	carry += vli_add(result, result, tmp);
-
-	/* d1 */
-	tmp[0] = (product[5] >> 32) | (product[6] << 32);
-	tmp[1] = (product[6] >> 32);
-	tmp[2] = 0;
-	tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
-	carry -= vli_sub(result, result, tmp);
-
-	/* d2 */
-	tmp[0] = product[6];
-	tmp[1] = product[7];
-	tmp[2] = 0;
-	tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
-	carry -= vli_sub(result, result, tmp);
-
-	/* d3 */
-	tmp[0] = (product[6] >> 32) | (product[7] << 32);
-	tmp[1] = (product[7] >> 32) | (product[4] << 32);
-	tmp[2] = (product[4] >> 32) | (product[5] << 32);
-	tmp[3] = (product[6] << 32);
-	carry -= vli_sub(result, result, tmp);
-
-	/* d4 */
-	tmp[0] = product[7];
-	tmp[1] = product[4] & 0xffffffff00000000ull;
-	tmp[2] = product[5];
-	tmp[3] = product[6] & 0xffffffff00000000ull;
-	carry -= vli_sub(result, result, tmp);
-
-	if (carry < 0) {
-		do {
-			carry += vli_add(result, result, curve_p);
-		} while (carry < 0);
-	} else {
-		while (carry || vli_cmp(curve_p, result) != 1)
-			carry -= vli_sub(result, result, curve_p);
-	}
-}
-
-/* Computes result = (left * right) % curve_p. */
-static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right)
-{
-	u64 product[2 * NUM_ECC_DIGITS];
-
-	vli_mult(product, left, right);
-	vli_mmod_fast(result, product);
-}
-
-/* Computes result = left^2 % curve_p. */
-static void vli_mod_square_fast(u64 *result, const u64 *left)
-{
-	u64 product[2 * NUM_ECC_DIGITS];
-
-	vli_square(product, left);
-	vli_mmod_fast(result, product);
-}
-
-#define EVEN(vli) (!(vli[0] & 1))
-/* Computes result = (1 / p_input) % mod. All VLIs are the same size.
- * See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
- * https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
- */
-static void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod)
-{
-	u64 a[NUM_ECC_DIGITS], b[NUM_ECC_DIGITS];
-	u64 u[NUM_ECC_DIGITS], v[NUM_ECC_DIGITS];
-	u64 carry;
-	int cmp_result;
-
-	if (vli_is_zero(input)) {
-		vli_clear(result);
-		return;
-	}
-
-	vli_set(a, input);
-	vli_set(b, mod);
-	vli_clear(u);
-	u[0] = 1;
-	vli_clear(v);
-
-	while ((cmp_result = vli_cmp(a, b)) != 0) {
-		carry = 0;
-
-		if (EVEN(a)) {
-			vli_rshift1(a);
-
-			if (!EVEN(u))
-				carry = vli_add(u, u, mod);
-
-			vli_rshift1(u);
-			if (carry)
-				u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
-		} else if (EVEN(b)) {
-			vli_rshift1(b);
-
-			if (!EVEN(v))
-				carry = vli_add(v, v, mod);
-
-			vli_rshift1(v);
-			if (carry)
-				v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
-		} else if (cmp_result > 0) {
-			vli_sub(a, a, b);
-			vli_rshift1(a);
-
-			if (vli_cmp(u, v) < 0)
-				vli_add(u, u, mod);
-
-			vli_sub(u, u, v);
-			if (!EVEN(u))
-				carry = vli_add(u, u, mod);
-
-			vli_rshift1(u);
-			if (carry)
-				u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
-		} else {
-			vli_sub(b, b, a);
-			vli_rshift1(b);
-
-			if (vli_cmp(v, u) < 0)
-				vli_add(v, v, mod);
-
-			vli_sub(v, v, u);
-			if (!EVEN(v))
-				carry = vli_add(v, v, mod);
-
-			vli_rshift1(v);
-			if (carry)
-				v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
-		}
-	}
-
-	vli_set(result, u);
-}
-
-/* ------ Point operations ------ */
-
-/* Returns true if p_point is the point at infinity, false otherwise. */
-static bool ecc_point_is_zero(const struct ecc_point *point)
-{
-	return (vli_is_zero(point->x) && vli_is_zero(point->y));
-}
-
-/* Point multiplication algorithm using Montgomery's ladder with co-Z
- * coordinates. From http://eprint.iacr.org/2011/338.pdf
- */
-
-/* Double in place */
-static void ecc_point_double_jacobian(u64 *x1, u64 *y1, u64 *z1)
-{
-	/* t1 = x, t2 = y, t3 = z */
-	u64 t4[NUM_ECC_DIGITS];
-	u64 t5[NUM_ECC_DIGITS];
-
-	if (vli_is_zero(z1))
-		return;
-
-	vli_mod_square_fast(t4, y1);   /* t4 = y1^2 */
-	vli_mod_mult_fast(t5, x1, t4); /* t5 = x1*y1^2 = A */
-	vli_mod_square_fast(t4, t4);   /* t4 = y1^4 */
-	vli_mod_mult_fast(y1, y1, z1); /* t2 = y1*z1 = z3 */
-	vli_mod_square_fast(z1, z1);   /* t3 = z1^2 */
-
-	vli_mod_add(x1, x1, z1, curve_p); /* t1 = x1 + z1^2 */
-	vli_mod_add(z1, z1, z1, curve_p); /* t3 = 2*z1^2 */
-	vli_mod_sub(z1, x1, z1, curve_p); /* t3 = x1 - z1^2 */
-	vli_mod_mult_fast(x1, x1, z1);    /* t1 = x1^2 - z1^4 */
-
-	vli_mod_add(z1, x1, x1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
-	vli_mod_add(x1, x1, z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
-	if (vli_test_bit(x1, 0)) {
-		u64 carry = vli_add(x1, x1, curve_p);
-		vli_rshift1(x1);
-		x1[NUM_ECC_DIGITS - 1] |= carry << 63;
-	} else {
-		vli_rshift1(x1);
-	}
-	/* t1 = 3/2*(x1^2 - z1^4) = B */
-
-	vli_mod_square_fast(z1, x1);      /* t3 = B^2 */
-	vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - A */
-	vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
-	vli_mod_sub(t5, t5, z1, curve_p); /* t5 = A - x3 */
-	vli_mod_mult_fast(x1, x1, t5);    /* t1 = B * (A - x3) */
-	vli_mod_sub(t4, x1, t4, curve_p); /* t4 = B * (A - x3) - y1^4 = y3 */
-
-	vli_set(x1, z1);
-	vli_set(z1, y1);
-	vli_set(y1, t4);
-}
-
-/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
-static void apply_z(u64 *x1, u64 *y1, u64 *z)
-{
-	u64 t1[NUM_ECC_DIGITS];
-
-	vli_mod_square_fast(t1, z);    /* z^2 */
-	vli_mod_mult_fast(x1, x1, t1); /* x1 * z^2 */
-	vli_mod_mult_fast(t1, t1, z);  /* z^3 */
-	vli_mod_mult_fast(y1, y1, t1); /* y1 * z^3 */
-}
-
-/* P = (x1, y1) => 2P, (x2, y2) => P' */
-static void xycz_initial_double(u64 *x1, u64 *y1, u64 *x2, u64 *y2,
-				u64 *p_initial_z)
-{
-	u64 z[NUM_ECC_DIGITS];
-
-	vli_set(x2, x1);
-	vli_set(y2, y1);
-
-	vli_clear(z);
-	z[0] = 1;
-
-	if (p_initial_z)
-		vli_set(z, p_initial_z);
-
-	apply_z(x1, y1, z);
-
-	ecc_point_double_jacobian(x1, y1, z);
-
-	apply_z(x2, y2, z);
-}
-
-/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
- * Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
- * or P => P', Q => P + Q
- */
-static void xycz_add(u64 *x1, u64 *y1, u64 *x2, u64 *y2)
-{
-	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
-	u64 t5[NUM_ECC_DIGITS];
-
-	vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
-	vli_mod_square_fast(t5, t5);      /* t5 = (x2 - x1)^2 = A */
-	vli_mod_mult_fast(x1, x1, t5);    /* t1 = x1*A = B */
-	vli_mod_mult_fast(x2, x2, t5);    /* t3 = x2*A = C */
-	vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
-	vli_mod_square_fast(t5, y2);      /* t5 = (y2 - y1)^2 = D */
-
-	vli_mod_sub(t5, t5, x1, curve_p); /* t5 = D - B */
-	vli_mod_sub(t5, t5, x2, curve_p); /* t5 = D - B - C = x3 */
-	vli_mod_sub(x2, x2, x1, curve_p); /* t3 = C - B */
-	vli_mod_mult_fast(y1, y1, x2);    /* t2 = y1*(C - B) */
-	vli_mod_sub(x2, x1, t5, curve_p); /* t3 = B - x3 */
-	vli_mod_mult_fast(y2, y2, x2);    /* t4 = (y2 - y1)*(B - x3) */
-	vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
-
-	vli_set(x2, t5);
-}
-
-/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
- * Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
- * or P => P - Q, Q => P + Q
- */
-static void xycz_add_c(u64 *x1, u64 *y1, u64 *x2, u64 *y2)
-{
-	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
-	u64 t5[NUM_ECC_DIGITS];
-	u64 t6[NUM_ECC_DIGITS];
-	u64 t7[NUM_ECC_DIGITS];
-
-	vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
-	vli_mod_square_fast(t5, t5);      /* t5 = (x2 - x1)^2 = A */
-	vli_mod_mult_fast(x1, x1, t5);    /* t1 = x1*A = B */
-	vli_mod_mult_fast(x2, x2, t5);    /* t3 = x2*A = C */
-	vli_mod_add(t5, y2, y1, curve_p); /* t4 = y2 + y1 */
-	vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
-
-	vli_mod_sub(t6, x2, x1, curve_p); /* t6 = C - B */
-	vli_mod_mult_fast(y1, y1, t6);    /* t2 = y1 * (C - B) */
-	vli_mod_add(t6, x1, x2, curve_p); /* t6 = B + C */
-	vli_mod_square_fast(x2, y2);      /* t3 = (y2 - y1)^2 */
-	vli_mod_sub(x2, x2, t6, curve_p); /* t3 = x3 */
-
-	vli_mod_sub(t7, x1, x2, curve_p); /* t7 = B - x3 */
-	vli_mod_mult_fast(y2, y2, t7);    /* t4 = (y2 - y1)*(B - x3) */
-	vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
-
-	vli_mod_square_fast(t7, t5);      /* t7 = (y2 + y1)^2 = F */
-	vli_mod_sub(t7, t7, t6, curve_p); /* t7 = x3' */
-	vli_mod_sub(t6, t7, x1, curve_p); /* t6 = x3' - B */
-	vli_mod_mult_fast(t6, t6, t5);    /* t6 = (y2 + y1)*(x3' - B) */
-	vli_mod_sub(y1, t6, y1, curve_p); /* t2 = y3' */
-
-	vli_set(x1, t7);
-}
-
-static void ecc_point_mult(struct ecc_point *result,
-			   const struct ecc_point *point, u64 *scalar,
-			   u64 *initial_z, int num_bits)
-{
-	/* R0 and R1 */
-	u64 rx[2][NUM_ECC_DIGITS];
-	u64 ry[2][NUM_ECC_DIGITS];
-	u64 z[NUM_ECC_DIGITS];
-	int i, nb;
-
-	vli_set(rx[1], point->x);
-	vli_set(ry[1], point->y);
-
-	xycz_initial_double(rx[1], ry[1], rx[0], ry[0], initial_z);
-
-	for (i = num_bits - 2; i > 0; i--) {
-		nb = !vli_test_bit(scalar, i);
-		xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
-		xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
-	}
-
-	nb = !vli_test_bit(scalar, 0);
-	xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
-
-	/* Find final 1/Z value. */
-	vli_mod_sub(z, rx[1], rx[0], curve_p); /* X1 - X0 */
-	vli_mod_mult_fast(z, z, ry[1 - nb]); /* Yb * (X1 - X0) */
-	vli_mod_mult_fast(z, z, point->x);   /* xP * Yb * (X1 - X0) */
-	vli_mod_inv(z, z, curve_p);          /* 1 / (xP * Yb * (X1 - X0)) */
-	vli_mod_mult_fast(z, z, point->y);   /* yP / (xP * Yb * (X1 - X0)) */
-	vli_mod_mult_fast(z, z, rx[1 - nb]); /* Xb * yP / (xP * Yb * (X1 - X0)) */
-	/* End 1/Z calculation */
-
-	xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
-
-	apply_z(rx[0], ry[0], z);
-
-	vli_set(result->x, rx[0]);
-	vli_set(result->y, ry[0]);
-}
-
-static void ecc_bytes2native(const u8 bytes[ECC_BYTES],
-			     u64 native[NUM_ECC_DIGITS])
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		const u8 *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
-
-		native[NUM_ECC_DIGITS - 1 - i] =
-				((u64) digit[0] << 0) |
-				((u64) digit[1] << 8) |
-				((u64) digit[2] << 16) |
-				((u64) digit[3] << 24) |
-				((u64) digit[4] << 32) |
-				((u64) digit[5] << 40) |
-				((u64) digit[6] << 48) |
-				((u64) digit[7] << 56);
-	}
-}
-
-static void ecc_native2bytes(const u64 native[NUM_ECC_DIGITS],
-			     u8 bytes[ECC_BYTES])
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		u8 *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
-
-		digit[0] = native[NUM_ECC_DIGITS - 1 - i] >> 0;
-		digit[1] = native[NUM_ECC_DIGITS - 1 - i] >> 8;
-		digit[2] = native[NUM_ECC_DIGITS - 1 - i] >> 16;
-		digit[3] = native[NUM_ECC_DIGITS - 1 - i] >> 24;
-		digit[4] = native[NUM_ECC_DIGITS - 1 - i] >> 32;
-		digit[5] = native[NUM_ECC_DIGITS - 1 - i] >> 40;
-		digit[6] = native[NUM_ECC_DIGITS - 1 - i] >> 48;
-		digit[7] = native[NUM_ECC_DIGITS - 1 - i] >> 56;
-	}
-}
-
-bool ecc_make_key(u8 public_key[64], u8 private_key[32])
-{
-	struct ecc_point pk;
-	u64 priv[NUM_ECC_DIGITS];
-	unsigned int tries = 0;
-
-	do {
-		if (tries++ >= MAX_TRIES)
-			return false;
-
-		get_random_bytes(priv, ECC_BYTES);
-
-		if (vli_is_zero(priv))
-			continue;
-
-		/* Make sure the private key is in the range [1, n-1]. */
-		if (vli_cmp(curve_n, priv) != 1)
-			continue;
-
-		ecc_point_mult(&pk, &curve_g, priv, NULL, vli_num_bits(priv));
-	} while (ecc_point_is_zero(&pk));
-
-	ecc_native2bytes(priv, private_key);
-	ecc_native2bytes(pk.x, public_key);
-	ecc_native2bytes(pk.y, &public_key[32]);
-
-	return true;
-}
-
-bool ecdh_shared_secret(const u8 public_key[64], const u8 private_key[32],
-		        u8 secret[32])
-{
-	u64 priv[NUM_ECC_DIGITS];
-	u64 rand[NUM_ECC_DIGITS];
-	struct ecc_point product, pk;
-
-	get_random_bytes(rand, ECC_BYTES);
-
-	ecc_bytes2native(public_key, pk.x);
-	ecc_bytes2native(&public_key[32], pk.y);
-	ecc_bytes2native(private_key, priv);
-
-	ecc_point_mult(&product, &pk, priv, rand, vli_num_bits(priv));
-
-	ecc_native2bytes(product.x, secret);
-
-	return !ecc_point_is_zero(&product);
-}
diff --git a/net/bluetooth/ecc.h b/net/bluetooth/ecc.h
deleted file mode 100644
index 8d6a2f4..0000000
--- a/net/bluetooth/ecc.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013, Kenneth MacKay
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *  * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* Create a public/private key pair.
- * Outputs:
- *	public_key  - Will be filled in with the public key.
- *	private_key - Will be filled in with the private key.
- *
- * Returns true if the key pair was generated successfully, false
- * if an error occurred. The keys are with the LSB first.
- */
-bool ecc_make_key(u8 public_key[64], u8 private_key[32]);
-
-/* Compute a shared secret given your secret key and someone else's
- * public key.
- * Note: It is recommended that you hash the result of ecdh_shared_secret
- * before using it for symmetric encryption or HMAC.
- *
- * Inputs:
- *	public_key  - The public key of the remote party
- *	private_key - Your private key.
- *
- * Outputs:
- *	secret - Will be filled in with the shared secret value.
- *
- * Returns true if the shared secret was generated successfully, false
- * if an error occurred. Both input and output parameters are with the
- * LSB first.
- */
-bool ecdh_shared_secret(const u8 public_key[64], const u8 private_key[32],
-		        u8 secret[32]);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index fe18825..b9517bd 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -141,11 +141,10 @@
 	 */
 	if (conn->type == ACL_LINK && conn->role == HCI_ROLE_MASTER) {
 		struct hci_dev *hdev = conn->hdev;
-		struct hci_cp_read_clock_offset clkoff_cp;
+		struct hci_cp_read_clock_offset cp;
 
-		clkoff_cp.handle = cpu_to_le16(conn->handle);
-		hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET, sizeof(clkoff_cp),
-			     &clkoff_cp);
+		cp.handle = cpu_to_le16(conn->handle);
+		hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET, sizeof(cp), &cp);
 	}
 
 	conn->state = BT_DISCONN;
@@ -416,7 +415,7 @@
 	 * happen with broken hardware or if low duty cycle was used
 	 * (which doesn't have a timeout of its own).
 	 */
-	if (conn->role == HCI_ROLE_SLAVE) {
+	if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
 		u8 enable = 0x00;
 		hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
 			     &enable);
@@ -449,7 +448,6 @@
 	conn->io_capability = hdev->io_capability;
 	conn->remote_auth = 0xff;
 	conn->key_type = 0xff;
-	conn->rssi = HCI_RSSI_INVALID;
 	conn->tx_power = HCI_TX_POWER_INVALID;
 	conn->max_tx_power = HCI_TX_POWER_INVALID;
 
@@ -519,7 +517,7 @@
 		/* Unacked frames */
 		hdev->acl_cnt += conn->sent;
 	} else if (conn->type == LE_LINK) {
-		cancel_delayed_work(&conn->le_conn_timeout);
+		cancel_delayed_work_sync(&conn->le_conn_timeout);
 
 		if (hdev->le_pkts)
 			hdev->le_cnt += conn->sent;
@@ -546,9 +544,6 @@
 
 	hci_conn_del_sysfs(conn);
 
-	if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
-		hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
-
 	hci_dev_put(hdev);
 
 	hci_conn_put(conn);
@@ -661,7 +656,7 @@
 	memset(&cp, 0, sizeof(cp));
 
 	/* Update random address, but set require_privacy to false so
-	 * that we never connect with an non-resolvable address.
+	 * that we never connect with an unresolvable address.
 	 */
 	if (hci_update_random_address(req, false, &own_addr_type))
 		return;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5dcacf9..cb05d7f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -200,6 +200,31 @@
 	.release	= single_release,
 };
 
+static int whitelist_show(struct seq_file *f, void *p)
+{
+	struct hci_dev *hdev = f->private;
+	struct bdaddr_list *b;
+
+	hci_dev_lock(hdev);
+	list_for_each_entry(b, &hdev->whitelist, list)
+		seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
+	hci_dev_unlock(hdev);
+
+	return 0;
+}
+
+static int whitelist_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, whitelist_show, inode->i_private);
+}
+
+static const struct file_operations whitelist_fops = {
+	.open		= whitelist_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static int uuids_show(struct seq_file *f, void *p)
 {
 	struct hci_dev *hdev = f->private;
@@ -274,13 +299,15 @@
 static int link_keys_show(struct seq_file *f, void *ptr)
 {
 	struct hci_dev *hdev = f->private;
-	struct link_key *key;
+	struct list_head *p, *n;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(key, &hdev->link_keys, list)
+	hci_dev_lock(hdev);
+	list_for_each_safe(p, n, &hdev->link_keys) {
+		struct link_key *key = list_entry(p, struct link_key, list);
 		seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
 			   HCI_LINK_KEY_SIZE, key->val, key->pin_len);
-	rcu_read_unlock();
+	}
+	hci_dev_unlock(hdev);
 
 	return 0;
 }
@@ -406,49 +433,6 @@
 	.llseek		= default_llseek,
 };
 
-static ssize_t force_lesc_support_read(struct file *file, char __user *user_buf,
-				       size_t count, loff_t *ppos)
-{
-	struct hci_dev *hdev = file->private_data;
-	char buf[3];
-
-	buf[0] = test_bit(HCI_FORCE_LESC, &hdev->dbg_flags) ? 'Y': 'N';
-	buf[1] = '\n';
-	buf[2] = '\0';
-	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
-}
-
-static ssize_t force_lesc_support_write(struct file *file,
-					const char __user *user_buf,
-					size_t count, loff_t *ppos)
-{
-	struct hci_dev *hdev = file->private_data;
-	char buf[32];
-	size_t buf_size = min(count, (sizeof(buf)-1));
-	bool enable;
-
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-
-	buf[buf_size] = '\0';
-	if (strtobool(buf, &enable))
-		return -EINVAL;
-
-	if (enable == test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
-		return -EALREADY;
-
-	change_bit(HCI_FORCE_LESC, &hdev->dbg_flags);
-
-	return count;
-}
-
-static const struct file_operations force_lesc_support_fops = {
-	.open		= simple_open,
-	.read		= force_lesc_support_read,
-	.write		= force_lesc_support_write,
-	.llseek		= default_llseek,
-};
-
 static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
 				 size_t count, loff_t *ppos)
 {
@@ -789,15 +773,16 @@
 static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
 {
 	struct hci_dev *hdev = f->private;
-	struct smp_irk *irk;
+	struct list_head *p, *n;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
+	hci_dev_lock(hdev);
+	list_for_each_safe(p, n, &hdev->identity_resolving_keys) {
+		struct smp_irk *irk = list_entry(p, struct smp_irk, list);
 		seq_printf(f, "%pMR (type %u) %*phN %pMR\n",
 			   &irk->bdaddr, irk->addr_type,
 			   16, irk->val, &irk->rpa);
 	}
-	rcu_read_unlock();
+	hci_dev_unlock(hdev);
 
 	return 0;
 }
@@ -818,15 +803,17 @@
 static int long_term_keys_show(struct seq_file *f, void *ptr)
 {
 	struct hci_dev *hdev = f->private;
-	struct smp_ltk *ltk;
+	struct list_head *p, *n;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(ltk, &hdev->long_term_keys, list)
+	hci_dev_lock(hdev);
+	list_for_each_safe(p, n, &hdev->long_term_keys) {
+		struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list);
 		seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n",
 			   &ltk->bdaddr, ltk->bdaddr_type, ltk->authenticated,
 			   ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
 			   __le64_to_cpu(ltk->rand), 16, ltk->val);
-	rcu_read_unlock();
+	}
+	hci_dev_unlock(hdev);
 
 	return 0;
 }
@@ -1043,13 +1030,10 @@
 {
 	struct hci_dev *hdev = f->private;
 	struct hci_conn_params *p;
-	struct bdaddr_list *b;
 
 	hci_dev_lock(hdev);
-	list_for_each_entry(b, &hdev->whitelist, list)
-		seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
 	list_for_each_entry(p, &hdev->le_conn_params, list) {
-		seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type,
+		seq_printf(f, "%pMR %u %u\n", &p->addr, p->addr_type,
 			   p->auto_connect);
 	}
 	hci_dev_unlock(hdev);
@@ -1163,16 +1147,13 @@
 
 	hdev->req_status = HCI_REQ_PEND;
 
+	err = hci_req_run(&req, hci_req_sync_complete);
+	if (err < 0)
+		return ERR_PTR(err);
+
 	add_wait_queue(&hdev->req_wait_q, &wait);
 	set_current_state(TASK_INTERRUPTIBLE);
 
-	err = hci_req_run(&req, hci_req_sync_complete);
-	if (err < 0) {
-		remove_wait_queue(&hdev->req_wait_q, &wait);
-		set_current_state(TASK_RUNNING);
-		return ERR_PTR(err);
-	}
-
 	schedule_timeout(timeout);
 
 	remove_wait_queue(&hdev->req_wait_q, &wait);
@@ -1230,16 +1211,10 @@
 
 	func(&req, opt);
 
-	add_wait_queue(&hdev->req_wait_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-
 	err = hci_req_run(&req, hci_req_sync_complete);
 	if (err < 0) {
 		hdev->req_status = 0;
 
-		remove_wait_queue(&hdev->req_wait_q, &wait);
-		set_current_state(TASK_RUNNING);
-
 		/* ENODATA means the HCI request command queue is empty.
 		 * This can happen when a request with conditionals doesn't
 		 * trigger any commands to be sent. This is normal behavior
@@ -1251,6 +1226,9 @@
 		return err;
 	}
 
+	add_wait_queue(&hdev->req_wait_q, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
 	schedule_timeout(timeout);
 
 	remove_wait_queue(&hdev->req_wait_q, &wait);
@@ -1373,6 +1351,8 @@
 
 static void bredr_setup(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
+
 	__le16 param;
 	__u8 flt_type;
 
@@ -1401,6 +1381,14 @@
 	/* Connection accept timeout ~20 secs */
 	param = cpu_to_le16(0x7d00);
 	hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
+
+	/* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2,
+	 * but it does not support page scan related HCI commands.
+	 */
+	if (hdev->manufacturer != 31 && hdev->hci_ver > BLUETOOTH_VER_1_1) {
+		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
+		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL);
+	}
 }
 
 static void le_setup(struct hci_request *req)
@@ -1708,16 +1696,6 @@
 	if (hdev->commands[5] & 0x10)
 		hci_setup_link_policy(req);
 
-	if (hdev->commands[8] & 0x01)
-		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
-
-	/* Some older Broadcom based Bluetooth 1.2 controllers do not
-	 * support the Read Page Scan Type command. Check support for
-	 * this command in the bit mask of supported commands.
-	 */
-	if (hdev->commands[13] & 0x01)
-		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL);
-
 	if (lmp_le_capable(hdev)) {
 		u8 events[8];
 
@@ -1735,28 +1713,6 @@
 						 * Parameter Request
 						 */
 
-		/* If the controller supports Extended Scanner Filter
-		 * Policies, enable the correspondig event.
-		 */
-		if (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY)
-			events[1] |= 0x04;	/* LE Direct Advertising
-						 * Report
-						 */
-
-		/* If the controller supports the LE Read Local P-256
-		 * Public Key command, enable the corresponding event.
-		 */
-		if (hdev->commands[34] & 0x02)
-			events[0] |= 0x80;	/* LE Read Local P-256
-						 * Public Key Complete
-						 */
-
-		/* If the controller supports the LE Generate DHKey
-		 * command, enable the corresponding event.
-		 */
-		if (hdev->commands[34] & 0x04)
-			events[1] |= 0x01;	/* LE Generate DHKey Complete */
-
 		hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
 			    events);
 
@@ -1799,7 +1755,9 @@
 		hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
 
 	/* Enable Secure Connections if supported and configured */
-	if (bredr_sc_enabled(hdev)) {
+	if ((lmp_sc_capable(hdev) ||
+	     test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) &&
+	    test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
 		u8 support = 0x01;
 		hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT,
 			    sizeof(support), &support);
@@ -1853,10 +1811,10 @@
 			   &hdev->manufacturer);
 	debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
 	debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
-	debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
-			    &device_list_fops);
 	debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
 			    &blacklist_fops);
+	debugfs_create_file("whitelist", 0444, hdev->debugfs, hdev,
+			    &whitelist_fops);
 	debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
 
 	debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
@@ -1882,10 +1840,6 @@
 				    hdev, &force_sc_support_fops);
 		debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
 				    hdev, &sc_only_mode_fops);
-		if (lmp_le_capable(hdev))
-			debugfs_create_file("force_lesc_support", 0644,
-					    hdev->debugfs, hdev,
-					    &force_lesc_support_fops);
 	}
 
 	if (lmp_sniff_capable(hdev)) {
@@ -1939,6 +1893,8 @@
 				    hdev, &adv_min_interval_fops);
 		debugfs_create_file("adv_max_interval", 0644, hdev->debugfs,
 				    hdev, &adv_max_interval_fops);
+		debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
+				    &device_list_fops);
 		debugfs_create_u16("discov_interleaved_timeout", 0644,
 				   hdev->debugfs,
 				   &hdev->discov_interleaved_timeout);
@@ -2182,7 +2138,7 @@
 
 	BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
 
-	hci_remove_remote_oob_data(hdev, &data->bdaddr, BDADDR_BREDR);
+	hci_remove_remote_oob_data(hdev, &data->bdaddr);
 
 	if (!data->ssp_mode)
 		flags |= MGMT_DEV_FOUND_LEGACY_PAIRING;
@@ -2628,18 +2584,7 @@
 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
 		cancel_delayed_work_sync(&hdev->rpa_expired);
 
-	/* Avoid potential lockdep warnings from the *_flush() calls by
-	 * ensuring the workqueue is empty up front.
-	 */
-	drain_workqueue(hdev->workqueue);
-
 	hci_dev_lock(hdev);
-
-	if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
-		if (hdev->dev_type == HCI_BREDR)
-			mgmt_powered(hdev, 0);
-	}
-
 	hci_inquiry_cache_flush(hdev);
 	hci_pend_le_actions_clear(hdev);
 	hci_conn_hash_flush(hdev);
@@ -2687,6 +2632,14 @@
 	hdev->flags &= BIT(HCI_RAW);
 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
 
+	if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
+		if (hdev->dev_type == HCI_BREDR) {
+			hci_dev_lock(hdev);
+			mgmt_powered(hdev, 0);
+			hci_dev_unlock(hdev);
+		}
+	}
+
 	/* Controller radio is available but is currently powered down */
 	hdev->amp_status = AMP_STATUS_POWERED_DOWN;
 
@@ -2754,11 +2707,6 @@
 	skb_queue_purge(&hdev->rx_q);
 	skb_queue_purge(&hdev->cmd_q);
 
-	/* Avoid potential lockdep warnings from the *_flush() calls by
-	 * ensuring the workqueue is empty up front.
-	 */
-	drain_workqueue(hdev->workqueue);
-
 	hci_dev_lock(hdev);
 	hci_inquiry_cache_flush(hdev);
 	hci_conn_hash_flush(hdev);
@@ -3081,9 +3029,7 @@
 
 	err = hci_dev_do_open(hdev);
 	if (err < 0) {
-		hci_dev_lock(hdev);
 		mgmt_set_powered_failed(hdev, err);
-		hci_dev_unlock(hdev);
 		return;
 	}
 
@@ -3166,31 +3112,35 @@
 
 void hci_link_keys_clear(struct hci_dev *hdev)
 {
-	struct link_key *key;
+	struct list_head *p, *n;
 
-	list_for_each_entry_rcu(key, &hdev->link_keys, list) {
-		list_del_rcu(&key->list);
-		kfree_rcu(key, rcu);
+	list_for_each_safe(p, n, &hdev->link_keys) {
+		struct link_key *key;
+
+		key = list_entry(p, struct link_key, list);
+
+		list_del(p);
+		kfree(key);
 	}
 }
 
 void hci_smp_ltks_clear(struct hci_dev *hdev)
 {
-	struct smp_ltk *k;
+	struct smp_ltk *k, *tmp;
 
-	list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
-		list_del_rcu(&k->list);
-		kfree_rcu(k, rcu);
+	list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
+		list_del(&k->list);
+		kfree(k);
 	}
 }
 
 void hci_smp_irks_clear(struct hci_dev *hdev)
 {
-	struct smp_irk *k;
+	struct smp_irk *k, *tmp;
 
-	list_for_each_entry_rcu(k, &hdev->identity_resolving_keys, list) {
-		list_del_rcu(&k->list);
-		kfree_rcu(k, rcu);
+	list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
+		list_del(&k->list);
+		kfree(k);
 	}
 }
 
@@ -3198,14 +3148,9 @@
 {
 	struct link_key *k;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(k, &hdev->link_keys, list) {
-		if (bacmp(bdaddr, &k->bdaddr) == 0) {
-			rcu_read_unlock();
+	list_for_each_entry(k, &hdev->link_keys, list)
+		if (bacmp(bdaddr, &k->bdaddr) == 0)
 			return k;
-		}
-	}
-	rcu_read_unlock();
 
 	return NULL;
 }
@@ -3229,10 +3174,6 @@
 	if (!conn)
 		return true;
 
-	/* BR/EDR key derived using SC from an LE link */
-	if (conn->type == LE_LINK)
-		return true;
-
 	/* Neither local nor remote side had no-bonding as requirement */
 	if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
 		return true;
@@ -3258,22 +3199,34 @@
 	return HCI_ROLE_SLAVE;
 }
 
-struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
-			     u8 addr_type, u8 role)
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
+			     u8 role)
 {
 	struct smp_ltk *k;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
-		if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr))
+	list_for_each_entry(k, &hdev->long_term_keys, list) {
+		if (k->ediv != ediv || k->rand != rand)
 			continue;
 
-		if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) {
-			rcu_read_unlock();
-			return k;
-		}
+		if (ltk_role(k->type) != role)
+			continue;
+
+		return k;
 	}
-	rcu_read_unlock();
+
+	return NULL;
+}
+
+struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				     u8 addr_type, u8 role)
+{
+	struct smp_ltk *k;
+
+	list_for_each_entry(k, &hdev->long_term_keys, list)
+		if (addr_type == k->bdaddr_type &&
+		    bacmp(bdaddr, &k->bdaddr) == 0 &&
+		    ltk_role(k->type) == role)
+			return k;
 
 	return NULL;
 }
@@ -3282,22 +3235,17 @@
 {
 	struct smp_irk *irk;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
-		if (!bacmp(&irk->rpa, rpa)) {
-			rcu_read_unlock();
+	list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
+		if (!bacmp(&irk->rpa, rpa))
 			return irk;
-		}
 	}
 
-	list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
+	list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
 		if (smp_irk_matches(hdev, irk->val, rpa)) {
 			bacpy(&irk->rpa, rpa);
-			rcu_read_unlock();
 			return irk;
 		}
 	}
-	rcu_read_unlock();
 
 	return NULL;
 }
@@ -3311,15 +3259,11 @@
 	if (addr_type == ADDR_LE_DEV_RANDOM && (bdaddr->b[5] & 0xc0) != 0xc0)
 		return NULL;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
+	list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
 		if (addr_type == irk->addr_type &&
-		    bacmp(bdaddr, &irk->bdaddr) == 0) {
-			rcu_read_unlock();
+		    bacmp(bdaddr, &irk->bdaddr) == 0)
 			return irk;
-		}
 	}
-	rcu_read_unlock();
 
 	return NULL;
 }
@@ -3340,7 +3284,7 @@
 		key = kzalloc(sizeof(*key), GFP_KERNEL);
 		if (!key)
 			return NULL;
-		list_add_rcu(&key->list, &hdev->link_keys);
+		list_add(&key->list, &hdev->link_keys);
 	}
 
 	BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
@@ -3378,14 +3322,14 @@
 	struct smp_ltk *key, *old_key;
 	u8 role = ltk_role(type);
 
-	old_key = hci_find_ltk(hdev, bdaddr, addr_type, role);
+	old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, role);
 	if (old_key)
 		key = old_key;
 	else {
 		key = kzalloc(sizeof(*key), GFP_KERNEL);
 		if (!key)
 			return NULL;
-		list_add_rcu(&key->list, &hdev->long_term_keys);
+		list_add(&key->list, &hdev->long_term_keys);
 	}
 
 	bacpy(&key->bdaddr, bdaddr);
@@ -3414,7 +3358,7 @@
 		bacpy(&irk->bdaddr, bdaddr);
 		irk->addr_type = addr_type;
 
-		list_add_rcu(&irk->list, &hdev->identity_resolving_keys);
+		list_add(&irk->list, &hdev->identity_resolving_keys);
 	}
 
 	memcpy(irk->val, val, 16);
@@ -3433,25 +3377,25 @@
 
 	BT_DBG("%s removing %pMR", hdev->name, bdaddr);
 
-	list_del_rcu(&key->list);
-	kfree_rcu(key, rcu);
+	list_del(&key->list);
+	kfree(key);
 
 	return 0;
 }
 
 int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
 {
-	struct smp_ltk *k;
+	struct smp_ltk *k, *tmp;
 	int removed = 0;
 
-	list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
+	list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
 		if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type)
 			continue;
 
 		BT_DBG("%s removing %pMR", hdev->name, bdaddr);
 
-		list_del_rcu(&k->list);
-		kfree_rcu(k, rcu);
+		list_del(&k->list);
+		kfree(k);
 		removed++;
 	}
 
@@ -3460,16 +3404,16 @@
 
 void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
 {
-	struct smp_irk *k;
+	struct smp_irk *k, *tmp;
 
-	list_for_each_entry_rcu(k, &hdev->identity_resolving_keys, list) {
+	list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
 		if (bacmp(bdaddr, &k->bdaddr) || k->addr_type != addr_type)
 			continue;
 
 		BT_DBG("%s removing %pMR", hdev->name, bdaddr);
 
-		list_del_rcu(&k->list);
-		kfree_rcu(k, rcu);
+		list_del(&k->list);
+		kfree(k);
 	}
 }
 
@@ -3493,31 +3437,26 @@
 }
 
 struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
-					  bdaddr_t *bdaddr, u8 bdaddr_type)
+					  bdaddr_t *bdaddr)
 {
 	struct oob_data *data;
 
-	list_for_each_entry(data, &hdev->remote_oob_data, list) {
-		if (bacmp(bdaddr, &data->bdaddr) != 0)
-			continue;
-		if (data->bdaddr_type != bdaddr_type)
-			continue;
-		return data;
-	}
+	list_for_each_entry(data, &hdev->remote_oob_data, list)
+		if (bacmp(bdaddr, &data->bdaddr) == 0)
+			return data;
 
 	return NULL;
 }
 
-int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
-			       u8 bdaddr_type)
+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
 	struct oob_data *data;
 
-	data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
+	data = hci_find_remote_oob_data(hdev, bdaddr);
 	if (!data)
 		return -ENOENT;
 
-	BT_DBG("%s removing %pMR (%u)", hdev->name, bdaddr, bdaddr_type);
+	BT_DBG("%s removing %pMR", hdev->name, bdaddr);
 
 	list_del(&data->list);
 	kfree(data);
@@ -3536,37 +3475,52 @@
 }
 
 int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
-			    u8 bdaddr_type, u8 *hash192, u8 *rand192,
-			    u8 *hash256, u8 *rand256)
+			    u8 *hash, u8 *randomizer)
 {
 	struct oob_data *data;
 
-	data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
+	data = hci_find_remote_oob_data(hdev, bdaddr);
 	if (!data) {
 		data = kmalloc(sizeof(*data), GFP_KERNEL);
 		if (!data)
 			return -ENOMEM;
 
 		bacpy(&data->bdaddr, bdaddr);
-		data->bdaddr_type = bdaddr_type;
 		list_add(&data->list, &hdev->remote_oob_data);
 	}
 
-	if (hash192 && rand192) {
-		memcpy(data->hash192, hash192, sizeof(data->hash192));
-		memcpy(data->rand192, rand192, sizeof(data->rand192));
-	} else {
-		memset(data->hash192, 0, sizeof(data->hash192));
-		memset(data->rand192, 0, sizeof(data->rand192));
+	memcpy(data->hash192, hash, sizeof(data->hash192));
+	memcpy(data->randomizer192, randomizer, sizeof(data->randomizer192));
+
+	memset(data->hash256, 0, sizeof(data->hash256));
+	memset(data->randomizer256, 0, sizeof(data->randomizer256));
+
+	BT_DBG("%s for %pMR", hdev->name, bdaddr);
+
+	return 0;
+}
+
+int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+				u8 *hash192, u8 *randomizer192,
+				u8 *hash256, u8 *randomizer256)
+{
+	struct oob_data *data;
+
+	data = hci_find_remote_oob_data(hdev, bdaddr);
+	if (!data) {
+		data = kmalloc(sizeof(*data), GFP_KERNEL);
+		if (!data)
+			return -ENOMEM;
+
+		bacpy(&data->bdaddr, bdaddr);
+		list_add(&data->list, &hdev->remote_oob_data);
 	}
 
-	if (hash256 && rand256) {
-		memcpy(data->hash256, hash256, sizeof(data->hash256));
-		memcpy(data->rand256, rand256, sizeof(data->rand256));
-	} else {
-		memset(data->hash256, 0, sizeof(data->hash256));
-		memset(data->rand256, 0, sizeof(data->rand256));
-	}
+	memcpy(data->hash192, hash192, sizeof(data->hash192));
+	memcpy(data->randomizer192, randomizer192, sizeof(data->randomizer192));
+
+	memcpy(data->hash256, hash256, sizeof(data->hash256));
+	memcpy(data->randomizer256, randomizer256, sizeof(data->randomizer256));
 
 	BT_DBG("%s for %pMR", hdev->name, bdaddr);
 
@@ -3959,29 +3913,17 @@
 	}
 
 	/* In case of required privacy without resolvable private address,
-	 * use an non-resolvable private address. This is useful for active
+	 * use an unresolvable private address. This is useful for active
 	 * scanning and non-connectable advertising.
 	 */
 	if (require_privacy) {
-		bdaddr_t nrpa;
+		bdaddr_t urpa;
 
-		while (true) {
-			/* The non-resolvable private address is generated
-			 * from random six bytes with the two most significant
-			 * bits cleared.
-			 */
-			get_random_bytes(&nrpa, 6);
-			nrpa.b[5] &= 0x3f;
-
-			/* The non-resolvable private address shall not be
-			 * equal to the public address.
-			 */
-			if (bacmp(&hdev->bdaddr, &nrpa))
-				break;
-		}
+		get_random_bytes(&urpa, 6);
+		urpa.b[5] &= 0x3f;	/* Clear two most significant bits */
 
 		*own_addr_type = ADDR_LE_DEV_RANDOM;
-		set_random_addr(req, &nrpa);
+		set_random_addr(req, &urpa);
 		return 0;
 	}
 
@@ -4278,7 +4220,6 @@
 	hci_remote_oob_data_clear(hdev);
 	hci_bdaddr_list_clear(&hdev->le_white_list);
 	hci_conn_params_clear_all(hdev);
-	hci_discovery_filter_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_dev_put(hdev);
@@ -4303,24 +4244,6 @@
 }
 EXPORT_SYMBOL(hci_resume_dev);
 
-/* Reset HCI device */
-int hci_reset_dev(struct hci_dev *hdev)
-{
-	const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 };
-	struct sk_buff *skb;
-
-	skb = bt_skb_alloc(3, GFP_ATOMIC);
-	if (!skb)
-		return -ENOMEM;
-
-	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
-	memcpy(skb_put(skb, 3), hw_err, 3);
-
-	/* Send Hardware Error to upper stack */
-	return hci_recv_frame(hdev, skb);
-}
-EXPORT_SYMBOL(hci_reset_dev);
-
 /* Receive frame from HCI drivers */
 int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
@@ -4554,7 +4477,7 @@
 
 	BT_DBG("length %u", skb_queue_len(&req->cmd_q));
 
-	/* If an error occurred during request building, remove all HCI
+	/* If an error occured during request building, remove all HCI
 	 * commands queued on the HCI request queue.
 	 */
 	if (req->err) {
@@ -4623,7 +4546,7 @@
 		return -ENOMEM;
 	}
 
-	/* Stand-alone HCI commands must be flagged as
+	/* Stand-alone HCI commands must be flaged as
 	 * single-command requests.
 	 */
 	bt_cb(skb)->req.start = true;
@@ -4643,7 +4566,7 @@
 
 	BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen);
 
-	/* If an error occurred during request building, there is no point in
+	/* If an error occured during request building, there is no point in
 	 * queueing the HCI command. We can simply return.
 	 */
 	if (req->err)
@@ -4738,12 +4661,8 @@
 
 		skb_shinfo(skb)->frag_list = NULL;
 
-		/* Queue all fragments atomically. We need to use spin_lock_bh
-		 * here because of 6LoWPAN links, as there this function is
-		 * called from softirq and using normal spin lock could cause
-		 * deadlocks.
-		 */
-		spin_lock_bh(&queue->lock);
+		/* Queue all fragments atomically */
+		spin_lock(&queue->lock);
 
 		__skb_queue_tail(queue, skb);
 
@@ -4760,7 +4679,7 @@
 			__skb_queue_tail(queue, skb);
 		} while (list);
 
-		spin_unlock_bh(&queue->lock);
+		spin_unlock(&queue->lock);
 	}
 }
 
@@ -5637,7 +5556,7 @@
 	u8 filter_policy;
 
 	/* Set require_privacy to false since no SCAN_REQ are send
-	 * during passive scanning. Not using an non-resolvable address
+	 * during passive scanning. Not using an unresolvable address
 	 * here is important so that peer devices using direct
 	 * advertising with our address will be correctly reported
 	 * by the controller.
@@ -5651,19 +5570,6 @@
 	 */
 	filter_policy = update_white_list(req);
 
-	/* When the controller is using random resolvable addresses and
-	 * with that having LE privacy enabled, then controllers with
-	 * Extended Scanner Filter Policies support can now enable support
-	 * for handling directed advertising.
-	 *
-	 * So instead of using filter polices 0x00 (no whitelist)
-	 * and 0x01 (whitelist enabled) use the new filter policies
-	 * 0x02 (no whitelist) and 0x03 (whitelist enabled).
-	 */
-	if (test_bit(HCI_PRIVACY, &hdev->dev_flags) &&
-	    (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY))
-		filter_policy |= 0x02;
-
 	memset(&param_cp, 0, sizeof(param_cp));
 	param_cp.type = LE_SCAN_PASSIVE;
 	param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
@@ -5715,15 +5621,6 @@
 	if (hdev->discovery.state != DISCOVERY_STOPPED)
 		return;
 
-	/* Reset RSSI and UUID filters when starting background scanning
-	 * since these filters are meant for service discovery only.
-	 *
-	 * The Start Discovery and Start Service Discovery operations
-	 * ensure to set proper values for RSSI threshold and UUID
-	 * filter list. So it is safe to just reset them here.
-	 */
-	hci_discovery_filter_clear(hdev);
-
 	hci_req_init(&req, hdev);
 
 	if (list_empty(&hdev->pend_le_conns) &&
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 39a5c8a..8b0a2a6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -189,9 +189,6 @@
 
 	clear_bit(HCI_RESET, &hdev->flags);
 
-	if (status)
-		return;
-
 	/* Reset all non-persistent flags */
 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
 
@@ -208,8 +205,6 @@
 	hdev->le_scan_type = LE_SCAN_PASSIVE;
 
 	hdev->ssp_debug_mode = 0;
-
-	hci_bdaddr_list_clear(&hdev->le_white_list);
 }
 
 static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -257,8 +252,6 @@
 	if (!sent)
 		return;
 
-	hci_dev_lock(hdev);
-
 	if (!status) {
 		__u8 param = *((__u8 *) sent);
 
@@ -270,8 +263,6 @@
 
 	if (test_bit(HCI_MGMT, &hdev->dev_flags))
 		mgmt_auth_enable_complete(hdev, status);
-
-	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
@@ -447,8 +438,6 @@
 	if (!sent)
 		return;
 
-	hci_dev_lock(hdev);
-
 	if (!status) {
 		if (sent->mode)
 			hdev->features[1][0] |= LMP_HOST_SSP;
@@ -464,8 +453,6 @@
 		else
 			clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
 	}
-
-	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
@@ -479,8 +466,6 @@
 	if (!sent)
 		return;
 
-	hci_dev_lock(hdev);
-
 	if (!status) {
 		if (sent->support)
 			hdev->features[1][0] |= LMP_HOST_SC;
@@ -496,8 +481,6 @@
 		else
 			clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
 	}
-
-	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1006,8 +989,8 @@
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
 	hci_dev_lock(hdev);
-	mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->rand, NULL, NULL,
-					  rp->status);
+	mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer,
+					  NULL, NULL, rp->status);
 	hci_dev_unlock(hdev);
 }
 
@@ -1019,8 +1002,8 @@
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
 	hci_dev_lock(hdev);
-	mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->rand192,
-					  rp->hash256, rp->rand256,
+	mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192,
+					  rp->hash256, rp->randomizer256,
 					  rp->status);
 	hci_dev_unlock(hdev);
 }
@@ -1062,7 +1045,7 @@
 
 	hci_dev_lock(hdev);
 
-	/* If we're doing connection initiation as peripheral. Set a
+	/* If we're doing connection initation as peripheral. Set a
 	 * timeout in case something goes wrong.
 	 */
 	if (*sent) {
@@ -1147,8 +1130,6 @@
 	if (!cp)
 		return;
 
-	hci_dev_lock(hdev);
-
 	switch (cp->enable) {
 	case LE_SCAN_ENABLE:
 		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
@@ -1198,8 +1179,6 @@
 		BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
 		break;
 	}
-
-	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
@@ -1294,8 +1273,6 @@
 	if (!sent)
 		return;
 
-	hci_dev_lock(hdev);
-
 	if (sent->le) {
 		hdev->features[1][0] |= LMP_HOST_LE;
 		set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
@@ -1309,8 +1286,6 @@
 		hdev->features[1][0] |= LMP_HOST_LE_BREDR;
 	else
 		hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
-
-	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1601,15 +1576,9 @@
 	struct discovery_state *discov = &hdev->discovery;
 	struct inquiry_entry *e;
 
-	/* Update the mgmt connected state if necessary. Be careful with
-	 * conn objects that exist but are not (yet) connected however.
-	 * Only those in BT_CONFIG or BT_CONNECTED states can be
-	 * considered connected.
-	 */
-	if (conn &&
-	    (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
-	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-		mgmt_device_connected(hdev, conn, 0, name, name_len);
+	if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+		mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
+				      name_len, conn->dev_class);
 
 	if (discov->state == DISCOVERY_STOPPED)
 		return;
@@ -1974,29 +1943,6 @@
 	hci_dev_unlock(hdev);
 }
 
-static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
-{
-	struct hci_cp_switch_role *cp;
-	struct hci_conn *conn;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-	if (!status)
-		return;
-
-	cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
-	if (!cp)
-		return;
-
-	hci_dev_lock(hdev);
-
-	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
-	if (conn)
-		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
-
-	hci_dev_unlock(hdev);
-}
-
 static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -2063,14 +2009,13 @@
 		data.pscan_mode		= info->pscan_mode;
 		memcpy(data.dev_class, info->dev_class, 3);
 		data.clock_offset	= info->clock_offset;
-		data.rssi		= HCI_RSSI_INVALID;
+		data.rssi		= 0x00;
 		data.ssp_mode		= 0x00;
 
 		flags = hci_inquiry_cache_update(hdev, &data, false);
 
 		mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
-				  info->dev_class, HCI_RSSI_INVALID,
-				  flags, NULL, 0, NULL, 0);
+				  info->dev_class, 0, flags, NULL, 0, NULL, 0);
 	}
 
 	hci_dev_unlock(hdev);
@@ -2591,7 +2536,9 @@
 		cp.pscan_rep_mode = 0x02;
 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-		mgmt_device_connected(hdev, conn, 0, NULL, 0);
+		mgmt_device_connected(hdev, &conn->dst, conn->type,
+				      conn->dst_type, 0, NULL, 0,
+				      conn->dev_class);
 
 	if (!hci_outgoing_auth_needed(hdev, conn)) {
 		conn->state = BT_CONNECTED;
@@ -2901,10 +2848,6 @@
 		hci_cs_create_conn(hdev, ev->status);
 		break;
 
-	case HCI_OP_DISCONNECT:
-		hci_cs_disconnect(hdev, ev->status);
-		break;
-
 	case HCI_OP_ADD_SCO:
 		hci_cs_add_sco(hdev, ev->status);
 		break;
@@ -2933,14 +2876,6 @@
 		hci_cs_setup_sync_conn(hdev, ev->status);
 		break;
 
-	case HCI_OP_CREATE_PHY_LINK:
-		hci_cs_create_phylink(hdev, ev->status);
-		break;
-
-	case HCI_OP_ACCEPT_PHY_LINK:
-		hci_cs_accept_phylink(hdev, ev->status);
-		break;
-
 	case HCI_OP_SNIFF_MODE:
 		hci_cs_sniff_mode(hdev, ev->status);
 		break;
@@ -2949,8 +2884,16 @@
 		hci_cs_exit_sniff_mode(hdev, ev->status);
 		break;
 
-	case HCI_OP_SWITCH_ROLE:
-		hci_cs_switch_role(hdev, ev->status);
+	case HCI_OP_DISCONNECT:
+		hci_cs_disconnect(hdev, ev->status);
+		break;
+
+	case HCI_OP_CREATE_PHY_LINK:
+		hci_cs_create_phylink(hdev, ev->status);
+		break;
+
+	case HCI_OP_ACCEPT_PHY_LINK:
+		hci_cs_accept_phylink(hdev, ev->status);
 		break;
 
 	case HCI_OP_LE_CREATE_CONN:
@@ -2980,13 +2923,6 @@
 	}
 }
 
-static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	struct hci_ev_hardware_error *ev = (void *) skb->data;
-
-	BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code);
-}
-
 static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_role_change *ev = (void *) skb->data;
@@ -3212,38 +3148,6 @@
 	hci_dev_unlock(hdev);
 }
 
-static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
-{
-	if (key_type == HCI_LK_CHANGED_COMBINATION)
-		return;
-
-	conn->pin_length = pin_len;
-	conn->key_type = key_type;
-
-	switch (key_type) {
-	case HCI_LK_LOCAL_UNIT:
-	case HCI_LK_REMOTE_UNIT:
-	case HCI_LK_DEBUG_COMBINATION:
-		return;
-	case HCI_LK_COMBINATION:
-		if (pin_len == 16)
-			conn->pending_sec_level = BT_SECURITY_HIGH;
-		else
-			conn->pending_sec_level = BT_SECURITY_MEDIUM;
-		break;
-	case HCI_LK_UNAUTH_COMBINATION_P192:
-	case HCI_LK_UNAUTH_COMBINATION_P256:
-		conn->pending_sec_level = BT_SECURITY_MEDIUM;
-		break;
-	case HCI_LK_AUTH_COMBINATION_P192:
-		conn->pending_sec_level = BT_SECURITY_HIGH;
-		break;
-	case HCI_LK_AUTH_COMBINATION_P256:
-		conn->pending_sec_level = BT_SECURITY_FIPS;
-		break;
-	}
-}
-
 static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_link_key_req *ev = (void *) skb->data;
@@ -3270,8 +3174,6 @@
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	if (conn) {
-		clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
-
 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
@@ -3287,7 +3189,8 @@
 			goto not_found;
 		}
 
-		conn_set_key(conn, key->type, key->pin_len);
+		conn->key_type = key->type;
+		conn->pin_length = key->pin_len;
 	}
 
 	bacpy(&cp.bdaddr, &ev->bdaddr);
@@ -3317,15 +3220,16 @@
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-	if (!conn)
-		goto unlock;
+	if (conn) {
+		hci_conn_hold(conn);
+		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+		pin_len = conn->pin_length;
 
-	hci_conn_hold(conn);
-	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
-	hci_conn_drop(conn);
+		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
+			conn->key_type = ev->key_type;
 
-	set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
-	conn_set_key(conn, ev->key_type, conn->pin_length);
+		hci_conn_drop(conn);
+	}
 
 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
 		goto unlock;
@@ -3335,12 +3239,6 @@
 	if (!key)
 		goto unlock;
 
-	/* Update connection information since adding the key will have
-	 * fixed up the type in the case of changed combination keys.
-	 */
-	if (ev->key_type == HCI_LK_CHANGED_COMBINATION)
-		conn_set_key(conn, key->type, key->pin_len);
-
 	mgmt_new_link_key(hdev, key, persistent);
 
 	/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
@@ -3350,16 +3248,15 @@
 	 */
 	if (key->type == HCI_LK_DEBUG_COMBINATION &&
 	    !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
-		list_del_rcu(&key->list);
-		kfree_rcu(key, rcu);
-		goto unlock;
+		list_del(&key->list);
+		kfree(key);
+	} else if (conn) {
+		if (persistent)
+			clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
+		else
+			set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
 	}
 
-	if (persistent)
-		clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
-	else
-		set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
-
 unlock:
 	hci_dev_unlock(hdev);
 }
@@ -3537,7 +3434,9 @@
 		cp.pscan_rep_mode = 0x02;
 		hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
 	} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-		mgmt_device_connected(hdev, conn, 0, NULL, 0);
+		mgmt_device_connected(hdev, &conn->dst, conn->type,
+				      conn->dst_type, 0, NULL, 0,
+				      conn->dev_class);
 
 	if (!hci_outgoing_auth_needed(hdev, conn)) {
 		conn->state = BT_CONNECTED;
@@ -3794,7 +3693,7 @@
 
 		cp.authentication = conn->auth_type;
 
-		if (hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR) &&
+		if (hci_find_remote_oob_data(hdev, &conn->dst) &&
 		    (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
 			cp.oob_data = 0x01;
 		else
@@ -4049,16 +3948,18 @@
 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
 		goto unlock;
 
-	data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
+	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
 	if (data) {
-		if (bredr_sc_enabled(hdev)) {
+		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
 			struct hci_cp_remote_oob_ext_data_reply cp;
 
 			bacpy(&cp.bdaddr, &ev->bdaddr);
 			memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
-			memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
+			memcpy(cp.randomizer192, data->randomizer192,
+			       sizeof(cp.randomizer192));
 			memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
-			memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
+			memcpy(cp.randomizer256, data->randomizer256,
+			       sizeof(cp.randomizer256));
 
 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
 				     sizeof(cp), &cp);
@@ -4067,7 +3968,8 @@
 
 			bacpy(&cp.bdaddr, &ev->bdaddr);
 			memcpy(cp.hash, data->hash192, sizeof(cp.hash));
-			memcpy(cp.rand, data->rand192, sizeof(cp.rand));
+			memcpy(cp.randomizer, data->randomizer192,
+			       sizeof(cp.randomizer));
 
 			hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
 				     sizeof(cp), &cp);
@@ -4312,7 +4214,8 @@
 	}
 
 	if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-		mgmt_device_connected(hdev, conn, 0, NULL, 0);
+		mgmt_device_connected(hdev, &conn->dst, conn->type,
+				      conn->dst_type, 0, NULL, 0, NULL);
 
 	conn->sec_level = BT_SECURITY_LOW;
 	conn->handle = __le16_to_cpu(ev->handle);
@@ -4366,26 +4269,25 @@
 }
 
 /* This function requires the caller holds hdev->lock */
-static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
-					      bdaddr_t *addr,
-					      u8 addr_type, u8 adv_type)
+static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
+				  u8 addr_type, u8 adv_type)
 {
 	struct hci_conn *conn;
 	struct hci_conn_params *params;
 
 	/* If the event is not connectable don't proceed further */
 	if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
-		return NULL;
+		return;
 
 	/* Ignore if the device is blocked */
 	if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
-		return NULL;
+		return;
 
 	/* Most controller will fail if we try to create new connections
 	 * while we have an existing one in slave role.
 	 */
 	if (hdev->conn_hash.le_num_slave > 0)
-		return NULL;
+		return;
 
 	/* If we're not connectable only connect devices that we have in
 	 * our pend_le_conns list.
@@ -4393,7 +4295,7 @@
 	params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
 					   addr, addr_type);
 	if (!params)
-		return NULL;
+		return;
 
 	switch (params->auto_connect) {
 	case HCI_AUTO_CONN_DIRECT:
@@ -4402,7 +4304,7 @@
 		 * incoming connections from slave devices.
 		 */
 		if (adv_type != LE_ADV_DIRECT_IND)
-			return NULL;
+			return;
 		break;
 	case HCI_AUTO_CONN_ALWAYS:
 		/* Devices advertising with ADV_IND or ADV_DIRECT_IND
@@ -4413,7 +4315,7 @@
 		 */
 		break;
 	default:
-		return NULL;
+		return;
 	}
 
 	conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
@@ -4426,7 +4328,7 @@
 		 * count consistent once the connection is established.
 		 */
 		params->conn = hci_conn_get(conn);
-		return conn;
+		return;
 	}
 
 	switch (PTR_ERR(conn)) {
@@ -4439,48 +4341,17 @@
 		break;
 	default:
 		BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
-		return NULL;
 	}
-
-	return NULL;
 }
 
 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
-			       u8 bdaddr_type, bdaddr_t *direct_addr,
-			       u8 direct_addr_type, s8 rssi, u8 *data, u8 len)
+			       u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
 {
 	struct discovery_state *d = &hdev->discovery;
 	struct smp_irk *irk;
-	struct hci_conn *conn;
 	bool match;
 	u32 flags;
 
-	/* If the direct address is present, then this report is from
-	 * a LE Direct Advertising Report event. In that case it is
-	 * important to see if the address is matching the local
-	 * controller address.
-	 */
-	if (direct_addr) {
-		/* Only resolvable random addresses are valid for these
-		 * kind of reports and others can be ignored.
-		 */
-		if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type))
-			return;
-
-		/* If the controller is not using resolvable random
-		 * addresses, then this report can be ignored.
-		 */
-		if (!test_bit(HCI_PRIVACY, &hdev->dev_flags))
-			return;
-
-		/* If the local IRK of the controller does not match
-		 * with the resolvable random address provided, then
-		 * this report can be ignored.
-		 */
-		if (!smp_irk_matches(hdev, hdev->irk, direct_addr))
-			return;
-	}
-
 	/* Check if we need to convert to identity address */
 	irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
 	if (irk) {
@@ -4489,14 +4360,7 @@
 	}
 
 	/* Check if we have been requested to connect to this device */
-	conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
-	if (conn && type == LE_ADV_IND) {
-		/* Store report for later inclusion by
-		 * mgmt_device_connected
-		 */
-		memcpy(conn->le_adv_data, data, len);
-		conn->le_adv_data_len = len;
-	}
+	check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
 
 	/* Passive scanning shouldn't trigger any device found events,
 	 * except for devices marked as CONN_REPORT for which we do send
@@ -4617,8 +4481,7 @@
 
 		rssi = ev->data[ev->length];
 		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
-				   ev->bdaddr_type, NULL, 0, rssi,
-				   ev->data, ev->length);
+				   ev->bdaddr_type, rssi, ev->data, ev->length);
 
 		ptr += sizeof(*ev) + ev->length + 1;
 	}
@@ -4642,20 +4505,10 @@
 	if (conn == NULL)
 		goto not_found;
 
-	ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role);
-	if (!ltk)
+	ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role);
+	if (ltk == NULL)
 		goto not_found;
 
-	if (smp_ltk_is_sc(ltk)) {
-		/* With SC both EDiv and Rand are set to zero */
-		if (ev->ediv || ev->rand)
-			goto not_found;
-	} else {
-		/* For non-SC keys check that EDiv and Rand match */
-		if (ev->ediv != ltk->ediv || ev->rand != ltk->rand)
-			goto not_found;
-	}
-
 	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
 	cp.handle = cpu_to_le16(conn->handle);
 
@@ -4673,8 +4526,8 @@
 	 */
 	if (ltk->type == SMP_STK) {
 		set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
-		list_del_rcu(&ltk->list);
-		kfree_rcu(ltk, rcu);
+		list_del(&ltk->list);
+		kfree(ltk);
 	} else {
 		clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
 	}
@@ -4759,27 +4612,6 @@
 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
 }
 
-static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
-					 struct sk_buff *skb)
-{
-	u8 num_reports = skb->data[0];
-	void *ptr = &skb->data[1];
-
-	hci_dev_lock(hdev);
-
-	while (num_reports--) {
-		struct hci_ev_le_direct_adv_info *ev = ptr;
-
-		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
-				   ev->bdaddr_type, &ev->direct_addr,
-				   ev->direct_addr_type, ev->rssi, NULL, 0);
-
-		ptr += sizeof(*ev);
-	}
-
-	hci_dev_unlock(hdev);
-}
-
 static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -4807,10 +4639,6 @@
 		hci_le_remote_conn_param_req_evt(hdev, skb);
 		break;
 
-	case HCI_EV_LE_DIRECT_ADV_REPORT:
-		hci_le_direct_adv_report_evt(hdev, skb);
-		break;
-
 	default:
 		break;
 	}
@@ -4907,10 +4735,6 @@
 		hci_cmd_status_evt(hdev, skb);
 		break;
 
-	case HCI_EV_HARDWARE_ERROR:
-		hci_hardware_error_evt(hdev, skb);
-		break;
-
 	case HCI_EV_ROLE_CHANGE:
 		hci_role_change_evt(hdev, skb);
 		break;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 2c245fd..115f149 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -878,7 +878,7 @@
 	}
 
 	skb_reset_transport_header(skb);
-	err = skb_copy_datagram_msg(skb, 0, msg, copied);
+	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
 	switch (hci_pi(sk)->channel) {
 	case HCI_CHANNEL_RAW:
@@ -947,7 +947,7 @@
 	if (!skb)
 		goto done;
 
-	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
 		err = -EFAULT;
 		goto drop;
 	}
@@ -987,7 +987,7 @@
 			skb_queue_tail(&hdev->raw_q, skb);
 			queue_work(hdev->workqueue, &hdev->tx_work);
 		} else {
-			/* Stand-alone HCI commands must be flagged as
+			/* Stand-alone HCI commands must be flaged as
 			 * single-command requests.
 			 */
 			bt_cb(skb)->req.start = true;
diff --git a/net/bluetooth/hidp/Kconfig b/net/bluetooth/hidp/Kconfig
index d63ec58..869dd8b 100644
--- a/net/bluetooth/hidp/Kconfig
+++ b/net/bluetooth/hidp/Kconfig
@@ -1,7 +1,7 @@
 config BT_HIDP
 	tristate "HIDP protocol support"
 	depends on m
-	depends on BT_BREDR && INPUT
+	depends on BT && INPUT
 	depends on HID
 	help
 	  HIDP (Human Interface Device Protocol) is a transport layer
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 867f53e..1687cc7 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -740,10 +740,14 @@
 	struct hid_device *hid;
 	int err;
 
-	session->rd_data = memdup_user(req->rd_data, req->rd_size);
-	if (IS_ERR(session->rd_data))
-		return PTR_ERR(session->rd_data);
+	session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
+	if (!session->rd_data)
+		return -ENOMEM;
 
+	if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
+		err = -EFAULT;
+		goto fault;
+	}
 	session->rd_size = req->rd_size;
 
 	hid = hid_allocate_device();
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3c6bfb1..b6f9777 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -46,6 +46,7 @@
 bool disable_ertm;
 
 static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
+static u8 l2cap_fixed_chan[8] = { L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS, };
 
 static LIST_HEAD(chan_list);
 static DEFINE_RWLOCK(chan_list_lock);
@@ -423,9 +424,6 @@
 
 	mutex_init(&chan->lock);
 
-	/* Set default lock nesting level */
-	atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
-
 	write_lock(&chan_list_lock);
 	list_add(&chan->global_l, &chan_list);
 	write_unlock(&chan_list_lock);
@@ -569,8 +567,7 @@
 
 	__clear_chan_timer(chan);
 
-	BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
-	       state_to_string(chan->state));
+	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
 
 	chan->ops->teardown(chan, err);
 
@@ -839,10 +836,7 @@
 	if (!skb)
 		return;
 
-	/* Use NO_FLUSH if supported or we have an LE link (which does
-	 * not support auto-flushing packets) */
-	if (lmp_no_flush_capable(conn->hcon->hdev) ||
-	    conn->hcon->type == LE_LINK)
+	if (lmp_no_flush_capable(conn->hcon->hdev))
 		flags = ACL_START_NO_FLUSH;
 	else
 		flags = ACL_START;
@@ -876,13 +870,8 @@
 		return;
 	}
 
-	/* Use NO_FLUSH for LE links (where this is the only option) or
-	 * if the BR/EDR link supports it and flushing has not been
-	 * explicitly requested (through FLAG_FLUSHABLE).
-	 */
-	if (hcon->type == LE_LINK ||
-	    (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
-	     lmp_no_flush_capable(hcon->hdev)))
+	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
+	    lmp_no_flush_capable(hcon->hdev))
 		flags = ACL_START_NO_FLUSH;
 	else
 		flags = ACL_START;
@@ -1119,10 +1108,10 @@
 	struct hci_dev *hdev;
 	bool amp_available = false;
 
-	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+	if (!conn->hs_enabled)
 		return false;
 
-	if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
+	if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP))
 		return false;
 
 	read_lock(&hci_dev_list_lock);
@@ -2103,12 +2092,8 @@
 	struct sk_buff **frag;
 	int sent = 0;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-	if (copy_from_iter(skb_put(skb, count), count, &msg->msg_iter) != count)
-#else
 	if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count),
 					msg->msg_iov, count))
-#endif
 		return -EFAULT;
 
 	sent += count;
@@ -2128,13 +2113,8 @@
 
 		*frag = tmp;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-		if (copy_from_iter(skb_put(*frag, count), count,
-				   &msg->msg_iter) != count)
-#else
 		if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count),
 						msg->msg_iov, count))
-#endif
 			return -EFAULT;
 
 		sent += count;
@@ -3104,14 +3084,12 @@
 
 static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
 {
-	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
-		(conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
+	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
 }
 
 static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
 {
-	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
-		(conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
+	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
 }
 
 static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
@@ -3340,7 +3318,7 @@
 			break;
 
 		case L2CAP_CONF_EWS:
-			if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
+			if (!chan->conn->hs_enabled)
 				return -ECONNREFUSED;
 
 			set_bit(FLAG_EXT_CTRL, &chan->flags);
@@ -3895,7 +3873,9 @@
 	hci_dev_lock(hdev);
 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
-		mgmt_device_connected(hdev, hcon, 0, NULL, 0);
+		mgmt_device_connected(hdev, &hcon->dst, hcon->type,
+				      hcon->dst_type, 0, NULL, 0,
+				      hcon->dev_class);
 	hci_dev_unlock(hdev);
 
 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
@@ -4104,7 +4084,7 @@
 		chan->num_conf_req++;
 	}
 
-	/* Got Conf Rsp PENDING from remote side and assume we sent
+	/* Got Conf Rsp PENDING from remote side and asume we sent
 	   Conf Rsp PENDING in the code above */
 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
@@ -4344,7 +4324,7 @@
 		if (!disable_ertm)
 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
 				| L2CAP_FEAT_FCS;
-		if (conn->local_fixed_chan & L2CAP_FC_A2MP)
+		if (conn->hs_enabled)
 			feat_mask |= L2CAP_FEAT_EXT_FLOW
 				| L2CAP_FEAT_EXT_WINDOW;
 
@@ -4355,10 +4335,14 @@
 		u8 buf[12];
 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
 
+		if (conn->hs_enabled)
+			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
+		else
+			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
+
 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
-		rsp->data[0] = conn->local_fixed_chan;
-		memset(rsp->data + 1, 0, 7);
+		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
 			       buf);
 	} else {
@@ -4424,7 +4408,7 @@
 		break;
 
 	case L2CAP_IT_FIXED_CHAN:
-		conn->remote_fixed_chan = rsp->data[0];
+		conn->fixed_chan_mask = rsp->data[0];
 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
 		conn->info_ident = 0;
 
@@ -4448,7 +4432,7 @@
 	if (cmd_len != sizeof(*req))
 		return -EPROTO;
 
-	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+	if (!conn->hs_enabled)
 		return -EINVAL;
 
 	psm = le16_to_cpu(req->psm);
@@ -4878,7 +4862,7 @@
 
 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
 
-	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+	if (!conn->hs_enabled)
 		return -EINVAL;
 
 	chan = l2cap_get_chan_by_dcid(conn, icid);
@@ -5233,10 +5217,9 @@
 				u8 *data)
 {
 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
-	struct hci_conn *hcon = conn->hcon;
 	u16 dcid, mtu, mps, credits, result;
 	struct l2cap_chan *chan;
-	int err, sec_level;
+	int err;
 
 	if (cmd_len < sizeof(*rsp))
 		return -EPROTO;
@@ -5275,26 +5258,6 @@
 		l2cap_chan_ready(chan);
 		break;
 
-	case L2CAP_CR_AUTHENTICATION:
-	case L2CAP_CR_ENCRYPTION:
-		/* If we already have MITM protection we can't do
-		 * anything.
-		 */
-		if (hcon->sec_level > BT_SECURITY_MEDIUM) {
-			l2cap_chan_del(chan, ECONNREFUSED);
-			break;
-		}
-
-		sec_level = hcon->sec_level + 1;
-		if (chan->sec_level < sec_level)
-			chan->sec_level = sec_level;
-
-		/* We'll need to send a new Connect Request */
-		clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
-
-		smp_conn_security(hcon, chan->sec_level);
-		break;
-
 	default:
 		l2cap_chan_del(chan, ECONNREFUSED);
 		break;
@@ -5427,8 +5390,7 @@
 	mutex_lock(&conn->chan_lock);
 	l2cap_chan_lock(pchan);
 
-	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
-				     SMP_ALLOW_STK)) {
+	if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) {
 		result = L2CAP_CR_AUTHENTICATION;
 		chan = NULL;
 		goto response_unlock;
@@ -5532,7 +5494,6 @@
 	if (credits > max_credits) {
 		BT_ERR("LE credits overflow");
 		l2cap_send_disconn_req(chan, ECONNRESET);
-		l2cap_chan_unlock(chan);
 
 		/* Return 0 so that we don't trigger an unnecessary
 		 * command reject packet.
@@ -6970,16 +6931,9 @@
 
 	conn->feat_mask = 0;
 
-	conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
-
-	if (hcon->type == ACL_LINK &&
-	    test_bit(HCI_HS_ENABLED, &hcon->hdev->dev_flags))
-		conn->local_fixed_chan |= L2CAP_FC_A2MP;
-
-	if (test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags) &&
-	    (bredr_sc_enabled(hcon->hdev) ||
-	     test_bit(HCI_FORCE_LESC, &hcon->hdev->dbg_flags)))
-		conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
+	if (hcon->type == ACL_LINK)
+		conn->hs_enabled = test_bit(HCI_HS_ENABLED,
+					    &hcon->hdev->dev_flags);
 
 	mutex_init(&conn->ident_lock);
 	mutex_init(&conn->chan_lock);
@@ -7376,8 +7330,7 @@
 				l2cap_start_connection(chan);
 			else
 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
-		} else if (chan->state == BT_CONNECT2 &&
-			   chan->mode != L2CAP_MODE_LE_FLOWCTL) {
+		} else if (chan->state == BT_CONNECT2) {
 			struct l2cap_conn_rsp rsp;
 			__u16 res, stat;
 
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index b2ca901..c53387f 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -285,12 +285,6 @@
 	sk->sk_max_ack_backlog = backlog;
 	sk->sk_ack_backlog = 0;
 
-	/* Listening channels need to use nested locking in order not to
-	 * cause lockdep warnings when the created child channels end up
-	 * being locked in the same thread as the parent channel.
-	 */
-	atomic_set(&chan->nesting, L2CAP_NESTING_PARENT);
-
 	chan->state = BT_LISTEN;
 	sk->sk_state = BT_LISTEN;
 
@@ -307,7 +301,7 @@
 	long timeo;
 	int err = 0;
 
-	lock_sock_nested(sk, L2CAP_NESTING_PARENT);
+	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
 	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
@@ -339,7 +333,7 @@
 
 		release_sock(sk);
 		timeo = schedule_timeout(timeo);
-		lock_sock_nested(sk, L2CAP_NESTING_PARENT);
+		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 	}
 	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(sk_sleep(sk), &wait);
@@ -1102,8 +1096,6 @@
 	chan = l2cap_pi(sk)->chan;
 	conn = chan->conn;
 
-	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
-
 	if (conn)
 		mutex_lock(&conn->chan_lock);
 
@@ -1161,16 +1153,12 @@
 {
 	struct sock *sk;
 
-	BT_DBG("parent %p state %s", parent,
-	       state_to_string(parent->sk_state));
+	BT_DBG("parent %p", parent);
 
 	/* Close not yet accepted channels */
 	while ((sk = bt_accept_dequeue(parent, NULL))) {
 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 
-		BT_DBG("child chan %p state %s", chan,
-		       state_to_string(chan->state));
-
 		l2cap_chan_lock(chan);
 		__clear_chan_timer(chan);
 		l2cap_chan_close(chan, ECONNRESET);
@@ -1258,16 +1246,7 @@
 	struct sock *sk = chan->data;
 	struct sock *parent;
 
-	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
-
-	/* This callback can be called both for server (BT_LISTEN)
-	 * sockets as well as "normal" ones. To avoid lockdep warnings
-	 * with child socket locking (through l2cap_sock_cleanup_listen)
-	 * we need separation into separate nesting levels. The simplest
-	 * way to accomplish this is to inherit the nesting level used
-	 * for the channel.
-	 */
-	lock_sock_nested(sk, atomic_read(&chan->nesting));
+	lock_sock(sk);
 
 	parent = bt_sk(sk)->parent;
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 693ce8b..efb71b0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -35,7 +35,7 @@
 #include "smp.h"
 
 #define MGMT_VERSION	1
-#define MGMT_REVISION	8
+#define MGMT_REVISION	7
 
 static const u16 mgmt_commands[] = {
 	MGMT_OP_READ_INDEX_LIST,
@@ -93,7 +93,6 @@
 	MGMT_OP_READ_CONFIG_INFO,
 	MGMT_OP_SET_EXTERNAL_CONFIG,
 	MGMT_OP_SET_PUBLIC_ADDRESS,
-	MGMT_OP_START_SERVICE_DISCOVERY,
 };
 
 static const u16 mgmt_events[] = {
@@ -135,10 +134,8 @@
 	u16 opcode;
 	int index;
 	void *param;
-	size_t param_len;
 	struct sock *sk;
 	void *user_data;
-	void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
 };
 
 /* HCI to MGMT error code conversion table */
@@ -577,7 +574,6 @@
 	if (lmp_le_capable(hdev)) {
 		settings |= MGMT_SETTING_LE;
 		settings |= MGMT_SETTING_ADVERTISING;
-		settings |= MGMT_SETTING_SECURE_CONN;
 		settings |= MGMT_SETTING_PRIVACY;
 	}
 
@@ -1206,13 +1202,14 @@
 	cmd->opcode = opcode;
 	cmd->index = hdev->id;
 
-	cmd->param = kmemdup(data, len, GFP_KERNEL);
+	cmd->param = kmalloc(len, GFP_KERNEL);
 	if (!cmd->param) {
 		kfree(cmd);
 		return NULL;
 	}
 
-	cmd->param_len = len;
+	if (data)
+		memcpy(cmd->param, data, len);
 
 	cmd->sk = sk;
 	sock_hold(sk);
@@ -1472,32 +1469,6 @@
 	mgmt_pending_remove(cmd);
 }
 
-static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
-{
-	if (cmd->cmd_complete) {
-		u8 *status = data;
-
-		cmd->cmd_complete(cmd, *status);
-		mgmt_pending_remove(cmd);
-
-		return;
-	}
-
-	cmd_status_rsp(cmd, data);
-}
-
-static void generic_cmd_complete(struct pending_cmd *cmd, u8 status)
-{
-	cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
-		     cmd->param_len);
-}
-
-static void addr_cmd_complete(struct pending_cmd *cmd, u8 status)
-{
-	cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
-		     sizeof(struct mgmt_addr_info));
-}
-
 static u8 mgmt_bredr_support(struct hci_dev *hdev)
 {
 	if (!lmp_bredr_capable(hdev))
@@ -2199,14 +2170,12 @@
 {
 	struct cmd_lookup match = { NULL, hdev };
 
-	hci_dev_lock(hdev);
-
 	if (status) {
 		u8 mgmt_err = mgmt_status(status);
 
 		mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
 				     &mgmt_err);
-		goto unlock;
+		return;
 	}
 
 	mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
@@ -2224,16 +2193,17 @@
 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
 		struct hci_request req;
 
+		hci_dev_lock(hdev);
+
 		hci_req_init(&req, hdev);
 		update_adv_data(&req);
 		update_scan_rsp_data(&req);
 		hci_req_run(&req, NULL);
 
 		hci_update_background_scan(hdev);
-	}
 
-unlock:
-	hci_dev_unlock(hdev);
+		hci_dev_unlock(hdev);
+	}
 }
 
 static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
@@ -2755,40 +2725,10 @@
 	}
 
 	if (cp->addr.type == BDADDR_BREDR) {
-		/* If disconnection is requested, then look up the
-		 * connection. If the remote device is connected, it
-		 * will be later used to terminate the link.
-		 *
-		 * Setting it to NULL explicitly will cause no
-		 * termination of the link.
-		 */
-		if (cp->disconnect)
-			conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
-						       &cp->addr.bdaddr);
-		else
-			conn = NULL;
-
 		err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
 	} else {
 		u8 addr_type;
 
-		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
-					       &cp->addr.bdaddr);
-		if (conn) {
-			/* Defer clearing up the connection parameters
-			 * until closing to give a chance of keeping
-			 * them if a repairing happens.
-			 */
-			set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
-
-			/* If disconnection is not requested, then
-			 * clear the connection variable so that the
-			 * link is not terminated.
-			 */
-			if (!cp->disconnect)
-				conn = NULL;
-		}
-
 		if (cp->addr.type == BDADDR_LE_PUBLIC)
 			addr_type = ADDR_LE_DEV_PUBLIC;
 		else
@@ -2796,6 +2736,8 @@
 
 		hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
 
+		hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
+
 		err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
 	}
 
@@ -2805,9 +2747,17 @@
 		goto unlock;
 	}
 
-	/* If the connection variable is set, then termination of the
-	 * link is requested.
-	 */
+	if (cp->disconnect) {
+		if (cp->addr.type == BDADDR_BREDR)
+			conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
+						       &cp->addr.bdaddr);
+		else
+			conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
+						       &cp->addr.bdaddr);
+	} else {
+		conn = NULL;
+	}
+
 	if (!conn) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
 				   &rp, sizeof(rp));
@@ -2822,8 +2772,6 @@
 		goto unlock;
 	}
 
-	cmd->cmd_complete = addr_cmd_complete;
-
 	dc.handle = cpu_to_le16(conn->handle);
 	dc.reason = 0x13; /* Remote User Terminated Connection */
 	err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
@@ -2887,8 +2835,6 @@
 		goto failed;
 	}
 
-	cmd->cmd_complete = generic_cmd_complete;
-
 	err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
@@ -3041,8 +2987,6 @@
 		goto failed;
 	}
 
-	cmd->cmd_complete = addr_cmd_complete;
-
 	bacpy(&reply.bdaddr, &cp->addr.bdaddr);
 	reply.pin_len = cp->pin_len;
 	memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
@@ -3115,13 +3059,9 @@
 	conn->disconn_cfm_cb = NULL;
 
 	hci_conn_drop(conn);
-
-	/* The device is paired so there is no need to remove
-	 * its connection parameters anymore.
-	 */
-	clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
-
 	hci_conn_put(conn);
+
+	mgmt_pending_remove(cmd);
 }
 
 void mgmt_smp_complete(struct hci_conn *conn, bool complete)
@@ -3130,10 +3070,8 @@
 	struct pending_cmd *cmd;
 
 	cmd = find_pairing(conn);
-	if (cmd) {
-		cmd->cmd_complete(cmd, status);
-		mgmt_pending_remove(cmd);
-	}
+	if (cmd)
+		pairing_complete(cmd, status);
 }
 
 static void pairing_complete_cb(struct hci_conn *conn, u8 status)
@@ -3143,13 +3081,10 @@
 	BT_DBG("status %u", status);
 
 	cmd = find_pairing(conn);
-	if (!cmd) {
+	if (!cmd)
 		BT_DBG("Unable to find a pending command");
-		return;
-	}
-
-	cmd->cmd_complete(cmd, mgmt_status(status));
-	mgmt_pending_remove(cmd);
+	else
+		pairing_complete(cmd, mgmt_status(status));
 }
 
 static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
@@ -3162,13 +3097,10 @@
 		return;
 
 	cmd = find_pairing(conn);
-	if (!cmd) {
+	if (!cmd)
 		BT_DBG("Unable to find a pending command");
-		return;
-	}
-
-	cmd->cmd_complete(cmd, mgmt_status(status));
-	mgmt_pending_remove(cmd);
+	else
+		pairing_complete(cmd, mgmt_status(status));
 }
 
 static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -3265,8 +3197,6 @@
 		goto unlock;
 	}
 
-	cmd->cmd_complete = pairing_complete;
-
 	/* For LE, just connecting isn't a proof that the pairing finished */
 	if (cp->addr.type == BDADDR_BREDR) {
 		conn->connect_cfm_cb = pairing_complete_cb;
@@ -3282,10 +3212,8 @@
 	cmd->user_data = hci_conn_get(conn);
 
 	if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
-	    hci_conn_security(conn, sec_level, auth_type, true)) {
-		cmd->cmd_complete(cmd, 0);
-		mgmt_pending_remove(cmd);
-	}
+	    hci_conn_security(conn, sec_level, auth_type, true))
+		pairing_complete(cmd, 0);
 
 	err = 0;
 
@@ -3327,8 +3255,7 @@
 		goto unlock;
 	}
 
-	cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
-	mgmt_pending_remove(cmd);
+	pairing_complete(cmd, MGMT_STATUS_CANCELLED);
 
 	err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
 			   addr, sizeof(*addr));
@@ -3386,8 +3313,6 @@
 		goto done;
 	}
 
-	cmd->cmd_complete = addr_cmd_complete;
-
 	/* Continue with pairing via HCI */
 	if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
 		struct hci_cp_user_passkey_reply cp;
@@ -3612,7 +3537,7 @@
 		goto unlock;
 	}
 
-	if (bredr_sc_enabled(hdev))
+	if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
 		err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
 				   0, NULL);
 	else
@@ -3639,17 +3564,8 @@
 		struct mgmt_cp_add_remote_oob_data *cp = data;
 		u8 status;
 
-		if (cp->addr.type != BDADDR_BREDR) {
-			err = cmd_complete(sk, hdev->id,
-					   MGMT_OP_ADD_REMOTE_OOB_DATA,
-					   MGMT_STATUS_INVALID_PARAMS,
-					   &cp->addr, sizeof(cp->addr));
-			goto unlock;
-		}
-
 		err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
-					      cp->addr.type, cp->hash,
-					      cp->rand, NULL, NULL);
+					      cp->hash, cp->randomizer);
 		if (err < 0)
 			status = MGMT_STATUS_FAILED;
 		else
@@ -3659,28 +3575,13 @@
 				   status, &cp->addr, sizeof(cp->addr));
 	} else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
 		struct mgmt_cp_add_remote_oob_ext_data *cp = data;
-		u8 *rand192, *hash192;
 		u8 status;
 
-		if (cp->addr.type != BDADDR_BREDR) {
-			err = cmd_complete(sk, hdev->id,
-					   MGMT_OP_ADD_REMOTE_OOB_DATA,
-					   MGMT_STATUS_INVALID_PARAMS,
-					   &cp->addr, sizeof(cp->addr));
-			goto unlock;
-		}
-
-		if (bdaddr_type_is_le(cp->addr.type)) {
-			rand192 = NULL;
-			hash192 = NULL;
-		} else {
-			rand192 = cp->rand192;
-			hash192 = cp->hash192;
-		}
-
-		err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
-					      cp->addr.type, hash192, rand192,
-					      cp->hash256, cp->rand256);
+		err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
+						  cp->hash192,
+						  cp->randomizer192,
+						  cp->hash256,
+						  cp->randomizer256);
 		if (err < 0)
 			status = MGMT_STATUS_FAILED;
 		else
@@ -3694,7 +3595,6 @@
 				 MGMT_STATUS_INVALID_PARAMS);
 	}
 
-unlock:
 	hci_dev_unlock(hdev);
 	return err;
 }
@@ -3708,26 +3608,14 @@
 
 	BT_DBG("%s", hdev->name);
 
-	if (cp->addr.type != BDADDR_BREDR)
-		return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
-				    MGMT_STATUS_INVALID_PARAMS,
-				    &cp->addr, sizeof(cp->addr));
-
 	hci_dev_lock(hdev);
 
-	if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
-		hci_remote_oob_data_clear(hdev);
-		status = MGMT_STATUS_SUCCESS;
-		goto done;
-	}
-
-	err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
+	err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
 	if (err < 0)
 		status = MGMT_STATUS_INVALID_PARAMS;
 	else
 		status = MGMT_STATUS_SUCCESS;
 
-done:
 	err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
 			   status, &cp->addr, sizeof(cp->addr));
 
@@ -3735,26 +3623,127 @@
 	return err;
 }
 
-static bool trigger_discovery(struct hci_request *req, u8 *status)
+static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
 {
-	struct hci_dev *hdev = req->hdev;
+	struct pending_cmd *cmd;
+	u8 type;
+	int err;
+
+	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+
+	cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
+	if (!cmd)
+		return -ENOENT;
+
+	type = hdev->discovery.type;
+
+	err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
+			   &type, sizeof(type));
+	mgmt_pending_remove(cmd);
+
+	return err;
+}
+
+static void start_discovery_complete(struct hci_dev *hdev, u8 status)
+{
+	unsigned long timeout = 0;
+
+	BT_DBG("status %d", status);
+
+	if (status) {
+		hci_dev_lock(hdev);
+		mgmt_start_discovery_failed(hdev, status);
+		hci_dev_unlock(hdev);
+		return;
+	}
+
+	hci_dev_lock(hdev);
+	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
+	hci_dev_unlock(hdev);
+
+	switch (hdev->discovery.type) {
+	case DISCOV_TYPE_LE:
+		timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
+		break;
+
+	case DISCOV_TYPE_INTERLEAVED:
+		timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
+		break;
+
+	case DISCOV_TYPE_BREDR:
+		break;
+
+	default:
+		BT_ERR("Invalid discovery type %d", hdev->discovery.type);
+	}
+
+	if (!timeout)
+		return;
+
+	queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
+}
+
+static int start_discovery(struct sock *sk, struct hci_dev *hdev,
+			   void *data, u16 len)
+{
+	struct mgmt_cp_start_discovery *cp = data;
+	struct pending_cmd *cmd;
 	struct hci_cp_le_set_scan_param param_cp;
 	struct hci_cp_le_set_scan_enable enable_cp;
 	struct hci_cp_inquiry inq_cp;
+	struct hci_request req;
 	/* General inquiry access code (GIAC) */
 	u8 lap[3] = { 0x33, 0x8b, 0x9e };
-	u8 own_addr_type;
+	u8 status, own_addr_type;
 	int err;
 
+	BT_DBG("%s", hdev->name);
+
+	hci_dev_lock(hdev);
+
+	if (!hdev_is_powered(hdev)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+				 MGMT_STATUS_NOT_POWERED);
+		goto failed;
+	}
+
+	if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+				 MGMT_STATUS_BUSY);
+		goto failed;
+	}
+
+	if (hdev->discovery.state != DISCOVERY_STOPPED) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+				 MGMT_STATUS_BUSY);
+		goto failed;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	hdev->discovery.type = cp->type;
+
+	hci_req_init(&req, hdev);
+
 	switch (hdev->discovery.type) {
 	case DISCOV_TYPE_BREDR:
-		*status = mgmt_bredr_support(hdev);
-		if (*status)
-			return false;
+		status = mgmt_bredr_support(hdev);
+		if (status) {
+			err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+					 status);
+			mgmt_pending_remove(cmd);
+			goto failed;
+		}
 
 		if (test_bit(HCI_INQUIRY, &hdev->flags)) {
-			*status = MGMT_STATUS_BUSY;
-			return false;
+			err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+					 MGMT_STATUS_BUSY);
+			mgmt_pending_remove(cmd);
+			goto failed;
 		}
 
 		hci_inquiry_cache_flush(hdev);
@@ -3762,19 +3751,25 @@
 		memset(&inq_cp, 0, sizeof(inq_cp));
 		memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
 		inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
-		hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
+		hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
 		break;
 
 	case DISCOV_TYPE_LE:
 	case DISCOV_TYPE_INTERLEAVED:
-		*status = mgmt_le_support(hdev);
-		if (*status)
-			return false;
+		status = mgmt_le_support(hdev);
+		if (status) {
+			err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+					 status);
+			mgmt_pending_remove(cmd);
+			goto failed;
+		}
 
 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
 		    !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
-			*status = MGMT_STATUS_NOT_SUPPORTED;
-			return false;
+			err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+					 MGMT_STATUS_NOT_SUPPORTED);
+			mgmt_pending_remove(cmd);
+			goto failed;
 		}
 
 		if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
@@ -3784,11 +3779,14 @@
 			 */
 			if (hci_conn_hash_lookup_state(hdev, LE_LINK,
 						       BT_CONNECT)) {
-				*status = MGMT_STATUS_REJECTED;
-				return false;
+				err = cmd_status(sk, hdev->id,
+						 MGMT_OP_START_DISCOVERY,
+						 MGMT_STATUS_REJECTED);
+				mgmt_pending_remove(cmd);
+				goto failed;
 			}
 
-			disable_advertising(req);
+			disable_advertising(&req);
 		}
 
 		/* If controller is scanning, it means the background scanning
@@ -3796,287 +3794,84 @@
 		 * set the discovery scanning parameters.
 		 */
 		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
-			hci_req_add_le_scan_disable(req);
+			hci_req_add_le_scan_disable(&req);
 
 		memset(&param_cp, 0, sizeof(param_cp));
 
 		/* All active scans will be done with either a resolvable
 		 * private address (when privacy feature has been enabled)
-		 * or non-resolvable private address.
+		 * or unresolvable private address.
 		 */
-		err = hci_update_random_address(req, true, &own_addr_type);
+		err = hci_update_random_address(&req, true, &own_addr_type);
 		if (err < 0) {
-			*status = MGMT_STATUS_FAILED;
-			return false;
+			err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+					 MGMT_STATUS_FAILED);
+			mgmt_pending_remove(cmd);
+			goto failed;
 		}
 
 		param_cp.type = LE_SCAN_ACTIVE;
 		param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
 		param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
 		param_cp.own_address_type = own_addr_type;
-		hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+		hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
 			    &param_cp);
 
 		memset(&enable_cp, 0, sizeof(enable_cp));
 		enable_cp.enable = LE_SCAN_ENABLE;
 		enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
-		hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+		hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
 			    &enable_cp);
 		break;
 
 	default:
-		*status = MGMT_STATUS_INVALID_PARAMS;
-		return false;
-	}
-
-	return true;
-}
-
-static void start_discovery_complete(struct hci_dev *hdev, u8 status)
-{
-	struct pending_cmd *cmd;
-	unsigned long timeout;
-
-	BT_DBG("status %d", status);
-
-	hci_dev_lock(hdev);
-
-	cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
-	if (!cmd)
-		cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
-
-	if (cmd) {
-		cmd->cmd_complete(cmd, mgmt_status(status));
-		mgmt_pending_remove(cmd);
-	}
-
-	if (status) {
-		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
-		goto unlock;
-	}
-
-	hci_discovery_set_state(hdev, DISCOVERY_FINDING);
-
-	switch (hdev->discovery.type) {
-	case DISCOV_TYPE_LE:
-		timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
-		break;
-	case DISCOV_TYPE_INTERLEAVED:
-		timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
-		break;
-	case DISCOV_TYPE_BREDR:
-		timeout = 0;
-		break;
-	default:
-		BT_ERR("Invalid discovery type %d", hdev->discovery.type);
-		timeout = 0;
-		break;
-	}
-
-	if (timeout)
-		queue_delayed_work(hdev->workqueue,
-				   &hdev->le_scan_disable, timeout);
-
-unlock:
-	hci_dev_unlock(hdev);
-}
-
-static int start_discovery(struct sock *sk, struct hci_dev *hdev,
-			   void *data, u16 len)
-{
-	struct mgmt_cp_start_discovery *cp = data;
-	struct pending_cmd *cmd;
-	struct hci_request req;
-	u8 status;
-	int err;
-
-	BT_DBG("%s", hdev->name);
-
-	hci_dev_lock(hdev);
-
-	if (!hdev_is_powered(hdev)) {
-		err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-				   MGMT_STATUS_NOT_POWERED,
-				   &cp->type, sizeof(cp->type));
-		goto failed;
-	}
-
-	if (hdev->discovery.state != DISCOVERY_STOPPED ||
-	    test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
-		err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-				   MGMT_STATUS_BUSY, &cp->type,
-				   sizeof(cp->type));
-		goto failed;
-	}
-
-	cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
-	if (!cmd) {
-		err = -ENOMEM;
-		goto failed;
-	}
-
-	cmd->cmd_complete = generic_cmd_complete;
-
-	/* Clear the discovery filter first to free any previously
-	 * allocated memory for the UUID list.
-	 */
-	hci_discovery_filter_clear(hdev);
-
-	hdev->discovery.type = cp->type;
-	hdev->discovery.report_invalid_rssi = false;
-
-	hci_req_init(&req, hdev);
-
-	if (!trigger_discovery(&req, &status)) {
-		err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-				   status, &cp->type, sizeof(cp->type));
+		err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+				 MGMT_STATUS_INVALID_PARAMS);
 		mgmt_pending_remove(cmd);
 		goto failed;
 	}
 
 	err = hci_req_run(&req, start_discovery_complete);
-	if (err < 0) {
+	if (err < 0)
 		mgmt_pending_remove(cmd);
-		goto failed;
-	}
-
-	hci_discovery_set_state(hdev, DISCOVERY_STARTING);
+	else
+		hci_discovery_set_state(hdev, DISCOVERY_STARTING);
 
 failed:
 	hci_dev_unlock(hdev);
 	return err;
 }
 
-static void service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
+static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
 {
-	cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param, 1);
-}
-
-static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
-				   void *data, u16 len)
-{
-	struct mgmt_cp_start_service_discovery *cp = data;
 	struct pending_cmd *cmd;
-	struct hci_request req;
-	const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
-	u16 uuid_count, expected_len;
-	u8 status;
 	int err;
 
-	BT_DBG("%s", hdev->name);
+	cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
+	if (!cmd)
+		return -ENOENT;
 
-	hci_dev_lock(hdev);
+	err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
+			   &hdev->discovery.type, sizeof(hdev->discovery.type));
+	mgmt_pending_remove(cmd);
 
-	if (!hdev_is_powered(hdev)) {
-		err = cmd_complete(sk, hdev->id,
-				   MGMT_OP_START_SERVICE_DISCOVERY,
-				   MGMT_STATUS_NOT_POWERED,
-				   &cp->type, sizeof(cp->type));
-		goto failed;
-	}
-
-	if (hdev->discovery.state != DISCOVERY_STOPPED ||
-	    test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
-		err = cmd_complete(sk, hdev->id,
-				   MGMT_OP_START_SERVICE_DISCOVERY,
-				   MGMT_STATUS_BUSY, &cp->type,
-				   sizeof(cp->type));
-		goto failed;
-	}
-
-	uuid_count = __le16_to_cpu(cp->uuid_count);
-	if (uuid_count > max_uuid_count) {
-		BT_ERR("service_discovery: too big uuid_count value %u",
-		       uuid_count);
-		err = cmd_complete(sk, hdev->id,
-				   MGMT_OP_START_SERVICE_DISCOVERY,
-				   MGMT_STATUS_INVALID_PARAMS, &cp->type,
-				   sizeof(cp->type));
-		goto failed;
-	}
-
-	expected_len = sizeof(*cp) + uuid_count * 16;
-	if (expected_len != len) {
-		BT_ERR("service_discovery: expected %u bytes, got %u bytes",
-		       expected_len, len);
-		err = cmd_complete(sk, hdev->id,
-				   MGMT_OP_START_SERVICE_DISCOVERY,
-				   MGMT_STATUS_INVALID_PARAMS, &cp->type,
-				   sizeof(cp->type));
-		goto failed;
-	}
-
-	cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
-			       hdev, data, len);
-	if (!cmd) {
-		err = -ENOMEM;
-		goto failed;
-	}
-
-	cmd->cmd_complete = service_discovery_cmd_complete;
-
-	/* Clear the discovery filter first to free any previously
-	 * allocated memory for the UUID list.
-	 */
-	hci_discovery_filter_clear(hdev);
-
-	hdev->discovery.type = cp->type;
-	hdev->discovery.rssi = cp->rssi;
-	hdev->discovery.uuid_count = uuid_count;
-
-	if (uuid_count > 0) {
-		hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
-						GFP_KERNEL);
-		if (!hdev->discovery.uuids) {
-			err = cmd_complete(sk, hdev->id,
-					   MGMT_OP_START_SERVICE_DISCOVERY,
-					   MGMT_STATUS_FAILED,
-					   &cp->type, sizeof(cp->type));
-			mgmt_pending_remove(cmd);
-			goto failed;
-		}
-	}
-
-	hci_req_init(&req, hdev);
-
-	if (!trigger_discovery(&req, &status)) {
-		err = cmd_complete(sk, hdev->id,
-				   MGMT_OP_START_SERVICE_DISCOVERY,
-				   status, &cp->type, sizeof(cp->type));
-		mgmt_pending_remove(cmd);
-		goto failed;
-	}
-
-	err = hci_req_run(&req, start_discovery_complete);
-	if (err < 0) {
-		mgmt_pending_remove(cmd);
-		goto failed;
-	}
-
-	hci_discovery_set_state(hdev, DISCOVERY_STARTING);
-
-failed:
-	hci_dev_unlock(hdev);
 	return err;
 }
 
 static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
 {
-	struct pending_cmd *cmd;
-
 	BT_DBG("status %d", status);
 
 	hci_dev_lock(hdev);
 
-	cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
-	if (cmd) {
-		cmd->cmd_complete(cmd, mgmt_status(status));
-		mgmt_pending_remove(cmd);
+	if (status) {
+		mgmt_stop_discovery_failed(hdev, status);
+		goto unlock;
 	}
 
-	if (!status)
-		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
 
+unlock:
 	hci_dev_unlock(hdev);
 }
 
@@ -4106,14 +3901,12 @@
 		goto unlock;
 	}
 
-	cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
+	cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
 	if (!cmd) {
 		err = -ENOMEM;
 		goto unlock;
 	}
 
-	cmd->cmd_complete = generic_cmd_complete;
-
 	hci_req_init(&req, hdev);
 
 	hci_stop_discovery(&req);
@@ -4290,14 +4083,12 @@
 {
 	struct cmd_lookup match = { NULL, hdev };
 
-	hci_dev_lock(hdev);
-
 	if (status) {
 		u8 mgmt_err = mgmt_status(status);
 
 		mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
 				     cmd_status_rsp, &mgmt_err);
-		goto unlock;
+		return;
 	}
 
 	if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
@@ -4312,9 +4103,6 @@
 
 	if (match.sk)
 		sock_put(match.sk);
-
-unlock:
-	hci_dev_unlock(hdev);
 }
 
 static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -4718,13 +4506,18 @@
 {
 	struct mgmt_mode *cp = data;
 	struct pending_cmd *cmd;
-	u8 val;
+	u8 val, status;
 	int err;
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
-	    !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
+	status = mgmt_bredr_support(hdev);
+	if (status)
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
+				  status);
+
+	if (!lmp_sc_capable(hdev) &&
+	    !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
 		return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
 				  MGMT_STATUS_NOT_SUPPORTED);
 
@@ -4734,10 +4527,7 @@
 
 	hci_dev_lock(hdev);
 
-	if (!hdev_is_powered(hdev) ||
-	    (!lmp_sc_capable(hdev) &&
-	     !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
-	    !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
+	if (!hdev_is_powered(hdev)) {
 		bool changed;
 
 		if (cp->val) {
@@ -5054,26 +4844,18 @@
 		else
 			addr_type = ADDR_LE_DEV_RANDOM;
 
+		if (key->master)
+			type = SMP_LTK;
+		else
+			type = SMP_LTK_SLAVE;
+
 		switch (key->type) {
 		case MGMT_LTK_UNAUTHENTICATED:
 			authenticated = 0x00;
-			type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
 			break;
 		case MGMT_LTK_AUTHENTICATED:
 			authenticated = 0x01;
-			type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
 			break;
-		case MGMT_LTK_P256_UNAUTH:
-			authenticated = 0x00;
-			type = SMP_LTK_P256;
-			break;
-		case MGMT_LTK_P256_AUTH:
-			authenticated = 0x01;
-			type = SMP_LTK_P256;
-			break;
-		case MGMT_LTK_P256_DEBUG:
-			authenticated = 0x00;
-			type = SMP_LTK_P256_DEBUG;
 		default:
 			continue;
 		}
@@ -5091,42 +4873,67 @@
 	return err;
 }
 
-static void conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
+struct cmd_conn_lookup {
+	struct hci_conn *conn;
+	bool valid_tx_power;
+	u8 mgmt_status;
+};
+
+static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
 {
-	struct hci_conn *conn = cmd->user_data;
+	struct cmd_conn_lookup *match = data;
+	struct mgmt_cp_get_conn_info *cp;
 	struct mgmt_rp_get_conn_info rp;
+	struct hci_conn *conn = cmd->user_data;
 
-	memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
+	if (conn != match->conn)
+		return;
 
-	if (status == MGMT_STATUS_SUCCESS) {
+	cp = (struct mgmt_cp_get_conn_info *) cmd->param;
+
+	memset(&rp, 0, sizeof(rp));
+	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
+	rp.addr.type = cp->addr.type;
+
+	if (!match->mgmt_status) {
 		rp.rssi = conn->rssi;
-		rp.tx_power = conn->tx_power;
-		rp.max_tx_power = conn->max_tx_power;
-	} else {
-		rp.rssi = HCI_RSSI_INVALID;
-		rp.tx_power = HCI_TX_POWER_INVALID;
-		rp.max_tx_power = HCI_TX_POWER_INVALID;
+
+		if (match->valid_tx_power) {
+			rp.tx_power = conn->tx_power;
+			rp.max_tx_power = conn->max_tx_power;
+		} else {
+			rp.tx_power = HCI_TX_POWER_INVALID;
+			rp.max_tx_power = HCI_TX_POWER_INVALID;
+		}
 	}
 
-	cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
-		     &rp, sizeof(rp));
+	cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
+		     match->mgmt_status, &rp, sizeof(rp));
 
 	hci_conn_drop(conn);
 	hci_conn_put(conn);
+
+	mgmt_pending_remove(cmd);
 }
 
-static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status)
+static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
 {
 	struct hci_cp_read_rssi *cp;
-	struct pending_cmd *cmd;
 	struct hci_conn *conn;
+	struct cmd_conn_lookup match;
 	u16 handle;
-	u8 status;
 
-	BT_DBG("status 0x%02x", hci_status);
+	BT_DBG("status 0x%02x", status);
 
 	hci_dev_lock(hdev);
 
+	/* TX power data is valid in case request completed successfully,
+	 * otherwise we assume it's not valid. At the moment we assume that
+	 * either both or none of current and max values are valid to keep code
+	 * simple.
+	 */
+	match.valid_tx_power = !status;
+
 	/* Commands sent in request are either Read RSSI or Read Transmit Power
 	 * Level so we check which one was last sent to retrieve connection
 	 * handle.  Both commands have handle as first parameter so it's safe to
@@ -5139,29 +4946,29 @@
 	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
 	if (!cp) {
 		cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
-		status = MGMT_STATUS_SUCCESS;
-	} else {
-		status = mgmt_status(hci_status);
+		status = 0;
 	}
 
 	if (!cp) {
-		BT_ERR("invalid sent_cmd in conn_info response");
+		BT_ERR("invalid sent_cmd in response");
 		goto unlock;
 	}
 
 	handle = __le16_to_cpu(cp->handle);
 	conn = hci_conn_hash_lookup_handle(hdev, handle);
 	if (!conn) {
-		BT_ERR("unknown handle (%d) in conn_info response", handle);
+		BT_ERR("unknown handle (%d) in response", handle);
 		goto unlock;
 	}
 
-	cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
-	if (!cmd)
-		goto unlock;
+	match.conn = conn;
+	match.mgmt_status = mgmt_status(status);
 
-	cmd->cmd_complete(cmd, status);
-	mgmt_pending_remove(cmd);
+	/* Cache refresh is complete, now reply for mgmt request for given
+	 * connection only.
+	 */
+	mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
+			     get_conn_info_complete, &match);
 
 unlock:
 	hci_dev_unlock(hdev);
@@ -5207,12 +5014,6 @@
 		goto unlock;
 	}
 
-	if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
-		err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
-				   MGMT_STATUS_BUSY, &rp, sizeof(rp));
-		goto unlock;
-	}
-
 	/* To avoid client trying to guess when to poll again for information we
 	 * calculate conn info age as random value between min/max set in hdev.
 	 */
@@ -5268,7 +5069,6 @@
 
 		hci_conn_hold(conn);
 		cmd->user_data = hci_conn_get(conn);
-		cmd->cmd_complete = conn_info_cmd_complete;
 
 		conn->conn_info_timestamp = jiffies;
 	} else {
@@ -5286,40 +5086,10 @@
 	return err;
 }
 
-static void clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
-{
-	struct hci_conn *conn = cmd->user_data;
-	struct mgmt_rp_get_clock_info rp;
-	struct hci_dev *hdev;
-
-	memset(&rp, 0, sizeof(rp));
-	memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
-
-	if (status)
-		goto complete;
-
-	hdev = hci_dev_get(cmd->index);
-	if (hdev) {
-		rp.local_clock = cpu_to_le32(hdev->clock);
-		hci_dev_put(hdev);
-	}
-
-	if (conn) {
-		rp.piconet_clock = cpu_to_le32(conn->clock);
-		rp.accuracy = cpu_to_le16(conn->clock_accuracy);
-	}
-
-complete:
-	cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, sizeof(rp));
-
-	if (conn) {
-		hci_conn_drop(conn);
-		hci_conn_put(conn);
-	}
-}
-
 static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
 {
+	struct mgmt_cp_get_clock_info *cp;
+	struct mgmt_rp_get_clock_info rp;
 	struct hci_cp_read_clock *hci_cp;
 	struct pending_cmd *cmd;
 	struct hci_conn *conn;
@@ -5343,8 +5113,29 @@
 	if (!cmd)
 		goto unlock;
 
-	cmd->cmd_complete(cmd, mgmt_status(status));
+	cp = cmd->param;
+
+	memset(&rp, 0, sizeof(rp));
+	memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
+
+	if (status)
+		goto send_rsp;
+
+	rp.local_clock = cpu_to_le32(hdev->clock);
+
+	if (conn) {
+		rp.piconet_clock = cpu_to_le32(conn->clock);
+		rp.accuracy = cpu_to_le16(conn->clock_accuracy);
+	}
+
+send_rsp:
+	cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
+		     &rp, sizeof(rp));
 	mgmt_pending_remove(cmd);
+	if (conn) {
+		hci_conn_drop(conn);
+		hci_conn_put(conn);
+	}
 
 unlock:
 	hci_dev_unlock(hdev);
@@ -5400,8 +5191,6 @@
 		goto unlock;
 	}
 
-	cmd->cmd_complete = clock_info_cmd_complete;
-
 	hci_req_init(&req, hdev);
 
 	memset(&hci_cp, 0, sizeof(hci_cp));
@@ -5891,7 +5680,6 @@
 	{ read_config_info,       false, MGMT_READ_CONFIG_INFO_SIZE },
 	{ set_external_config,    false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
 	{ set_public_address,     false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
-	{ start_service_discovery,true,  MGMT_START_SERVICE_DISCOVERY_SIZE },
 };
 
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
@@ -5913,7 +5701,7 @@
 	if (!buf)
 		return -ENOMEM;
 
-	if (memcpy_from_msg(buf, msg, msglen)) {
+	if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
 		err = -EFAULT;
 		goto done;
 	}
@@ -6028,7 +5816,7 @@
 	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
 		return;
 
-	mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
+	mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
 
 	if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
 		mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
@@ -6097,11 +5885,6 @@
 		hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
 	}
 
-	if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
-		u8 sc = 0x01;
-		hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, sizeof(sc), &sc);
-	}
-
 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
 	    lmp_bredr_capable(hdev)) {
 		struct hci_cp_write_le_host_supported cp;
@@ -6151,7 +5934,8 @@
 int mgmt_powered(struct hci_dev *hdev, u8 powered)
 {
 	struct cmd_lookup match = { NULL, hdev };
-	u8 status, zero_cod[] = { 0, 0, 0 };
+	u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
+	u8 zero_cod[] = { 0, 0, 0 };
 	int err;
 
 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
@@ -6167,20 +5951,7 @@
 	}
 
 	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
-
-	/* If the power off is because of hdev unregistration let
-	 * use the appropriate INVALID_INDEX status. Otherwise use
-	 * NOT_POWERED. We cover both scenarios here since later in
-	 * mgmt_index_removed() any hci_conn callbacks will have already
-	 * been triggered, potentially causing misleading DISCONNECTED
-	 * status responses.
-	 */
-	if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
-		status = MGMT_STATUS_INVALID_INDEX;
-	else
-		status = MGMT_STATUS_NOT_POWERED;
-
-	mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
+	mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
 
 	if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
 		mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
@@ -6264,19 +6035,8 @@
 
 static u8 mgmt_ltk_type(struct smp_ltk *ltk)
 {
-	switch (ltk->type) {
-	case SMP_LTK:
-	case SMP_LTK_SLAVE:
-		if (ltk->authenticated)
-			return MGMT_LTK_AUTHENTICATED;
-		return MGMT_LTK_UNAUTHENTICATED;
-	case SMP_LTK_P256:
-		if (ltk->authenticated)
-			return MGMT_LTK_P256_AUTH;
-		return MGMT_LTK_P256_UNAUTH;
-	case SMP_LTK_P256_DEBUG:
-		return MGMT_LTK_P256_DEBUG;
-	}
+	if (ltk->authenticated)
+		return MGMT_LTK_AUTHENTICATED;
 
 	return MGMT_LTK_UNAUTHENTICATED;
 }
@@ -6411,36 +6171,26 @@
 	return eir_len;
 }
 
-void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
-			   u32 flags, u8 *name, u8 name_len)
+void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+			   u8 addr_type, u32 flags, u8 *name, u8 name_len,
+			   u8 *dev_class)
 {
 	char buf[512];
 	struct mgmt_ev_device_connected *ev = (void *) buf;
 	u16 eir_len = 0;
 
-	bacpy(&ev->addr.bdaddr, &conn->dst);
-	ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
+	bacpy(&ev->addr.bdaddr, bdaddr);
+	ev->addr.type = link_to_bdaddr(link_type, addr_type);
 
 	ev->flags = __cpu_to_le32(flags);
 
-	/* We must ensure that the EIR Data fields are ordered and
-	 * unique. Keep it simple for now and avoid the problem by not
-	 * adding any BR/EDR data to the LE adv.
-	 */
-	if (conn->le_adv_data_len > 0) {
-		memcpy(&ev->eir[eir_len],
-		       conn->le_adv_data, conn->le_adv_data_len);
-		eir_len = conn->le_adv_data_len;
-	} else {
-		if (name_len > 0)
-			eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
-						  name, name_len);
+	if (name_len > 0)
+		eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
+					  name, name_len);
 
-		if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
-			eir_len = eir_append_data(ev->eir, eir_len,
-						  EIR_CLASS_OF_DEV,
-						  conn->dev_class, 3);
-	}
+	if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
+		eir_len = eir_append_data(ev->eir, eir_len,
+					  EIR_CLASS_OF_DEV, dev_class, 3);
 
 	ev->eir_len = cpu_to_le16(eir_len);
 
@@ -6450,9 +6200,15 @@
 
 static void disconnect_rsp(struct pending_cmd *cmd, void *data)
 {
+	struct mgmt_cp_disconnect *cp = cmd->param;
 	struct sock **sk = data;
+	struct mgmt_rp_disconnect rp;
 
-	cmd->cmd_complete(cmd, 0);
+	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
+	rp.addr.type = cp->addr.type;
+
+	cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
+		     sizeof(rp));
 
 	*sk = cmd->sk;
 	sock_hold(*sk);
@@ -6464,10 +6220,16 @@
 {
 	struct hci_dev *hdev = data;
 	struct mgmt_cp_unpair_device *cp = cmd->param;
+	struct mgmt_rp_unpair_device rp;
+
+	memset(&rp, 0, sizeof(rp));
+	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
+	rp.addr.type = cp->addr.type;
 
 	device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
 
-	cmd->cmd_complete(cmd, 0);
+	cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
+
 	mgmt_pending_remove(cmd);
 }
 
@@ -6528,6 +6290,7 @@
 {
 	u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
 	struct mgmt_cp_disconnect *cp;
+	struct mgmt_rp_disconnect rp;
 	struct pending_cmd *cmd;
 
 	mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
@@ -6545,7 +6308,12 @@
 	if (cp->addr.type != bdaddr_type)
 		return;
 
-	cmd->cmd_complete(cmd, mgmt_status(status));
+	bacpy(&rp.addr.bdaddr, bdaddr);
+	rp.addr.type = bdaddr_type;
+
+	cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
+		     mgmt_status(status), &rp, sizeof(rp));
+
 	mgmt_pending_remove(cmd);
 }
 
@@ -6584,12 +6352,18 @@
 				  u8 status)
 {
 	struct pending_cmd *cmd;
+	struct mgmt_rp_pin_code_reply rp;
 
 	cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
 	if (!cmd)
 		return;
 
-	cmd->cmd_complete(cmd, mgmt_status(status));
+	bacpy(&rp.addr.bdaddr, bdaddr);
+	rp.addr.type = BDADDR_BREDR;
+
+	cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
+		     mgmt_status(status), &rp, sizeof(rp));
+
 	mgmt_pending_remove(cmd);
 }
 
@@ -6597,12 +6371,18 @@
 				      u8 status)
 {
 	struct pending_cmd *cmd;
+	struct mgmt_rp_pin_code_reply rp;
 
 	cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
 	if (!cmd)
 		return;
 
-	cmd->cmd_complete(cmd, mgmt_status(status));
+	bacpy(&rp.addr.bdaddr, bdaddr);
+	rp.addr.type = BDADDR_BREDR;
+
+	cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
+		     mgmt_status(status), &rp, sizeof(rp));
+
 	mgmt_pending_remove(cmd);
 }
 
@@ -6642,15 +6422,21 @@
 				      u8 opcode)
 {
 	struct pending_cmd *cmd;
+	struct mgmt_rp_user_confirm_reply rp;
+	int err;
 
 	cmd = mgmt_pending_find(opcode, hdev);
 	if (!cmd)
 		return -ENOENT;
 
-	cmd->cmd_complete(cmd, mgmt_status(status));
+	bacpy(&rp.addr.bdaddr, bdaddr);
+	rp.addr.type = link_to_bdaddr(link_type, addr_type);
+	err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
+			   &rp, sizeof(rp));
+
 	mgmt_pending_remove(cmd);
 
-	return 0;
+	return err;
 }
 
 int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
@@ -6714,10 +6500,8 @@
 	mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
 		    cmd ? cmd->sk : NULL);
 
-	if (cmd) {
-		cmd->cmd_complete(cmd, status);
-		mgmt_pending_remove(cmd);
-	}
+	if (cmd)
+		pairing_complete(cmd, status);
 }
 
 void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
@@ -6909,8 +6693,8 @@
 }
 
 void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
-				       u8 *rand192, u8 *hash256, u8 *rand256,
-				       u8 status)
+				       u8 *randomizer192, u8 *hash256,
+				       u8 *randomizer256, u8 status)
 {
 	struct pending_cmd *cmd;
 
@@ -6924,14 +6708,17 @@
 		cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
 			   mgmt_status(status));
 	} else {
-		if (bredr_sc_enabled(hdev) && hash256 && rand256) {
+		if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
+		    hash256 && randomizer256) {
 			struct mgmt_rp_read_local_oob_ext_data rp;
 
 			memcpy(rp.hash192, hash192, sizeof(rp.hash192));
-			memcpy(rp.rand192, rand192, sizeof(rp.rand192));
+			memcpy(rp.randomizer192, randomizer192,
+			       sizeof(rp.randomizer192));
 
 			memcpy(rp.hash256, hash256, sizeof(rp.hash256));
-			memcpy(rp.rand256, rand256, sizeof(rp.rand256));
+			memcpy(rp.randomizer256, randomizer256,
+			       sizeof(rp.randomizer256));
 
 			cmd_complete(cmd->sk, hdev->id,
 				     MGMT_OP_READ_LOCAL_OOB_DATA, 0,
@@ -6940,7 +6727,8 @@
 			struct mgmt_rp_read_local_oob_data rp;
 
 			memcpy(rp.hash, hash192, sizeof(rp.hash));
-			memcpy(rp.rand, rand192, sizeof(rp.rand));
+			memcpy(rp.randomizer, randomizer192,
+			       sizeof(rp.randomizer));
 
 			cmd_complete(cmd->sk, hdev->id,
 				     MGMT_OP_READ_LOCAL_OOB_DATA, 0,
@@ -6951,73 +6739,6 @@
 	mgmt_pending_remove(cmd);
 }
 
-static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
-{
-	int i;
-
-	for (i = 0; i < uuid_count; i++) {
-		if (!memcmp(uuid, uuids[i], 16))
-			return true;
-	}
-
-	return false;
-}
-
-static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
-{
-	u16 parsed = 0;
-
-	while (parsed < eir_len) {
-		u8 field_len = eir[0];
-		u8 uuid[16];
-		int i;
-
-		if (field_len == 0)
-			break;
-
-		if (eir_len - parsed < field_len + 1)
-			break;
-
-		switch (eir[1]) {
-		case EIR_UUID16_ALL:
-		case EIR_UUID16_SOME:
-			for (i = 0; i + 3 <= field_len; i += 2) {
-				memcpy(uuid, bluetooth_base_uuid, 16);
-				uuid[13] = eir[i + 3];
-				uuid[12] = eir[i + 2];
-				if (has_uuid(uuid, uuid_count, uuids))
-					return true;
-			}
-			break;
-		case EIR_UUID32_ALL:
-		case EIR_UUID32_SOME:
-			for (i = 0; i + 5 <= field_len; i += 4) {
-				memcpy(uuid, bluetooth_base_uuid, 16);
-				uuid[15] = eir[i + 5];
-				uuid[14] = eir[i + 4];
-				uuid[13] = eir[i + 3];
-				uuid[12] = eir[i + 2];
-				if (has_uuid(uuid, uuid_count, uuids))
-					return true;
-			}
-			break;
-		case EIR_UUID128_ALL:
-		case EIR_UUID128_SOME:
-			for (i = 0; i + 17 <= field_len; i += 16) {
-				memcpy(uuid, eir + i + 2, 16);
-				if (has_uuid(uuid, uuid_count, uuids))
-					return true;
-			}
-			break;
-		}
-
-		parsed += field_len + 1;
-		eir += field_len + 1;
-	}
-
-	return false;
-}
-
 void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
 		       u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
 		       u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
@@ -7025,7 +6746,6 @@
 	char buf[512];
 	struct mgmt_ev_device_found *ev = (void *) buf;
 	size_t ev_size;
-	bool match;
 
 	/* Don't send events for a non-kernel initiated discovery. With
 	 * LE one exception is if we have pend_le_reports > 0 in which
@@ -7038,18 +6758,6 @@
 			return;
 	}
 
-	/* When using service discovery with a RSSI threshold, then check
-	 * if such a RSSI threshold is specified. If a RSSI threshold has
-	 * been specified, then all results with a RSSI smaller than the
-	 * RSSI threshold will be dropped.
-	 *
-	 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
-	 * the results are also dropped.
-	 */
-	if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
-	    (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID))
-		return;
-
 	/* Make sure that the buffer is big enough. The 5 extra bytes
 	 * are for the potential CoD field.
 	 */
@@ -7058,79 +6766,20 @@
 
 	memset(buf, 0, sizeof(buf));
 
-	/* In case of device discovery with BR/EDR devices (pre 1.2), the
-	 * RSSI value was reported as 0 when not available. This behavior
-	 * is kept when using device discovery. This is required for full
-	 * backwards compatibility with the API.
-	 *
-	 * However when using service discovery, the value 127 will be
-	 * returned when the RSSI is not available.
-	 */
-	if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi)
-		rssi = 0;
-
 	bacpy(&ev->addr.bdaddr, bdaddr);
 	ev->addr.type = link_to_bdaddr(link_type, addr_type);
 	ev->rssi = rssi;
 	ev->flags = cpu_to_le32(flags);
 
-	if (eir_len > 0) {
-		/* When using service discovery and a list of UUID is
-		 * provided, results with no matching UUID should be
-		 * dropped. In case there is a match the result is
-		 * kept and checking possible scan response data
-		 * will be skipped.
-		 */
-		if (hdev->discovery.uuid_count > 0)
-			match = eir_has_uuids(eir, eir_len,
-					      hdev->discovery.uuid_count,
-					      hdev->discovery.uuids);
-		else
-			match = true;
-
-		if (!match && !scan_rsp_len)
-			return;
-
-		/* Copy EIR or advertising data into event */
+	if (eir_len > 0)
 		memcpy(ev->eir, eir, eir_len);
-	} else {
-		/* When using service discovery and a list of UUID is
-		 * provided, results with empty EIR or advertising data
-		 * should be dropped since they do not match any UUID.
-		 */
-		if (hdev->discovery.uuid_count > 0 && !scan_rsp_len)
-			return;
-
-		match = false;
-	}
 
 	if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
 		eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
 					  dev_class, 3);
 
-	if (scan_rsp_len > 0) {
-		/* When using service discovery and a list of UUID is
-		 * provided, results with no matching UUID should be
-		 * dropped if there is no previous match from the
-		 * advertising data.
-		 */
-		if (hdev->discovery.uuid_count > 0) {
-			if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
-						     hdev->discovery.uuid_count,
-						     hdev->discovery.uuids))
-				return;
-		}
-
-		/* Append scan response data to event */
+	if (scan_rsp_len > 0)
 		memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
-	} else {
-		/* When using service discovery and a list of UUID is
-		 * provided, results with empty scan response and no
-		 * previous matched advertising data should be dropped.
-		 */
-		if (hdev->discovery.uuid_count > 0 && !match)
-			return;
-	}
 
 	ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
 	ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
@@ -7164,9 +6813,23 @@
 void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
 {
 	struct mgmt_ev_discovering ev;
+	struct pending_cmd *cmd;
 
 	BT_DBG("%s discovering %u", hdev->name, discovering);
 
+	if (discovering)
+		cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
+	else
+		cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
+
+	if (cmd != NULL) {
+		u8 type = hdev->discovery.type;
+
+		cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
+			     sizeof(type));
+		mgmt_pending_remove(cmd);
+	}
+
 	memset(&ev, 0, sizeof(ev));
 	ev.type = hdev->discovery.type;
 	ev.discovering = discovering;
diff --git a/net/bluetooth/rfcomm/Kconfig b/net/bluetooth/rfcomm/Kconfig
index 073e07f..1ab7444 100644
--- a/net/bluetooth/rfcomm/Kconfig
+++ b/net/bluetooth/rfcomm/Kconfig
@@ -1,7 +1,7 @@
 config BT_RFCOMM
 	tristate "RFCOMM protocol support"
 	depends on m
-	depends on BT_BREDR
+	depends on BT
 	help
 	  RFCOMM provides connection oriented stream transport.  RFCOMM
 	  support is required for Dialup Networking, OBEX and other Bluetooth
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 8b5b653..aa3bee4 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -78,10 +78,8 @@
 #define __get_type(b)     ((b & 0xef))
 
 #define __test_ea(b)      ((b & 0x01))
-#define __test_cr(b)      (!!(b & 0x02))
-#define __test_pf(b)      (!!(b & 0x10))
-
-#define __session_dir(s)  ((s)->initiator ? 0x00 : 0x01)
+#define __test_cr(b)      ((b & 0x02))
+#define __test_pf(b)      ((b & 0x10))
 
 #define __addr(cr, dlci)       (((dlci & 0x3f) << 2) | (cr << 1) | 0x01)
 #define __ctrl(type, pf)       (((type & 0xef) | (pf << 4)))
@@ -103,11 +101,11 @@
 #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
 #define __get_rpn_parity(line)    (((line) >> 3) & 0x7)
 
-static DECLARE_WAIT_QUEUE_HEAD(rfcomm_wq);
-
 static void rfcomm_schedule(void)
 {
-	wake_up_all(&rfcomm_wq);
+	if (!rfcomm_thread)
+		return;
+	wake_up_process(rfcomm_thread);
 }
 
 /* ---- RFCOMM FCS computation ---- */
@@ -398,7 +396,7 @@
 			return err;
 	}
 
-	dlci = __dlci(__session_dir(s), channel);
+	dlci = __dlci(!s->initiator, channel);
 
 	/* Check if DLCI already exists */
 	if (rfcomm_dlc_get(s, dlci))
@@ -553,7 +551,7 @@
 	rfcomm_lock();
 	s = rfcomm_session_get(src, dst);
 	if (s) {
-		dlci = __dlci(__session_dir(s), channel);
+		dlci = __dlci(!s->initiator, channel);
 		dlc = rfcomm_dlc_get(s, dlci);
 	}
 	rfcomm_unlock();
@@ -914,7 +912,7 @@
 	hdr->len  = __len8(sizeof(*mcc) + 1);
 
 	mcc = (void *) ptr; ptr += sizeof(*mcc);
-	mcc->type = __mcc_type(0, RFCOMM_NSC);
+	mcc->type = __mcc_type(cr, RFCOMM_NSC);
 	mcc->len  = __len8(1);
 
 	/* Type that we didn't like */
@@ -2100,22 +2098,24 @@
 
 static int rfcomm_run(void *unused)
 {
-	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	BT_DBG("");
 
 	set_user_nice(current, -10);
 
 	rfcomm_add_listener(BDADDR_ANY);
 
-	add_wait_queue(&rfcomm_wq, &wait);
-	while (!kthread_should_stop()) {
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (kthread_should_stop())
+			break;
 
 		/* Process stuff */
 		rfcomm_process_sessions();
 
-		wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+		schedule();
 	}
-	remove_wait_queue(&rfcomm_wq, &wait);
+	__set_current_state(TASK_RUNNING);
 
 	rfcomm_kill_listener();
 
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index acaac1b..4688936 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -596,7 +596,7 @@
 		}
 		skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
 
-		err = memcpy_from_msg(skb_put(skb, size), msg, size);
+		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 		if (err) {
 			kfree_skb(skb);
 			if (sent == 0)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 73bc2c3..c4db547 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -285,7 +285,7 @@
 	if (!skb)
 		return err;
 
-	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
 		kfree_skb(skb);
 		return -EFAULT;
 	}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index ef0de39..f09b6b6 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -29,34 +29,14 @@
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/mgmt.h>
 
-#include "ecc.h"
 #include "smp.h"
 
-/* Low-level debug macros to be used for stuff that we don't want
- * accidentially in dmesg, i.e. the values of the various crypto keys
- * and the inputs & outputs of crypto functions.
- */
-#ifdef DEBUG
-#define SMP_DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, \
-				 ##__VA_ARGS__)
-#else
-#define SMP_DBG(fmt, ...) no_printk(KERN_DEBUG "%s: " fmt, __func__, \
-				    ##__VA_ARGS__)
-#endif
-
 #define SMP_ALLOW_CMD(smp, code)	set_bit(code, &smp->allow_cmd)
 
-/* Keys which are not distributed with Secure Connections */
-#define SMP_SC_NO_DIST (SMP_DIST_ENC_KEY | SMP_DIST_LINK_KEY);
-
 #define SMP_TIMEOUT	msecs_to_jiffies(30000)
 
-#define AUTH_REQ_MASK(dev)	(test_bit(HCI_SC_ENABLED, &(dev)->dev_flags) ? \
-				 0x1f : 0x07)
-#define KEY_DIST_MASK		0x07
-
-/* Maximum message length that can be passed to aes_cmac */
-#define CMAC_MSG_MAX	80
+#define AUTH_REQ_MASK   0x07
+#define KEY_DIST_MASK	0x07
 
 enum {
 	SMP_FLAG_TK_VALID,
@@ -64,12 +44,6 @@
 	SMP_FLAG_MITM_AUTH,
 	SMP_FLAG_COMPLETE,
 	SMP_FLAG_INITIATOR,
-	SMP_FLAG_SC,
-	SMP_FLAG_REMOTE_PK,
-	SMP_FLAG_DEBUG_KEY,
-	SMP_FLAG_WAIT_USER,
-	SMP_FLAG_DHKEY_PENDING,
-	SMP_FLAG_OOB,
 };
 
 struct smp_chan {
@@ -83,7 +57,6 @@
 	u8		rrnd[16]; /* SMP Pairing Random (remote) */
 	u8		pcnf[16]; /* SMP Pairing Confirm */
 	u8		tk[16]; /* SMP Temporary Key */
-	u8		rr[16];
 	u8		enc_key_size;
 	u8		remote_key_dist;
 	bdaddr_t	id_addr;
@@ -94,43 +67,9 @@
 	struct smp_ltk	*ltk;
 	struct smp_ltk	*slave_ltk;
 	struct smp_irk	*remote_irk;
-	u8		*link_key;
 	unsigned long	flags;
-	u8		method;
-	u8		passkey_round;
-
-	/* Secure Connections variables */
-	u8			local_pk[64];
-	u8			local_sk[32];
-	u8			remote_pk[64];
-	u8			dhkey[32];
-	u8			mackey[16];
 
 	struct crypto_blkcipher	*tfm_aes;
-	struct crypto_hash	*tfm_cmac;
-};
-
-/* These debug key values are defined in the SMP section of the core
- * specification. debug_pk is the public debug key and debug_sk the
- * private debug key.
- */
-static const u8 debug_pk[64] = {
-		0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
-		0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
-		0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
-		0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
-
-		0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
-		0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
-		0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
-		0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc,
-};
-
-static const u8 debug_sk[32] = {
-		0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58,
-		0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a,
-		0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74,
-		0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f,
 };
 
 static inline void swap_buf(const u8 *src, u8 *dst, size_t len)
@@ -141,214 +80,6 @@
 		dst[len - 1 - i] = src[i];
 }
 
-/* The following functions map to the LE SC SMP crypto functions
- * AES-CMAC, f4, f5, f6, g2 and h6.
- */
-
-static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
-		    size_t len, u8 mac[16])
-{
-	uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX];
-	struct hash_desc desc;
-	struct scatterlist sg;
-	int err;
-
-	if (len > CMAC_MSG_MAX)
-		return -EFBIG;
-
-	if (!tfm) {
-		BT_ERR("tfm %p", tfm);
-		return -EINVAL;
-	}
-
-	desc.tfm = tfm;
-	desc.flags = 0;
-
-	crypto_hash_init(&desc);
-
-	/* Swap key and message from LSB to MSB */
-	swap_buf(k, tmp, 16);
-	swap_buf(m, msg_msb, len);
-
-	SMP_DBG("msg (len %zu) %*phN", len, (int) len, m);
-	SMP_DBG("key %16phN", k);
-
-	err = crypto_hash_setkey(tfm, tmp, 16);
-	if (err) {
-		BT_ERR("cipher setkey failed: %d", err);
-		return err;
-	}
-
-	sg_init_one(&sg, msg_msb, len);
-
-	err = crypto_hash_update(&desc, &sg, len);
-	if (err) {
-		BT_ERR("Hash update error %d", err);
-		return err;
-	}
-
-	err = crypto_hash_final(&desc, mac_msb);
-	if (err) {
-		BT_ERR("Hash final error %d", err);
-		return err;
-	}
-
-	swap_buf(mac_msb, mac, 16);
-
-	SMP_DBG("mac %16phN", mac);
-
-	return 0;
-}
-
-static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
-		  const u8 x[16], u8 z, u8 res[16])
-{
-	u8 m[65];
-	int err;
-
-	SMP_DBG("u %32phN", u);
-	SMP_DBG("v %32phN", v);
-	SMP_DBG("x %16phN z %02x", x, z);
-
-	m[0] = z;
-	memcpy(m + 1, v, 32);
-	memcpy(m + 33, u, 32);
-
-	err = aes_cmac(tfm_cmac, x, m, sizeof(m), res);
-	if (err)
-		return err;
-
-	SMP_DBG("res %16phN", res);
-
-	return err;
-}
-
-static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
-		  u8 a1[7], u8 a2[7], u8 mackey[16], u8 ltk[16])
-{
-	/* The btle, salt and length "magic" values are as defined in
-	 * the SMP section of the Bluetooth core specification. In ASCII
-	 * the btle value ends up being 'btle'. The salt is just a
-	 * random number whereas length is the value 256 in little
-	 * endian format.
-	 */
-	const u8 btle[4] = { 0x65, 0x6c, 0x74, 0x62 };
-	const u8 salt[16] = { 0xbe, 0x83, 0x60, 0x5a, 0xdb, 0x0b, 0x37, 0x60,
-			      0x38, 0xa5, 0xf5, 0xaa, 0x91, 0x83, 0x88, 0x6c };
-	const u8 length[2] = { 0x00, 0x01 };
-	u8 m[53], t[16];
-	int err;
-
-	SMP_DBG("w %32phN", w);
-	SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
-	SMP_DBG("a1 %7phN a2 %7phN", a1, a2);
-
-	err = aes_cmac(tfm_cmac, salt, w, 32, t);
-	if (err)
-		return err;
-
-	SMP_DBG("t %16phN", t);
-
-	memcpy(m, length, 2);
-	memcpy(m + 2, a2, 7);
-	memcpy(m + 9, a1, 7);
-	memcpy(m + 16, n2, 16);
-	memcpy(m + 32, n1, 16);
-	memcpy(m + 48, btle, 4);
-
-	m[52] = 0; /* Counter */
-
-	err = aes_cmac(tfm_cmac, t, m, sizeof(m), mackey);
-	if (err)
-		return err;
-
-	SMP_DBG("mackey %16phN", mackey);
-
-	m[52] = 1; /* Counter */
-
-	err = aes_cmac(tfm_cmac, t, m, sizeof(m), ltk);
-	if (err)
-		return err;
-
-	SMP_DBG("ltk %16phN", ltk);
-
-	return 0;
-}
-
-static int smp_f6(struct crypto_hash *tfm_cmac, const u8 w[16],
-		  const u8 n1[16], u8 n2[16], const u8 r[16],
-		  const u8 io_cap[3], const u8 a1[7], const u8 a2[7],
-		  u8 res[16])
-{
-	u8 m[65];
-	int err;
-
-	SMP_DBG("w %16phN", w);
-	SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
-	SMP_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2);
-
-	memcpy(m, a2, 7);
-	memcpy(m + 7, a1, 7);
-	memcpy(m + 14, io_cap, 3);
-	memcpy(m + 17, r, 16);
-	memcpy(m + 33, n2, 16);
-	memcpy(m + 49, n1, 16);
-
-	err = aes_cmac(tfm_cmac, w, m, sizeof(m), res);
-	if (err)
-		return err;
-
-	BT_DBG("res %16phN", res);
-
-	return err;
-}
-
-static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
-		  const u8 x[16], const u8 y[16], u32 *val)
-{
-	u8 m[80], tmp[16];
-	int err;
-
-	SMP_DBG("u %32phN", u);
-	SMP_DBG("v %32phN", v);
-	SMP_DBG("x %16phN y %16phN", x, y);
-
-	memcpy(m, y, 16);
-	memcpy(m + 16, v, 32);
-	memcpy(m + 48, u, 32);
-
-	err = aes_cmac(tfm_cmac, x, m, sizeof(m), tmp);
-	if (err)
-		return err;
-
-	*val = get_unaligned_le32(tmp);
-	*val %= 1000000;
-
-	SMP_DBG("val %06u", *val);
-
-	return 0;
-}
-
-static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
-		  const u8 key_id[4], u8 res[16])
-{
-	int err;
-
-	SMP_DBG("w %16phN key_id %4phN", w, key_id);
-
-	err = aes_cmac(tfm_cmac, w, key_id, 4, res);
-	if (err)
-		return err;
-
-	SMP_DBG("res %16phN", res);
-
-	return err;
-}
-
-/* The following functions map to the legacy SMP crypto functions e, c1,
- * s1 and ah.
- */
-
 static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
 {
 	struct blkcipher_desc desc;
@@ -356,7 +87,7 @@
 	uint8_t tmp[16], data[16];
 	int err;
 
-	if (!tfm) {
+	if (tfm == NULL) {
 		BT_ERR("tfm %p", tfm);
 		return -EINVAL;
 	}
@@ -388,65 +119,7 @@
 	return err;
 }
 
-static int smp_c1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
-		  const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
-		  const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
-{
-	u8 p1[16], p2[16];
-	int err;
-
-	memset(p1, 0, 16);
-
-	/* p1 = pres || preq || _rat || _iat */
-	p1[0] = _iat;
-	p1[1] = _rat;
-	memcpy(p1 + 2, preq, 7);
-	memcpy(p1 + 9, pres, 7);
-
-	/* p2 = padding || ia || ra */
-	memcpy(p2, ra, 6);
-	memcpy(p2 + 6, ia, 6);
-	memset(p2 + 12, 0, 4);
-
-	/* res = r XOR p1 */
-	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
-
-	/* res = e(k, res) */
-	err = smp_e(tfm_aes, k, res);
-	if (err) {
-		BT_ERR("Encrypt data error");
-		return err;
-	}
-
-	/* res = res XOR p2 */
-	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
-
-	/* res = e(k, res) */
-	err = smp_e(tfm_aes, k, res);
-	if (err)
-		BT_ERR("Encrypt data error");
-
-	return err;
-}
-
-static int smp_s1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
-		  const u8 r1[16], const u8 r2[16], u8 _r[16])
-{
-	int err;
-
-	/* Just least significant octets from r1 and r2 are considered */
-	memcpy(_r, r2, 8);
-	memcpy(_r + 8, r1, 8);
-
-	err = smp_e(tfm_aes, k, _r);
-	if (err)
-		BT_ERR("Encrypt data error");
-
-	return err;
-}
-
-static int smp_ah(struct crypto_blkcipher *tfm, const u8 irk[16],
-		  const u8 r[3], u8 res[3])
+static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
 {
 	u8 _res[16];
 	int err;
@@ -472,8 +145,7 @@
 	return 0;
 }
 
-bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
-		     const bdaddr_t *bdaddr)
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
 {
 	struct l2cap_chan *chan = hdev->smp_data;
 	struct crypto_blkcipher *tfm;
@@ -494,7 +166,7 @@
 	return !memcmp(bdaddr->b, hash, 3);
 }
 
-int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
 {
 	struct l2cap_chan *chan = hdev->smp_data;
 	struct crypto_blkcipher *tfm;
@@ -519,6 +191,69 @@
 	return 0;
 }
 
+static int smp_c1(struct smp_chan *smp, u8 k[16], u8 r[16], u8 preq[7],
+		  u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat, bdaddr_t *ra,
+		  u8 res[16])
+{
+	struct hci_dev *hdev = smp->conn->hcon->hdev;
+	u8 p1[16], p2[16];
+	int err;
+
+	BT_DBG("%s", hdev->name);
+
+	memset(p1, 0, 16);
+
+	/* p1 = pres || preq || _rat || _iat */
+	p1[0] = _iat;
+	p1[1] = _rat;
+	memcpy(p1 + 2, preq, 7);
+	memcpy(p1 + 9, pres, 7);
+
+	/* p2 = padding || ia || ra */
+	memcpy(p2, ra, 6);
+	memcpy(p2 + 6, ia, 6);
+	memset(p2 + 12, 0, 4);
+
+	/* res = r XOR p1 */
+	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+	/* res = e(k, res) */
+	err = smp_e(smp->tfm_aes, k, res);
+	if (err) {
+		BT_ERR("Encrypt data error");
+		return err;
+	}
+
+	/* res = res XOR p2 */
+	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+	/* res = e(k, res) */
+	err = smp_e(smp->tfm_aes, k, res);
+	if (err)
+		BT_ERR("Encrypt data error");
+
+	return err;
+}
+
+static int smp_s1(struct smp_chan *smp, u8 k[16], u8 r1[16], u8 r2[16],
+		  u8 _r[16])
+{
+	struct hci_dev *hdev = smp->conn->hcon->hdev;
+	int err;
+
+	BT_DBG("%s", hdev->name);
+
+	/* Just least significant octets from r1 and r2 are considered */
+	memcpy(_r, r2, 8);
+	memcpy(_r + 8, r1, 8);
+
+	err = smp_e(smp->tfm_aes, k, _r);
+	if (err)
+		BT_ERR("Encrypt data error");
+
+	return err;
+}
+
 static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
 {
 	struct l2cap_chan *chan = conn->smp;
@@ -539,12 +274,8 @@
 
 	memset(&msg, 0, sizeof(msg));
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-	iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iv, 2, 1 + len);
-#else
 	msg.msg_iov = (struct iovec *) &iv;
 	msg.msg_iovlen = 2;
-#endif
 
 	l2cap_chan_send(chan, &msg, 1 + len);
 
@@ -557,22 +288,17 @@
 	schedule_delayed_work(&smp->security_timer, SMP_TIMEOUT);
 }
 
-static u8 authreq_to_seclevel(u8 authreq)
+static __u8 authreq_to_seclevel(__u8 authreq)
 {
-	if (authreq & SMP_AUTH_MITM) {
-		if (authreq & SMP_AUTH_SC)
-			return BT_SECURITY_FIPS;
-		else
-			return BT_SECURITY_HIGH;
-	} else {
+	if (authreq & SMP_AUTH_MITM)
+		return BT_SECURITY_HIGH;
+	else
 		return BT_SECURITY_MEDIUM;
-	}
 }
 
 static __u8 seclevel_to_authreq(__u8 sec_level)
 {
 	switch (sec_level) {
-	case BT_SECURITY_FIPS:
 	case BT_SECURITY_HIGH:
 		return SMP_AUTH_MITM | SMP_AUTH_BONDING;
 	case BT_SECURITY_MEDIUM:
@@ -590,7 +316,7 @@
 	struct smp_chan *smp = chan->data;
 	struct hci_conn *hcon = conn->hcon;
 	struct hci_dev *hdev = hcon->hdev;
-	u8 local_dist = 0, remote_dist = 0, oob_flag = SMP_OOB_NOT_PRESENT;
+	u8 local_dist = 0, remote_dist = 0;
 
 	if (test_bit(HCI_BONDABLE, &conn->hcon->hdev->dev_flags)) {
 		local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
@@ -606,52 +332,24 @@
 	if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
 		local_dist |= SMP_DIST_ID_KEY;
 
-	if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
-	    (authreq & SMP_AUTH_SC)) {
-		struct oob_data *oob_data;
-		u8 bdaddr_type;
-
-		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
-			local_dist |= SMP_DIST_LINK_KEY;
-			remote_dist |= SMP_DIST_LINK_KEY;
-		}
-
-		if (hcon->dst_type == ADDR_LE_DEV_PUBLIC)
-			bdaddr_type = BDADDR_LE_PUBLIC;
-		else
-			bdaddr_type = BDADDR_LE_RANDOM;
-
-		oob_data = hci_find_remote_oob_data(hdev, &hcon->dst,
-						    bdaddr_type);
-		if (oob_data) {
-			set_bit(SMP_FLAG_OOB, &smp->flags);
-			oob_flag = SMP_OOB_PRESENT;
-			memcpy(smp->rr, oob_data->rand256, 16);
-			memcpy(smp->pcnf, oob_data->hash256, 16);
-		}
-
-	} else {
-		authreq &= ~SMP_AUTH_SC;
-	}
-
 	if (rsp == NULL) {
 		req->io_capability = conn->hcon->io_capability;
-		req->oob_flag = oob_flag;
+		req->oob_flag = SMP_OOB_NOT_PRESENT;
 		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
 		req->init_key_dist = local_dist;
 		req->resp_key_dist = remote_dist;
-		req->auth_req = (authreq & AUTH_REQ_MASK(hdev));
+		req->auth_req = (authreq & AUTH_REQ_MASK);
 
 		smp->remote_key_dist = remote_dist;
 		return;
 	}
 
 	rsp->io_capability = conn->hcon->io_capability;
-	rsp->oob_flag = oob_flag;
+	rsp->oob_flag = SMP_OOB_NOT_PRESENT;
 	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
 	rsp->init_key_dist = req->init_key_dist & remote_dist;
 	rsp->resp_key_dist = req->resp_key_dist & local_dist;
-	rsp->auth_req = (authreq & AUTH_REQ_MASK(hdev));
+	rsp->auth_req = (authreq & AUTH_REQ_MASK);
 
 	smp->remote_key_dist = rsp->init_key_dist;
 }
@@ -674,7 +372,6 @@
 {
 	struct l2cap_chan *chan = conn->smp;
 	struct smp_chan *smp = chan->data;
-	struct hci_conn *hcon = conn->hcon;
 	bool complete;
 
 	BUG_ON(!smp);
@@ -682,46 +379,34 @@
 	cancel_delayed_work_sync(&smp->security_timer);
 
 	complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
-	mgmt_smp_complete(hcon, complete);
+	mgmt_smp_complete(conn->hcon, complete);
 
 	kfree(smp->csrk);
 	kfree(smp->slave_csrk);
-	kfree(smp->link_key);
 
 	crypto_free_blkcipher(smp->tfm_aes);
-	crypto_free_hash(smp->tfm_cmac);
-
-	/* Ensure that we don't leave any debug key around if debug key
-	 * support hasn't been explicitly enabled.
-	 */
-	if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG &&
-	    !test_bit(HCI_KEEP_DEBUG_KEYS, &hcon->hdev->dev_flags)) {
-		list_del_rcu(&smp->ltk->list);
-		kfree_rcu(smp->ltk, rcu);
-		smp->ltk = NULL;
-	}
 
 	/* If pairing failed clean up any keys we might have */
 	if (!complete) {
 		if (smp->ltk) {
-			list_del_rcu(&smp->ltk->list);
-			kfree_rcu(smp->ltk, rcu);
+			list_del(&smp->ltk->list);
+			kfree(smp->ltk);
 		}
 
 		if (smp->slave_ltk) {
-			list_del_rcu(&smp->slave_ltk->list);
-			kfree_rcu(smp->slave_ltk, rcu);
+			list_del(&smp->slave_ltk->list);
+			kfree(smp->slave_ltk);
 		}
 
 		if (smp->remote_irk) {
-			list_del_rcu(&smp->remote_irk->list);
-			kfree_rcu(smp->remote_irk, rcu);
+			list_del(&smp->remote_irk->list);
+			kfree(smp->remote_irk);
 		}
 	}
 
 	chan->data = NULL;
 	kfree(smp);
-	hci_conn_drop(hcon);
+	hci_conn_drop(conn->hcon);
 }
 
 static void smp_failure(struct l2cap_conn *conn, u8 reason)
@@ -745,7 +430,6 @@
 #define REQ_PASSKEY	0x02
 #define CFM_PASSKEY	0x03
 #define REQ_OOB		0x04
-#define DSP_PASSKEY	0x05
 #define OVERLAP		0xFF
 
 static const u8 gen_method[5][5] = {
@@ -756,14 +440,6 @@
 	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP     },
 };
 
-static const u8 sc_method[5][5] = {
-	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
-	{ JUST_WORKS,  CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
-	{ DSP_PASSKEY, DSP_PASSKEY, REQ_PASSKEY, JUST_WORKS, DSP_PASSKEY },
-	{ JUST_WORKS,  JUST_CFM,    JUST_WORKS,  JUST_WORKS, JUST_CFM    },
-	{ DSP_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
-};
-
 static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io)
 {
 	/* If either side has unknown io_caps, use JUST_CFM (which gets
@@ -773,9 +449,6 @@
 	    remote_io > SMP_IO_KEYBOARD_DISPLAY)
 		return JUST_CFM;
 
-	if (test_bit(SMP_FLAG_SC, &smp->flags))
-		return sc_method[remote_io][local_io];
-
 	return gen_method[remote_io][local_io];
 }
 
@@ -785,6 +458,7 @@
 	struct hci_conn *hcon = conn->hcon;
 	struct l2cap_chan *chan = conn->smp;
 	struct smp_chan *smp = chan->data;
+	u8 method;
 	u32 passkey = 0;
 	int ret = 0;
 
@@ -801,28 +475,26 @@
 	 * table.
 	 */
 	if (!(auth & SMP_AUTH_MITM))
-		smp->method = JUST_CFM;
+		method = JUST_CFM;
 	else
-		smp->method = get_auth_method(smp, local_io, remote_io);
+		method = get_auth_method(smp, local_io, remote_io);
 
 	/* Don't confirm locally initiated pairing attempts */
-	if (smp->method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR,
-						&smp->flags))
-		smp->method = JUST_WORKS;
+	if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
+		method = JUST_WORKS;
 
 	/* Don't bother user space with no IO capabilities */
-	if (smp->method == JUST_CFM &&
-	    hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
-		smp->method = JUST_WORKS;
+	if (method == JUST_CFM && hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
+		method = JUST_WORKS;
 
 	/* If Just Works, Continue with Zero TK */
-	if (smp->method == JUST_WORKS) {
+	if (method == JUST_WORKS) {
 		set_bit(SMP_FLAG_TK_VALID, &smp->flags);
 		return 0;
 	}
 
 	/* Not Just Works/Confirm results in MITM Authentication */
-	if (smp->method != JUST_CFM) {
+	if (method != JUST_CFM) {
 		set_bit(SMP_FLAG_MITM_AUTH, &smp->flags);
 		if (hcon->pending_sec_level < BT_SECURITY_HIGH)
 			hcon->pending_sec_level = BT_SECURITY_HIGH;
@@ -831,15 +503,15 @@
 	/* If both devices have Keyoard-Display I/O, the master
 	 * Confirms and the slave Enters the passkey.
 	 */
-	if (smp->method == OVERLAP) {
+	if (method == OVERLAP) {
 		if (hcon->role == HCI_ROLE_MASTER)
-			smp->method = CFM_PASSKEY;
+			method = CFM_PASSKEY;
 		else
-			smp->method = REQ_PASSKEY;
+			method = REQ_PASSKEY;
 	}
 
 	/* Generate random passkey. */
-	if (smp->method == CFM_PASSKEY) {
+	if (method == CFM_PASSKEY) {
 		memset(smp->tk, 0, sizeof(smp->tk));
 		get_random_bytes(&passkey, sizeof(passkey));
 		passkey %= 1000000;
@@ -848,10 +520,12 @@
 		set_bit(SMP_FLAG_TK_VALID, &smp->flags);
 	}
 
-	if (smp->method == REQ_PASSKEY)
+	hci_dev_lock(hcon->hdev);
+
+	if (method == REQ_PASSKEY)
 		ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
 						hcon->type, hcon->dst_type);
-	else if (smp->method == JUST_CFM)
+	else if (method == JUST_CFM)
 		ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
 						hcon->type, hcon->dst_type,
 						passkey, 1);
@@ -860,6 +534,8 @@
 						hcon->type, hcon->dst_type,
 						passkey, 0);
 
+	hci_dev_unlock(hcon->hdev);
+
 	return ret;
 }
 
@@ -871,7 +547,7 @@
 
 	BT_DBG("conn %p", conn);
 
-	ret = smp_c1(smp->tfm_aes, smp->tk, smp->prnd, smp->preq, smp->prsp,
+	ret = smp_c1(smp, smp->tk, smp->prnd, smp->preq, smp->prsp,
 		     conn->hcon->init_addr_type, &conn->hcon->init_addr,
 		     conn->hcon->resp_addr_type, &conn->hcon->resp_addr,
 		     cp.confirm_val);
@@ -902,7 +578,7 @@
 
 	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
 
-	ret = smp_c1(smp->tfm_aes, smp->tk, smp->rrnd, smp->preq, smp->prsp,
+	ret = smp_c1(smp, smp->tk, smp->rrnd, smp->preq, smp->prsp,
 		     hcon->init_addr_type, &hcon->init_addr,
 		     hcon->resp_addr_type, &hcon->resp_addr, confirm);
 	if (ret)
@@ -918,7 +594,7 @@
 		__le64 rand = 0;
 		__le16 ediv = 0;
 
-		smp_s1(smp->tfm_aes, smp->tk, smp->rrnd, smp->prnd, stk);
+		smp_s1(smp, smp->tk, smp->rrnd, smp->prnd, stk);
 
 		memset(stk + smp->enc_key_size, 0,
 		       SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
@@ -937,7 +613,7 @@
 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
 			     smp->prnd);
 
-		smp_s1(smp->tfm_aes, smp->tk, smp->prnd, smp->rrnd, stk);
+		smp_s1(smp, smp->tk, smp->prnd, smp->rrnd, stk);
 
 		memset(stk + smp->enc_key_size, 0,
 		       SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
@@ -972,13 +648,11 @@
 		mgmt_new_irk(hdev, smp->remote_irk);
 		/* Now that user space can be considered to know the
 		 * identity address track the connection based on it
-		 * from now on (assuming this is an LE link).
+		 * from now on.
 		 */
-		if (hcon->type == LE_LINK) {
-			bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
-			hcon->dst_type = smp->remote_irk->addr_type;
-			queue_work(hdev->workqueue, &conn->id_addr_update_work);
-		}
+		bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
+		hcon->dst_type = smp->remote_irk->addr_type;
+		queue_work(hdev->workqueue, &conn->id_addr_update_work);
 
 		/* When receiving an indentity resolving key for
 		 * a remote device that does not use a resolvable
@@ -991,26 +665,16 @@
 		 * just remove it.
 		 */
 		if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) {
-			list_del_rcu(&smp->remote_irk->list);
-			kfree_rcu(smp->remote_irk, rcu);
+			list_del(&smp->remote_irk->list);
+			kfree(smp->remote_irk);
 			smp->remote_irk = NULL;
 		}
 	}
 
-	if (hcon->type == ACL_LINK) {
-		if (hcon->key_type == HCI_LK_DEBUG_COMBINATION)
-			persistent = false;
-		else
-			persistent = !test_bit(HCI_CONN_FLUSH_KEY,
-					       &hcon->flags);
-	} else {
-		/* The LTKs and CSRKs should be persistent only if both sides
-		 * had the bonding bit set in their authentication requests.
-		 */
-		persistent = !!((req->auth_req & rsp->auth_req) &
-				SMP_AUTH_BONDING);
-	}
-
+	/* The LTKs and CSRKs should be persistent only if both sides
+	 * had the bonding bit set in their authentication requests.
+	 */
+	persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING);
 
 	if (smp->csrk) {
 		smp->csrk->bdaddr_type = hcon->dst_type;
@@ -1035,81 +699,6 @@
 		bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
 		mgmt_new_ltk(hdev, smp->slave_ltk, persistent);
 	}
-
-	if (smp->link_key) {
-		struct link_key *key;
-		u8 type;
-
-		if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
-			type = HCI_LK_DEBUG_COMBINATION;
-		else if (hcon->sec_level == BT_SECURITY_FIPS)
-			type = HCI_LK_AUTH_COMBINATION_P256;
-		else
-			type = HCI_LK_UNAUTH_COMBINATION_P256;
-
-		key = hci_add_link_key(hdev, smp->conn->hcon, &hcon->dst,
-				       smp->link_key, type, 0, &persistent);
-		if (key) {
-			mgmt_new_link_key(hdev, key, persistent);
-
-			/* Don't keep debug keys around if the relevant
-			 * flag is not set.
-			 */
-			if (!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags) &&
-			    key->type == HCI_LK_DEBUG_COMBINATION) {
-				list_del_rcu(&key->list);
-				kfree_rcu(key, rcu);
-			}
-		}
-	}
-}
-
-static void sc_add_ltk(struct smp_chan *smp)
-{
-	struct hci_conn *hcon = smp->conn->hcon;
-	u8 key_type, auth;
-
-	if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
-		key_type = SMP_LTK_P256_DEBUG;
-	else
-		key_type = SMP_LTK_P256;
-
-	if (hcon->pending_sec_level == BT_SECURITY_FIPS)
-		auth = 1;
-	else
-		auth = 0;
-
-	memset(smp->tk + smp->enc_key_size, 0,
-	       SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
-
-	smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
-			       key_type, auth, smp->tk, smp->enc_key_size,
-			       0, 0);
-}
-
-static void sc_generate_link_key(struct smp_chan *smp)
-{
-	/* These constants are as specified in the core specification.
-	 * In ASCII they spell out to 'tmp1' and 'lebr'.
-	 */
-	const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
-	const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
-
-	smp->link_key = kzalloc(16, GFP_KERNEL);
-	if (!smp->link_key)
-		return;
-
-	if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
-		kfree(smp->link_key);
-		smp->link_key = NULL;
-		return;
-	}
-
-	if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
-		kfree(smp->link_key);
-		smp->link_key = NULL;
-		return;
-	}
 }
 
 static void smp_allow_key_dist(struct smp_chan *smp)
@@ -1126,35 +715,6 @@
 		SMP_ALLOW_CMD(smp, SMP_CMD_SIGN_INFO);
 }
 
-static void sc_generate_ltk(struct smp_chan *smp)
-{
-	/* These constants are as specified in the core specification.
-	 * In ASCII they spell out to 'tmp2' and 'brle'.
-	 */
-	const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
-	const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
-	struct hci_conn *hcon = smp->conn->hcon;
-	struct hci_dev *hdev = hcon->hdev;
-	struct link_key *key;
-
-	key = hci_find_link_key(hdev, &hcon->dst);
-	if (!key) {
-		BT_ERR("%s No Link Key found to generate LTK", hdev->name);
-		return;
-	}
-
-	if (key->type == HCI_LK_DEBUG_COMBINATION)
-		set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
-
-	if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
-		return;
-
-	if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk))
-		return;
-
-	sc_add_ltk(smp);
-}
-
 static void smp_distribute_keys(struct smp_chan *smp)
 {
 	struct smp_cmd_pairing *req, *rsp;
@@ -1183,16 +743,6 @@
 		*keydist &= req->resp_key_dist;
 	}
 
-	if (test_bit(SMP_FLAG_SC, &smp->flags)) {
-		if (hcon->type == LE_LINK && (*keydist & SMP_DIST_LINK_KEY))
-			sc_generate_link_key(smp);
-		if (hcon->type == ACL_LINK && (*keydist & SMP_DIST_ENC_KEY))
-			sc_generate_ltk(smp);
-
-		/* Clear the keys which are generated but not distributed */
-		*keydist &= ~SMP_SC_NO_DIST;
-	}
-
 	BT_DBG("keydist 0x%x", *keydist);
 
 	if (*keydist & SMP_DIST_ENC_KEY) {
@@ -1304,14 +854,6 @@
 		return NULL;
 	}
 
-	smp->tfm_cmac = crypto_alloc_hash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(smp->tfm_cmac)) {
-		BT_ERR("Unable to create CMAC crypto context");
-		crypto_free_blkcipher(smp->tfm_aes);
-		kfree(smp);
-		return NULL;
-	}
-
 	smp->conn = conn;
 	chan->data = smp;
 
@@ -1324,213 +866,6 @@
 	return smp;
 }
 
-static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
-{
-	struct hci_conn *hcon = smp->conn->hcon;
-	u8 *na, *nb, a[7], b[7];
-
-	if (hcon->out) {
-		na   = smp->prnd;
-		nb   = smp->rrnd;
-	} else {
-		na   = smp->rrnd;
-		nb   = smp->prnd;
-	}
-
-	memcpy(a, &hcon->init_addr, 6);
-	memcpy(b, &hcon->resp_addr, 6);
-	a[6] = hcon->init_addr_type;
-	b[6] = hcon->resp_addr_type;
-
-	return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk);
-}
-
-static void sc_dhkey_check(struct smp_chan *smp)
-{
-	struct hci_conn *hcon = smp->conn->hcon;
-	struct smp_cmd_dhkey_check check;
-	u8 a[7], b[7], *local_addr, *remote_addr;
-	u8 io_cap[3], r[16];
-
-	memcpy(a, &hcon->init_addr, 6);
-	memcpy(b, &hcon->resp_addr, 6);
-	a[6] = hcon->init_addr_type;
-	b[6] = hcon->resp_addr_type;
-
-	if (hcon->out) {
-		local_addr = a;
-		remote_addr = b;
-		memcpy(io_cap, &smp->preq[1], 3);
-	} else {
-		local_addr = b;
-		remote_addr = a;
-		memcpy(io_cap, &smp->prsp[1], 3);
-	}
-
-	memset(r, 0, sizeof(r));
-
-	if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
-		put_unaligned_le32(hcon->passkey_notify, r);
-
-	if (smp->method == REQ_OOB)
-		memcpy(r, smp->rr, 16);
-
-	smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
-	       local_addr, remote_addr, check.e);
-
-	smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check);
-}
-
-static u8 sc_passkey_send_confirm(struct smp_chan *smp)
-{
-	struct l2cap_conn *conn = smp->conn;
-	struct hci_conn *hcon = conn->hcon;
-	struct smp_cmd_pairing_confirm cfm;
-	u8 r;
-
-	r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
-	r |= 0x80;
-
-	get_random_bytes(smp->prnd, sizeof(smp->prnd));
-
-	if (smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, r,
-		   cfm.confirm_val))
-		return SMP_UNSPECIFIED;
-
-	smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm);
-
-	return 0;
-}
-
-static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
-{
-	struct l2cap_conn *conn = smp->conn;
-	struct hci_conn *hcon = conn->hcon;
-	struct hci_dev *hdev = hcon->hdev;
-	u8 cfm[16], r;
-
-	/* Ignore the PDU if we've already done 20 rounds (0 - 19) */
-	if (smp->passkey_round >= 20)
-		return 0;
-
-	switch (smp_op) {
-	case SMP_CMD_PAIRING_RANDOM:
-		r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
-		r |= 0x80;
-
-		if (smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
-			   smp->rrnd, r, cfm))
-			return SMP_UNSPECIFIED;
-
-		if (memcmp(smp->pcnf, cfm, 16))
-			return SMP_CONFIRM_FAILED;
-
-		smp->passkey_round++;
-
-		if (smp->passkey_round == 20) {
-			/* Generate MacKey and LTK */
-			if (sc_mackey_and_ltk(smp, smp->mackey, smp->tk))
-				return SMP_UNSPECIFIED;
-		}
-
-		/* The round is only complete when the initiator
-		 * receives pairing random.
-		 */
-		if (!hcon->out) {
-			smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
-				     sizeof(smp->prnd), smp->prnd);
-			if (smp->passkey_round == 20)
-				SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
-			else
-				SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-			return 0;
-		}
-
-		/* Start the next round */
-		if (smp->passkey_round != 20)
-			return sc_passkey_round(smp, 0);
-
-		/* Passkey rounds are complete - start DHKey Check */
-		sc_dhkey_check(smp);
-		SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
-
-		break;
-
-	case SMP_CMD_PAIRING_CONFIRM:
-		if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
-			set_bit(SMP_FLAG_CFM_PENDING, &smp->flags);
-			return 0;
-		}
-
-		SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
-
-		if (hcon->out) {
-			smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
-				     sizeof(smp->prnd), smp->prnd);
-			return 0;
-		}
-
-		return sc_passkey_send_confirm(smp);
-
-	case SMP_CMD_PUBLIC_KEY:
-	default:
-		/* Initiating device starts the round */
-		if (!hcon->out)
-			return 0;
-
-		BT_DBG("%s Starting passkey round %u", hdev->name,
-		       smp->passkey_round + 1);
-
-		SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-
-		return sc_passkey_send_confirm(smp);
-	}
-
-	return 0;
-}
-
-static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
-{
-	struct l2cap_conn *conn = smp->conn;
-	struct hci_conn *hcon = conn->hcon;
-	u8 smp_op;
-
-	clear_bit(SMP_FLAG_WAIT_USER, &smp->flags);
-
-	switch (mgmt_op) {
-	case MGMT_OP_USER_PASSKEY_NEG_REPLY:
-		smp_failure(smp->conn, SMP_PASSKEY_ENTRY_FAILED);
-		return 0;
-	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
-		smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED);
-		return 0;
-	case MGMT_OP_USER_PASSKEY_REPLY:
-		hcon->passkey_notify = le32_to_cpu(passkey);
-		smp->passkey_round = 0;
-
-		if (test_and_clear_bit(SMP_FLAG_CFM_PENDING, &smp->flags))
-			smp_op = SMP_CMD_PAIRING_CONFIRM;
-		else
-			smp_op = 0;
-
-		if (sc_passkey_round(smp, smp_op))
-			return -EIO;
-
-		return 0;
-	}
-
-	/* Initiator sends DHKey check first */
-	if (hcon->out) {
-		sc_dhkey_check(smp);
-		SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
-	} else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) {
-		sc_dhkey_check(smp);
-		sc_add_ltk(smp);
-	}
-
-	return 0;
-}
-
 int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
 {
 	struct l2cap_conn *conn = hcon->l2cap_data;
@@ -1556,11 +891,6 @@
 
 	smp = chan->data;
 
-	if (test_bit(SMP_FLAG_SC, &smp->flags)) {
-		err = sc_user_reply(smp, mgmt_op, passkey);
-		goto unlock;
-	}
-
 	switch (mgmt_op) {
 	case MGMT_OP_USER_PASSKEY_REPLY:
 		value = le32_to_cpu(passkey);
@@ -1596,46 +926,6 @@
 	return err;
 }
 
-static void build_bredr_pairing_cmd(struct smp_chan *smp,
-				    struct smp_cmd_pairing *req,
-				    struct smp_cmd_pairing *rsp)
-{
-	struct l2cap_conn *conn = smp->conn;
-	struct hci_dev *hdev = conn->hcon->hdev;
-	u8 local_dist = 0, remote_dist = 0;
-
-	if (test_bit(HCI_BONDABLE, &hdev->dev_flags)) {
-		local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
-		remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
-	}
-
-	if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags))
-		remote_dist |= SMP_DIST_ID_KEY;
-
-	if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
-		local_dist |= SMP_DIST_ID_KEY;
-
-	if (!rsp) {
-		memset(req, 0, sizeof(*req));
-
-		req->init_key_dist   = local_dist;
-		req->resp_key_dist   = remote_dist;
-		req->max_key_size    = SMP_MAX_ENC_KEY_SIZE;
-
-		smp->remote_key_dist = remote_dist;
-
-		return;
-	}
-
-	memset(rsp, 0, sizeof(*rsp));
-
-	rsp->max_key_size    = SMP_MAX_ENC_KEY_SIZE;
-	rsp->init_key_dist   = req->init_key_dist & remote_dist;
-	rsp->resp_key_dist   = req->resp_key_dist & local_dist;
-
-	smp->remote_key_dist = rsp->init_key_dist;
-}
-
 static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_pairing rsp, *req = (void *) skb->data;
@@ -1662,50 +952,16 @@
 		return SMP_UNSPECIFIED;
 
 	/* We didn't start the pairing, so match remote */
-	auth = req->auth_req & AUTH_REQ_MASK(hdev);
+	auth = req->auth_req & AUTH_REQ_MASK;
 
 	if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) &&
 	    (auth & SMP_AUTH_BONDING))
 		return SMP_PAIRING_NOTSUPP;
 
-	if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
-		return SMP_AUTH_REQUIREMENTS;
-
 	smp->preq[0] = SMP_CMD_PAIRING_REQ;
 	memcpy(&smp->preq[1], req, sizeof(*req));
 	skb_pull(skb, sizeof(*req));
 
-	/* SMP over BR/EDR requires special treatment */
-	if (conn->hcon->type == ACL_LINK) {
-		/* We must have a BR/EDR SC link */
-		if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) &&
-		    !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
-			return SMP_CROSS_TRANSP_NOT_ALLOWED;
-
-		set_bit(SMP_FLAG_SC, &smp->flags);
-
-		build_bredr_pairing_cmd(smp, req, &rsp);
-
-		key_size = min(req->max_key_size, rsp.max_key_size);
-		if (check_enc_key_size(conn, key_size))
-			return SMP_ENC_KEY_SIZE;
-
-		/* Clear bits which are generated but not distributed */
-		smp->remote_key_dist &= ~SMP_SC_NO_DIST;
-
-		smp->prsp[0] = SMP_CMD_PAIRING_RSP;
-		memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
-		smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
-
-		smp_distribute_keys(smp);
-		return 0;
-	}
-
-	build_pairing_cmd(conn, req, &rsp, auth);
-
-	if (rsp.auth_req & SMP_AUTH_SC)
-		set_bit(SMP_FLAG_SC, &smp->flags);
-
 	if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
 		sec_level = BT_SECURITY_MEDIUM;
 	else
@@ -1714,7 +970,7 @@
 	if (sec_level > conn->hcon->pending_sec_level)
 		conn->hcon->pending_sec_level = sec_level;
 
-	/* If we need MITM check that it can be achieved */
+	/* If we need MITM check that it can be acheived */
 	if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
 		u8 method;
 
@@ -1724,6 +980,8 @@
 			return SMP_AUTH_REQUIREMENTS;
 	}
 
+	build_pairing_cmd(conn, req, &rsp, auth);
+
 	key_size = min(req->max_key_size, rsp.max_key_size);
 	if (check_enc_key_size(conn, key_size))
 		return SMP_ENC_KEY_SIZE;
@@ -1734,18 +992,7 @@
 	memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
 
 	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
-
-	clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
-
-	if (test_bit(SMP_FLAG_SC, &smp->flags)) {
-		SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY);
-		/* Clear bits which are generated but not distributed */
-		smp->remote_key_dist &= ~SMP_SC_NO_DIST;
-		/* Wait for Public Key from Initiating Device */
-		return 0;
-	} else {
-		SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-	}
+	SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
 
 	/* Request setup of TK */
 	ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
@@ -1755,46 +1002,11 @@
 	return 0;
 }
 
-static u8 sc_send_public_key(struct smp_chan *smp)
-{
-	struct hci_dev *hdev = smp->conn->hcon->hdev;
-
-	BT_DBG("");
-
-	if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) {
-		BT_DBG("Using debug keys");
-		memcpy(smp->local_pk, debug_pk, 64);
-		memcpy(smp->local_sk, debug_sk, 32);
-		set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
-	} else {
-		while (true) {
-			/* Generate local key pair for Secure Connections */
-			if (!ecc_make_key(smp->local_pk, smp->local_sk))
-				return SMP_UNSPECIFIED;
-
-			/* This is unlikely, but we need to check that
-			 * we didn't accidentially generate a debug key.
-			 */
-			if (memcmp(smp->local_sk, debug_sk, 32))
-				break;
-		}
-	}
-
-	SMP_DBG("Local Public Key X: %32phN", smp->local_pk);
-	SMP_DBG("Local Public Key Y: %32phN", &smp->local_pk[32]);
-	SMP_DBG("Local Private Key:  %32phN", smp->local_sk);
-
-	smp_send_cmd(smp->conn, SMP_CMD_PUBLIC_KEY, 64, smp->local_pk);
-
-	return 0;
-}
-
 static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
 	struct l2cap_chan *chan = conn->smp;
 	struct smp_chan *smp = chan->data;
-	struct hci_dev *hdev = conn->hcon->hdev;
 	u8 key_size, auth;
 	int ret;
 
@@ -1814,33 +1026,9 @@
 	if (check_enc_key_size(conn, key_size))
 		return SMP_ENC_KEY_SIZE;
 
-	auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
+	auth = rsp->auth_req & AUTH_REQ_MASK;
 
-	if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
-		return SMP_AUTH_REQUIREMENTS;
-
-	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
-	memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
-
-	/* Update remote key distribution in case the remote cleared
-	 * some bits that we had enabled in our request.
-	 */
-	smp->remote_key_dist &= rsp->resp_key_dist;
-
-	/* For BR/EDR this means we're done and can start phase 3 */
-	if (conn->hcon->type == ACL_LINK) {
-		/* Clear bits which are generated but not distributed */
-		smp->remote_key_dist &= ~SMP_SC_NO_DIST;
-		smp_distribute_keys(smp);
-		return 0;
-	}
-
-	if ((req->auth_req & SMP_AUTH_SC) && (auth & SMP_AUTH_SC))
-		set_bit(SMP_FLAG_SC, &smp->flags);
-	else if (conn->hcon->pending_sec_level > BT_SECURITY_HIGH)
-		conn->hcon->pending_sec_level = BT_SECURITY_HIGH;
-
-	/* If we need MITM check that it can be achieved */
+	/* If we need MITM check that it can be acheived */
 	if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
 		u8 method;
 
@@ -1852,18 +1040,14 @@
 
 	get_random_bytes(smp->prnd, sizeof(smp->prnd));
 
+	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
+	memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
+
 	/* Update remote key distribution in case the remote cleared
 	 * some bits that we had enabled in our request.
 	 */
 	smp->remote_key_dist &= rsp->resp_key_dist;
 
-	if (test_bit(SMP_FLAG_SC, &smp->flags)) {
-		/* Clear bits which are generated but not distributed */
-		smp->remote_key_dist &= ~SMP_SC_NO_DIST;
-		SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY);
-		return sc_send_public_key(smp);
-	}
-
 	auth |= req->auth_req;
 
 	ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
@@ -1879,28 +1063,6 @@
 	return 0;
 }
 
-static u8 sc_check_confirm(struct smp_chan *smp)
-{
-	struct l2cap_conn *conn = smp->conn;
-
-	BT_DBG("");
-
-	/* Public Key exchange must happen before any other steps */
-	if (!test_bit(SMP_FLAG_REMOTE_PK, &smp->flags))
-		return SMP_UNSPECIFIED;
-
-	if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
-		return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
-
-	if (conn->hcon->out) {
-		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
-			     smp->prnd);
-		SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
-	}
-
-	return 0;
-}
-
 static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct l2cap_chan *chan = conn->smp;
@@ -1914,9 +1076,6 @@
 	memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
 	skb_pull(skb, sizeof(smp->pcnf));
 
-	if (test_bit(SMP_FLAG_SC, &smp->flags))
-		return sc_check_confirm(smp);
-
 	if (conn->hcon->out) {
 		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
 			     smp->prnd);
@@ -1936,10 +1095,6 @@
 {
 	struct l2cap_chan *chan = conn->smp;
 	struct smp_chan *smp = chan->data;
-	struct hci_conn *hcon = conn->hcon;
-	u8 *pkax, *pkbx, *na, *nb;
-	u32 passkey;
-	int err;
 
 	BT_DBG("conn %p", conn);
 
@@ -1949,75 +1104,7 @@
 	memcpy(smp->rrnd, skb->data, sizeof(smp->rrnd));
 	skb_pull(skb, sizeof(smp->rrnd));
 
-	if (!test_bit(SMP_FLAG_SC, &smp->flags))
-		return smp_random(smp);
-
-	if (hcon->out) {
-		pkax = smp->local_pk;
-		pkbx = smp->remote_pk;
-		na   = smp->prnd;
-		nb   = smp->rrnd;
-	} else {
-		pkax = smp->remote_pk;
-		pkbx = smp->local_pk;
-		na   = smp->rrnd;
-		nb   = smp->prnd;
-	}
-
-	if (smp->method == REQ_OOB) {
-		if (!hcon->out)
-			smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
-				     sizeof(smp->prnd), smp->prnd);
-		SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
-		goto mackey_and_ltk;
-	}
-
-	/* Passkey entry has special treatment */
-	if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
-		return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
-
-	if (hcon->out) {
-		u8 cfm[16];
-
-		err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
-			     smp->rrnd, 0, cfm);
-		if (err)
-			return SMP_UNSPECIFIED;
-
-		if (memcmp(smp->pcnf, cfm, 16))
-			return SMP_CONFIRM_FAILED;
-	} else {
-		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
-			     smp->prnd);
-		SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
-	}
-
-mackey_and_ltk:
-	/* Generate MacKey and LTK */
-	err = sc_mackey_and_ltk(smp, smp->mackey, smp->tk);
-	if (err)
-		return SMP_UNSPECIFIED;
-
-	if (smp->method == JUST_WORKS || smp->method == REQ_OOB) {
-		if (hcon->out) {
-			sc_dhkey_check(smp);
-			SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
-		}
-		return 0;
-	}
-
-	err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
-	if (err)
-		return SMP_UNSPECIFIED;
-
-	err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type,
-					hcon->dst_type, passkey, 0);
-	if (err)
-		return SMP_UNSPECIFIED;
-
-	set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
-
-	return 0;
+	return smp_random(smp);
 }
 
 static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
@@ -2025,7 +1112,8 @@
 	struct smp_ltk *key;
 	struct hci_conn *hcon = conn->hcon;
 
-	key = hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role);
+	key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
+				   hcon->role);
 	if (!key)
 		return false;
 
@@ -2044,21 +1132,20 @@
 	return true;
 }
 
-bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
-			     enum smp_key_pref key_pref)
+bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
 {
 	if (sec_level == BT_SECURITY_LOW)
 		return true;
 
-	/* If we're encrypted with an STK but the caller prefers using
-	 * LTK claim insufficient security. This way we allow the
-	 * connection to be re-encrypted with an LTK, even if the LTK
-	 * provides the same level of security. Only exception is if we
-	 * don't have an LTK (e.g. because of key distribution bits).
+	/* If we're encrypted with an STK always claim insufficient
+	 * security. This way we allow the connection to be re-encrypted
+	 * with an LTK, even if the LTK provides the same level of
+	 * security. Only exception is if we don't have an LTK (e.g.
+	 * because of key distribution bits).
 	 */
-	if (key_pref == SMP_USE_LTK &&
-	    test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
-	    hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role))
+	if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
+	    hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
+				 hcon->role))
 		return false;
 
 	if (hcon->sec_level >= sec_level)
@@ -2072,7 +1159,6 @@
 	struct smp_cmd_security_req *rp = (void *) skb->data;
 	struct smp_cmd_pairing cp;
 	struct hci_conn *hcon = conn->hcon;
-	struct hci_dev *hdev = hcon->hdev;
 	struct smp_chan *smp;
 	u8 sec_level, auth;
 
@@ -2084,17 +1170,14 @@
 	if (hcon->role != HCI_ROLE_MASTER)
 		return SMP_CMD_NOTSUPP;
 
-	auth = rp->auth_req & AUTH_REQ_MASK(hdev);
-
-	if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
-		return SMP_AUTH_REQUIREMENTS;
+	auth = rp->auth_req & AUTH_REQ_MASK;
 
 	if (hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
 		sec_level = BT_SECURITY_MEDIUM;
 	else
 		sec_level = authreq_to_seclevel(auth);
 
-	if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
+	if (smp_sufficient_security(hcon, sec_level))
 		return 0;
 
 	if (sec_level > hcon->pending_sec_level)
@@ -2144,7 +1227,7 @@
 	if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
 		return 1;
 
-	if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
+	if (smp_sufficient_security(hcon, sec_level))
 		return 1;
 
 	if (sec_level > hcon->pending_sec_level)
@@ -2170,9 +1253,6 @@
 
 	authreq = seclevel_to_authreq(sec_level);
 
-	if (test_bit(HCI_SC_ENABLED, &hcon->hdev->dev_flags))
-		authreq |= SMP_AUTH_SC;
-
 	/* Require MITM if IO Capability allows or the security level
 	 * requires it.
 	 */
@@ -2249,6 +1329,7 @@
 
 	skb_pull(skb, sizeof(*rp));
 
+	hci_dev_lock(hdev);
 	authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
 	ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, SMP_LTK,
 			  authenticated, smp->tk, smp->enc_key_size,
@@ -2256,6 +1337,7 @@
 	smp->ltk = ltk;
 	if (!(smp->remote_key_dist & KEY_DIST_MASK))
 		smp_distribute_keys(smp);
+	hci_dev_unlock(hdev);
 
 	return 0;
 }
@@ -2302,6 +1384,8 @@
 
 	skb_pull(skb, sizeof(*info));
 
+	hci_dev_lock(hcon->hdev);
+
 	/* Strictly speaking the Core Specification (4.1) allows sending
 	 * an empty address which would force us to rely on just the IRK
 	 * as "identity information". However, since such
@@ -2329,6 +1413,8 @@
 	if (!(smp->remote_key_dist & KEY_DIST_MASK))
 		smp_distribute_keys(smp);
 
+	hci_dev_unlock(hcon->hdev);
+
 	return 0;
 }
 
@@ -2337,6 +1423,7 @@
 	struct smp_cmd_sign_info *rp = (void *) skb->data;
 	struct l2cap_chan *chan = conn->smp;
 	struct smp_chan *smp = chan->data;
+	struct hci_dev *hdev = conn->hcon->hdev;
 	struct smp_csrk *csrk;
 
 	BT_DBG("conn %p", conn);
@@ -2349,6 +1436,7 @@
 
 	skb_pull(skb, sizeof(*rp));
 
+	hci_dev_lock(hdev);
 	csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
 	if (csrk) {
 		csrk->master = 0x01;
@@ -2356,234 +1444,7 @@
 	}
 	smp->csrk = csrk;
 	smp_distribute_keys(smp);
-
-	return 0;
-}
-
-static u8 sc_select_method(struct smp_chan *smp)
-{
-	struct l2cap_conn *conn = smp->conn;
-	struct hci_conn *hcon = conn->hcon;
-	struct smp_cmd_pairing *local, *remote;
-	u8 local_mitm, remote_mitm, local_io, remote_io, method;
-
-	if (test_bit(SMP_FLAG_OOB, &smp->flags))
-		return REQ_OOB;
-
-	/* The preq/prsp contain the raw Pairing Request/Response PDUs
-	 * which are needed as inputs to some crypto functions. To get
-	 * the "struct smp_cmd_pairing" from them we need to skip the
-	 * first byte which contains the opcode.
-	 */
-	if (hcon->out) {
-		local = (void *) &smp->preq[1];
-		remote = (void *) &smp->prsp[1];
-	} else {
-		local = (void *) &smp->prsp[1];
-		remote = (void *) &smp->preq[1];
-	}
-
-	local_io = local->io_capability;
-	remote_io = remote->io_capability;
-
-	local_mitm = (local->auth_req & SMP_AUTH_MITM);
-	remote_mitm = (remote->auth_req & SMP_AUTH_MITM);
-
-	/* If either side wants MITM, look up the method from the table,
-	 * otherwise use JUST WORKS.
-	 */
-	if (local_mitm || remote_mitm)
-		method = get_auth_method(smp, local_io, remote_io);
-	else
-		method = JUST_WORKS;
-
-	/* Don't confirm locally initiated pairing attempts */
-	if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
-		method = JUST_WORKS;
-
-	return method;
-}
-
-static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
-{
-	struct smp_cmd_public_key *key = (void *) skb->data;
-	struct hci_conn *hcon = conn->hcon;
-	struct l2cap_chan *chan = conn->smp;
-	struct smp_chan *smp = chan->data;
-	struct hci_dev *hdev = hcon->hdev;
-	struct smp_cmd_pairing_confirm cfm;
-	int err;
-
-	BT_DBG("conn %p", conn);
-
-	if (skb->len < sizeof(*key))
-		return SMP_INVALID_PARAMS;
-
-	memcpy(smp->remote_pk, key, 64);
-
-	/* Non-initiating device sends its public key after receiving
-	 * the key from the initiating device.
-	 */
-	if (!hcon->out) {
-		err = sc_send_public_key(smp);
-		if (err)
-			return err;
-	}
-
-	SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk);
-	SMP_DBG("Remote Public Key Y: %32phN", &smp->remote_pk[32]);
-
-	if (!ecdh_shared_secret(smp->remote_pk, smp->local_sk, smp->dhkey))
-		return SMP_UNSPECIFIED;
-
-	SMP_DBG("DHKey %32phN", smp->dhkey);
-
-	set_bit(SMP_FLAG_REMOTE_PK, &smp->flags);
-
-	smp->method = sc_select_method(smp);
-
-	BT_DBG("%s selected method 0x%02x", hdev->name, smp->method);
-
-	/* JUST_WORKS and JUST_CFM result in an unauthenticated key */
-	if (smp->method == JUST_WORKS || smp->method == JUST_CFM)
-		hcon->pending_sec_level = BT_SECURITY_MEDIUM;
-	else
-		hcon->pending_sec_level = BT_SECURITY_FIPS;
-
-	if (!memcmp(debug_pk, smp->remote_pk, 64))
-		set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
-
-	if (smp->method == DSP_PASSKEY) {
-		get_random_bytes(&hcon->passkey_notify,
-				 sizeof(hcon->passkey_notify));
-		hcon->passkey_notify %= 1000000;
-		hcon->passkey_entered = 0;
-		smp->passkey_round = 0;
-		if (mgmt_user_passkey_notify(hdev, &hcon->dst, hcon->type,
-					     hcon->dst_type,
-					     hcon->passkey_notify,
-					     hcon->passkey_entered))
-			return SMP_UNSPECIFIED;
-		SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-		return sc_passkey_round(smp, SMP_CMD_PUBLIC_KEY);
-	}
-
-	if (smp->method == REQ_OOB) {
-		err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->remote_pk,
-			     smp->rr, 0, cfm.confirm_val);
-		if (err)
-			return SMP_UNSPECIFIED;
-
-		if (memcmp(cfm.confirm_val, smp->pcnf, 16))
-			return SMP_CONFIRM_FAILED;
-
-		if (hcon->out)
-			smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
-				     sizeof(smp->prnd), smp->prnd);
-
-		SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
-
-		return 0;
-	}
-
-	if (hcon->out)
-		SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-
-	if (smp->method == REQ_PASSKEY) {
-		if (mgmt_user_passkey_request(hdev, &hcon->dst, hcon->type,
-					      hcon->dst_type))
-			return SMP_UNSPECIFIED;
-		SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-		set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
-		return 0;
-	}
-
-	/* The Initiating device waits for the non-initiating device to
-	 * send the confirm value.
-	 */
-	if (conn->hcon->out)
-		return 0;
-
-	err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
-		     0, cfm.confirm_val);
-	if (err)
-		return SMP_UNSPECIFIED;
-
-	smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm);
-	SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
-
-	return 0;
-}
-
-static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
-{
-	struct smp_cmd_dhkey_check *check = (void *) skb->data;
-	struct l2cap_chan *chan = conn->smp;
-	struct hci_conn *hcon = conn->hcon;
-	struct smp_chan *smp = chan->data;
-	u8 a[7], b[7], *local_addr, *remote_addr;
-	u8 io_cap[3], r[16], e[16];
-	int err;
-
-	BT_DBG("conn %p", conn);
-
-	if (skb->len < sizeof(*check))
-		return SMP_INVALID_PARAMS;
-
-	memcpy(a, &hcon->init_addr, 6);
-	memcpy(b, &hcon->resp_addr, 6);
-	a[6] = hcon->init_addr_type;
-	b[6] = hcon->resp_addr_type;
-
-	if (hcon->out) {
-		local_addr = a;
-		remote_addr = b;
-		memcpy(io_cap, &smp->prsp[1], 3);
-	} else {
-		local_addr = b;
-		remote_addr = a;
-		memcpy(io_cap, &smp->preq[1], 3);
-	}
-
-	memset(r, 0, sizeof(r));
-
-	if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
-		put_unaligned_le32(hcon->passkey_notify, r);
-
-	err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r,
-		     io_cap, remote_addr, local_addr, e);
-	if (err)
-		return SMP_UNSPECIFIED;
-
-	if (memcmp(check->e, e, 16))
-		return SMP_DHKEY_CHECK_FAILED;
-
-	if (!hcon->out) {
-		if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
-			set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags);
-			return 0;
-		}
-
-		/* Slave sends DHKey check as response to master */
-		sc_dhkey_check(smp);
-	}
-
-	sc_add_ltk(smp);
-
-	if (hcon->out) {
-		hci_le_start_enc(hcon, 0, 0, smp->tk);
-		hcon->enc_key_size = smp->enc_key_size;
-	}
-
-	return 0;
-}
-
-static int smp_cmd_keypress_notify(struct l2cap_conn *conn,
-				   struct sk_buff *skb)
-{
-	struct smp_cmd_keypress_notify *kp = (void *) skb->data;
-
-	BT_DBG("value 0x%02x", kp->value);
+	hci_dev_unlock(hdev);
 
 	return 0;
 }
@@ -2596,6 +1457,11 @@
 	__u8 code, reason;
 	int err = 0;
 
+	if (hcon->type != LE_LINK) {
+		kfree_skb(skb);
+		return 0;
+	}
+
 	if (skb->len < 1)
 		return -EILSEQ;
 
@@ -2667,18 +1533,6 @@
 		reason = smp_cmd_sign_info(conn, skb);
 		break;
 
-	case SMP_CMD_PUBLIC_KEY:
-		reason = smp_cmd_public_key(conn, skb);
-		break;
-
-	case SMP_CMD_DHKEY_CHECK:
-		reason = smp_cmd_dhkey_check(conn, skb);
-		break;
-
-	case SMP_CMD_KEYPRESS_NOTIFY:
-		reason = smp_cmd_keypress_notify(conn, skb);
-		break;
-
 	default:
 		BT_DBG("Unknown command code 0x%2.2x", code);
 		reason = SMP_CMD_NOTSUPP;
@@ -2714,74 +1568,6 @@
 	l2cap_chan_put(chan);
 }
 
-static void bredr_pairing(struct l2cap_chan *chan)
-{
-	struct l2cap_conn *conn = chan->conn;
-	struct hci_conn *hcon = conn->hcon;
-	struct hci_dev *hdev = hcon->hdev;
-	struct smp_cmd_pairing req;
-	struct smp_chan *smp;
-
-	BT_DBG("chan %p", chan);
-
-	/* Only new pairings are interesting */
-	if (!test_bit(HCI_CONN_NEW_LINK_KEY, &hcon->flags))
-		return;
-
-	/* Don't bother if we're not encrypted */
-	if (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
-		return;
-
-	/* Only master may initiate SMP over BR/EDR */
-	if (hcon->role != HCI_ROLE_MASTER)
-		return;
-
-	/* Secure Connections support must be enabled */
-	if (!test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
-		return;
-
-	/* BR/EDR must use Secure Connections for SMP */
-	if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) &&
-	    !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
-		return;
-
-	/* If our LE support is not enabled don't do anything */
-	if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
-		return;
-
-	/* Don't bother if remote LE support is not enabled */
-	if (!lmp_host_le_capable(hcon))
-		return;
-
-	/* Remote must support SMP fixed chan for BR/EDR */
-	if (!(conn->remote_fixed_chan & L2CAP_FC_SMP_BREDR))
-		return;
-
-	/* Don't bother if SMP is already ongoing */
-	if (chan->data)
-		return;
-
-	smp = smp_chan_create(conn);
-	if (!smp) {
-		BT_ERR("%s unable to create SMP context for BR/EDR",
-		       hdev->name);
-		return;
-	}
-
-	set_bit(SMP_FLAG_SC, &smp->flags);
-
-	BT_DBG("%s starting SMP over BR/EDR", hdev->name);
-
-	/* Prepare and send the BR/EDR SMP Pairing Request */
-	build_bredr_pairing_cmd(smp, &req, NULL);
-
-	smp->preq[0] = SMP_CMD_PAIRING_REQ;
-	memcpy(&smp->preq[1], &req, sizeof(req));
-
-	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(req), &req);
-	SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP);
-}
-
 static void smp_resume_cb(struct l2cap_chan *chan)
 {
 	struct smp_chan *smp = chan->data;
@@ -2790,11 +1576,6 @@
 
 	BT_DBG("chan %p", chan);
 
-	if (hcon->type == ACL_LINK) {
-		bredr_pairing(chan);
-		return;
-	}
-
 	if (!smp)
 		return;
 
@@ -2809,15 +1590,11 @@
 static void smp_ready_cb(struct l2cap_chan *chan)
 {
 	struct l2cap_conn *conn = chan->conn;
-	struct hci_conn *hcon = conn->hcon;
 
 	BT_DBG("chan %p", chan);
 
 	conn->smp = chan;
 	l2cap_chan_hold(chan);
-
-	if (hcon->type == ACL_LINK && test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
-		bredr_pairing(chan);
 }
 
 static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
@@ -2891,13 +1668,6 @@
 	chan->omtu	= pchan->omtu;
 	chan->mode	= pchan->mode;
 
-	/* Other L2CAP channels may request SMP routines in order to
-	 * change the security level. This means that the SMP channel
-	 * lock must be considered in its own category to avoid lockdep
-	 * warnings.
-	 */
-	atomic_set(&chan->nesting, L2CAP_NESTING_SMP);
-
 	BT_DBG("created chan %p", chan);
 
 	return chan;
@@ -2922,56 +1692,53 @@
 	.memcpy_fromiovec	= l2cap_chan_no_memcpy_fromiovec,
 };
 
-static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
+int smp_register(struct hci_dev *hdev)
 {
 	struct l2cap_chan *chan;
 	struct crypto_blkcipher	*tfm_aes;
 
-	if (cid == L2CAP_CID_SMP_BREDR) {
-		tfm_aes = NULL;
-		goto create_chan;
-	}
+	BT_DBG("%s", hdev->name);
 
-	tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 0);
+	tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(tfm_aes)) {
+		int err = PTR_ERR(tfm_aes);
 		BT_ERR("Unable to create crypto context");
-		return ERR_CAST(tfm_aes);
+		return err;
 	}
 
-create_chan:
 	chan = l2cap_chan_create();
 	if (!chan) {
 		crypto_free_blkcipher(tfm_aes);
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	chan->data = tfm_aes;
 
-	l2cap_add_scid(chan, cid);
+	l2cap_add_scid(chan, L2CAP_CID_SMP);
 
 	l2cap_chan_set_defaults(chan);
 
 	bacpy(&chan->src, &hdev->bdaddr);
-	if (cid == L2CAP_CID_SMP)
-		chan->src_type = BDADDR_LE_PUBLIC;
-	else
-		chan->src_type = BDADDR_BREDR;
+	chan->src_type = BDADDR_LE_PUBLIC;
 	chan->state = BT_LISTEN;
 	chan->mode = L2CAP_MODE_BASIC;
 	chan->imtu = L2CAP_DEFAULT_MTU;
 	chan->ops = &smp_root_chan_ops;
 
-	/* Set correct nesting level for a parent/listening channel */
-	atomic_set(&chan->nesting, L2CAP_NESTING_PARENT);
+	hdev->smp_data = chan;
 
-	return chan;
+	return 0;
 }
 
-static void smp_del_chan(struct l2cap_chan *chan)
+void smp_unregister(struct hci_dev *hdev)
 {
-	struct crypto_blkcipher	*tfm_aes;
+	struct l2cap_chan *chan = hdev->smp_data;
+	struct crypto_blkcipher *tfm_aes;
 
-	BT_DBG("chan %p", chan);
+	if (!chan)
+		return;
+
+	BT_DBG("%s chan %p", hdev->name, chan);
 
 	tfm_aes = chan->data;
 	if (tfm_aes) {
@@ -2979,52 +1746,6 @@
 		crypto_free_blkcipher(tfm_aes);
 	}
 
+	hdev->smp_data = NULL;
 	l2cap_chan_put(chan);
 }
-
-int smp_register(struct hci_dev *hdev)
-{
-	struct l2cap_chan *chan;
-
-	BT_DBG("%s", hdev->name);
-
-	chan = smp_add_cid(hdev, L2CAP_CID_SMP);
-	if (IS_ERR(chan))
-		return PTR_ERR(chan);
-
-	hdev->smp_data = chan;
-
-	if (!lmp_sc_capable(hdev) &&
-	    !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
-		return 0;
-
-	chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR);
-	if (IS_ERR(chan)) {
-		int err = PTR_ERR(chan);
-		chan = hdev->smp_data;
-		hdev->smp_data = NULL;
-		smp_del_chan(chan);
-		return err;
-	}
-
-	hdev->smp_bredr_data = chan;
-
-	return 0;
-}
-
-void smp_unregister(struct hci_dev *hdev)
-{
-	struct l2cap_chan *chan;
-
-	if (hdev->smp_bredr_data) {
-		chan = hdev->smp_bredr_data;
-		hdev->smp_bredr_data = NULL;
-		smp_del_chan(chan);
-	}
-
-	if (hdev->smp_data) {
-		chan = hdev->smp_data;
-		hdev->smp_data = NULL;
-		smp_del_chan(chan);
-	}
-}
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index 3296bf4..86a683a 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -50,13 +50,10 @@
 #define SMP_DIST_ENC_KEY	0x01
 #define SMP_DIST_ID_KEY		0x02
 #define SMP_DIST_SIGN		0x04
-#define SMP_DIST_LINK_KEY	0x08
 
 #define SMP_AUTH_NONE		0x00
 #define SMP_AUTH_BONDING	0x01
 #define SMP_AUTH_MITM		0x04
-#define SMP_AUTH_SC		0x08
-#define SMP_AUTH_KEYPRESS	0x10
 
 #define SMP_CMD_PAIRING_CONFIRM	0x03
 struct smp_cmd_pairing_confirm {
@@ -105,23 +102,7 @@
 	__u8	auth_req;
 } __packed;
 
-#define SMP_CMD_PUBLIC_KEY	0x0c
-struct smp_cmd_public_key {
-	__u8	x[32];
-	__u8	y[32];
-} __packed;
-
-#define SMP_CMD_DHKEY_CHECK	0x0d
-struct smp_cmd_dhkey_check {
-	__u8	e[16];
-} __packed;
-
-#define SMP_CMD_KEYPRESS_NOTIFY	0x0e
-struct smp_cmd_keypress_notify {
-	__u8	value;
-} __packed;
-
-#define SMP_CMD_MAX		0x0e
+#define SMP_CMD_MAX		0x0b
 
 #define SMP_PASSKEY_ENTRY_FAILED	0x01
 #define SMP_OOB_NOT_AVAIL		0x02
@@ -133,10 +114,6 @@
 #define SMP_UNSPECIFIED			0x08
 #define SMP_REPEATED_ATTEMPTS		0x09
 #define SMP_INVALID_PARAMS		0x0a
-#define SMP_DHKEY_CHECK_FAILED		0x0b
-#define SMP_NUMERIC_COMP_FAILED		0x0c
-#define SMP_BREDR_PAIRING_IN_PROGRESS	0x0d
-#define SMP_CROSS_TRANSP_NOT_ALLOWED	0x0e
 
 #define SMP_MIN_ENC_KEY_SIZE		7
 #define SMP_MAX_ENC_KEY_SIZE		16
@@ -146,48 +123,23 @@
 	SMP_STK,
 	SMP_LTK,
 	SMP_LTK_SLAVE,
-	SMP_LTK_P256,
-	SMP_LTK_P256_DEBUG,
 };
 
-static inline bool smp_ltk_is_sc(struct smp_ltk *key)
-{
-	switch (key->type) {
-	case SMP_LTK_P256:
-	case SMP_LTK_P256_DEBUG:
-		return true;
-	}
-
-	return false;
-}
-
 static inline u8 smp_ltk_sec_level(struct smp_ltk *key)
 {
-	if (key->authenticated) {
-		if (smp_ltk_is_sc(key))
-			return BT_SECURITY_FIPS;
-		else
-			return BT_SECURITY_HIGH;
-	}
+	if (key->authenticated)
+		return BT_SECURITY_HIGH;
 
 	return BT_SECURITY_MEDIUM;
 }
 
-/* Key preferences for smp_sufficient security */
-enum smp_key_pref {
-	SMP_ALLOW_STK,
-	SMP_USE_LTK,
-};
-
 /* SMP Commands */
-bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
-			     enum smp_key_pref key_pref);
+bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
 int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
 int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
 
-bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
-		     const bdaddr_t *bdaddr);
-int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa);
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr);
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa);
 
 int smp_register(struct hci_dev *hdev);
 void smp_unregister(struct hci_dev *hdev);
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index dc34d84..69cbc62 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -49,8 +49,8 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/netdevice.h>
-#include <linux/ieee802154.h>
 #include <net/af_ieee802154.h>
+#include <net/ieee802154.h>
 #include <net/ieee802154_netdev.h>
 #include <net/6lowpan.h>
 #include <net/ipv6.h>
@@ -58,13 +58,12 @@
 #include "reassembly.h"
 
 static LIST_HEAD(lowpan_devices);
-static int lowpan_open_count;
 
 /* private device info */
 struct lowpan_dev_info {
 	struct net_device	*real_dev; /* real WPAN device ptr */
 	struct mutex		dev_list_mtx; /* mutex for list ops */
-	u16			fragment_tag;
+	__be16			fragment_tag;
 };
 
 struct lowpan_dev_record {
@@ -141,33 +140,24 @@
 	struct sk_buff *skb_cp;
 	int stat = NET_RX_SUCCESS;
 
-	skb->protocol = htons(ETH_P_IPV6);
-	skb->pkt_type = PACKET_HOST;
-
 	rcu_read_lock();
 	list_for_each_entry_rcu(entry, &lowpan_devices, list)
 		if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
 			skb_cp = skb_copy(skb, GFP_ATOMIC);
 			if (!skb_cp) {
-				kfree_skb(skb);
-				rcu_read_unlock();
-				return NET_RX_DROP;
+				stat = -ENOMEM;
+				break;
 			}
 
 			skb_cp->dev = entry->ldev;
 			stat = netif_rx(skb_cp);
-			if (stat == NET_RX_DROP)
-				break;
 		}
 	rcu_read_unlock();
 
-	consume_skb(skb);
-
 	return stat;
 }
 
-static int
-iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
+static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 {
 	u8 iphc0, iphc1;
 	struct ieee802154_addr_sa sa, da;
@@ -176,13 +166,13 @@
 	raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
 	/* at least two bytes will be used for the encoding */
 	if (skb->len < 2)
-		return -EINVAL;
+		goto drop;
 
 	if (lowpan_fetch_skb_u8(skb, &iphc0))
-		return -EINVAL;
+		goto drop;
 
 	if (lowpan_fetch_skb_u8(skb, &iphc1))
-		return -EINVAL;
+		goto drop;
 
 	ieee802154_addr_to_sa(&sa, &hdr->source);
 	ieee802154_addr_to_sa(&da, &hdr->dest);
@@ -197,9 +187,27 @@
 	else
 		dap = &da.hwaddr;
 
-	return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type,
-					IEEE802154_ADDR_LEN, dap, da.addr_type,
-					IEEE802154_ADDR_LEN, iphc0, iphc1);
+	return lowpan_process_data(skb, skb->dev, sap, sa.addr_type,
+				   IEEE802154_ADDR_LEN, dap, da.addr_type,
+				   IEEE802154_ADDR_LEN, iphc0, iphc1,
+				   lowpan_give_skb_to_devices);
+
+drop:
+	kfree_skb(skb);
+	return -EINVAL;
+}
+
+static int lowpan_set_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *sa = p;
+
+	if (netif_running(dev))
+		return -EBUSY;
+
+	/* TODO: validate addr */
+	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+	return 0;
 }
 
 static struct sk_buff*
@@ -225,7 +233,7 @@
 				     &master_hdr->source, size);
 		if (rc < 0) {
 			kfree_skb(frag);
-			return ERR_PTR(rc);
+			return ERR_PTR(-rc);
 		}
 	} else {
 		frag = ERR_PTR(-ENOMEM);
@@ -267,8 +275,7 @@
 
 	dgram_size = lowpan_uncompress_size(skb, &dgram_offset) -
 		     skb->mac_len;
-	frag_tag = htons(lowpan_dev_info(dev)->fragment_tag);
-	lowpan_dev_info(dev)->fragment_tag++;
+	frag_tag = lowpan_dev_info(dev)->fragment_tag++;
 
 	frag_hdr[0] = LOWPAN_DISPATCH_FRAG1 | ((dgram_size >> 8) & 0x07);
 	frag_hdr[1] = dgram_size & 0xff;
@@ -287,7 +294,7 @@
 				  frag_len + skb_network_header_len(skb));
 	if (rc) {
 		pr_debug("%s unable to send FRAG1 packet (tag: %d)",
-			 __func__, ntohs(frag_tag));
+			 __func__, frag_tag);
 		goto err;
 	}
 
@@ -308,7 +315,7 @@
 					  frag_len);
 		if (rc) {
 			pr_debug("%s unable to send a FRAGN packet. (tag: %d, offset: %d)\n",
-				 __func__, ntohs(frag_tag), skb_offset);
+				 __func__, frag_tag, skb_offset);
 			goto err;
 		}
 	} while (skb_unprocessed > frag_cap);
@@ -403,6 +410,13 @@
 	}
 }
 
+static struct wpan_phy *lowpan_get_phy(const struct net_device *dev)
+{
+	struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+
+	return ieee802154_mlme_ops(real_dev)->get_phy(real_dev);
+}
+
 static __le16 lowpan_get_pan_id(const struct net_device *dev)
 {
 	struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
@@ -441,6 +455,7 @@
 			  &lowpan_netdev_xmit_lock_key);
 }
 
+
 static int lowpan_dev_init(struct net_device *dev)
 {
 	netdev_for_each_tx_queue(dev, lowpan_set_lockdep_class_one, NULL);
@@ -453,10 +468,12 @@
 static const struct net_device_ops lowpan_netdev_ops = {
 	.ndo_init		= lowpan_dev_init,
 	.ndo_start_xmit		= lowpan_xmit,
+	.ndo_set_mac_address	= lowpan_set_address,
 };
 
 static struct ieee802154_mlme_ops lowpan_mlme = {
 	.get_pan_id = lowpan_get_pan_id,
+	.get_phy = lowpan_get_phy,
 	.get_short_addr = lowpan_get_short_addr,
 	.get_dsn = lowpan_get_dsn,
 };
@@ -502,9 +519,6 @@
 	if (!netif_running(dev))
 		goto drop_skb;
 
-	if (skb->pkt_type == PACKET_OTHERHOST)
-		goto drop_skb;
-
 	if (dev->type != ARPHRD_IEEE802154)
 		goto drop_skb;
 
@@ -513,67 +527,55 @@
 
 	/* check that it's our buffer */
 	if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
+		skb->protocol = htons(ETH_P_IPV6);
+		skb->pkt_type = PACKET_HOST;
+
 		/* Pull off the 1-byte of 6lowpan header. */
 		skb_pull(skb, 1);
-		return lowpan_give_skb_to_devices(skb, NULL);
+
+		ret = lowpan_give_skb_to_devices(skb, NULL);
+		if (ret == NET_RX_DROP)
+			goto drop;
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
-			ret = iphc_decompress(skb, &hdr);
-			if (ret < 0)
-				goto drop_skb;
-
-			return lowpan_give_skb_to_devices(skb, NULL);
+			ret = process_data(skb, &hdr);
+			if (ret == NET_RX_DROP)
+				goto drop;
+			break;
 		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
 			if (ret == 1) {
-				ret = iphc_decompress(skb, &hdr);
-				if (ret < 0)
-					goto drop_skb;
-
-				return lowpan_give_skb_to_devices(skb, NULL);
-			} else if (ret == -1) {
-				return NET_RX_DROP;
-			} else {
-				return NET_RX_SUCCESS;
+				ret = process_data(skb, &hdr);
+				if (ret == NET_RX_DROP)
+					goto drop;
 			}
+			break;
 		case LOWPAN_DISPATCH_FRAGN:	/* next fragments headers */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
 			if (ret == 1) {
-				ret = iphc_decompress(skb, &hdr);
-				if (ret < 0)
-					goto drop_skb;
-
-				return lowpan_give_skb_to_devices(skb, NULL);
-			} else if (ret == -1) {
-				return NET_RX_DROP;
-			} else {
-				return NET_RX_SUCCESS;
+				ret = process_data(skb, &hdr);
+				if (ret == NET_RX_DROP)
+					goto drop;
 			}
+			break;
 		default:
 			break;
 		}
 	}
 
+	return NET_RX_SUCCESS;
 drop_skb:
 	kfree_skb(skb);
 drop:
 	return NET_RX_DROP;
 }
 
-static struct packet_type lowpan_packet_type = {
-	.type = htons(ETH_P_IEEE802154),
-	.func = lowpan_rcv,
-};
-
 static int lowpan_newlink(struct net *src_net, struct net_device *dev,
 			  struct nlattr *tb[], struct nlattr *data[])
 {
 	struct net_device *real_dev;
 	struct lowpan_dev_record *entry;
-	int ret;
-
-	ASSERT_RTNL();
 
 	pr_debug("adding new link\n");
 
@@ -600,7 +602,7 @@
 
 	entry->ldev = dev;
 
-	/* Set the lowpan hardware address to the wpan hardware address. */
+	/* Set the lowpan harware address to the wpan hardware address. */
 	memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
 
 	mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
@@ -608,14 +610,9 @@
 	list_add_tail(&entry->list, &lowpan_devices);
 	mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
 
-	ret = register_netdevice(dev);
-	if (ret >= 0) {
-		if (!lowpan_open_count)
-			dev_add_pack(&lowpan_packet_type);
-		lowpan_open_count++;
-	}
+	register_netdevice(dev);
 
-	return ret;
+	return 0;
 }
 
 static void lowpan_dellink(struct net_device *dev, struct list_head *head)
@@ -626,10 +623,6 @@
 
 	ASSERT_RTNL();
 
-	lowpan_open_count--;
-	if (!lowpan_open_count)
-		dev_remove_pack(&lowpan_packet_type);
-
 	mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
 	list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
 		if (entry->ldev == dev) {
@@ -692,6 +685,11 @@
 	.notifier_call = lowpan_device_event,
 };
 
+static struct packet_type lowpan_packet_type = {
+	.type = htons(ETH_P_IEEE802154),
+	.func = lowpan_rcv,
+};
+
 static int __init lowpan_init_module(void)
 {
 	int err = 0;
@@ -704,6 +702,8 @@
 	if (err < 0)
 		goto out_frag;
 
+	dev_add_pack(&lowpan_packet_type);
+
 	err = register_netdevice_notifier(&lowpan_dev_notifier);
 	if (err < 0)
 		goto out_pack;
@@ -711,6 +711,7 @@
 	return 0;
 
 out_pack:
+	dev_remove_pack(&lowpan_packet_type);
 	lowpan_netlink_fini();
 out_frag:
 	lowpan_net_frag_exit();
@@ -722,6 +723,8 @@
 {
 	lowpan_netlink_fini();
 
+	dev_remove_pack(&lowpan_packet_type);
+
 	lowpan_net_frag_exit();
 
 	unregister_netdevice_notifier(&lowpan_dev_notifier);
diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig
index c509e93..24fe2a5 100644
--- a/net/ieee802154/Kconfig
+++ b/net/ieee802154/Kconfig
@@ -1,5 +1,5 @@
 config IEEE802154
-	depends on !KERNEL_3_19
+	depends on !BACKPORT_KERNEL_3_1
 	tristate "IEEE Std 802.15.4 Low-Rate Wireless Personal Area Networks support"
 	depends on m
 	---help---
@@ -13,7 +13,7 @@
 	  compile it as modules.
 
 config IEEE802154_6LOWPAN
-	depends on !KERNEL_3_5
+	depends on !BACKPORT_KERNEL_3_5
 	tristate "6lowpan support over IEEE 802.15.4"
 	depends on m
 	depends on IEEE802154 && 6LOWPAN
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
index 9e6d3d6..57fdfef 100644
--- a/net/ieee802154/Makefile
+++ b/net/ieee802154/Makefile
@@ -2,8 +2,8 @@
 obj-$(CPTCFG_IEEE802154_6LOWPAN) += ieee802154_6lowpan.o
 
 ieee802154_6lowpan-y := 6lowpan_rtnl.o reassembly.o
-ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \
-                header_ops.o sysfs.o nl802154.o
+ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \
+                header_ops.o
 af_802154-y := af_ieee802154.o raw.o dgram.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/ieee802154/af802154.h b/net/ieee802154/af802154.h
index 343b63e..8330a09 100644
--- a/net/ieee802154/af802154.h
+++ b/net/ieee802154/af802154.h
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c
index d0a1282..29e0de6 100644
--- a/net/ieee802154/af_ieee802154.c
+++ b/net/ieee802154/af_ieee802154.c
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
@@ -99,7 +103,6 @@
 	}
 	return 0;
 }
-
 static int ieee802154_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 				   struct msghdr *msg, size_t len)
 {
@@ -232,6 +235,7 @@
 #endif
 };
 
+
 /* Create a socket. Initialise the socket, blank the addresses
  * set the state.
  */
@@ -320,6 +324,7 @@
 	return NET_RX_DROP;
 }
 
+
 static struct packet_type ieee802154_packet_type = {
 	.type = htons(ETH_P_IEEE802154),
 	.func = ieee802154_rcv,
@@ -353,7 +358,6 @@
 out:
 	return rc;
 }
-
 static void __exit af_ieee802154_remove(void)
 {
 	dev_remove_pack(&ieee802154_packet_type);
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
deleted file mode 100644
index 18bc7e7..0000000
--- a/net/ieee802154/core.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2007, 2008, 2009 Siemens AG
- *
- * 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.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-
-#include <net/cfg802154.h>
-#include <net/rtnetlink.h>
-
-#include "ieee802154.h"
-#include "nl802154.h"
-#include "sysfs.h"
-#include "core.h"
-
-/* RCU-protected (and RTNL for writers) */
-LIST_HEAD(cfg802154_rdev_list);
-int cfg802154_rdev_list_generation;
-
-static int wpan_phy_match(struct device *dev, const void *data)
-{
-	return !strcmp(dev_name(dev), (const char *)data);
-}
-
-struct wpan_phy *wpan_phy_find(const char *str)
-{
-	struct device *dev;
-
-	if (WARN_ON(!str))
-		return NULL;
-
-	dev = class_find_device(&wpan_phy_class, NULL, str, wpan_phy_match);
-	if (!dev)
-		return NULL;
-
-	return container_of(dev, struct wpan_phy, dev);
-}
-EXPORT_SYMBOL(wpan_phy_find);
-
-struct wpan_phy_iter_data {
-	int (*fn)(struct wpan_phy *phy, void *data);
-	void *data;
-};
-
-static int wpan_phy_iter(struct device *dev, void *_data)
-{
-	struct wpan_phy_iter_data *wpid = _data;
-	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
-
-	return wpid->fn(phy, wpid->data);
-}
-
-int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data),
-		      void *data)
-{
-	struct wpan_phy_iter_data wpid = {
-		.fn = fn,
-		.data = data,
-	};
-
-	return class_for_each_device(&wpan_phy_class, NULL,
-			&wpid, wpan_phy_iter);
-}
-EXPORT_SYMBOL(wpan_phy_for_each);
-
-struct cfg802154_registered_device *
-cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx)
-{
-	struct cfg802154_registered_device *result = NULL, *rdev;
-
-	ASSERT_RTNL();
-
-	list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
-		if (rdev->wpan_phy_idx == wpan_phy_idx) {
-			result = rdev;
-			break;
-		}
-	}
-
-	return result;
-}
-
-struct wpan_phy *
-wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
-{
-	static atomic_t wpan_phy_counter = ATOMIC_INIT(0);
-	struct cfg802154_registered_device *rdev;
-	size_t alloc_size;
-
-	alloc_size = sizeof(*rdev) + priv_size;
-	rdev = kzalloc(alloc_size, GFP_KERNEL);
-	if (!rdev)
-		return NULL;
-
-	rdev->ops = ops;
-
-	rdev->wpan_phy_idx = atomic_inc_return(&wpan_phy_counter);
-
-	if (unlikely(rdev->wpan_phy_idx < 0)) {
-		/* ugh, wrapped! */
-		atomic_dec(&wpan_phy_counter);
-		kfree(rdev);
-		return NULL;
-	}
-
-	/* atomic_inc_return makes it start at 1, make it start at 0 */
-	rdev->wpan_phy_idx--;
-
-	mutex_init(&rdev->wpan_phy.pib_lock);
-
-	INIT_LIST_HEAD(&rdev->wpan_dev_list);
-	device_initialize(&rdev->wpan_phy.dev);
-	dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy_idx);
-
-	rdev->wpan_phy.dev.class = &wpan_phy_class;
-	rdev->wpan_phy.dev.platform_data = rdev;
-
-	init_waitqueue_head(&rdev->dev_wait);
-
-	return &rdev->wpan_phy;
-}
-EXPORT_SYMBOL(wpan_phy_new);
-
-int wpan_phy_register(struct wpan_phy *phy)
-{
-	struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(phy);
-	int ret;
-
-	rtnl_lock();
-	ret = device_add(&phy->dev);
-	if (ret) {
-		rtnl_unlock();
-		return ret;
-	}
-
-	list_add_rcu(&rdev->list, &cfg802154_rdev_list);
-	cfg802154_rdev_list_generation++;
-
-	/* TODO phy registered lock */
-	rtnl_unlock();
-
-	/* TODO nl802154 phy notify */
-
-	return 0;
-}
-EXPORT_SYMBOL(wpan_phy_register);
-
-void wpan_phy_unregister(struct wpan_phy *phy)
-{
-	struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(phy);
-
-	wait_event(rdev->dev_wait, ({
-		int __count;
-		rtnl_lock();
-		__count = rdev->opencount;
-		rtnl_unlock();
-		__count == 0; }));
-
-	rtnl_lock();
-	/* TODO nl802154 phy notify */
-	/* TODO phy registered lock */
-
-	WARN_ON(!list_empty(&rdev->wpan_dev_list));
-
-	/* First remove the hardware from everywhere, this makes
-	 * it impossible to find from userspace.
-	 */
-	list_del_rcu(&rdev->list);
-	synchronize_rcu();
-
-	cfg802154_rdev_list_generation++;
-
-	device_del(&phy->dev);
-
-	rtnl_unlock();
-}
-EXPORT_SYMBOL(wpan_phy_unregister);
-
-void wpan_phy_free(struct wpan_phy *phy)
-{
-	put_device(&phy->dev);
-}
-EXPORT_SYMBOL(wpan_phy_free);
-
-void cfg802154_dev_free(struct cfg802154_registered_device *rdev)
-{
-	kfree(rdev);
-}
-
-static void
-cfg802154_update_iface_num(struct cfg802154_registered_device *rdev,
-			   int iftype, int num)
-{
-	ASSERT_RTNL();
-
-	rdev->num_running_ifaces += num;
-}
-
-static int cfg802154_netdev_notifier_call(struct notifier_block *nb,
-					  unsigned long state, void *ptr)
-{
-	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
-	struct cfg802154_registered_device *rdev;
-
-	if (!wpan_dev)
-		return NOTIFY_DONE;
-
-	rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
-
-	/* TODO WARN_ON unspec type */
-
-	switch (state) {
-		/* TODO NETDEV_DEVTYPE */
-	case NETDEV_REGISTER:
-		wpan_dev->identifier = ++rdev->wpan_dev_id;
-		list_add_rcu(&wpan_dev->list, &rdev->wpan_dev_list);
-		rdev->devlist_generation++;
-
-		wpan_dev->netdev = dev;
-		break;
-	case NETDEV_DOWN:
-		cfg802154_update_iface_num(rdev, wpan_dev->iftype, -1);
-
-		rdev->opencount--;
-		wake_up(&rdev->dev_wait);
-		break;
-	case NETDEV_UP:
-		cfg802154_update_iface_num(rdev, wpan_dev->iftype, 1);
-
-		rdev->opencount++;
-		break;
-	case NETDEV_UNREGISTER:
-		/* It is possible to get NETDEV_UNREGISTER
-		 * multiple times. To detect that, check
-		 * that the interface is still on the list
-		 * of registered interfaces, and only then
-		 * remove and clean it up.
-		 */
-		if (!list_empty(&wpan_dev->list)) {
-			list_del_rcu(&wpan_dev->list);
-			rdev->devlist_generation++;
-		}
-		/* synchronize (so that we won't find this netdev
-		 * from other code any more) and then clear the list
-		 * head so that the above code can safely check for
-		 * !list_empty() to avoid double-cleanup.
-		 */
-		synchronize_rcu();
-		INIT_LIST_HEAD(&wpan_dev->list);
-		break;
-	default:
-		return NOTIFY_DONE;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block cfg802154_netdev_notifier = {
-	.notifier_call = cfg802154_netdev_notifier_call,
-};
-
-static int __init wpan_phy_class_init(void)
-{
-	int rc;
-
-	rc = wpan_phy_sysfs_init();
-	if (rc)
-		goto err;
-
-	rc = register_netdevice_notifier(&cfg802154_netdev_notifier);
-	if (rc)
-		goto err_nl;
-
-	rc = ieee802154_nl_init();
-	if (rc)
-		goto err_notifier;
-
-	rc = nl802154_init();
-	if (rc)
-		goto err_ieee802154_nl;
-
-	return 0;
-
-err_ieee802154_nl:
-	ieee802154_nl_exit();
-
-err_notifier:
-	unregister_netdevice_notifier(&cfg802154_netdev_notifier);
-err_nl:
-	wpan_phy_sysfs_exit();
-err:
-	return rc;
-}
-subsys_initcall(wpan_phy_class_init);
-
-static void __exit wpan_phy_class_exit(void)
-{
-	nl802154_exit();
-	ieee802154_nl_exit();
-	unregister_netdevice_notifier(&cfg802154_netdev_notifier);
-	wpan_phy_sysfs_exit();
-}
-module_exit(wpan_phy_class_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("IEEE 802.15.4 configuration interface");
-MODULE_AUTHOR("Dmitry Eremin-Solenikov");
-
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h
deleted file mode 100644
index f3e9558..0000000
--- a/net/ieee802154/core.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef __IEEE802154_CORE_H
-#define __IEEE802154_CORE_H
-
-#include <net/cfg802154.h>
-
-struct cfg802154_registered_device {
-	const struct cfg802154_ops *ops;
-	struct list_head list;
-
-	/* wpan_phy index, internal only */
-	int wpan_phy_idx;
-
-	/* also protected by devlist_mtx */
-	int opencount;
-	wait_queue_head_t dev_wait;
-
-	/* protected by RTNL only */
-	int num_running_ifaces;
-
-	/* associated wpan interfaces, protected by rtnl or RCU */
-	struct list_head wpan_dev_list;
-	int devlist_generation, wpan_dev_id;
-
-	/* must be last because of the way we do wpan_phy_priv(),
-	 * and it should at least be aligned to NETDEV_ALIGN
-	 */
-	struct wpan_phy wpan_phy __aligned(NETDEV_ALIGN);
-};
-
-static inline struct cfg802154_registered_device *
-wpan_phy_to_rdev(struct wpan_phy *wpan_phy)
-{
-	BUG_ON(!wpan_phy);
-	return container_of(wpan_phy, struct cfg802154_registered_device,
-			    wpan_phy);
-}
-
-extern struct list_head cfg802154_rdev_list;
-extern int cfg802154_rdev_list_generation;
-
-/* free object */
-void cfg802154_dev_free(struct cfg802154_registered_device *rdev);
-struct cfg802154_registered_device *
-cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx);
-
-#endif /* __IEEE802154_CORE_H */
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index a866820..0961336 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -23,9 +27,9 @@
 #include <linux/if_arp.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/ieee802154.h>
 #include <net/sock.h>
 #include <net/af_ieee802154.h>
+#include <net/ieee802154.h>
 #include <net/ieee802154_netdev.h>
 
 #include <asm/ioctls.h>
@@ -154,6 +158,7 @@
 		spin_unlock_bh(&sk->sk_receive_queue.lock);
 		return put_user(amount, (int __user *)arg);
 	}
+
 	}
 
 	return -ENOIOCTLCMD;
@@ -275,7 +280,7 @@
 	if (err < 0)
 		goto out_skb;
 
-	err = memcpy_from_msg(skb_put(skb, size), msg, size);
+	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 	if (err < 0)
 		goto out_skb;
 
@@ -319,7 +324,7 @@
 	}
 
 	/* FIXME: skip headers if necessary ?! */
-	err = skb_copy_datagram_msg(skb, 0, msg, copied);
+	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 	if (err)
 		goto done;
 
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c
index a051b69..c09294e 100644
--- a/net/ieee802154/header_ops.c
+++ b/net/ieee802154/header_ops.c
@@ -14,9 +14,8 @@
  * Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
  */
 
-#include <linux/ieee802154.h>
-
 #include <net/mac802154.h>
+#include <net/ieee802154.h>
 #include <net/ieee802154_netdev.h>
 
 static int
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h
index a5d7515..5d352f8 100644
--- a/net/ieee802154/ieee802154.h
+++ b/net/ieee802154/ieee802154.h
@@ -10,12 +10,16 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  */
 #ifndef IEEE_802154_LOCAL_H
 #define IEEE_802154_LOCAL_H
 
 int __init ieee802154_nl_init(void);
-void ieee802154_nl_exit(void);
+void __exit ieee802154_nl_exit(void);
 
 #define IEEE802154_OP(_cmd, _func)			\
 	{						\
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 78cc7cd..50a167a 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -1,5 +1,5 @@
 /*
- * Netlink interface for IEEE 802.15.4 stack
+ * Netlink inteface for IEEE 802.15.4 stack
  *
  * Copyright 2007, 2008 Siemens AG
  *
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -73,7 +77,7 @@
 }
 
 struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info,
-					int flags, u8 req)
+		int flags, u8 req)
 {
 	void *hdr;
 	struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -147,6 +151,7 @@
 	[IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
 };
 
+
 int __init ieee802154_nl_init(void)
 {
 	return genl_register_family_with_ops_groups(&nl802154_family,
@@ -154,7 +159,7 @@
 						    ieee802154_mcgrps);
 }
 
-void ieee802154_nl_exit(void)
+void __exit ieee802154_nl_exit(void)
 {
 	genl_unregister_family(&nl802154_family);
 }
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
index 25ff57e..cd28596 100644
--- a/net/ieee802154/nl-mac.c
+++ b/net/ieee802154/nl-mac.c
@@ -1,5 +1,5 @@
 /*
- * Netlink interface for IEEE 802.15.4 stack
+ * Netlink inteface for IEEE 802.15.4 stack
  *
  * Copyright 2007, 2008 Siemens AG
  *
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -22,15 +26,16 @@
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
-#include <linux/ieee802154.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 #include <net/sock.h>
 #include <linux/nl802154.h>
 #include <linux/export.h>
 #include <net/af_ieee802154.h>
+#include <net/nl802154.h>
+#include <net/ieee802154.h>
 #include <net/ieee802154_netdev.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
 
 #include "ieee802154.h"
 
@@ -54,7 +59,186 @@
 	return cpu_to_le16(nla_get_u16(nla));
 }
 
-static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
+int ieee802154_nl_assoc_indic(struct net_device *dev,
+			      struct ieee802154_addr *addr,
+			      u8 cap)
+{
+	struct sk_buff *msg;
+
+	pr_debug("%s\n", __func__);
+
+	if (addr->mode != IEEE802154_ADDR_LONG) {
+		pr_err("%s: received non-long source address!\n", __func__);
+		return -EINVAL;
+	}
+
+	msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC);
+	if (!msg)
+		return -ENOBUFS;
+
+	if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+	    nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+	    nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+		    dev->dev_addr) ||
+	    nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
+			   addr->extended_addr) ||
+	    nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap))
+		goto nla_put_failure;
+
+	return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_assoc_indic);
+
+int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr,
+				u8 status)
+{
+	struct sk_buff *msg;
+
+	pr_debug("%s\n", __func__);
+
+	msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF);
+	if (!msg)
+		return -ENOBUFS;
+
+	if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+	    nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+	    nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+		    dev->dev_addr) ||
+	    nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
+	    nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
+		goto nla_put_failure;
+	return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_assoc_confirm);
+
+int ieee802154_nl_disassoc_indic(struct net_device *dev,
+				 struct ieee802154_addr *addr,
+				 u8 reason)
+{
+	struct sk_buff *msg;
+
+	pr_debug("%s\n", __func__);
+
+	msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC);
+	if (!msg)
+		return -ENOBUFS;
+
+	if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+	    nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+	    nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+		    dev->dev_addr))
+		goto nla_put_failure;
+	if (addr->mode == IEEE802154_ADDR_LONG) {
+		if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
+				   addr->extended_addr))
+			goto nla_put_failure;
+	} else {
+		if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR,
+				      addr->short_addr))
+			goto nla_put_failure;
+	}
+	if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason))
+		goto nla_put_failure;
+	return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_disassoc_indic);
+
+int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status)
+{
+	struct sk_buff *msg;
+
+	pr_debug("%s\n", __func__);
+
+	msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF);
+	if (!msg)
+		return -ENOBUFS;
+
+	if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+	    nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+	    nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+		    dev->dev_addr) ||
+	    nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
+		goto nla_put_failure;
+	return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm);
+
+int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
+			       __le16 coord_addr)
+{
+	struct sk_buff *msg;
+
+	pr_debug("%s\n", __func__);
+
+	msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC);
+	if (!msg)
+		return -ENOBUFS;
+
+	if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+	    nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+	    nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+		    dev->dev_addr) ||
+	    nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR,
+			      coord_addr) ||
+	    nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid))
+		goto nla_put_failure;
+	return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_beacon_indic);
+
+int ieee802154_nl_scan_confirm(struct net_device *dev,
+			       u8 status, u8 scan_type,
+			       u32 unscanned, u8 page,
+			       u8 *edl/* , struct list_head *pan_desc_list */)
+{
+	struct sk_buff *msg;
+
+	pr_debug("%s\n", __func__);
+
+	msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF);
+	if (!msg)
+		return -ENOBUFS;
+
+	if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+	    nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+	    nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+		    dev->dev_addr) ||
+	    nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) ||
+	    nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) ||
+	    nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) ||
+	    nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) ||
+	    (edl &&
+	     nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl)))
+		goto nla_put_failure;
+	return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_scan_confirm);
+
+int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
 {
 	struct sk_buff *msg;
 
@@ -94,9 +278,8 @@
 		goto out;
 
 	ops = ieee802154_mlme_ops(dev);
-	phy = dev->ieee802154_ptr->wpan_phy;
+	phy = ops->get_phy(dev);
 	BUG_ON(!phy);
-	get_device(&phy->dev);
 
 	short_addr = ops->get_short_addr(dev);
 	pan_id = ops->get_pan_id(dev);
@@ -113,9 +296,7 @@
 	if (ops->get_mac_params) {
 		struct ieee802154_mac_params params;
 
-		rtnl_lock();
 		ops->get_mac_params(dev, &params);
-		rtnl_unlock();
 
 		if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER,
 			       params.transmit_power) ||
@@ -166,10 +347,7 @@
 	if (!dev)
 		return NULL;
 
-	/* Check on mtu is currently a hacked solution because lowpan
-	 * and wpan have the same ARPHRD type.
-	 */
-	if (dev->type != ARPHRD_IEEE802154 || dev->mtu != IEEE802154_MTU) {
+	if (dev->type != ARPHRD_IEEE802154) {
 		dev_put(dev);
 		return NULL;
 	}
@@ -303,7 +481,7 @@
 	u8 channel, bcn_ord, sf_ord;
 	u8 page;
 	int pan_coord, blx, coord_realign;
-	int ret = -EBUSY;
+	int ret = -EOPNOTSUPP;
 
 	if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
 	    !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
@@ -319,15 +497,9 @@
 	dev = ieee802154_nl_get_dev(info);
 	if (!dev)
 		return -ENODEV;
-
-	if (netif_running(dev))
+	if (!ieee802154_mlme_ops(dev)->start_req)
 		goto out;
 
-	if (!ieee802154_mlme_ops(dev)->start_req) {
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-
 	addr.mode = IEEE802154_ADDR_SHORT;
 	addr.short_addr = nla_get_shortaddr(
 			info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
@@ -346,21 +518,15 @@
 	else
 		page = 0;
 
+
 	if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) {
 		ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS);
 		dev_put(dev);
 		return -EINVAL;
 	}
 
-	rtnl_lock();
 	ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
 		bcn_ord, sf_ord, pan_coord, blx, coord_realign);
-	rtnl_unlock();
-
-	/* FIXME: add validation for unused parameters to be sane
-	 * for SoftMAC
-	 */
-	ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
 
 out:
 	dev_put(dev);
@@ -396,6 +562,7 @@
 	else
 		page = 0;
 
+
 	ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels,
 						 page, duration);
 
@@ -450,11 +617,7 @@
 
 	idx = 0;
 	for_each_netdev(net, dev) {
-		/* Check on mtu is currently a hacked solution because lowpan
-		 * and wpan have the same ARPHRD type.
-		 */
-		if (idx < s_idx || dev->type != ARPHRD_IEEE802154 ||
-		    dev->mtu != IEEE802154_MTU)
+		if (idx < s_idx || (dev->type != ARPHRD_IEEE802154))
 			goto cont;
 
 		if (ieee802154_nl_fill_iface(skb, NETLINK_CB_PORTID(cb->skb),
@@ -504,10 +667,22 @@
 	    !info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
 		goto out;
 
-	phy = dev->ieee802154_ptr->wpan_phy;
-	get_device(&phy->dev);
+	phy = ops->get_phy(dev);
 
-	rtnl_lock();
+	if ((!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) ||
+	    (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) ||
+	    (!phy->set_cca_ed_level &&
+	     info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) ||
+	    (!phy->set_csma_params &&
+	     (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] ||
+	      info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] ||
+	      info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])) ||
+	    (!phy->set_frame_retries &&
+	     info->attrs[IEEE802154_ATTR_FRAME_RETRIES])) {
+		rc = -EOPNOTSUPP;
+		goto out_phy;
+	}
+
 	ops->get_mac_params(dev, &params);
 
 	if (info->attrs[IEEE802154_ATTR_TXPOWER])
@@ -535,18 +710,20 @@
 		params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
 
 	rc = ops->set_mac_params(dev, &params);
-	rtnl_unlock();
 
 	wpan_phy_put(phy);
 	dev_put(dev);
+	return rc;
 
-	return 0;
-
+out_phy:
+	wpan_phy_put(phy);
 out:
 	dev_put(dev);
 	return rc;
 }
 
+
+
 static int
 ieee802154_llsec_parse_key_id(struct genl_info *info,
 			      struct ieee802154_llsec_key_id *desc)
@@ -762,6 +939,8 @@
 	return rc;
 }
 
+
+
 struct llsec_dump_data {
 	struct sk_buff *skb;
 	int s_idx, s_idx2;
@@ -784,11 +963,7 @@
 	int rc;
 
 	for_each_netdev(net, dev) {
-		/* Check on mtu is currently a hacked solution because lowpan
-		 * and wpan have the same ARPHRD type.
-		 */
-		if (idx < first_dev || dev->type != ARPHRD_IEEE802154 ||
-		    dev->mtu != IEEE802154_MTU)
+		if (idx < first_dev || dev->type != ARPHRD_IEEE802154)
 			goto skip;
 
 		data.ops = ieee802154_mlme_ops(dev);
@@ -838,6 +1013,8 @@
 	return rc;
 }
 
+
+
 static int
 ieee802154_llsec_parse_key(struct genl_info *info,
 			   struct ieee802154_llsec_key *key)
@@ -982,6 +1159,8 @@
 	return ieee802154_llsec_dump_table(skb, cb, llsec_iter_keys);
 }
 
+
+
 static int
 llsec_parse_dev(struct genl_info *info,
 		struct ieee802154_llsec_device *dev)
@@ -1112,6 +1291,8 @@
 	return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devs);
 }
 
+
+
 static int llsec_add_devkey(struct net_device *dev, struct genl_info *info)
 {
 	struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
@@ -1226,6 +1407,8 @@
 	return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devkeys);
 }
 
+
+
 static int
 llsec_parse_seclevel(struct genl_info *info,
 		     struct ieee802154_llsec_seclevel *sl)
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 2b8b724..07c503f 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -1,5 +1,5 @@
 /*
- * Netlink interface for IEEE 802.15.4 stack
+ * Netlink inteface for IEEE 802.15.4 stack
  *
  * Copyright 2007, 2008 Siemens AG
  *
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -23,15 +27,13 @@
 #include <linux/if_arp.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
 #include <net/af_ieee802154.h>
 #include <net/ieee802154_netdev.h>
 #include <net/rtnetlink.h> /* for rtnl_{un,}lock */
 #include <linux/nl802154.h>
 
 #include "ieee802154.h"
-#include "rdev-ops.h"
-#include "core.h"
 
 static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 				  u32 seq, int flags, struct wpan_phy *phy)
@@ -94,6 +96,7 @@
 	if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0')
 		return -EINVAL; /* phy name should be null-terminated */
 
+
 	phy = wpan_phy_find(name);
 	if (!phy)
 		return -ENODEV;
@@ -205,6 +208,11 @@
 	if (!msg)
 		goto out_dev;
 
+	if (!phy->add_iface) {
+		rc = -EINVAL;
+		goto nla_put_failure;
+	}
+
 	if (info->attrs[IEEE802154_ATTR_HW_ADDR] &&
 	    nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) !=
 			IEEE802154_ADDR_LEN) {
@@ -220,13 +228,11 @@
 		}
 	}
 
-	dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname,
-					       type);
+	dev = phy->add_iface(phy, devname, type);
 	if (IS_ERR(dev)) {
 		rc = PTR_ERR(dev);
 		goto nla_put_failure;
 	}
-	dev_hold(dev);
 
 	if (info->attrs[IEEE802154_ATTR_HW_ADDR]) {
 		struct sockaddr addr;
@@ -256,7 +262,7 @@
 
 dev_unregister:
 	rtnl_lock(); /* del_iface must be called with RTNL lock */
-	rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev);
+	phy->del_iface(phy, dev);
 	dev_put(dev);
 	rtnl_unlock();
 nla_put_failure:
@@ -287,9 +293,8 @@
 	if (!dev)
 		return -ENODEV;
 
-	phy = dev->ieee802154_ptr->wpan_phy;
+	phy = ieee802154_mlme_ops(dev)->get_phy(dev);
 	BUG_ON(!phy);
-	get_device(&phy->dev);
 
 	rc = -EINVAL;
 	/* phy name is optional, but should be checked if it's given */
@@ -319,8 +324,13 @@
 	if (!msg)
 		goto out_dev;
 
+	if (!phy->del_iface) {
+		rc = -EINVAL;
+		goto nla_put_failure;
+	}
+
 	rtnl_lock();
-	rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev);
+	phy->del_iface(phy, dev);
 
 	/* We don't have device anymore */
 	dev_put(dev);
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
deleted file mode 100644
index 47be111..0000000
--- a/net/ieee802154/nl802154.c
+++ /dev/null
@@ -1,957 +0,0 @@
-/* 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.
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- *
- * Based on: net/wireless/nl80211.c
- */
-
-#include <linux/rtnetlink.h>
-
-#include <net/cfg802154.h>
-#include <net/genetlink.h>
-#include <net/mac802154.h>
-#include <net/netlink.h>
-#include <net/nl802154.h>
-#include <net/sock.h>
-
-#include "nl802154.h"
-#include "rdev-ops.h"
-#include "core.h"
-
-static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
-			     struct genl_info *info);
-
-static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
-			       struct genl_info *info);
-
-/* the netlink family */
-static struct genl_family nl802154_fam = {
-	.id = GENL_ID_GENERATE,		/* don't bother with a hardcoded ID */
-	.name = NL802154_GENL_NAME,	/* have users key off the name instead */
-	.hdrsize = 0,			/* no private header */
-	.version = 1,			/* no particular meaning now */
-	.maxattr = NL802154_ATTR_MAX,
-	.netnsok = true,
-	.pre_doit = nl802154_pre_doit,
-	.post_doit = nl802154_post_doit,
-};
-
-/* multicast groups */
-enum nl802154_multicast_groups {
-	NL802154_MCGRP_CONFIG,
-};
-
-static const struct genl_multicast_group nl802154_mcgrps[] = {
-	[NL802154_MCGRP_CONFIG] = { .name = "config", },
-};
-
-/* returns ERR_PTR values */
-static struct wpan_dev *
-__cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs)
-{
-	struct cfg802154_registered_device *rdev;
-	struct wpan_dev *result = NULL;
-	bool have_ifidx = attrs[NL802154_ATTR_IFINDEX];
-	bool have_wpan_dev_id = attrs[NL802154_ATTR_WPAN_DEV];
-	u64 wpan_dev_id;
-	int wpan_phy_idx = -1;
-	int ifidx = -1;
-
-	ASSERT_RTNL();
-
-	if (!have_ifidx && !have_wpan_dev_id)
-		return ERR_PTR(-EINVAL);
-
-	if (have_ifidx)
-		ifidx = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
-	if (have_wpan_dev_id) {
-		wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
-		wpan_phy_idx = wpan_dev_id >> 32;
-	}
-
-	list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
-		struct wpan_dev *wpan_dev;
-
-		/* TODO netns compare */
-
-		if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx)
-			continue;
-
-		list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
-			if (have_ifidx && wpan_dev->netdev &&
-			    wpan_dev->netdev->ifindex == ifidx) {
-				result = wpan_dev;
-				break;
-			}
-			if (have_wpan_dev_id &&
-			    wpan_dev->identifier == (u32)wpan_dev_id) {
-				result = wpan_dev;
-				break;
-			}
-		}
-
-		if (result)
-			break;
-	}
-
-	if (result)
-		return result;
-
-	return ERR_PTR(-ENODEV);
-}
-
-static struct cfg802154_registered_device *
-__cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
-{
-	struct cfg802154_registered_device *rdev = NULL, *tmp;
-	struct net_device *netdev;
-
-	ASSERT_RTNL();
-
-	if (!attrs[NL802154_ATTR_WPAN_PHY] &&
-	    !attrs[NL802154_ATTR_IFINDEX] &&
-	    !attrs[NL802154_ATTR_WPAN_DEV])
-		return ERR_PTR(-EINVAL);
-
-	if (attrs[NL802154_ATTR_WPAN_PHY])
-		rdev = cfg802154_rdev_by_wpan_phy_idx(
-				nla_get_u32(attrs[NL802154_ATTR_WPAN_PHY]));
-
-	if (attrs[NL802154_ATTR_WPAN_DEV]) {
-		u64 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
-		struct wpan_dev *wpan_dev;
-		bool found = false;
-
-		tmp = cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id >> 32);
-		if (tmp) {
-			/* make sure wpan_dev exists */
-			list_for_each_entry(wpan_dev, &tmp->wpan_dev_list, list) {
-				if (wpan_dev->identifier != (u32)wpan_dev_id)
-					continue;
-				found = true;
-				break;
-			}
-
-			if (!found)
-				tmp = NULL;
-
-			if (rdev && tmp != rdev)
-				return ERR_PTR(-EINVAL);
-			rdev = tmp;
-		}
-	}
-
-	if (attrs[NL802154_ATTR_IFINDEX]) {
-		int ifindex = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
-
-		netdev = __dev_get_by_index(netns, ifindex);
-		if (netdev) {
-			if (netdev->ieee802154_ptr)
-				tmp = wpan_phy_to_rdev(
-						netdev->ieee802154_ptr->wpan_phy);
-			else
-				tmp = NULL;
-
-			/* not wireless device -- return error */
-			if (!tmp)
-				return ERR_PTR(-EINVAL);
-
-			/* mismatch -- return error */
-			if (rdev && tmp != rdev)
-				return ERR_PTR(-EINVAL);
-
-			rdev = tmp;
-		}
-	}
-
-	if (!rdev)
-		return ERR_PTR(-ENODEV);
-
-	/* TODO netns compare */
-
-	return rdev;
-}
-
-/* This function returns a pointer to the driver
- * that the genl_info item that is passed refers to.
- *
- * The result of this can be a PTR_ERR and hence must
- * be checked with IS_ERR() for errors.
- */
-static struct cfg802154_registered_device *
-cfg802154_get_dev_from_info(struct net *netns, struct genl_info *info)
-{
-	return __cfg802154_rdev_from_attrs(netns, info->attrs);
-}
-
-/* policy for the attributes */
-static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
-	[NL802154_ATTR_WPAN_PHY] = { .type = NLA_U32 },
-	[NL802154_ATTR_WPAN_PHY_NAME] = { .type = NLA_NUL_STRING,
-					  .len = 20-1 },
-
-	[NL802154_ATTR_IFINDEX] = { .type = NLA_U32 },
-	[NL802154_ATTR_IFTYPE] = { .type = NLA_U32 },
-	[NL802154_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
-
-	[NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 },
-
-	[NL802154_ATTR_PAGE] = { .type = NLA_U8, },
-	[NL802154_ATTR_CHANNEL] = { .type = NLA_U8, },
-
-	[NL802154_ATTR_TX_POWER] = { .type = NLA_S8, },
-
-	[NL802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
-
-	[NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, },
-
-	[NL802154_ATTR_PAN_ID] = { .type = NLA_U16, },
-	[NL802154_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
-	[NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, },
-
-	[NL802154_ATTR_MIN_BE] = { .type = NLA_U8, },
-	[NL802154_ATTR_MAX_BE] = { .type = NLA_U8, },
-	[NL802154_ATTR_MAX_CSMA_BACKOFFS] = { .type = NLA_U8, },
-
-	[NL802154_ATTR_MAX_FRAME_RETRIES] = { .type = NLA_S8, },
-
-	[NL802154_ATTR_LBT_MODE] = { .type = NLA_U8, },
-};
-
-/* message building helper */
-static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
-				    int flags, u8 cmd)
-{
-	/* since there is no private header just add the generic one */
-	return genlmsg_put(skb, portid, seq, &nl802154_fam, flags, cmd);
-}
-
-static int
-nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev,
-				struct sk_buff *msg)
-{
-	struct nlattr *nl_page;
-	unsigned long page;
-
-	nl_page = nla_nest_start(msg, NL802154_ATTR_CHANNELS_SUPPORTED);
-	if (!nl_page)
-		return -ENOBUFS;
-
-	for (page = 0; page <= IEEE802154_MAX_PAGE; page++) {
-		if (nla_put_u32(msg, NL802154_ATTR_SUPPORTED_CHANNEL,
-				rdev->wpan_phy.channels_supported[page]))
-			return -ENOBUFS;
-	}
-	nla_nest_end(msg, nl_page);
-
-	return 0;
-}
-
-static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev,
-				  enum nl802154_commands cmd,
-				  struct sk_buff *msg, u32 portid, u32 seq,
-				  int flags)
-{
-	void *hdr;
-
-	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
-	if (!hdr)
-		return -ENOBUFS;
-
-	if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
-	    nla_put_string(msg, NL802154_ATTR_WPAN_PHY_NAME,
-			   wpan_phy_name(&rdev->wpan_phy)) ||
-	    nla_put_u32(msg, NL802154_ATTR_GENERATION,
-			cfg802154_rdev_list_generation))
-		goto nla_put_failure;
-
-	if (cmd != NL802154_CMD_NEW_WPAN_PHY)
-		goto finish;
-
-	/* DUMP PHY PIB */
-
-	/* current channel settings */
-	if (nla_put_u8(msg, NL802154_ATTR_PAGE,
-		       rdev->wpan_phy.current_page) ||
-	    nla_put_u8(msg, NL802154_ATTR_CHANNEL,
-		       rdev->wpan_phy.current_channel))
-		goto nla_put_failure;
-
-	/* supported channels array */
-	if (nl802154_send_wpan_phy_channels(rdev, msg))
-		goto nla_put_failure;
-
-	/* cca mode */
-	if (nla_put_u8(msg, NL802154_ATTR_CCA_MODE,
-		       rdev->wpan_phy.cca_mode))
-		goto nla_put_failure;
-
-	if (nla_put_s8(msg, NL802154_ATTR_TX_POWER,
-		       rdev->wpan_phy.transmit_power))
-		goto nla_put_failure;
-
-finish:
-	return genlmsg_end(msg, hdr);
-
-nla_put_failure:
-	genlmsg_cancel(msg, hdr);
-	return -EMSGSIZE;
-}
-
-struct nl802154_dump_wpan_phy_state {
-	s64 filter_wpan_phy;
-	long start;
-
-};
-
-static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
-					struct netlink_callback *cb,
-					struct nl802154_dump_wpan_phy_state *state)
-{
-	struct nlattr **tb = nl802154_fam.attrbuf;
-	int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
-			      tb, nl802154_fam.maxattr, nl802154_policy);
-
-	/* TODO check if we can handle error here,
-	 * we have no backward compatibility
-	 */
-	if (ret)
-		return 0;
-
-	if (tb[NL802154_ATTR_WPAN_PHY])
-		state->filter_wpan_phy = nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]);
-	if (tb[NL802154_ATTR_WPAN_DEV])
-		state->filter_wpan_phy = nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]) >> 32;
-	if (tb[NL802154_ATTR_IFINDEX]) {
-		struct net_device *netdev;
-		struct cfg802154_registered_device *rdev;
-		int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]);
-
-		/* TODO netns */
-		netdev = __dev_get_by_index(&init_net, ifidx);
-		if (!netdev)
-			return -ENODEV;
-		if (netdev->ieee802154_ptr) {
-			rdev = wpan_phy_to_rdev(
-					netdev->ieee802154_ptr->wpan_phy);
-			state->filter_wpan_phy = rdev->wpan_phy_idx;
-		}
-	}
-
-	return 0;
-}
-
-static int
-nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb)
-{
-	int idx = 0, ret;
-	struct nl802154_dump_wpan_phy_state *state = (void *)cb->args[0];
-	struct cfg802154_registered_device *rdev;
-
-	rtnl_lock();
-	if (!state) {
-		state = kzalloc(sizeof(*state), GFP_KERNEL);
-		if (!state) {
-			rtnl_unlock();
-			return -ENOMEM;
-		}
-		state->filter_wpan_phy = -1;
-		ret = nl802154_dump_wpan_phy_parse(skb, cb, state);
-		if (ret) {
-			kfree(state);
-			rtnl_unlock();
-			return ret;
-		}
-		cb->args[0] = (long)state;
-	}
-
-	list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
-		/* TODO net ns compare */
-		if (++idx <= state->start)
-			continue;
-		if (state->filter_wpan_phy != -1 &&
-		    state->filter_wpan_phy != rdev->wpan_phy_idx)
-			continue;
-		/* attempt to fit multiple wpan_phy data chunks into the skb */
-		ret = nl802154_send_wpan_phy(rdev,
-					     NL802154_CMD_NEW_WPAN_PHY,
-					     skb,
-					     NETLINK_CB_PORTID(cb->skb),
-					     cb->nlh->nlmsg_seq, NLM_F_MULTI);
-		if (ret < 0) {
-			if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
-			    !skb->len && cb->min_dump_alloc < 4096) {
-				cb->min_dump_alloc = 4096;
-				rtnl_unlock();
-				return 1;
-			}
-			idx--;
-			break;
-		}
-		break;
-	}
-	rtnl_unlock();
-
-	state->start = idx;
-
-	return skb->len;
-}
-
-static int nl802154_dump_wpan_phy_done(struct netlink_callback *cb)
-{
-	kfree((void *)cb->args[0]);
-	return 0;
-}
-
-static int nl802154_get_wpan_phy(struct sk_buff *skb, struct genl_info *info)
-{
-	struct sk_buff *msg;
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg)
-		return -ENOMEM;
-
-	if (nl802154_send_wpan_phy(rdev, NL802154_CMD_NEW_WPAN_PHY, msg,
-				   genl_info_snd_portid(info), info->snd_seq, 0) < 0) {
-		nlmsg_free(msg);
-		return -ENOBUFS;
-	}
-
-	return genlmsg_reply(msg, info);
-}
-
-static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev)
-{
-	return (u64)wpan_dev->identifier |
-	       ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32);
-}
-
-static int
-nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
-		    struct cfg802154_registered_device *rdev,
-		    struct wpan_dev *wpan_dev)
-{
-	struct net_device *dev = wpan_dev->netdev;
-	void *hdr;
-
-	hdr = nl802154hdr_put(msg, portid, seq, flags,
-			      NL802154_CMD_NEW_INTERFACE);
-	if (!hdr)
-		return -1;
-
-	if (dev &&
-	    (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) ||
-	     nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name)))
-		goto nla_put_failure;
-
-	if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
-	    nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) ||
-	    nla_put_u64(msg, NL802154_ATTR_WPAN_DEV, wpan_dev_id(wpan_dev)) ||
-	    nla_put_u32(msg, NL802154_ATTR_GENERATION,
-			rdev->devlist_generation ^
-			(cfg802154_rdev_list_generation << 2)))
-		goto nla_put_failure;
-
-	/* address settings */
-	if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR,
-			 wpan_dev->extended_addr) ||
-	    nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR,
-			 wpan_dev->short_addr) ||
-	    nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id))
-		goto nla_put_failure;
-
-	/* ARET handling */
-	if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES,
-		       wpan_dev->frame_retries) ||
-	    nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) ||
-	    nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS,
-		       wpan_dev->csma_retries) ||
-	    nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be))
-		goto nla_put_failure;
-
-	/* listen before transmit */
-	if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt))
-		goto nla_put_failure;
-
-	return genlmsg_end(msg, hdr);
-
-nla_put_failure:
-	genlmsg_cancel(msg, hdr);
-	return -EMSGSIZE;
-}
-
-static int
-nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
-{
-	int wp_idx = 0;
-	int if_idx = 0;
-	int wp_start = cb->args[0];
-	int if_start = cb->args[1];
-	struct cfg802154_registered_device *rdev;
-	struct wpan_dev *wpan_dev;
-
-	rtnl_lock();
-	list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
-		/* TODO netns compare */
-		if (wp_idx < wp_start) {
-			wp_idx++;
-			continue;
-		}
-		if_idx = 0;
-
-		list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
-			if (if_idx < if_start) {
-				if_idx++;
-				continue;
-			}
-			if (nl802154_send_iface(skb, NETLINK_CB_PORTID(cb->skb),
-						cb->nlh->nlmsg_seq, NLM_F_MULTI,
-						rdev, wpan_dev) < 0) {
-				goto out;
-			}
-			if_idx++;
-		}
-
-		wp_idx++;
-	}
-out:
-	rtnl_unlock();
-
-	cb->args[0] = wp_idx;
-	cb->args[1] = if_idx;
-
-	return skb->len;
-}
-
-static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info)
-{
-	struct sk_buff *msg;
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	struct wpan_dev *wdev = info->user_ptr[1];
-
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg)
-		return -ENOMEM;
-
-	if (nl802154_send_iface(msg, genl_info_snd_portid(info), info->snd_seq, 0,
-				rdev, wdev) < 0) {
-		nlmsg_free(msg);
-		return -ENOBUFS;
-	}
-
-	return genlmsg_reply(msg, info);
-}
-
-static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC;
-	__le64 extended_addr = cpu_to_le64(0x0000000000000000ULL);
-
-	/* TODO avoid failing a new interface
-	 * creation due to pending removal?
-	 */
-
-	if (!info->attrs[NL802154_ATTR_IFNAME])
-		return -EINVAL;
-
-	if (info->attrs[NL802154_ATTR_IFTYPE]) {
-		type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]);
-		if (type > NL802154_IFTYPE_MAX)
-			return -EINVAL;
-	}
-
-	/* TODO add nla_get_le64 to netlink */
-	if (info->attrs[NL802154_ATTR_EXTENDED_ADDR])
-		extended_addr = (__force __le64)nla_get_u64(
-				info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
-
-	if (!rdev->ops->add_virtual_intf)
-		return -EOPNOTSUPP;
-
-	return rdev_add_virtual_intf(rdev,
-				     nla_data(info->attrs[NL802154_ATTR_IFNAME]),
-				     type, extended_addr);
-}
-
-static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	struct wpan_dev *wpan_dev = info->user_ptr[1];
-
-	if (!rdev->ops->del_virtual_intf)
-		return -EOPNOTSUPP;
-
-	/* If we remove a wpan device without a netdev then clear
-	 * user_ptr[1] so that nl802154_post_doit won't dereference it
-	 * to check if it needs to do dev_put(). Otherwise it crashes
-	 * since the wpan_dev has been freed, unlike with a netdev where
-	 * we need the dev_put() for the netdev to really be freed.
-	 */
-	if (!wpan_dev->netdev)
-		info->user_ptr[1] = NULL;
-
-	return rdev_del_virtual_intf(rdev, wpan_dev);
-}
-
-static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	u8 channel, page;
-
-	if (!info->attrs[NL802154_ATTR_PAGE] ||
-	    !info->attrs[NL802154_ATTR_CHANNEL])
-		return -EINVAL;
-
-	page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
-	channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]);
-
-	/* check 802.15.4 constraints */
-	if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL)
-		return -EINVAL;
-
-	return rdev_set_channel(rdev, page, channel);
-}
-
-static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
-	__le16 pan_id;
-
-	/* conflict here while tx/rx calls */
-	if (netif_running(dev))
-		return -EBUSY;
-
-	/* don't change address fields on monitor */
-	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
-		return -EINVAL;
-
-	if (!info->attrs[NL802154_ATTR_PAN_ID])
-		return -EINVAL;
-
-	pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
-
-	return rdev_set_pan_id(rdev, wpan_dev, pan_id);
-}
-
-static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
-	__le16 short_addr;
-
-	/* conflict here while tx/rx calls */
-	if (netif_running(dev))
-		return -EBUSY;
-
-	/* don't change address fields on monitor */
-	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
-		return -EINVAL;
-
-	if (!info->attrs[NL802154_ATTR_SHORT_ADDR])
-		return -EINVAL;
-
-	short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
-
-	return rdev_set_short_addr(rdev, wpan_dev, short_addr);
-}
-
-static int
-nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
-	u8 min_be, max_be;
-
-	/* should be set on netif open inside phy settings */
-	if (netif_running(dev))
-		return -EBUSY;
-
-	if (!info->attrs[NL802154_ATTR_MIN_BE] ||
-	    !info->attrs[NL802154_ATTR_MAX_BE])
-		return -EINVAL;
-
-	min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]);
-	max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]);
-
-	/* check 802.15.4 constraints */
-	if (max_be < 3 || max_be > 8 || min_be > max_be)
-		return -EINVAL;
-
-	return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be);
-}
-
-static int
-nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
-	u8 max_csma_backoffs;
-
-	/* conflict here while other running iface settings */
-	if (netif_running(dev))
-		return -EBUSY;
-
-	if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS])
-		return -EINVAL;
-
-	max_csma_backoffs = nla_get_u8(
-			info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]);
-
-	/* check 802.15.4 constraints */
-	if (max_csma_backoffs > 5)
-		return -EINVAL;
-
-	return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs);
-}
-
-static int
-nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
-	s8 max_frame_retries;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES])
-		return -EINVAL;
-
-	max_frame_retries = nla_get_s8(
-			info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]);
-
-	/* check 802.15.4 constraints */
-	if (max_frame_retries < -1 || max_frame_retries > 7)
-		return -EINVAL;
-
-	return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries);
-}
-
-static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
-	bool mode;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	if (!info->attrs[NL802154_ATTR_LBT_MODE])
-		return -EINVAL;
-
-	mode = !!nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]);
-	return rdev_set_lbt_mode(rdev, wpan_dev, mode);
-}
-
-#define NL802154_FLAG_NEED_WPAN_PHY	0x01
-#define NL802154_FLAG_NEED_NETDEV	0x02
-#define NL802154_FLAG_NEED_RTNL		0x04
-#define NL802154_FLAG_CHECK_NETDEV_UP	0x08
-#define NL802154_FLAG_NEED_NETDEV_UP	(NL802154_FLAG_NEED_NETDEV |\
-					 NL802154_FLAG_CHECK_NETDEV_UP)
-#define NL802154_FLAG_NEED_WPAN_DEV	0x10
-#define NL802154_FLAG_NEED_WPAN_DEV_UP	(NL802154_FLAG_NEED_WPAN_DEV |\
-					 NL802154_FLAG_CHECK_NETDEV_UP)
-
-static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
-			     struct genl_info *info)
-{
-	struct cfg802154_registered_device *rdev;
-	struct wpan_dev *wpan_dev;
-	struct net_device *dev;
-	bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL;
-
-	if (rtnl)
-		rtnl_lock();
-
-	if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) {
-		rdev = cfg802154_get_dev_from_info(genl_info_net(info), info);
-		if (IS_ERR(rdev)) {
-			if (rtnl)
-				rtnl_unlock();
-			return PTR_ERR(rdev);
-		}
-		info->user_ptr[0] = rdev;
-	} else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV ||
-		   ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
-		ASSERT_RTNL();
-		wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info),
-							   info->attrs);
-		if (IS_ERR(wpan_dev)) {
-			if (rtnl)
-				rtnl_unlock();
-			return PTR_ERR(wpan_dev);
-		}
-
-		dev = wpan_dev->netdev;
-		rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
-
-		if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) {
-			if (!dev) {
-				if (rtnl)
-					rtnl_unlock();
-				return -EINVAL;
-			}
-
-			info->user_ptr[1] = dev;
-		} else {
-			info->user_ptr[1] = wpan_dev;
-		}
-
-		if (dev) {
-			if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP &&
-			    !netif_running(dev)) {
-				if (rtnl)
-					rtnl_unlock();
-				return -ENETDOWN;
-			}
-
-			dev_hold(dev);
-		}
-
-		info->user_ptr[0] = rdev;
-	}
-
-	return 0;
-}
-
-static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
-			       struct genl_info *info)
-{
-	if (info->user_ptr[1]) {
-		if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
-			struct wpan_dev *wpan_dev = info->user_ptr[1];
-
-			if (wpan_dev->netdev)
-				dev_put(wpan_dev->netdev);
-		} else {
-			dev_put(info->user_ptr[1]);
-		}
-	}
-
-	if (ops->internal_flags & NL802154_FLAG_NEED_RTNL)
-		rtnl_unlock();
-}
-
-static const struct genl_ops nl802154_ops[] = {
-	{
-		.cmd = NL802154_CMD_GET_WPAN_PHY,
-		.doit = nl802154_get_wpan_phy,
-		.dumpit = nl802154_dump_wpan_phy,
-		.done = nl802154_dump_wpan_phy_done,
-		.policy = nl802154_policy,
-		/* can be retrieved by unprivileged users */
-		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_GET_INTERFACE,
-		.doit = nl802154_get_interface,
-		.dumpit = nl802154_dump_interface,
-		.policy = nl802154_policy,
-		/* can be retrieved by unprivileged users */
-		.internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_NEW_INTERFACE,
-		.doit = nl802154_new_interface,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_DEL_INTERFACE,
-		.doit = nl802154_del_interface,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_SET_CHANNEL,
-		.doit = nl802154_set_channel,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_SET_PAN_ID,
-		.doit = nl802154_set_pan_id,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_NETDEV |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_SET_SHORT_ADDR,
-		.doit = nl802154_set_short_addr,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_NETDEV |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_SET_BACKOFF_EXPONENT,
-		.doit = nl802154_set_backoff_exponent,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_NETDEV |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
-		.doit = nl802154_set_max_csma_backoffs,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_NETDEV |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES,
-		.doit = nl802154_set_max_frame_retries,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_NETDEV |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL802154_CMD_SET_LBT_MODE,
-		.doit = nl802154_set_lbt_mode,
-		.policy = nl802154_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL802154_FLAG_NEED_NETDEV |
-				  NL802154_FLAG_NEED_RTNL,
-	},
-};
-
-/* initialisation/exit functions */
-int nl802154_init(void)
-{
-	return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops,
-						    nl802154_mcgrps);
-}
-
-void nl802154_exit(void)
-{
-	genl_unregister_family(&nl802154_fam);
-}
diff --git a/net/ieee802154/nl802154.h b/net/ieee802154/nl802154.h
deleted file mode 100644
index 3846a89..0000000
--- a/net/ieee802154/nl802154.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __IEEE802154_NL802154_H
-#define __IEEE802154_NL802154_H
-
-int nl802154_init(void);
-void nl802154_exit(void);
-
-#endif /* __IEEE802154_NL802154_H */
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index 35c4326..3a703ab 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  */
 
 #include <linux/kernel.h>
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c
index 1674b11..9d1f648 100644
--- a/net/ieee802154/raw.c
+++ b/net/ieee802154/raw.c
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -150,7 +154,7 @@
 	skb_reset_mac_header(skb);
 	skb_reset_network_header(skb);
 
-	err = memcpy_from_msg(skb_put(skb, size), msg, size);
+	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 	if (err < 0)
 		goto out_skb;
 
@@ -191,7 +195,7 @@
 		copied = len;
 	}
 
-	err = skb_copy_datagram_msg(skb, 0, msg, copied);
+	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 	if (err)
 		goto done;
 
@@ -221,6 +225,7 @@
 	return NET_RX_SUCCESS;
 }
 
+
 void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb)
 {
 	struct sock *sk;
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h
deleted file mode 100644
index aff54fb..0000000
--- a/net/ieee802154/rdev-ops.h
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef __CFG802154_RDEV_OPS
-#define __CFG802154_RDEV_OPS
-
-#include <net/cfg802154.h>
-
-#include "core.h"
-
-static inline struct net_device *
-rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev,
-				 const char *name, int type)
-{
-	return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name,
-						      type);
-}
-
-static inline void
-rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev,
-				 struct net_device *dev)
-{
-	rdev->ops->del_virtual_intf_deprecated(&rdev->wpan_phy, dev);
-}
-
-static inline int
-rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name,
-		      enum nl802154_iftype type, __le64 extended_addr)
-{
-	return rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, type,
-					   extended_addr);
-}
-
-static inline int
-rdev_del_virtual_intf(struct cfg802154_registered_device *rdev,
-		      struct wpan_dev *wpan_dev)
-{
-	return rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev);
-}
-
-static inline int
-rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel)
-{
-	return rdev->ops->set_channel(&rdev->wpan_phy, page, channel);
-}
-
-static inline int
-rdev_set_pan_id(struct cfg802154_registered_device *rdev,
-		struct wpan_dev *wpan_dev, __le16 pan_id)
-{
-	return rdev->ops->set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id);
-}
-
-static inline int
-rdev_set_short_addr(struct cfg802154_registered_device *rdev,
-		    struct wpan_dev *wpan_dev, __le16 short_addr)
-{
-	return rdev->ops->set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr);
-}
-
-static inline int
-rdev_set_backoff_exponent(struct cfg802154_registered_device *rdev,
-			  struct wpan_dev *wpan_dev, u8 min_be, u8 max_be)
-{
-	return rdev->ops->set_backoff_exponent(&rdev->wpan_phy, wpan_dev,
-					       min_be, max_be);
-}
-
-static inline int
-rdev_set_max_csma_backoffs(struct cfg802154_registered_device *rdev,
-			   struct wpan_dev *wpan_dev, u8 max_csma_backoffs)
-{
-	return rdev->ops->set_max_csma_backoffs(&rdev->wpan_phy, wpan_dev,
-						max_csma_backoffs);
-}
-
-static inline int
-rdev_set_max_frame_retries(struct cfg802154_registered_device *rdev,
-			   struct wpan_dev *wpan_dev, s8 max_frame_retries)
-{
-	return rdev->ops->set_max_frame_retries(&rdev->wpan_phy, wpan_dev,
-						max_frame_retries);
-}
-
-static inline int
-rdev_set_lbt_mode(struct cfg802154_registered_device *rdev,
-		  struct wpan_dev *wpan_dev, bool mode)
-{
-	return rdev->ops->set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode);
-}
-
-#endif /* __CFG802154_RDEV_OPS */
diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c
index f133b62..4862bb5 100644
--- a/net/ieee802154/reassembly.c
+++ b/net/ieee802154/reassembly.c
@@ -33,7 +33,7 @@
 static const char lowpan_frags_cache_name[] = "lowpan-frags";
 
 struct lowpan_frag_info {
-	u16 d_tag;
+	__be16 d_tag;
 	u16 d_size;
 	u8 d_offset;
 };
@@ -48,7 +48,7 @@
 static int lowpan_frag_reasm(struct lowpan_frag_queue *fq,
 			     struct sk_buff *prev, struct net_device *dev);
 
-static unsigned int lowpan_hash_frag(u16 tag, u16 d_size,
+static unsigned int lowpan_hash_frag(__be16 tag, u16 d_size,
 				     const struct ieee802154_addr *saddr,
 				     const struct ieee802154_addr *daddr)
 {
@@ -337,13 +337,11 @@
 {
 	bool fail;
 	u8 pattern = 0, low = 0;
-	__be16 d_tag = 0;
 
 	fail = lowpan_fetch_skb(skb, &pattern, 1);
 	fail |= lowpan_fetch_skb(skb, &low, 1);
 	frag_info->d_size = (pattern & 7) << 8 | low;
-	fail |= lowpan_fetch_skb(skb, &d_tag, 2);
-	frag_info->d_tag = ntohs(d_tag);
+	fail |= lowpan_fetch_skb(skb, &frag_info->d_tag, 2);
 
 	if (frag_type == LOWPAN_DISPATCH_FRAGN) {
 		fail |= lowpan_fetch_skb(skb, &frag_info->d_offset, 1);
diff --git a/net/ieee802154/reassembly.h b/net/ieee802154/reassembly.h
index 082e9d4..32797ac 100644
--- a/net/ieee802154/reassembly.h
+++ b/net/ieee802154/reassembly.h
@@ -5,7 +5,7 @@
 #include <linux/spinlock.h>
 
 struct lowpan_create_arg {
-	u16 tag;
+	__be16 tag;
 	u16 d_size;
 	const struct ieee802154_addr *src;
 	const struct ieee802154_addr *dst;
@@ -16,7 +16,7 @@
 struct lowpan_frag_queue {
 	struct inet_frag_queue	q;
 
-	u16			tag;
+	__be16			tag;
 	u16			d_size;
 	struct ieee802154_addr	saddr;
 	struct ieee802154_addr	daddr;
diff --git a/net/ieee802154/sysfs.c b/net/ieee802154/sysfs.c
deleted file mode 100644
index 2aec368..0000000
--- a/net/ieee802154/sysfs.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/* 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.
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- *
- * Based on: net/wireless/sysfs.c
- */
-
-#include <linux/device.h>
-
-#include <net/cfg802154.h>
-
-#include "core.h"
-#include "sysfs.h"
-
-static inline struct cfg802154_registered_device *
-dev_to_rdev(struct device *dev)
-{
-	return container_of(dev, struct cfg802154_registered_device,
-			    wpan_phy.dev);
-}
-
-#define SHOW_FMT(name, fmt, member)					\
-static ssize_t name ## _show(struct device *dev,			\
-			     struct device_attribute *attr,		\
-			     char *buf)					\
-{									\
-	return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member);	\
-}									\
-static DEVICE_ATTR_RO(name)
-
-SHOW_FMT(index, "%d", wpan_phy_idx);
-
-static ssize_t name_show(struct device *dev,
-			 struct device_attribute *attr,
-			 char *buf)
-{
-	struct wpan_phy *wpan_phy = &dev_to_rdev(dev)->wpan_phy;
-
-	return sprintf(buf, "%s\n", dev_name(&wpan_phy->dev));
-}
-static DEVICE_ATTR_RO(name);
-
-#define MASTER_SHOW_COMPLEX(name, format_string, args...)		\
-static ssize_t name ## _show(struct device *dev,			\
-			    struct device_attribute *attr, char *buf)	\
-{									\
-	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);	\
-	int ret;							\
-									\
-	mutex_lock(&phy->pib_lock);					\
-	ret = snprintf(buf, PAGE_SIZE, format_string "\n", args);	\
-	mutex_unlock(&phy->pib_lock);					\
-	return ret;							\
-}									\
-static DEVICE_ATTR_RO(name)
-
-#define MASTER_SHOW(field, format_string)				\
-	MASTER_SHOW_COMPLEX(field, format_string, phy->field)
-
-MASTER_SHOW(current_channel, "%d");
-MASTER_SHOW(current_page, "%d");
-MASTER_SHOW(transmit_power, "%d +- 1 dB");
-MASTER_SHOW(cca_mode, "%d");
-
-static ssize_t channels_supported_show(struct device *dev,
-				       struct device_attribute *attr,
-				       char *buf)
-{
-	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
-	int ret;
-	int i, len = 0;
-
-	mutex_lock(&phy->pib_lock);
-	for (i = 0; i < 32; i++) {
-		ret = snprintf(buf + len, PAGE_SIZE - len,
-			       "%#09x\n", phy->channels_supported[i]);
-		if (ret < 0)
-			break;
-		len += ret;
-	}
-	mutex_unlock(&phy->pib_lock);
-	return len;
-}
-static DEVICE_ATTR_RO(channels_supported);
-
-static void wpan_phy_release(struct device *dev)
-{
-	struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
-
-	cfg802154_dev_free(rdev);
-}
-
-static struct attribute *pmib_attrs[] = {
-	&dev_attr_index.attr,
-	&dev_attr_name.attr,
-	/* below will be removed soon */
-	&dev_attr_current_channel.attr,
-	&dev_attr_current_page.attr,
-	&dev_attr_channels_supported.attr,
-	&dev_attr_transmit_power.attr,
-	&dev_attr_cca_mode.attr,
-	NULL,
-};
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
-ATTRIBUTE_GROUPS(pmib);
-#else
-#define BP_ATTR_GRP_STRUCT device_attribute
-ATTRIBUTE_GROUPS_BACKPORT(pmib);
-#endif
-
-struct class wpan_phy_class = {
-	.name = "ieee802154",
-	.dev_release = wpan_phy_release,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
-	.dev_groups = pmib_groups,
-#else
-	.dev_attrs = pmib_dev_attrs,
-#endif
-};
-
-int wpan_phy_sysfs_init(void)
-{
-	init_pmib_attrs();
-	return class_register(&wpan_phy_class);
-}
-
-void wpan_phy_sysfs_exit(void)
-{
-	class_unregister(&wpan_phy_class);
-}
diff --git a/net/ieee802154/sysfs.h b/net/ieee802154/sysfs.h
deleted file mode 100644
index aa42e39..0000000
--- a/net/ieee802154/sysfs.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __IEEE802154_SYSFS_H
-#define __IEEE802154_SYSFS_H
-
-int wpan_phy_sysfs_init(void);
-void wpan_phy_sysfs_exit(void);
-
-extern struct class wpan_phy_class;
-
-#endif /* __IEEE802154_SYSFS_H */
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
new file mode 100644
index 0000000..06ca147
--- /dev/null
+++ b/net/ieee802154/wpan-class.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <net/wpan-phy.h>
+
+#include "ieee802154.h"
+
+#define MASTER_SHOW_COMPLEX(name, format_string, args...)		\
+static ssize_t name ## _show(struct device *dev,			\
+			    struct device_attribute *attr, char *buf)	\
+{									\
+	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);	\
+	int ret;							\
+									\
+	mutex_lock(&phy->pib_lock);					\
+	ret = snprintf(buf, PAGE_SIZE, format_string "\n", args);	\
+	mutex_unlock(&phy->pib_lock);					\
+	return ret;							\
+}									\
+static DEVICE_ATTR_RO(name);
+
+#define MASTER_SHOW(field, format_string)				\
+	MASTER_SHOW_COMPLEX(field, format_string, phy->field)
+
+MASTER_SHOW(current_channel, "%d");
+MASTER_SHOW(current_page, "%d");
+MASTER_SHOW(transmit_power, "%d +- 1 dB");
+MASTER_SHOW(cca_mode, "%d");
+
+static ssize_t channels_supported_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
+	int ret;
+	int i, len = 0;
+
+	mutex_lock(&phy->pib_lock);
+	for (i = 0; i < 32; i++) {
+		ret = snprintf(buf + len, PAGE_SIZE - len,
+			       "%#09x\n", phy->channels_supported[i]);
+		if (ret < 0)
+			break;
+		len += ret;
+	}
+	mutex_unlock(&phy->pib_lock);
+	return len;
+}
+static DEVICE_ATTR_RO(channels_supported);
+
+static struct attribute *pmib_attrs[] = {
+	&dev_attr_current_channel.attr,
+	&dev_attr_current_page.attr,
+	&dev_attr_channels_supported.attr,
+	&dev_attr_transmit_power.attr,
+	&dev_attr_cca_mode.attr,
+	NULL,
+};
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
+ATTRIBUTE_GROUPS(pmib);
+#else
+#define BP_ATTR_GRP_STRUCT device_attribute
+ATTRIBUTE_GROUPS_BACKPORT(pmib);
+#endif
+
+static void wpan_phy_release(struct device *d)
+{
+	struct wpan_phy *phy = container_of(d, struct wpan_phy, dev);
+
+	kfree(phy);
+}
+
+static struct class wpan_phy_class = {
+	.name = "ieee802154",
+	.dev_release = wpan_phy_release,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
+	.dev_groups = pmib_groups,
+#else
+	.dev_attrs = pmib_dev_attrs,
+#endif
+};
+
+static DEFINE_MUTEX(wpan_phy_mutex);
+static int wpan_phy_idx;
+
+static int wpan_phy_match(struct device *dev, const void *data)
+{
+	return !strcmp(dev_name(dev), (const char *)data);
+}
+
+struct wpan_phy *wpan_phy_find(const char *str)
+{
+	struct device *dev;
+
+	if (WARN_ON(!str))
+		return NULL;
+
+	dev = class_find_device(&wpan_phy_class, NULL, str, wpan_phy_match);
+	if (!dev)
+		return NULL;
+
+	return container_of(dev, struct wpan_phy, dev);
+}
+EXPORT_SYMBOL(wpan_phy_find);
+
+struct wpan_phy_iter_data {
+	int (*fn)(struct wpan_phy *phy, void *data);
+	void *data;
+};
+
+static int wpan_phy_iter(struct device *dev, void *_data)
+{
+	struct wpan_phy_iter_data *wpid = _data;
+	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
+
+	return wpid->fn(phy, wpid->data);
+}
+
+int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data),
+		      void *data)
+{
+	struct wpan_phy_iter_data wpid = {
+		.fn = fn,
+		.data = data,
+	};
+
+	return class_for_each_device(&wpan_phy_class, NULL,
+			&wpid, wpan_phy_iter);
+}
+EXPORT_SYMBOL(wpan_phy_for_each);
+
+static int wpan_phy_idx_valid(int idx)
+{
+	return idx >= 0;
+}
+
+struct wpan_phy *wpan_phy_alloc(size_t priv_size)
+{
+	struct wpan_phy *phy = kzalloc(sizeof(*phy) + priv_size,
+			GFP_KERNEL);
+
+	if (!phy)
+		goto out;
+	mutex_lock(&wpan_phy_mutex);
+	phy->idx = wpan_phy_idx++;
+	if (unlikely(!wpan_phy_idx_valid(phy->idx))) {
+		wpan_phy_idx--;
+		mutex_unlock(&wpan_phy_mutex);
+		kfree(phy);
+		goto out;
+	}
+	mutex_unlock(&wpan_phy_mutex);
+
+	mutex_init(&phy->pib_lock);
+
+	device_initialize(&phy->dev);
+	dev_set_name(&phy->dev, "wpan-phy%d", phy->idx);
+
+	phy->dev.class = &wpan_phy_class;
+
+	phy->current_channel = -1; /* not initialised */
+	phy->current_page = 0; /* for compatibility */
+
+	return phy;
+
+out:
+	return NULL;
+}
+EXPORT_SYMBOL(wpan_phy_alloc);
+
+int wpan_phy_register(struct wpan_phy *phy)
+{
+	return device_add(&phy->dev);
+}
+EXPORT_SYMBOL(wpan_phy_register);
+
+void wpan_phy_unregister(struct wpan_phy *phy)
+{
+	device_del(&phy->dev);
+}
+EXPORT_SYMBOL(wpan_phy_unregister);
+
+void wpan_phy_free(struct wpan_phy *phy)
+{
+	put_device(&phy->dev);
+}
+EXPORT_SYMBOL(wpan_phy_free);
+
+static int __init wpan_phy_class_init(void)
+{
+	int rc;
+
+	init_pmib_attrs();
+	rc = class_register(&wpan_phy_class);
+	if (rc)
+		goto err;
+
+	rc = ieee802154_nl_init();
+	if (rc)
+		goto err_nl;
+
+	return 0;
+err_nl:
+	class_unregister(&wpan_phy_class);
+err:
+	return rc;
+}
+subsys_initcall(wpan_phy_class_init);
+
+static void __exit wpan_phy_class_exit(void)
+{
+	ieee802154_nl_exit();
+	class_unregister(&wpan_phy_class);
+}
+module_exit(wpan_phy_class_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("IEEE 802.15.4 configuration interface");
+MODULE_AUTHOR("Dmitry Eremin-Solenikov");
+
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 543f13a..60677e1 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -5,9 +5,9 @@
 	depends on CRYPTO
 	depends on CRYPTO_ARC4
 	depends on CRYPTO_AES
-	select BPAUTO_CRYPTO_CCM
+	select BACKPORT_CRYPTO_CCM
 	depends on CRC32
-	select BPAUTO_AVERAGE
+	select BACKPORT_AVERAGE
 	---help---
 	  This option enables the hardware independent IEEE 802.11
 	  networking stack.
@@ -34,13 +34,6 @@
 	---help---
 	  This option enables the 'minstrel_ht' TX rate control algorithm
 
-config MAC80211_RC_MINSTREL_VHT
-	bool "Minstrel 802.11ac support" if EXPERT
-	depends on MAC80211_RC_MINSTREL_HT
-	default n
-	---help---
-	  This option enables VHT in the 'minstrel_ht' TX rate control algorithm
-
 choice
 	prompt "Default rate control algorithm"
 	depends on MAC80211_HAS_RC
@@ -85,7 +78,7 @@
 	bool "Enable LED triggers"
 	depends on MAC80211
 	depends on LEDS_CLASS
-	select BPAUTO_LEDS_TRIGGERS
+	select BACKPORT_LEDS_TRIGGERS
 	---help---
 	  This option enables a few LED triggers for different
 	  packet receive/transmit events.
@@ -177,17 +170,6 @@
 
 	  Do not select this option.
 
-config MAC80211_OCB_DEBUG
-	bool "Verbose OCB debugging"
-	depends on MAC80211_DEBUG_MENU
-	---help---
-	  Selecting this option causes mac80211 to print out
-	  very verbose OCB debugging messages. It should not
-	  be selected on production systems as those messages
-	  are remotely triggerable.
-
-	  Do not select this option.
-
 config MAC80211_IBSS_DEBUG
 	bool "Verbose IBSS debugging"
 	depends on MAC80211_DEBUG_MENU
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index c09aa25..285af62 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -27,8 +27,7 @@
 	event.o \
 	chan.o \
 	trace.o mlme.o \
-	tdls.o \
-	ocb.o
+	tdls.o
 
 mac80211-$(CPTCFG_MAC80211_LEDS) += led.o
 mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 09d9caa..ec24378 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -53,9 +53,6 @@
 		__aligned(__alignof__(struct aead_request));
 	struct aead_request *aead_req = (void *) aead_req_data;
 
-	if (data_len == 0)
-		return -EINVAL;
-
 	memset(aead_req, 0, sizeof(aead_req_data));
 
 	sg_init_one(&pt, data, data_len);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index a360c15..d6986f3 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -149,6 +149,11 @@
 	rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
 }
 
+static inline int ieee80211_ac_from_tid(int tid)
+{
+	return ieee802_1d_to_ac[tid & 7];
+}
+
 /*
  * When multiple aggregation sessions on multiple stations
  * are being created/destroyed simultaneously, we need to
@@ -509,10 +514,6 @@
 	struct tid_ampdu_tx *tid_tx;
 	int ret = 0;
 
-	if (WARN(sta->reserved_tid == tid,
-		 "Requested to start BA session on reserved tid=%d", tid))
-		return -EINVAL;
-
 	trace_api_start_tx_ba_session(pubsta, tid);
 
 	if (WARN_ON_ONCE(!local->ops->ampdu_action))
@@ -769,9 +770,6 @@
 		goto unlock;
 	}
 
-	WARN(sta->reserved_tid == tid,
-	     "Requested to stop BA session on reserved tid=%d", tid);
-
 	if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
 		/* already in progress stopping it */
 		ret = 0;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a527ac3..a46ff74 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -20,7 +20,6 @@
 #include "cfg.h"
 #include "rate.h"
 #include "mesh.h"
-#include "wme.h"
 
 static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
 						const char *name,
@@ -191,7 +190,7 @@
 		 * receive the key. When wpa_supplicant has roamed
 		 * using FT, it attempts to set the key before
 		 * association has completed, this rejects that attempt
-		 * so it will set the key again after association.
+		 * so it will set the key again after assocation.
 		 *
 		 * TODO: accept the key if we have a station entry and
 		 *       add it to the device after the station.
@@ -230,7 +229,6 @@
 	case NUM_NL80211_IFTYPES:
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_P2P_GO:
-	case NL80211_IFTYPE_OCB:
 		/* shouldn't happen */
 		WARN_ON_ONCE(1);
 		break;
@@ -1042,13 +1040,6 @@
 			clear_sta_flag(sta, WLAN_STA_TDLS_PEER);
 	}
 
-	/* mark TDLS channel switch support, if the AP allows it */
-	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
-	    !sdata->u.mgd.tdls_chan_switch_prohibited &&
-	    params->ext_capab_len >= 4 &&
-	    params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)
-		set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH);
-
 	if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
 		sta->sta.uapsd_queues = params->uapsd_queues;
 		sta->sta.max_sp = params->max_sp;
@@ -1234,14 +1225,14 @@
 }
 
 static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
-				 struct station_del_parameters *params)
+				 const u8 *mac)
 {
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-	if (params->mac)
-		return sta_info_destroy_addr_bss(sdata, params->mac);
+	if (mac)
+		return sta_info_destroy_addr_bss(sdata, mac);
 
 	sta_info_flush(sdata);
 	return 0;
@@ -1525,57 +1516,6 @@
 	return 0;
 }
 
-static void mpp_set_pinfo(struct mesh_path *mpath, u8 *mpp,
-			  struct mpath_info *pinfo)
-{
-	memset(pinfo, 0, sizeof(*pinfo));
-	memcpy(mpp, mpath->mpp, ETH_ALEN);
-
-	pinfo->generation = mpp_paths_generation;
-}
-
-static int ieee80211_get_mpp(struct wiphy *wiphy, struct net_device *dev,
-			     u8 *dst, u8 *mpp, struct mpath_info *pinfo)
-
-{
-	struct ieee80211_sub_if_data *sdata;
-	struct mesh_path *mpath;
-
-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-	rcu_read_lock();
-	mpath = mpp_path_lookup(sdata, dst);
-	if (!mpath) {
-		rcu_read_unlock();
-		return -ENOENT;
-	}
-	memcpy(dst, mpath->dst, ETH_ALEN);
-	mpp_set_pinfo(mpath, mpp, pinfo);
-	rcu_read_unlock();
-	return 0;
-}
-
-static int ieee80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev,
-			      int idx, u8 *dst, u8 *mpp,
-			      struct mpath_info *pinfo)
-{
-	struct ieee80211_sub_if_data *sdata;
-	struct mesh_path *mpath;
-
-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-	rcu_read_lock();
-	mpath = mpp_path_lookup_by_idx(sdata, idx);
-	if (!mpath) {
-		rcu_read_unlock();
-		return -ENOENT;
-	}
-	memcpy(dst, mpath->dst, ETH_ALEN);
-	mpp_set_pinfo(mpath, mpp, pinfo);
-	rcu_read_unlock();
-	return 0;
-}
-
 static int ieee80211_get_mesh_config(struct wiphy *wiphy,
 				struct net_device *dev,
 				struct mesh_config *conf)
@@ -2026,17 +1966,6 @@
 	return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev));
 }
 
-static int ieee80211_join_ocb(struct wiphy *wiphy, struct net_device *dev,
-			      struct ocb_setup *setup)
-{
-	return ieee80211_ocb_join(IEEE80211_DEV_TO_SUB_IF(dev), setup);
-}
-
-static int ieee80211_leave_ocb(struct wiphy *wiphy, struct net_device *dev)
-{
-	return ieee80211_ocb_leave(IEEE80211_DEV_TO_SUB_IF(dev));
-}
-
 static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
 				    int rate[IEEE80211_NUM_BANDS])
 {
@@ -2152,9 +2081,6 @@
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 
-	if (local->ops->get_txpower)
-		return drv_get_txpower(local, sdata, dbm);
-
 	if (!local->use_chanctx)
 		*dbm = local->hw.conf.power_level;
 	else
@@ -2924,7 +2850,11 @@
 		if (sdata->reserved_ready)
 			return 0;
 
-		return ieee80211_vif_use_reserved_context(sdata);
+		err = ieee80211_vif_use_reserved_context(sdata);
+		if (err)
+			return err;
+
+		return 0;
 	}
 
 	if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
@@ -2938,6 +2868,7 @@
 		return err;
 
 	ieee80211_bss_info_change_notify(sdata, changed);
+	cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
 
 	if (sdata->csa_block_tx) {
 		ieee80211_wake_vif_queues(local, sdata,
@@ -2945,12 +2876,6 @@
 		sdata->csa_block_tx = false;
 	}
 
-	err = drv_post_channel_switch(sdata);
-	if (err)
-		return err;
-
-	cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
-
 	return 0;
 }
 
@@ -3128,11 +3053,9 @@
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_channel_switch ch_switch;
 	struct ieee80211_chanctx_conf *conf;
 	struct ieee80211_chanctx *chanctx;
-	u32 changed = 0;
-	int err;
+	int err, changed = 0;
 
 	sdata_assert_lock(sdata);
 	lockdep_assert_held(&local->mtx);
@@ -3165,16 +3088,6 @@
 		goto out;
 	}
 
-	ch_switch.timestamp = 0;
-	ch_switch.device_timestamp = 0;
-	ch_switch.block_tx = params->block_tx;
-	ch_switch.chandef = params->chandef;
-	ch_switch.count = params->count;
-
-	err = drv_pre_channel_switch(sdata, &ch_switch);
-	if (err)
-		goto out;
-
 	err = ieee80211_vif_reserve_chanctx(sdata, &params->chandef,
 					    chanctx->mode,
 					    params->radar_required);
@@ -3202,9 +3115,6 @@
 		ieee80211_stop_vif_queues(local, sdata,
 					  IEEE80211_QUEUE_STOP_REASON_CSA);
 
-	cfg80211_ch_switch_started_notify(sdata->dev, &sdata->csa_chandef,
-					  params->count);
-
 	if (changed) {
 		ieee80211_bss_info_change_notify(sdata, changed);
 		drv_channel_switch_beacon(sdata, &params->chandef);
@@ -3521,7 +3431,6 @@
 
 	info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
 		       IEEE80211_TX_INTFL_NL80211_FRAME_TX;
-	info->band = band;
 
 	skb_set_queue_mapping(skb, IEEE80211_AC_VO);
 	skb->priority = 7;
@@ -3529,7 +3438,7 @@
 		nullfunc->qos_ctrl = cpu_to_le16(7);
 
 	local_bh_disable();
-	ieee80211_xmit(sdata, skb);
+	ieee80211_xmit(sdata, skb, band);
 	local_bh_enable();
 	rcu_read_unlock();
 
@@ -3549,7 +3458,7 @@
 	rcu_read_lock();
 	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
 	if (chanctx_conf) {
-		*chandef = sdata->vif.bss_conf.chandef;
+		*chandef = chanctx_conf->def;
 		ret = 0;
 	} else if (local->open_count > 0 &&
 		   local->open_count == local->monitors &&
@@ -3612,76 +3521,6 @@
 	return ret;
 }
 
-static int ieee80211_add_tx_ts(struct wiphy *wiphy, struct net_device *dev,
-			       u8 tsid, const u8 *peer, u8 up,
-			       u16 admitted_time)
-{
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-	int ac = ieee802_1d_to_ac[up];
-
-	if (sdata->vif.type != NL80211_IFTYPE_STATION)
-		return -EOPNOTSUPP;
-
-	if (!(sdata->wmm_acm & BIT(up)))
-		return -EINVAL;
-
-	if (ifmgd->tx_tspec[ac].admitted_time)
-		return -EBUSY;
-
-	if (admitted_time) {
-		ifmgd->tx_tspec[ac].admitted_time = 32 * admitted_time;
-		ifmgd->tx_tspec[ac].tsid = tsid;
-		ifmgd->tx_tspec[ac].up = up;
-	}
-
-	return 0;
-}
-
-static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
-			       u8 tsid, const u8 *peer)
-{
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-	struct ieee80211_local *local = wiphy_priv(wiphy);
-	int ac;
-
-	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-		struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
-
-		/* skip unused entries */
-		if (!tx_tspec->admitted_time)
-			continue;
-
-		if (tx_tspec->tsid != tsid)
-			continue;
-
-		/* due to this new packets will be reassigned to non-ACM ACs */
-		tx_tspec->up = -1;
-
-		/* Make sure that all packets have been sent to avoid to
-		 * restore the QoS params on packets that are still on the
-		 * queues.
-		 */
-		synchronize_net();
-		ieee80211_flush_queues(local, sdata);
-
-		/* restore the normal QoS parameters
-		 * (unconditionally to avoid races)
-		 */
-		tx_tspec->action = TX_TSPEC_ACTION_STOP_DOWNGRADE;
-		tx_tspec->downgraded = false;
-		ieee80211_sta_handle_tspec_ac_params(sdata);
-
-		/* finally clear all the data */
-		memset(tx_tspec, 0, sizeof(*tx_tspec));
-
-		return 0;
-	}
-
-	return -ENOENT;
-}
-
 const struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -3708,15 +3547,11 @@
 	.change_mpath = ieee80211_change_mpath,
 	.get_mpath = ieee80211_get_mpath,
 	.dump_mpath = ieee80211_dump_mpath,
-	.get_mpp = ieee80211_get_mpp,
-	.dump_mpp = ieee80211_dump_mpp,
 	.update_mesh_config = ieee80211_update_mesh_config,
 	.get_mesh_config = ieee80211_get_mesh_config,
 	.join_mesh = ieee80211_join_mesh,
 	.leave_mesh = ieee80211_leave_mesh,
 #endif
-	.join_ocb = ieee80211_join_ocb,
-	.leave_ocb = ieee80211_leave_ocb,
 	.change_bss = ieee80211_change_bss,
 	.set_txq_params = ieee80211_set_txq_params,
 	.set_monitor_channel = ieee80211_set_monitor_channel,
@@ -3752,8 +3587,6 @@
 	.set_rekey_data = ieee80211_set_rekey_data,
 	.tdls_oper = ieee80211_tdls_oper,
 	.tdls_mgmt = ieee80211_tdls_mgmt,
-	.tdls_channel_switch = ieee80211_tdls_channel_switch,
-	.tdls_cancel_channel_switch = ieee80211_tdls_cancel_channel_switch,
 	.probe_client = ieee80211_probe_client,
 	.set_noack_map = ieee80211_set_noack_map,
 #ifdef CONFIG_PM
@@ -3764,6 +3597,4 @@
 	.channel_switch = ieee80211_channel_switch,
 	.set_qos_map = ieee80211_set_qos_map,
 	.set_ap_chanwidth = ieee80211_set_ap_chanwidth,
-	.add_tx_ts = ieee80211_add_tx_ts,
-	.del_tx_ts = ieee80211_del_tx_ts,
 };
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index da1c12c..4c74e8d 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -270,7 +270,6 @@
 		case NL80211_IFTYPE_ADHOC:
 		case NL80211_IFTYPE_WDS:
 		case NL80211_IFTYPE_MESH_POINT:
-		case NL80211_IFTYPE_OCB:
 			width = vif->bss_conf.chandef.width;
 			break;
 		case NL80211_IFTYPE_UNSPECIFIED:
@@ -675,7 +674,6 @@
 		case NL80211_IFTYPE_ADHOC:
 		case NL80211_IFTYPE_WDS:
 		case NL80211_IFTYPE_MESH_POINT:
-		case NL80211_IFTYPE_OCB:
 			break;
 		default:
 			WARN_ON_ONCE(1);
@@ -911,7 +909,6 @@
 	case NL80211_IFTYPE_ADHOC:
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_MESH_POINT:
-	case NL80211_IFTYPE_OCB:
 		ieee80211_queue_work(&sdata->local->hw,
 				     &sdata->csa_finalize_work);
 		break;
@@ -932,21 +929,6 @@
 	}
 }
 
-static void
-ieee80211_vif_update_chandef(struct ieee80211_sub_if_data *sdata,
-			     const struct cfg80211_chan_def *chandef)
-{
-	struct ieee80211_sub_if_data *vlan;
-
-	sdata->vif.bss_conf.chandef = *chandef;
-
-	if (sdata->vif.type != NL80211_IFTYPE_AP)
-		return;
-
-	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
-		vlan->vif.bss_conf.chandef = *chandef;
-}
-
 static int
 ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
 {
@@ -1009,11 +991,7 @@
 	if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width)
 		changed = BSS_CHANGED_BANDWIDTH;
 
-	ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef);
-
-	ieee80211_recalc_smps_chanctx(local, new_ctx);
-	ieee80211_recalc_radar_chanctx(local, new_ctx);
-	ieee80211_recalc_chanctx_min_def(local, new_ctx);
+	sdata->vif.bss_conf.chandef = sdata->reserved_chandef;
 
 	if (changed)
 		ieee80211_bss_info_change_notify(sdata, changed);
@@ -1355,7 +1333,7 @@
 			    sdata->reserved_chandef.width)
 				changed = BSS_CHANGED_BANDWIDTH;
 
-			ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef);
+			sdata->vif.bss_conf.chandef = sdata->reserved_chandef;
 			if (changed)
 				ieee80211_bss_info_change_notify(sdata,
 								 changed);
@@ -1526,7 +1504,7 @@
 		goto out;
 	}
 
-	ieee80211_vif_update_chandef(sdata, chandef);
+	sdata->vif.bss_conf.chandef = *chandef;
 
 	ret = ieee80211_assign_vif_chanctx(sdata, ctx);
 	if (ret) {
@@ -1656,7 +1634,7 @@
 		}
 		break;
 	case IEEE80211_CHANCTX_WILL_BE_REPLACED:
-		/* TODO: Perhaps the bandwidth change could be treated as a
+		/* TODO: Perhaps the bandwith change could be treated as a
 		 * reservation itself? */
 		ret = -EBUSY;
 		goto out;
@@ -1668,7 +1646,7 @@
 		break;
 	}
 
-	ieee80211_vif_update_chandef(sdata, chandef);
+	sdata->vif.bss_conf.chandef = *chandef;
 
 	ieee80211_recalc_chanctx_chantype(local, ctx);
 
diff --git a/net/mac80211/debug.h b/net/mac80211/debug.h
index c0ba105..ddbc904 100644
--- a/net/mac80211/debug.h
+++ b/net/mac80211/debug.h
@@ -2,12 +2,6 @@
 #define __MAC80211_DEBUG_H
 #include <net/cfg80211.h>
 
-#ifdef CPTCFG_MAC80211_OCB_DEBUG
-#define MAC80211_OCB_DEBUG 1
-#else
-#define MAC80211_OCB_DEBUG 0
-#endif
-
 #ifdef CPTCFG_MAC80211_IBSS_DEBUG
 #define MAC80211_IBSS_DEBUG 1
 #else
@@ -137,10 +131,6 @@
 	_sdata_dbg(MAC80211_HT_DEBUG && net_ratelimit(),		\
 		   sdata, fmt, ##__VA_ARGS__)
 
-#define ocb_dbg(sdata, fmt, ...)					\
-	_sdata_dbg(MAC80211_OCB_DEBUG,					\
-		   sdata, fmt, ##__VA_ARGS__)
-
 #define ibss_dbg(sdata, fmt, ...)					\
 	_sdata_dbg(MAC80211_IBSS_DEBUG,					\
 		   sdata, fmt, ##__VA_ARGS__)
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 5523b94..1521cab 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -300,8 +300,10 @@
 
 	lockdep_assert_held(&sdata->local->key_mtx);
 
-	debugfs_remove(sdata->debugfs.default_unicast_key);
-	sdata->debugfs.default_unicast_key = NULL;
+	if (sdata->debugfs.default_unicast_key) {
+		debugfs_remove(sdata->debugfs.default_unicast_key);
+		sdata->debugfs.default_unicast_key = NULL;
+	}
 
 	if (sdata->default_unicast_key) {
 		key = key_mtx_dereference(sdata->local,
@@ -312,8 +314,10 @@
 					       sdata->vif.debugfs_dir, buf);
 	}
 
-	debugfs_remove(sdata->debugfs.default_multicast_key);
-	sdata->debugfs.default_multicast_key = NULL;
+	if (sdata->debugfs.default_multicast_key) {
+		debugfs_remove(sdata->debugfs.default_multicast_key);
+		sdata->debugfs.default_multicast_key = NULL;
+	}
 
 	if (sdata->default_multicast_key) {
 		key = key_mtx_dereference(sdata->local,
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 94c7009..bafe489 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -74,7 +74,7 @@
 	test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
 
 	int res = scnprintf(buf, sizeof(buf),
-			    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+			    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
 			    TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
 			    TEST(PS_DRIVER), TEST(AUTHORIZED),
 			    TEST(SHORT_PREAMBLE),
@@ -82,11 +82,10 @@
 			    TEST(WDS), TEST(CLEAR_PS_FILT),
 			    TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
 			    TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
-			    TEST(TDLS_PEER_AUTH), TEST(TDLS_INITIATOR),
-			    TEST(TDLS_CHAN_SWITCH), TEST(TDLS_OFF_CHANNEL),
-			    TEST(4ADDR_EVENT), TEST(INSERTED),
-			    TEST(RATE_CONTROL), TEST(TOFFSET_KNOWN),
-			    TEST(MPSP_OWNER), TEST(MPSP_RECIPIENT));
+			    TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
+			    TEST(INSERTED), TEST(RATE_CONTROL),
+			    TEST(TOFFSET_KNOWN), TEST(MPSP_OWNER),
+			    TEST(MPSP_RECIPIENT));
 #undef TEST
 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
 }
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 754c893..6da526b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -214,8 +214,7 @@
 				    BSS_CHANGED_BEACON_ENABLED) &&
 			 sdata->vif.type != NL80211_IFTYPE_AP &&
 			 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-			 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-			 sdata->vif.type != NL80211_IFTYPE_OCB))
+			 sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
 		return;
 
 	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
@@ -380,26 +379,23 @@
 	return ret;
 }
 
-static inline void drv_sw_scan_start(struct ieee80211_local *local,
-				     struct ieee80211_sub_if_data *sdata,
-				     const u8 *mac_addr)
+static inline void drv_sw_scan_start(struct ieee80211_local *local)
 {
 	might_sleep();
 
-	trace_drv_sw_scan_start(local, sdata, mac_addr);
+	trace_drv_sw_scan_start(local);
 	if (local->ops->sw_scan_start)
-		local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr);
+		local->ops->sw_scan_start(&local->hw);
 	trace_drv_return_void(local);
 }
 
-static inline void drv_sw_scan_complete(struct ieee80211_local *local,
-					struct ieee80211_sub_if_data *sdata)
+static inline void drv_sw_scan_complete(struct ieee80211_local *local)
 {
 	might_sleep();
 
-	trace_drv_sw_scan_complete(local, sdata);
+	trace_drv_sw_scan_complete(local);
 	if (local->ops->sw_scan_complete)
-		local->ops->sw_scan_complete(&local->hw, &sdata->vif);
+		local->ops->sw_scan_complete(&local->hw);
 	trace_drv_return_void(local);
 }
 
@@ -624,21 +620,6 @@
 	trace_drv_return_void(local);
 }
 
-static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local,
-					   struct ieee80211_sub_if_data *sdata,
-					   struct ieee80211_sta *sta)
-{
-	sdata = get_bss_sdata(sdata);
-	if (!check_sdata_in_driver(sdata))
-		return;
-
-	trace_drv_sta_rate_tbl_update(local, sdata, sta);
-	if (local->ops->sta_rate_tbl_update)
-		local->ops->sta_rate_tbl_update(&local->hw, &sdata->vif, sta);
-
-	trace_drv_return_void(local);
-}
-
 static inline int drv_conf_tx(struct ieee80211_local *local,
 			      struct ieee80211_sub_if_data *sdata, u16 ac,
 			      const struct ieee80211_tx_queue_params *params)
@@ -650,12 +631,6 @@
 	if (!check_sdata_in_driver(sdata))
 		return -EIO;
 
-	if (WARN_ONCE(params->cw_min == 0 ||
-		      params->cw_min > params->cw_max,
-		      "%s: invalid CW_min/CW_max: %d/%d\n",
-		      sdata->name, params->cw_min, params->cw_max))
-		return -EINVAL;
-
 	trace_drv_conf_tx(local, sdata, ac, params);
 	if (local->ops->conf_tx)
 		ret = local->ops->conf_tx(&local->hw, &sdata->vif,
@@ -789,13 +764,12 @@
 }
 
 static inline void drv_channel_switch(struct ieee80211_local *local,
-				      struct ieee80211_sub_if_data *sdata,
-				      struct ieee80211_channel_switch *ch_switch)
+				     struct ieee80211_channel_switch *ch_switch)
 {
 	might_sleep();
 
-	trace_drv_channel_switch(local, sdata, ch_switch);
-	local->ops->channel_switch(&local->hw, &sdata->vif, ch_switch);
+	trace_drv_channel_switch(local, ch_switch);
+	local->ops->channel_switch(&local->hw, ch_switch);
 	trace_drv_return_void(local);
 }
 
@@ -1170,15 +1144,13 @@
 	trace_drv_return_void(local);
 }
 
-static inline void
-drv_reconfig_complete(struct ieee80211_local *local,
-		      enum ieee80211_reconfig_type reconfig_type)
+static inline void drv_restart_complete(struct ieee80211_local *local)
 {
 	might_sleep();
 
-	trace_drv_reconfig_complete(local, reconfig_type);
-	if (local->ops->reconfig_complete)
-		local->ops->reconfig_complete(&local->hw, reconfig_type);
+	trace_drv_restart_complete(local);
+	if (local->ops->restart_complete)
+		local->ops->restart_complete(&local->hw);
 	trace_drv_return_void(local);
 }
 
@@ -1224,40 +1196,6 @@
 	}
 }
 
-static inline int
-drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata,
-		       struct ieee80211_channel_switch *ch_switch)
-{
-	struct ieee80211_local *local = sdata->local;
-	int ret = 0;
-
-	if (!check_sdata_in_driver(sdata))
-		return -EIO;
-
-	trace_drv_pre_channel_switch(local, sdata, ch_switch);
-	if (local->ops->pre_channel_switch)
-		ret = local->ops->pre_channel_switch(&local->hw, &sdata->vif,
-						     ch_switch);
-	trace_drv_return_int(local, ret);
-	return ret;
-}
-
-static inline int
-drv_post_channel_switch(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_local *local = sdata->local;
-	int ret = 0;
-
-	if (!check_sdata_in_driver(sdata))
-		return -EIO;
-
-	trace_drv_post_channel_switch(local, sdata);
-	if (local->ops->post_channel_switch)
-		ret = local->ops->post_channel_switch(&local->hw, &sdata->vif);
-	trace_drv_return_int(local, ret);
-	return ret;
-}
-
 static inline int drv_join_ibss(struct ieee80211_local *local,
 				struct ieee80211_sub_if_data *sdata)
 {
@@ -1300,71 +1238,4 @@
 	return ret;
 }
 
-static inline int drv_get_txpower(struct ieee80211_local *local,
-				  struct ieee80211_sub_if_data *sdata, int *dbm)
-{
-	int ret;
-
-	if (!local->ops->get_txpower)
-		return -EOPNOTSUPP;
-
-	ret = local->ops->get_txpower(&local->hw, &sdata->vif, dbm);
-	trace_drv_get_txpower(local, sdata, *dbm, ret);
-
-	return ret;
-}
-
-static inline int
-drv_tdls_channel_switch(struct ieee80211_local *local,
-			struct ieee80211_sub_if_data *sdata,
-			struct ieee80211_sta *sta, u8 oper_class,
-			struct cfg80211_chan_def *chandef,
-			struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie)
-{
-	int ret;
-
-	might_sleep();
-	if (!check_sdata_in_driver(sdata))
-		return -EIO;
-
-	if (!local->ops->tdls_channel_switch)
-		return -EOPNOTSUPP;
-
-	trace_drv_tdls_channel_switch(local, sdata, sta, oper_class, chandef);
-	ret = local->ops->tdls_channel_switch(&local->hw, &sdata->vif, sta,
-					      oper_class, chandef, tmpl_skb,
-					      ch_sw_tm_ie);
-	trace_drv_return_int(local, ret);
-	return ret;
-}
-
-static inline void
-drv_tdls_cancel_channel_switch(struct ieee80211_local *local,
-			       struct ieee80211_sub_if_data *sdata,
-			       struct ieee80211_sta *sta)
-{
-	might_sleep();
-	if (!check_sdata_in_driver(sdata))
-		return;
-
-	if (!local->ops->tdls_cancel_channel_switch)
-		return;
-
-	trace_drv_tdls_cancel_channel_switch(local, sdata, sta);
-	local->ops->tdls_cancel_channel_switch(&local->hw, &sdata->vif, sta);
-	trace_drv_return_void(local);
-}
-
-static inline void
-drv_tdls_recv_channel_switch(struct ieee80211_local *local,
-			     struct ieee80211_sub_if_data *sdata,
-			     struct ieee80211_tdls_ch_sw_params *params)
-{
-	trace_drv_tdls_recv_channel_switch(local, sdata, params);
-	if (local->ops->tdls_recv_channel_switch)
-		local->ops->tdls_recv_channel_switch(&local->hw, &sdata->vif,
-						     params);
-	trace_drv_return_void(local);
-}
-
 #endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 509bc15..56b5357 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -805,7 +805,7 @@
 
 	memset(&params, 0, sizeof(params));
 	memset(&csa_ie, 0, sizeof(csa_ie));
-	err = ieee80211_parse_ch_switch_ie(sdata, elems,
+	err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon,
 					   ifibss->chandef.chan->band,
 					   sta_flags, ifibss->bssid, &csa_ie);
 	/* can't switch to destination channel, fail */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f08f4b9..a02fa58 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -131,7 +131,7 @@
  *
  * These are bss flags that are attached to a bss in the
  * @valid_data field of &struct ieee80211_bss.  They show which parts
- * of the data structure were received as a result of an un-corrupted
+ * of the data structure were recieved as a result of an un-corrupted
  * beacon/probe response.
  */
 enum ieee80211_bss_valid_data_flags {
@@ -399,24 +399,6 @@
 	u8 ie[];
 };
 
-struct ieee80211_sta_tx_tspec {
-	/* timestamp of the first packet in the time slice */
-	unsigned long time_slice_start;
-
-	u32 admitted_time; /* in usecs, unlike over the air */
-	u8 tsid;
-	s8 up; /* signed to be able to invalidate with -1 during teardown */
-
-	/* consumed TX time in microseconds in the time slice */
-	u32 consumed_tx_time;
-	enum {
-		TX_TSPEC_ACTION_NONE = 0,
-		TX_TSPEC_ACTION_DOWNGRADE,
-		TX_TSPEC_ACTION_STOP_DOWNGRADE,
-	} action;
-	bool downgraded;
-};
-
 struct ieee80211_if_managed {
 	struct timer_list timer;
 	struct timer_list conn_mon_timer;
@@ -452,8 +434,6 @@
 
 	unsigned int flags;
 
-	bool csa_waiting_bcn;
-
 	bool beacon_crc_valid;
 	u32 beacon_crc;
 
@@ -525,23 +505,8 @@
 	struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */
 	struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */
 
-	/* TDLS support */
 	u8 tdls_peer[ETH_ALEN] __aligned(2);
 	struct delayed_work tdls_peer_del_work;
-	struct sk_buff *orig_teardown_skb; /* The original teardown skb */
-	struct sk_buff *teardown_skb; /* A copy to send through the AP */
-	spinlock_t teardown_lock; /* To lock changing teardown_skb */
-	bool tdls_chan_switch_prohibited;
-
-	/* WMM-AC TSPEC support */
-	struct ieee80211_sta_tx_tspec tx_tspec[IEEE80211_NUM_ACS];
-	/* Use a separate work struct so that we can do something here
-	 * while the sdata->work is flushing the queues, for example.
-	 * otherwise, in scenarios where we hardly get any traffic out
-	 * on the BE queue, but there's a lot of VO traffic, we might
-	 * get stuck in a downgraded situation and flush takes forever.
-	 */
-	struct delayed_work tx_tspec_wk;
 };
 
 struct ieee80211_if_ibss {
@@ -582,25 +547,6 @@
 };
 
 /**
- * struct ieee80211_if_ocb - OCB mode state
- *
- * @housekeeping_timer: timer for periodic invocation of a housekeeping task
- * @wrkq_flags: OCB deferred task action
- * @incomplete_lock: delayed STA insertion lock
- * @incomplete_stations: list of STAs waiting for delayed insertion
- * @joined: indication if the interface is connected to an OCB network
- */
-struct ieee80211_if_ocb {
-	struct timer_list housekeeping_timer;
-	unsigned long wrkq_flags;
-
-	spinlock_t incomplete_lock;
-	struct list_head incomplete_stations;
-
-	bool joined;
-};
-
-/**
  * struct ieee80211_mesh_sync_ops - Extensible synchronization framework interface
  *
  * these declarations define the interface, which enables
@@ -893,7 +839,6 @@
 		struct ieee80211_if_managed mgd;
 		struct ieee80211_if_ibss ibss;
 		struct ieee80211_if_mesh mesh;
-		struct ieee80211_if_ocb ocb;
 		u32 mntr_flags;
 	} u;
 
@@ -993,7 +938,6 @@
 	IEEE80211_SDATA_QUEUE_AGG_STOP		= 2,
 	IEEE80211_SDATA_QUEUE_RX_AGG_START	= 3,
 	IEEE80211_SDATA_QUEUE_RX_AGG_STOP	= 4,
-	IEEE80211_SDATA_QUEUE_TDLS_CHSW		= 5,
 };
 
 enum {
@@ -1011,7 +955,6 @@
 	IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
 	IEEE80211_QUEUE_STOP_REASON_FLUSH,
 	IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN,
-	IEEE80211_QUEUE_STOP_REASON_RESERVE_TID,
 
 	IEEE80211_QUEUE_STOP_REASONS,
 };
@@ -1238,7 +1181,7 @@
 	unsigned long scanning;
 	struct cfg80211_ssid scan_ssid;
 	struct cfg80211_scan_request *int_scan_req;
-	struct cfg80211_scan_request __rcu *scan_req;
+	struct cfg80211_scan_request *scan_req;
 	struct ieee80211_scan_request *hw_scan_req;
 	struct cfg80211_chan_def scan_chandef;
 	enum ieee80211_band hw_scan_band;
@@ -1248,8 +1191,7 @@
 
 	struct work_struct sched_scan_stopped_work;
 	struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
-	struct cfg80211_sched_scan_request __rcu *sched_scan_req;
-	u8 scan_addr[ETH_ALEN];
+	struct cfg80211_sched_scan_request *sched_scan_req;
 
 	unsigned long leave_oper_channel_time;
 	enum mac80211_scan_state next_scan_state;
@@ -1368,9 +1310,6 @@
 	/* virtual monitor interface */
 	struct ieee80211_sub_if_data __rcu *monitor_sdata;
 	struct cfg80211_chan_def monitor_chandef;
-
-	/* extended capabilities provided by mac80211 */
-	u8 ext_capa[8];
 };
 
 static inline struct ieee80211_sub_if_data *
@@ -1406,9 +1345,6 @@
 	size_t total_len;
 
 	/* pointers to IEs */
-	const struct ieee80211_tdls_lnkie *lnk_id;
-	const struct ieee80211_ch_switch_timing *ch_sw_timing;
-	const u8 *ext_capab;
 	const u8 *ssid;
 	const u8 *supp_rates;
 	const u8 *ds_params;
@@ -1443,7 +1379,6 @@
 	const struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie;
 
 	/* length of them, respectively */
-	u8 ext_capab_len;
 	u8 ssid_len;
 	u8 supp_rates_len;
 	u8 tim_len;
@@ -1522,7 +1457,6 @@
 				  __le16 fc, bool acked);
 void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
-void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata);
 
 /* IBSS code */
 void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
@@ -1540,15 +1474,6 @@
 int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata);
 void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata);
 
-/* OCB code */
-void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata);
-void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
-			     const u8 *bssid, const u8 *addr, u32 supp_rates);
-void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata);
-int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
-		       struct ocb_setup *setup);
-int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata);
-
 /* mesh code */
 void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata);
 void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
@@ -1640,14 +1565,8 @@
 					 struct net_device *dev);
 netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 				       struct net_device *dev);
-void __ieee80211_subif_start_xmit(struct sk_buff *skb,
-				  struct net_device *dev,
-				  u32 info_flags);
 void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
 			      struct sk_buff_head *skbs);
-struct sk_buff *
-ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
-			      struct sk_buff *skb, u32 info_flags);
 
 /* HT */
 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
@@ -1726,6 +1645,7 @@
  * ieee80211_parse_ch_switch_ie - parses channel switch IEs
  * @sdata: the sdata of the interface which has received the frame
  * @elems: parsed 802.11 elements received with the frame
+ * @beacon: indicates if the frame was a beacon or probe response
  * @current_band: indicates the current band
  * @sta_flags: contains information about own capabilities and restrictions
  *	to decide which channel switch announcements can be accepted. Only the
@@ -1739,7 +1659,7 @@
  * Return: 0 on success, <0 on error and >0 if there is nothing to parse.
  */
 int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
-				 struct ieee802_11_elems *elems,
+				 struct ieee802_11_elems *elems, bool beacon,
 				 enum ieee80211_band current_band,
 				 u32 sta_flags, u8 *bssid,
 				 struct ieee80211_csa_ie *csa_ie);
@@ -1774,7 +1694,8 @@
 				     gfp_t gfp);
 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
 			       bool bss_notify);
-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+		    enum ieee80211_band band);
 
 void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
 				 struct sk_buff *skb, int tid,
@@ -1840,13 +1761,6 @@
 	return true;
 }
 
-extern const int ieee802_1d_to_ac[8];
-
-static inline int ieee80211_ac_from_tid(int tid)
-{
-	return ieee802_1d_to_ac[tid & 7];
-}
-
 void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
 void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
 void ieee80211_dynamic_ps_timer(unsigned long data);
@@ -1856,7 +1770,7 @@
 void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
 			     struct ieee80211_hdr *hdr);
 void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
-			     struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
+			     struct ieee80211_hdr *hdr, bool ack);
 
 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
 				     unsigned long queues,
@@ -1885,9 +1799,6 @@
 				struct sk_buff_head *skbs);
 void ieee80211_flush_queues(struct ieee80211_local *local,
 			    struct ieee80211_sub_if_data *sdata);
-void __ieee80211_flush_queues(struct ieee80211_local *local,
-			      struct ieee80211_sub_if_data *sdata,
-			      unsigned int queues);
 
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
 			 u16 transaction, u16 auth_alg, u16 status,
@@ -1904,14 +1815,12 @@
 			     u8 bands_used, u32 *rate_masks,
 			     struct cfg80211_chan_def *chandef);
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-					  const u8 *src, const u8 *dst,
-					  u32 ratemask,
+					  u8 *dst, u32 ratemask,
 					  struct ieee80211_channel *chan,
 					  const u8 *ssid, size_t ssid_len,
 					  const u8 *ie, size_t ie_len,
 					  bool directed);
-void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
-			      const u8 *src, const u8 *dst,
+void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 			      const u8 *ssid, size_t ssid_len,
 			      const u8 *ie, size_t ie_len,
 			      u32 ratemask, bool directed, u32 tx_flags,
@@ -1927,10 +1836,8 @@
 void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
 void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
 
-size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
-			      const u8 *ids, int n_ids,
-			      const u8 *after_ric, int n_after_ric,
-			      size_t offset);
+size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
+			  const u8 *ids, int n_ids, size_t offset);
 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
 u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
 			      u16 cap);
@@ -2017,14 +1924,6 @@
 int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
 			const u8 *peer, enum nl80211_tdls_operation oper);
 void ieee80211_tdls_peer_del_work(struct work_struct *wk);
-int ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
-				  const u8 *addr, u8 oper_class,
-				  struct cfg80211_chan_def *chandef);
-void ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
-					  struct net_device *dev,
-					  const u8 *addr);
-void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata,
-					   struct sk_buff *skb);
 
 extern const struct ethtool_ops ieee80211_ethtool_ops;
 
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index f7c759a..b7402fe 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -259,15 +259,6 @@
 	list_for_each_entry(nsdata, &local->interfaces, list) {
 		if (nsdata != sdata && ieee80211_sdata_running(nsdata)) {
 			/*
-			 * Only OCB and monitor mode may coexist
-			 */
-			if ((sdata->vif.type == NL80211_IFTYPE_OCB &&
-			     nsdata->vif.type != NL80211_IFTYPE_MONITOR) ||
-			    (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
-			     nsdata->vif.type == NL80211_IFTYPE_OCB))
-				return -EBUSY;
-
-			/*
 			 * Allow only a single IBSS interface to be up at any
 			 * time. This is restricted because beacon distribution
 			 * cannot work properly if both are in the same IBSS.
@@ -520,7 +511,6 @@
 		sdata->vif.cab_queue = master->vif.cab_queue;
 		memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
 		       sizeof(sdata->vif.hw_queue));
-		sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef;
 		break;
 		}
 	case NL80211_IFTYPE_AP:
@@ -531,7 +521,6 @@
 	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_ADHOC:
 	case NL80211_IFTYPE_P2P_DEVICE:
-	case NL80211_IFTYPE_OCB:
 		/* no special treatment */
 		break;
 	case NL80211_IFTYPE_UNSPECIFIED:
@@ -642,7 +631,6 @@
 		case NL80211_IFTYPE_ADHOC:
 		case NL80211_IFTYPE_AP:
 		case NL80211_IFTYPE_MESH_POINT:
-		case NL80211_IFTYPE_OCB:
 			netif_carrier_off(dev);
 			break;
 		case NL80211_IFTYPE_WDS:
@@ -778,12 +766,10 @@
 	int i, flushed;
 	struct ps_data *ps;
 	struct cfg80211_chan_def chandef;
-	bool cancel_scan;
 
 	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
-	cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
-	if (cancel_scan)
+	if (rcu_access_pointer(local->scan_sdata) == sdata)
 		ieee80211_scan_cancel(local);
 
 	/*
@@ -856,8 +842,6 @@
 	sdata_lock(sdata);
 	mutex_lock(&local->mtx);
 	sdata->vif.csa_active = false;
-	if (sdata->vif.type == NL80211_IFTYPE_STATION)
-		sdata->u.mgd.csa_waiting_bcn = false;
 	if (sdata->csa_block_tx) {
 		ieee80211_wake_vif_queues(local, sdata,
 					  IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -914,8 +898,6 @@
 		list_del(&sdata->u.vlan.list);
 		mutex_unlock(&local->mtx);
 		RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
-		/* see comment in the default case below */
-		ieee80211_free_keys(sdata, true);
 		/* no need to tell driver */
 		break;
 	case NL80211_IFTYPE_MONITOR:
@@ -941,16 +923,17 @@
 		/*
 		 * When we get here, the interface is marked down.
 		 * Free the remaining keys, if there are any
-		 * (which can happen in AP mode if userspace sets
-		 * keys before the interface is operating, and maybe
-		 * also in WDS mode)
+		 * (shouldn't be, except maybe in WDS mode?)
 		 *
 		 * Force the key freeing to always synchronize_net()
 		 * to wait for the RX path in case it is using this
-		 * interface enqueuing frames at this very time on
+		 * interface enqueuing frames * at this very time on
 		 * another CPU.
 		 */
 		ieee80211_free_keys(sdata, true);
+
+		/* fall through */
+	case NL80211_IFTYPE_AP:
 		skb_queue_purge(&sdata->skb_queue);
 	}
 
@@ -1008,9 +991,6 @@
 
 	ieee80211_recalc_ps(local, -1);
 
-	if (cancel_scan)
-		flush_delayed_work(&local->scan_work);
-
 	if (local->open_count == 0) {
 		ieee80211_stop_device(local);
 
@@ -1229,8 +1209,6 @@
 							WLAN_BACK_RECIPIENT, 0,
 							false);
 			mutex_unlock(&local->sta_mtx);
-		} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_TDLS_CHSW) {
-			ieee80211_process_tdls_channel_switch(sdata, skb);
 		} else if (ieee80211_is_action(mgmt->frame_control) &&
 			   mgmt->u.action.category == WLAN_CATEGORY_BACK) {
 			int len = skb->len;
@@ -1321,9 +1299,6 @@
 			break;
 		ieee80211_mesh_work(sdata);
 		break;
-	case NL80211_IFTYPE_OCB:
-		ieee80211_ocb_work(sdata);
-		break;
 	default:
 		break;
 	}
@@ -1343,9 +1318,6 @@
 static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 				  enum nl80211_iftype type)
 {
-	static const u8 bssid_wildcard[ETH_ALEN] = {0xff, 0xff, 0xff,
-						    0xff, 0xff, 0xff};
-
 	/* clear type-dependent union */
 	memset(&sdata->u, 0, sizeof(sdata->u));
 
@@ -1397,10 +1369,6 @@
 		sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
 		ieee80211_sta_setup_sdata(sdata);
 		break;
-	case NL80211_IFTYPE_OCB:
-		sdata->vif.bss_conf.bssid = bssid_wildcard;
-		ieee80211_ocb_setup_sdata(sdata);
-		break;
 	case NL80211_IFTYPE_ADHOC:
 		sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
 		ieee80211_ibss_setup_sdata(sdata);
@@ -1448,7 +1416,6 @@
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_OCB:
 		/*
 		 * Could maybe also all others here?
 		 * Just not sure how that interacts
@@ -1464,7 +1431,6 @@
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_OCB:
 		/*
 		 * Could probably support everything
 		 * but WDS here (WDS do_open can fail
@@ -1723,10 +1689,7 @@
 		}
 
 		ieee80211_assign_perm_addr(local, ndev->perm_addr, type);
-		if (params && is_valid_ether_addr(params->macaddr))
-			memcpy(ndev->dev_addr, params->macaddr, ETH_ALEN);
-		else
-			memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
+		memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
 		SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
 
 		/* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 0bb7038..4712150 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -94,17 +94,8 @@
 
 	might_sleep();
 
-	if (key->flags & KEY_FLAG_TAINTED) {
-		/* If we get here, it's during resume and the key is
-		 * tainted so shouldn't be used/programmed any more.
-		 * However, its flags may still indicate that it was
-		 * programmed into the device (since we're in resume)
-		 * so clear that flag now to avoid trying to remove
-		 * it again later.
-		 */
-		key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
+	if (key->flags & KEY_FLAG_TAINTED)
 		return -EINVAL;
-	}
 
 	if (!key->local->ops->set_key)
 		goto out_unsupported;
@@ -656,7 +647,7 @@
 	int i;
 
 	mutex_lock(&local->key_mtx);
-	for (i = 0; i < ARRAY_SIZE(sta->gtk); i++) {
+	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 		key = key_mtx_dereference(local, sta->gtk[i]);
 		if (!key)
 			continue;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 8c5a3cf..bc8ae88 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -478,9 +478,13 @@
 	},
 };
 
-struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
-					   const struct ieee80211_ops *ops,
-					   const char *requested_name)
+static const u8 extended_capabilities[] = {
+	0, 0, 0, 0, 0, 0, 0,
+	WLAN_EXT_CAPA8_OPMODE_NOTIF,
+};
+
+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+					const struct ieee80211_ops *ops)
 {
 	struct ieee80211_local *local;
 	int priv_size, i;
@@ -520,7 +524,7 @@
 	 */
 	priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
 
-	wiphy = wiphy_new_nm(&mac80211_config_ops, priv_size, requested_name);
+	wiphy = wiphy_new(&mac80211_config_ops, priv_size);
 
 	if (!wiphy)
 		return NULL;
@@ -535,6 +539,10 @@
 			WIPHY_FLAG_REPORTS_OBSS |
 			WIPHY_FLAG_OFFCHAN_TX;
 
+	wiphy->extended_capabilities = extended_capabilities;
+	wiphy->extended_capabilities_mask = extended_capabilities;
+	wiphy->extended_capabilities_len = ARRAY_SIZE(extended_capabilities);
+
 	if (ops->remain_on_channel)
 		wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 
@@ -542,7 +550,6 @@
 			   NL80211_FEATURE_SAE |
 			   NL80211_FEATURE_HT_IBSS |
 			   NL80211_FEATURE_VIF_TXPOWER |
-			   NL80211_FEATURE_MAC_ON_CREATE |
 			   NL80211_FEATURE_USERSPACE_MPM;
 
 	if (!ops->hw_scan)
@@ -584,13 +591,6 @@
 	wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
 	wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask;
 
-	local->ext_capa[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF;
-
-	wiphy->extended_capabilities = local->ext_capa;
-	wiphy->extended_capabilities_mask = local->ext_capa;
-	wiphy->extended_capabilities_len =
-		ARRAY_SIZE(local->ext_capa);
-
 	INIT_LIST_HEAD(&local->interfaces);
 
 	__hw_addr_init(&local->mc_list);
@@ -651,7 +651,7 @@
 
 	return &local->hw;
 }
-EXPORT_SYMBOL(ieee80211_alloc_hw_nm);
+EXPORT_SYMBOL(ieee80211_alloc_hw);
 
 static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 {
@@ -764,12 +764,6 @@
 	     local->hw.offchannel_tx_hw_queue >= local->hw.queues))
 		return -EINVAL;
 
-	if ((hw->wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
-	    (!local->ops->tdls_channel_switch ||
-	     !local->ops->tdls_cancel_channel_switch ||
-	     !local->ops->tdls_recv_channel_switch))
-		return -EOPNOTSUPP;
-
 #ifdef CONFIG_PM
 	if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume))
 		return -EINVAL;
@@ -793,14 +787,13 @@
 		if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
 			return -EINVAL;
 
-		/* DFS is not supported with multi-channel combinations yet */
+		/* DFS currently not supported with channel context drivers */
 		for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
 			const struct ieee80211_iface_combination *comb;
 
 			comb = &local->hw.wiphy->iface_combinations[i];
 
-			if (comb->radar_detect_widths &&
-			    comb->num_different_channels > 1)
+			if (comb->radar_detect_widths)
 				return -EINVAL;
 		}
 	}
@@ -965,10 +958,6 @@
 	if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
 		local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
 
-	/* mac80211 supports eCSA, if the driver supports STA CSA at all */
-	if (local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)
-		local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING;
-
 	local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
 
 	result = wiphy_register(local->hw.wiphy);
@@ -1030,8 +1019,7 @@
 	}
 
 	/* add one default STA interface if supported */
-	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) &&
-	    !(hw->flags & IEEE80211_HW_NO_AUTO_VIF)) {
+	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
 		result = ieee80211_if_add(local, "wlan%d", NULL,
 					  NL80211_IFTYPE_STATION, NULL);
 		if (result)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 0c8b2a7..e9f99c1 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -874,7 +874,7 @@
 
 	memset(&params, 0, sizeof(params));
 	memset(&csa_ie, 0, sizeof(csa_ie));
-	err = ieee80211_parse_ch_switch_ie(sdata, elems, band,
+	err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band,
 					   sta_flags, sdata->vif.addr,
 					   &csa_ie);
 	if (err < 0)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index b718db3..af9cb55 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -270,8 +270,6 @@
 		 const u8 *dst, const u8 *mpp);
 struct mesh_path *
 mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx);
-struct mesh_path *
-mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx);
 void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
@@ -319,7 +317,6 @@
 
 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
 extern int mesh_paths_generation;
-extern int mpp_paths_generation;
 
 #ifdef CPTCFG_MAC80211_MESH
 static inline
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index b890e22..a6699dc 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -44,7 +44,6 @@
 static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */
 
 int mesh_paths_generation;
-int mpp_paths_generation;
 
 /* This lock will have the grow table function as writer and add / delete nodes
  * as readers. RCU provides sufficient protection only when reading the table
@@ -411,33 +410,6 @@
 }
 
 /**
- * mpp_path_lookup_by_idx - look up a path in the proxy path table by its index
- * @idx: index
- * @sdata: local subif, or NULL for all entries
- *
- * Returns: pointer to the proxy path structure, or NULL if not found.
- *
- * Locking: must be called within a read rcu section.
- */
-struct mesh_path *
-mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx)
-{
-	struct mesh_table *tbl = rcu_dereference(mpp_paths);
-	struct mpath_node *node;
-	int i;
-	int j = 0;
-
-	for_each_mesh_entry(tbl, node, i) {
-		if (sdata && node->mpath->sdata != sdata)
-			continue;
-		if (j++ == idx)
-			return node->mpath;
-	}
-
-	return NULL;
-}
-
-/**
  * mesh_path_add_gate - add the given mpath to a mesh gate to our path table
  * @mpath: gate path to add to table
  */
@@ -719,9 +691,6 @@
 
 	spin_unlock(&tbl->hashwlock[hash_idx]);
 	read_unlock_bh(&pathtbl_resize_lock);
-
-	mpp_paths_generation++;
-
 	if (grow) {
 		set_bit(MESH_WORK_GROW_MPP_TABLE,  &ifmsh->wrkq_flags);
 		ieee80211_queue_work(&local->hw, &sdata->work);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2c36c47..2de8870 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -174,7 +174,6 @@
 	if (!(ht_cap->cap_info &
 	      cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40))) {
 		ret = IEEE80211_STA_DISABLE_40MHZ;
-		vht_chandef = *chandef;
 		goto out;
 	}
 
@@ -553,17 +552,13 @@
 	cap = vht_cap.cap;
 
 	if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) {
-		u32 bw = cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
-
-		cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
-		if (bw == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ||
-		    bw == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
-			cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+		cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+		cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
 	}
 
 	if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) {
 		cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
-		cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+		cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
 	}
 
 	/*
@@ -780,30 +775,11 @@
 			WLAN_EID_QOS_CAPA,
 			WLAN_EID_RRM_ENABLED_CAPABILITIES,
 			WLAN_EID_MOBILITY_DOMAIN,
-			WLAN_EID_FAST_BSS_TRANSITION,	/* reassoc only */
-			WLAN_EID_RIC_DATA,		/* reassoc only */
 			WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
 		};
-		static const u8 after_ric[] = {
-			WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
-			WLAN_EID_HT_CAPABILITY,
-			WLAN_EID_BSS_COEX_2040,
-			WLAN_EID_EXT_CAPABILITY,
-			WLAN_EID_QOS_TRAFFIC_CAPA,
-			WLAN_EID_TIM_BCAST_REQ,
-			WLAN_EID_INTERWORKING,
-			/* 60GHz doesn't happen right now */
-			WLAN_EID_VHT_CAPABILITY,
-			WLAN_EID_OPMODE_NOTIF,
-		};
-
-		noffset = ieee80211_ie_split_ric(assoc_data->ie,
-						 assoc_data->ie_len,
-						 before_ht,
-						 ARRAY_SIZE(before_ht),
-						 after_ric,
-						 ARRAY_SIZE(after_ric),
-						 offset);
+		noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
+					     before_ht, ARRAY_SIZE(before_ht),
+					     offset);
 		pos = skb_put(skb, noffset - offset);
 		memcpy(pos, assoc_data->ie + offset, noffset - offset);
 		offset = noffset;
@@ -837,8 +813,6 @@
 			WLAN_EID_TIM_BCAST_REQ,
 			WLAN_EID_INTERWORKING,
 		};
-
-		/* RIC already taken above, so no need to handle here anymore */
 		noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
 					     before_vht, ARRAY_SIZE(before_vht),
 					     offset);
@@ -1027,7 +1001,14 @@
 	/* XXX: shouldn't really modify cfg80211-owned data! */
 	ifmgd->associated->channel = sdata->csa_chandef.chan;
 
-	ifmgd->csa_waiting_bcn = true;
+	sdata->vif.csa_active = false;
+
+	/* XXX: wait for a beacon first? */
+	if (sdata->csa_block_tx) {
+		ieee80211_wake_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
+		sdata->csa_block_tx = false;
+	}
 
 	ieee80211_sta_reset_beacon_monitor(sdata);
 	ieee80211_sta_reset_conn_monitor(sdata);
@@ -1038,37 +1019,6 @@
 	sdata_unlock(sdata);
 }
 
-static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-	int ret;
-
-	sdata_assert_lock(sdata);
-
-	WARN_ON(!sdata->vif.csa_active);
-
-	if (sdata->csa_block_tx) {
-		ieee80211_wake_vif_queues(local, sdata,
-					  IEEE80211_QUEUE_STOP_REASON_CSA);
-		sdata->csa_block_tx = false;
-	}
-
-	cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef);
-
-	sdata->vif.csa_active = false;
-	ifmgd->csa_waiting_bcn = false;
-
-	ret = drv_post_channel_switch(sdata);
-	if (ret) {
-		sdata_info(sdata,
-			   "driver post channel switch failed, disconnecting\n");
-		ieee80211_queue_work(&local->hw,
-				     &ifmgd->csa_connection_drop_work);
-		return;
-	}
-}
-
 void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
 {
 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
@@ -1096,8 +1046,7 @@
 
 static void
 ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
-				 u64 timestamp, u32 device_timestamp,
-				 struct ieee802_11_elems *elems,
+				 u64 timestamp, struct ieee802_11_elems *elems,
 				 bool beacon)
 {
 	struct ieee80211_local *local = sdata->local;
@@ -1107,7 +1056,6 @@
 	struct ieee80211_chanctx *chanctx;
 	enum ieee80211_band current_band;
 	struct ieee80211_csa_ie csa_ie;
-	struct ieee80211_channel_switch ch_switch;
 	int res;
 
 	sdata_assert_lock(sdata);
@@ -1124,7 +1072,7 @@
 
 	current_band = cbss->channel->band;
 	memset(&csa_ie, 0, sizeof(csa_ie));
-	res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
+	res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band,
 					   ifmgd->flags,
 					   ifmgd->associated->bssid, &csa_ie);
 	if (res	< 0)
@@ -1162,31 +1110,21 @@
 
 	chanctx = container_of(conf, struct ieee80211_chanctx, conf);
 
-	if (local->use_chanctx &&
-	    !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) {
-		sdata_info(sdata,
-			   "driver doesn't support chan-switch with channel contexts\n");
-		ieee80211_queue_work(&local->hw,
-				     &ifmgd->csa_connection_drop_work);
-		mutex_unlock(&local->chanctx_mtx);
-		mutex_unlock(&local->mtx);
-		return;
-	}
+	if (local->use_chanctx) {
+		u32 num_chanctx = 0;
+		list_for_each_entry(chanctx, &local->chanctx_list, list)
+		       num_chanctx++;
 
-	ch_switch.timestamp = timestamp;
-	ch_switch.device_timestamp = device_timestamp;
-	ch_switch.block_tx = csa_ie.mode;
-	ch_switch.chandef = csa_ie.chandef;
-	ch_switch.count = csa_ie.count;
-
-	if (drv_pre_channel_switch(sdata, &ch_switch)) {
-		sdata_info(sdata,
-			   "preparing for channel switch failed, disconnecting\n");
-		ieee80211_queue_work(&local->hw,
-				     &ifmgd->csa_connection_drop_work);
-		mutex_unlock(&local->chanctx_mtx);
-		mutex_unlock(&local->mtx);
-		return;
+		if (num_chanctx > 1 ||
+		    !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) {
+			sdata_info(sdata,
+				   "not handling chan-switch with channel contexts\n");
+			ieee80211_queue_work(&local->hw,
+					     &ifmgd->csa_connection_drop_work);
+			mutex_unlock(&local->chanctx_mtx);
+			mutex_unlock(&local->mtx);
+			return;
+		}
 	}
 
 	res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef,
@@ -1212,12 +1150,16 @@
 					  IEEE80211_QUEUE_STOP_REASON_CSA);
 	mutex_unlock(&local->mtx);
 
-	cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
-					  csa_ie.count);
-
 	if (local->ops->channel_switch) {
 		/* use driver's channel switch callback */
-		drv_channel_switch(local, sdata, &ch_switch);
+		struct ieee80211_channel_switch ch_switch = {
+			.timestamp = timestamp,
+			.block_tx = csa_ie.mode,
+			.chandef = csa_ie.chandef,
+			.count = csa_ie.count,
+		};
+
+		drv_channel_switch(local, &ch_switch);
 		return;
 	}
 
@@ -1226,8 +1168,7 @@
 		ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
 	else
 		mod_timer(&ifmgd->chswitch_timer,
-			  TU_TO_EXP_TIME((csa_ie.count - 1) *
-					 cbss->beacon_interval));
+			  TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
 }
 
 static bool
@@ -1638,95 +1579,6 @@
 	mutex_unlock(&sdata->local->mtx);
 }
 
-static bool
-__ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-	bool ret;
-	int ac;
-
-	if (local->hw.queues < IEEE80211_NUM_ACS)
-		return false;
-
-	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-		struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
-		int non_acm_ac;
-		unsigned long now = jiffies;
-
-		if (tx_tspec->action == TX_TSPEC_ACTION_NONE &&
-		    tx_tspec->admitted_time &&
-		    time_after(now, tx_tspec->time_slice_start + HZ)) {
-			tx_tspec->consumed_tx_time = 0;
-			tx_tspec->time_slice_start = now;
-
-			if (tx_tspec->downgraded)
-				tx_tspec->action =
-					TX_TSPEC_ACTION_STOP_DOWNGRADE;
-		}
-
-		switch (tx_tspec->action) {
-		case TX_TSPEC_ACTION_STOP_DOWNGRADE:
-			/* take the original parameters */
-			if (drv_conf_tx(local, sdata, ac, &sdata->tx_conf[ac]))
-				sdata_err(sdata,
-					  "failed to set TX queue parameters for queue %d\n",
-					  ac);
-			tx_tspec->action = TX_TSPEC_ACTION_NONE;
-			tx_tspec->downgraded = false;
-			ret = true;
-			break;
-		case TX_TSPEC_ACTION_DOWNGRADE:
-			if (time_after(now, tx_tspec->time_slice_start + HZ)) {
-				tx_tspec->action = TX_TSPEC_ACTION_NONE;
-				ret = true;
-				break;
-			}
-			/* downgrade next lower non-ACM AC */
-			for (non_acm_ac = ac + 1;
-			     non_acm_ac < IEEE80211_NUM_ACS;
-			     non_acm_ac++)
-				if (!(sdata->wmm_acm & BIT(7 - 2 * non_acm_ac)))
-					break;
-			/* The loop will result in using BK even if it requires
-			 * admission control, such configuration makes no sense
-			 * and we have to transmit somehow - the AC selection
-			 * does the same thing.
-			 */
-			if (drv_conf_tx(local, sdata, ac,
-					&sdata->tx_conf[non_acm_ac]))
-				sdata_err(sdata,
-					  "failed to set TX queue parameters for queue %d\n",
-					  ac);
-			tx_tspec->action = TX_TSPEC_ACTION_NONE;
-			ret = true;
-			schedule_delayed_work(&ifmgd->tx_tspec_wk,
-				tx_tspec->time_slice_start + HZ - now + 1);
-			break;
-		case TX_TSPEC_ACTION_NONE:
-			/* nothing now */
-			break;
-		}
-	}
-
-	return ret;
-}
-
-void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
-{
-	if (__ieee80211_sta_handle_tspec_ac_params(sdata))
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
-}
-
-static void ieee80211_sta_handle_tspec_ac_params_wk(struct work_struct *work)
-{
-	struct ieee80211_sub_if_data *sdata;
-
-	sdata = container_of(work, struct ieee80211_sub_if_data,
-			     u.mgd.tx_tspec_wk.work);
-	ieee80211_sta_handle_tspec_ac_params(sdata);
-}
-
 /* MLME */
 static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
 				     struct ieee80211_sub_if_data *sdata,
@@ -1811,14 +1663,12 @@
 		params.uapsd = uapsd;
 
 		mlme_dbg(sdata,
-			 "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
+			 "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
 			 queue, aci, acm,
 			 params.aifs, params.cw_min, params.cw_max,
-			 params.txop, params.uapsd,
-			 ifmgd->tx_tspec[queue].downgraded);
+			 params.txop, params.uapsd);
 		sdata->tx_conf[queue] = params;
-		if (!ifmgd->tx_tspec[queue].downgraded &&
-		    drv_conf_tx(local, sdata, queue, &params))
+		if (drv_conf_tx(local, sdata, queue, &params))
 			sdata_err(sdata,
 				  "failed to set TX queue parameters for queue %d\n",
 				  queue);
@@ -2073,7 +1923,6 @@
 	ieee80211_vif_release_channel(sdata);
 
 	sdata->vif.csa_active = false;
-	ifmgd->csa_waiting_bcn = false;
 	if (sdata->csa_block_tx) {
 		ieee80211_wake_vif_queues(local, sdata,
 					  IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -2081,10 +1930,6 @@
 	}
 	mutex_unlock(&local->mtx);
 
-	/* existing TX TSPEC sessions no longer exist */
-	memset(ifmgd->tx_tspec, 0, sizeof(ifmgd->tx_tspec));
-	cancel_delayed_work_sync(&ifmgd->tx_tspec_wk);
-
 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
 }
 
@@ -2137,46 +1982,9 @@
 	mutex_unlock(&local->mtx);
 }
 
-static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
-					   struct ieee80211_hdr *hdr,
-					   u16 tx_time)
-{
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-	u16 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
-	int ac = ieee80211_ac_from_tid(tid);
-	struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
-	unsigned long now = jiffies;
-
-	if (likely(!tx_tspec->admitted_time))
-		return;
-
-	if (time_after(now, tx_tspec->time_slice_start + HZ)) {
-		tx_tspec->consumed_tx_time = 0;
-		tx_tspec->time_slice_start = now;
-
-		if (tx_tspec->downgraded) {
-			tx_tspec->action = TX_TSPEC_ACTION_STOP_DOWNGRADE;
-			schedule_delayed_work(&ifmgd->tx_tspec_wk, 0);
-		}
-	}
-
-	if (tx_tspec->downgraded)
-		return;
-
-	tx_tspec->consumed_tx_time += tx_time;
-
-	if (tx_tspec->consumed_tx_time >= tx_tspec->admitted_time) {
-		tx_tspec->downgraded = true;
-		tx_tspec->action = TX_TSPEC_ACTION_DOWNGRADE;
-		schedule_delayed_work(&ifmgd->tx_tspec_wk, 0);
-	}
-}
-
 void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
-			     struct ieee80211_hdr *hdr, bool ack, u16 tx_time)
+			     struct ieee80211_hdr *hdr, bool ack)
 {
-	ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time);
-
 	if (!ieee80211_is_data(hdr->frame_control))
 	    return;
 
@@ -2231,8 +2039,7 @@
 		else
 			ssid_len = ssid[1];
 
-		ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
-					 ssid + 2, ssid_len, NULL,
+		ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
 					 0, (u32) -1, true, 0,
 					 ifmgd->associated->channel, false);
 		rcu_read_unlock();
@@ -2240,6 +2047,8 @@
 
 	ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
 	run_again(sdata, ifmgd->probe_timeout);
+	if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
+		ieee80211_flush_queues(sdata->local, sdata);
 }
 
 static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
@@ -2268,7 +2077,9 @@
 				     "detected beacon loss from AP (missed %d beacons) - probing\n",
 				     beacon_loss_count);
 
-		ieee80211_cqm_beacon_loss_notify(&sdata->vif, GFP_KERNEL);
+		ieee80211_cqm_rssi_notify(&sdata->vif,
+					  NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
+					  GFP_KERNEL);
 	}
 
 	/*
@@ -2333,7 +2144,7 @@
 	else
 		ssid_len = ssid[1];
 
-	skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid,
+	skb = ieee80211_build_probe_req(sdata, cbss->bssid,
 					(u32) -1, cbss->channel,
 					ssid + 2, ssid_len,
 					NULL, 0, true);
@@ -2360,7 +2171,6 @@
 			       true, frame_buf);
 	mutex_lock(&local->mtx);
 	sdata->vif.csa_active = false;
-	ifmgd->csa_waiting_bcn = false;
 	if (sdata->csa_block_tx) {
 		ieee80211_wake_vif_queues(local, sdata,
 					  IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -2807,9 +2617,6 @@
 	}
 
 	ifmgd->aid = aid;
-	ifmgd->tdls_chan_switch_prohibited =
-		elems.ext_capab && elems.ext_capab_len >= 5 &&
-		(elems.ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED);
 
 	/*
 	 * Some APs are erroneously not including some information in their
@@ -3388,9 +3195,6 @@
 		}
 	}
 
-	if (ifmgd->csa_waiting_bcn)
-		ieee80211_chswitch_post_beacon(sdata);
-
 	if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
 		return;
 	ifmgd->beacon_crc = ncrc;
@@ -3399,7 +3203,6 @@
 	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
 
 	ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
-					 rx_status->device_timestamp,
 					 &elems, true);
 
 	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
@@ -3531,9 +3334,8 @@
 				break;
 
 			ieee80211_sta_process_chanswitch(sdata,
-						 rx_status->mactime,
-						 rx_status->device_timestamp,
-						 &elems, false);
+							 rx_status->mactime,
+							 &elems, false);
 		} else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
 			ies_len = skb->len -
 				  offsetof(struct ieee80211_mgmt,
@@ -3554,9 +3356,8 @@
 				&mgmt->u.action.u.ext_chan_switch.data;
 
 			ieee80211_sta_process_chanswitch(sdata,
-						 rx_status->mactime,
-						 rx_status->device_timestamp,
-						 &elems, false);
+							 rx_status->mactime,
+							 &elems, false);
 		}
 		break;
 	}
@@ -3654,8 +3455,7 @@
 		 * Direct probe is sent to broadcast address as some APs
 		 * will not answer to direct packet in unassociated state.
 		 */
-		ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
-					 ssidie + 2, ssidie[1],
+		ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
 					 NULL, 0, (u32) -1, true, 0,
 					 auth_data->bss->channel, false);
 		rcu_read_unlock();
@@ -3864,12 +3664,11 @@
 	struct ieee80211_sub_if_data *sdata =
 		(struct ieee80211_sub_if_data *) data;
 	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
 	if (local->quiescing)
 		return;
 
-	if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
+	if (sdata->vif.csa_active)
 		return;
 
 	sdata->u.mgd.connection_loss = false;
@@ -3887,7 +3686,7 @@
 	if (local->quiescing)
 		return;
 
-	if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
+	if (sdata->vif.csa_active)
 		return;
 
 	ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
@@ -3999,8 +3798,6 @@
 		    (unsigned long) sdata);
 	setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
 		    (unsigned long) sdata);
-	INIT_DELAYED_WORK(&ifmgd->tx_tspec_wk,
-			  ieee80211_sta_handle_tspec_ac_params_wk);
 
 	ifmgd->flags = 0;
 	ifmgd->powersave = sdata->wdev.ps;
@@ -4012,11 +3809,6 @@
 		ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
 	else
 		ifmgd->req_smps = IEEE80211_SMPS_OFF;
-
-	/* Setup TDLS data */
-	spin_lock_init(&ifmgd->teardown_lock);
-	ifmgd->teardown_skb = NULL;
-	ifmgd->orig_teardown_skb = NULL;
 }
 
 /* scan finished notification */
@@ -4879,13 +4671,6 @@
 	}
 	if (ifmgd->auth_data)
 		ieee80211_destroy_auth_data(sdata, false);
-	spin_lock_bh(&ifmgd->teardown_lock);
-	if (ifmgd->teardown_skb) {
-		kfree_skb(ifmgd->teardown_skb);
-		ifmgd->teardown_skb = NULL;
-		ifmgd->orig_teardown_skb = NULL;
-	}
-	spin_unlock_bh(&ifmgd->teardown_lock);
 	del_timer_sync(&ifmgd->timer);
 	sdata_unlock(sdata);
 }
@@ -4901,13 +4686,3 @@
 	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
 }
 EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
-
-void ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp)
-{
-	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-
-	trace_api_cqm_beacon_loss_notify(sdata->local, sdata);
-
-	cfg80211_cqm_beacon_loss_notify(sdata->dev, gfp);
-}
-EXPORT_SYMBOL(ieee80211_cqm_beacon_loss_notify);
diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c
deleted file mode 100644
index 358d5f9..0000000
--- a/net/mac80211/ocb.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * OCB mode implementation
- *
- * Copyright: (c) 2014 Czech Technical University in Prague
- *            (c) 2014 Volkswagen Group Research
- * Author:    Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
- * Funded by: Volkswagen Group Research
- *
- * 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/delay.h>
-#include <linux/if_ether.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
-#include <net/mac80211.h>
-#include <asm/unaligned.h>
-
-#include "ieee80211_i.h"
-#include "driver-ops.h"
-#include "rate.h"
-
-#define IEEE80211_OCB_HOUSEKEEPING_INTERVAL		(60 * HZ)
-#define IEEE80211_OCB_PEER_INACTIVITY_LIMIT		(240 * HZ)
-#define IEEE80211_OCB_MAX_STA_ENTRIES			128
-
-/**
- * enum ocb_deferred_task_flags - mac80211 OCB deferred tasks
- * @OCB_WORK_HOUSEKEEPING: run the periodic OCB housekeeping tasks
- *
- * These flags are used in @wrkq_flags field of &struct ieee80211_if_ocb
- */
-enum ocb_deferred_task_flags {
-	OCB_WORK_HOUSEKEEPING,
-};
-
-void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
-			     const u8 *bssid, const u8 *addr,
-			     u32 supp_rates)
-{
-	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_chanctx_conf *chanctx_conf;
-	struct ieee80211_supported_band *sband;
-	enum nl80211_bss_scan_width scan_width;
-	struct sta_info *sta;
-	int band;
-
-	/* XXX: Consider removing the least recently used entry and
-	 *      allow new one to be added.
-	 */
-	if (local->num_sta >= IEEE80211_OCB_MAX_STA_ENTRIES) {
-		net_info_ratelimited("%s: No room for a new OCB STA entry %pM\n",
-				     sdata->name, addr);
-		return;
-	}
-
-	ocb_dbg(sdata, "Adding new OCB station %pM\n", addr);
-
-	rcu_read_lock();
-	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-	if (WARN_ON_ONCE(!chanctx_conf)) {
-		rcu_read_unlock();
-		return;
-	}
-	band = chanctx_conf->def.chan->band;
-	scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
-	rcu_read_unlock();
-
-	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
-	if (!sta)
-		return;
-
-	sta->last_rx = jiffies;
-
-	/* Add only mandatory rates for now */
-	sband = local->hw.wiphy->bands[band];
-	sta->sta.supp_rates[band] =
-		ieee80211_mandatory_rates(sband, scan_width);
-
-	spin_lock(&ifocb->incomplete_lock);
-	list_add(&sta->list, &ifocb->incomplete_stations);
-	spin_unlock(&ifocb->incomplete_lock);
-	ieee80211_queue_work(&local->hw, &sdata->work);
-}
-
-static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta)
-	__acquires(RCU)
-{
-	struct ieee80211_sub_if_data *sdata = sta->sdata;
-	u8 addr[ETH_ALEN];
-
-	memcpy(addr, sta->sta.addr, ETH_ALEN);
-
-	ocb_dbg(sdata, "Adding new IBSS station %pM (dev=%s)\n",
-		addr, sdata->name);
-
-	sta_info_move_state(sta, IEEE80211_STA_AUTH);
-	sta_info_move_state(sta, IEEE80211_STA_ASSOC);
-	sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
-
-	rate_control_rate_init(sta);
-
-	/* If it fails, maybe we raced another insertion? */
-	if (sta_info_insert_rcu(sta))
-		return sta_info_get(sdata, addr);
-	return sta;
-}
-
-static void ieee80211_ocb_housekeeping(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-
-	ocb_dbg(sdata, "Running ocb housekeeping\n");
-
-	ieee80211_sta_expire(sdata, IEEE80211_OCB_PEER_INACTIVITY_LIMIT);
-
-	mod_timer(&ifocb->housekeeping_timer,
-		  round_jiffies(jiffies + IEEE80211_OCB_HOUSEKEEPING_INTERVAL));
-}
-
-void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-	struct sta_info *sta;
-
-	if (ifocb->joined != true)
-		return;
-
-	sdata_lock(sdata);
-
-	spin_lock_bh(&ifocb->incomplete_lock);
-	while (!list_empty(&ifocb->incomplete_stations)) {
-		sta = list_first_entry(&ifocb->incomplete_stations,
-				       struct sta_info, list);
-		list_del(&sta->list);
-		spin_unlock_bh(&ifocb->incomplete_lock);
-
-		ieee80211_ocb_finish_sta(sta);
-		rcu_read_unlock();
-		spin_lock_bh(&ifocb->incomplete_lock);
-	}
-	spin_unlock_bh(&ifocb->incomplete_lock);
-
-	if (test_and_clear_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags))
-		ieee80211_ocb_housekeeping(sdata);
-
-	sdata_unlock(sdata);
-}
-
-static void ieee80211_ocb_housekeeping_timer(unsigned long data)
-{
-	struct ieee80211_sub_if_data *sdata = (void *)data;
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-
-	set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
-
-	ieee80211_queue_work(&local->hw, &sdata->work);
-}
-
-void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-
-	setup_timer(&ifocb->housekeeping_timer,
-		    ieee80211_ocb_housekeeping_timer,
-		    (unsigned long)sdata);
-	INIT_LIST_HEAD(&ifocb->incomplete_stations);
-	spin_lock_init(&ifocb->incomplete_lock);
-}
-
-int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
-		       struct ocb_setup *setup)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-	u32 changed = BSS_CHANGED_OCB;
-	int err;
-
-	if (ifocb->joined == true)
-		return -EINVAL;
-
-	sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
-	sdata->smps_mode = IEEE80211_SMPS_OFF;
-	sdata->needed_rx_chains = sdata->local->rx_chains;
-
-	mutex_lock(&sdata->local->mtx);
-	err = ieee80211_vif_use_channel(sdata, &setup->chandef,
-					IEEE80211_CHANCTX_SHARED);
-	mutex_unlock(&sdata->local->mtx);
-	if (err)
-		return err;
-
-	ieee80211_bss_info_change_notify(sdata, changed);
-
-	ifocb->joined = true;
-
-	set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
-	ieee80211_queue_work(&local->hw, &sdata->work);
-
-	netif_carrier_on(sdata->dev);
-	return 0;
-}
-
-int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-	struct ieee80211_local *local = sdata->local;
-	struct sta_info *sta;
-
-	ifocb->joined = false;
-	sta_info_flush(sdata);
-
-	spin_lock_bh(&ifocb->incomplete_lock);
-	while (!list_empty(&ifocb->incomplete_stations)) {
-		sta = list_first_entry(&ifocb->incomplete_stations,
-				       struct sta_info, list);
-		list_del(&sta->list);
-		spin_unlock_bh(&ifocb->incomplete_lock);
-
-		sta_info_free(local, sta);
-		spin_lock_bh(&ifocb->incomplete_lock);
-	}
-	spin_unlock_bh(&ifocb->incomplete_lock);
-
-	netif_carrier_off(sdata->dev);
-	clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_OCB);
-
-	mutex_lock(&sdata->local->mtx);
-	ieee80211_vif_release_channel(sdata);
-	mutex_unlock(&sdata->local->mtx);
-
-	skb_queue_purge(&sdata->skb_queue);
-
-	del_timer_sync(&sdata->u.ocb.housekeeping_timer);
-	/* If the timer fired while we waited for it, it will have
-	 * requeued the work. Now the work will be running again
-	 * but will not rearm the timer again because it checks
-	 * whether we are connected to the network or not -- at this
-	 * point we shouldn't be anymore.
-	 */
-
-	return 0;
-}
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index bc5270e..2c70248 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -385,7 +385,7 @@
 			*rate = alt_rate;
 			return;
 		}
-	} else if (!(rate->flags & IEEE80211_TX_RC_VHT_MCS)) {
+	} else {
 		/* handle legacy rates */
 		if (rate_idx_match_legacy_mask(rate, sband->n_bitrates, mask))
 			return;
@@ -446,10 +446,9 @@
 	 *
 	 * XXX: Should this check all retry rates?
 	 */
-	if (!(rates[0].flags &
-	      (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))) {
+	if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) {
 		u32 basic_rates = vif->bss_conf.basic_rates;
-		s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0;
+		s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0;
 
 		rate = &sband->bitrates[rates[0].idx];
 
@@ -697,7 +696,6 @@
 			   struct ieee80211_sta *pubsta,
 			   struct ieee80211_sta_rates *rates)
 {
-	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
 	struct ieee80211_sta_rates *old;
 
 	/*
@@ -711,8 +709,6 @@
 	if (old)
 		kfree_rcu(old, rcu_head);
 
-	drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta);
-
 	return 0;
 }
 EXPORT_SYMBOL(rate_control_set_rates);
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index a7d5439..d75147c 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -37,35 +37,13 @@
 	struct rate_control_ref *ref = local->rate_ctrl;
 	struct ieee80211_sta *ista = &sta->sta;
 	void *priv_sta = sta->rate_ctrl_priv;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 	if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
 		return;
 
-	if (ref->ops->tx_status)
-		ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
-	else
-		ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
+	ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
 }
 
-static inline void
-rate_control_tx_status_noskb(struct ieee80211_local *local,
-			     struct ieee80211_supported_band *sband,
-			     struct sta_info *sta,
-			     struct ieee80211_tx_info *info)
-{
-	struct rate_control_ref *ref = local->rate_ctrl;
-	struct ieee80211_sta *ista = &sta->sta;
-	void *priv_sta = sta->rate_ctrl_priv;
-
-	if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
-		return;
-
-	if (WARN_ON_ONCE(!ref->ops->tx_status_noskb))
-		return;
-
-	ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
-}
 
 static inline void rate_control_rate_init(struct sta_info *sta)
 {
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 217e379..2cd8250 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -191,7 +191,7 @@
 		 * (1) if any success probabilitiy >= 95%, out of those rates
 		 * choose the maximum throughput rate as max_prob_rate
 		 * (2) if all success probabilities < 95%, the rate with
-		 * highest success probability is chosen as max_prob_rate */
+		 * highest success probability is choosen as max_prob_rate */
 		if (mrs->probability >= MINSTREL_FRAC(95, 100)) {
 			if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp)
 				tmp_prob_rate = i;
@@ -223,10 +223,11 @@
 static void
 minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
 		   struct ieee80211_sta *sta, void *priv_sta,
-		   struct ieee80211_tx_info *info)
+		   struct sk_buff *skb)
 {
 	struct minstrel_priv *mp = priv;
 	struct minstrel_sta_info *mi = priv_sta;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_tx_rate *ar = info->status.rates;
 	int i, ndx;
 	int success;
@@ -673,7 +674,7 @@
 
 const struct rate_control_ops mac80211_minstrel = {
 	.name = "minstrel",
-	.tx_status_noskb = minstrel_tx_status,
+	.tx_status = minstrel_tx_status,
 	.get_rate = minstrel_get_rate,
 	.rate_init = minstrel_rate_init,
 	.alloc = minstrel_alloc,
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 2acab1b..edde723 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -62,14 +62,14 @@
 	unsigned int i, tp, prob, eprob;
 	char *p;
 
-	ms = kmalloc(2048, GFP_KERNEL);
+	ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL);
 	if (!ms)
 		return -ENOMEM;
 
 	file->private_data = ms;
 	p = ms->buf;
-	p += sprintf(p, "rate          tpt eprob *prob"
-			"  *ok(*cum)        ok(      cum)\n");
+	p += sprintf(p, "rate      throughput  ewma prob  this prob  "
+			"this succ/attempt   success    attempts\n");
 	for (i = 0; i < mi->n_rates; i++) {
 		struct minstrel_rate *mr = &mi->r[i];
 		struct minstrel_rate_stats *mrs = &mi->r[i].stats;
@@ -86,8 +86,8 @@
 		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mrs->probability * 1000);
 
-		p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u"
-				" %4u(%4u) %9llu(%9llu)\n",
+		p += sprintf(p, "  %6u.%1u   %6u.%1u   %6u.%1u        "
+				"   %3u(%3u)  %8llu    %8llu\n",
 				tp / 10, tp % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
@@ -102,8 +102,6 @@
 			mi->sample_packets);
 	ms->len = p - ms->buf;
 
-	WARN_ON(ms->len + sizeof(*ms) > 2048);
-
 	return 0;
 }
 
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index e8d8bec..08f80e8 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -10,7 +10,6 @@
 #include <linux/skbuff.h>
 #include <linux/debugfs.h>
 #include <linux/random.h>
-#include <linux/moduleparam.h>
 #include <linux/ieee80211.h>
 #include <net/mac80211.h>
 #include "rate.h"
@@ -35,17 +34,12 @@
 /* Transmit duration for the raw data part of an average sized packet */
 #define MCS_DURATION(streams, sgi, bps) MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps)))
 
-#define BW_20			0
-#define BW_40			1
-#define BW_80			2
-
 /*
  * Define group sort order: HT40 -> SGI -> #streams
  */
 #define GROUP_IDX(_streams, _sgi, _ht40)	\
-	MINSTREL_HT_GROUP_0 +			\
 	MINSTREL_MAX_STREAMS * 2 * _ht40 +	\
-	MINSTREL_MAX_STREAMS * _sgi +	\
+	MINSTREL_MAX_STREAMS * _sgi +		\
 	_streams - 1
 
 /* MCS rate information for an MCS group */
@@ -53,7 +47,6 @@
 	[GROUP_IDX(_streams, _sgi, _ht40)] = {				\
 	.streams = _streams,						\
 	.flags =							\
-		IEEE80211_TX_RC_MCS |					\
 		(_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) |			\
 		(_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0),		\
 	.duration = {							\
@@ -68,47 +61,6 @@
 	}								\
 }
 
-#define VHT_GROUP_IDX(_streams, _sgi, _bw)				\
-	(MINSTREL_VHT_GROUP_0 +						\
-	 MINSTREL_MAX_STREAMS * 2 * (_bw) +				\
-	 MINSTREL_MAX_STREAMS * (_sgi) +				\
-	 (_streams) - 1)
-
-#define BW2VBPS(_bw, r3, r2, r1)					\
-	(_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
-
-#define VHT_GROUP(_streams, _sgi, _bw)					\
-	[VHT_GROUP_IDX(_streams, _sgi, _bw)] = {			\
-	.streams = _streams,						\
-	.flags =							\
-		IEEE80211_TX_RC_VHT_MCS |				\
-		(_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) |			\
-		(_bw == BW_80 ? IEEE80211_TX_RC_80_MHZ_WIDTH :		\
-		 _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0),	\
-	.duration = {							\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw,  117,  54,  26)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw,  234, 108,  52)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw,  351, 162,  78)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw,  468, 216, 104)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw,  702, 324, 156)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw,  936, 432, 208)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw, 1053, 486, 234)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw, 1170, 540, 260)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw, 1404, 648, 312)),		\
-		MCS_DURATION(_streams, _sgi,				\
-			     BW2VBPS(_bw, 1560, 720, 346))		\
-	}								\
-}
-
 #define CCK_DURATION(_bitrate, _short, _len)		\
 	(1000 * (10 /* SIFS */ +			\
 	 (_short ? 72 + 24 : 144 + 48) +		\
@@ -124,161 +76,70 @@
 	CCK_ACK_DURATION(55, _short),			\
 	CCK_ACK_DURATION(110, _short)
 
-#define CCK_GROUP					\
-	[MINSTREL_CCK_GROUP] = {			\
-		.streams = 0,				\
-		.flags = 0,				\
-		.duration = {				\
-			CCK_DURATION_LIST(false),	\
-			CCK_DURATION_LIST(true)		\
-		}					\
+#define CCK_GROUP						\
+	[MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS] = {	\
+		.streams = 0,					\
+		.duration = {					\
+			CCK_DURATION_LIST(false),		\
+			CCK_DURATION_LIST(true)			\
+		}						\
 	}
 
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-static bool minstrel_vht_only = true;
-module_param(minstrel_vht_only, bool, 0644);
-MODULE_PARM_DESC(minstrel_vht_only,
-		 "Use only VHT rates when VHT is supported by sta.");
-#endif
-
 /*
  * To enable sufficiently targeted rate sampling, MCS rates are divided into
  * groups, based on the number of streams and flags (HT40, SGI) that they
  * use.
  *
  * Sortorder has to be fixed for GROUP_IDX macro to be applicable:
- * BW -> SGI -> #streams
+ * HT40 -> SGI -> #streams
  */
 const struct mcs_group minstrel_mcs_groups[] = {
-	MCS_GROUP(1, 0, BW_20),
-	MCS_GROUP(2, 0, BW_20),
+	MCS_GROUP(1, 0, 0),
+	MCS_GROUP(2, 0, 0),
 #if MINSTREL_MAX_STREAMS >= 3
-	MCS_GROUP(3, 0, BW_20),
+	MCS_GROUP(3, 0, 0),
 #endif
 
-	MCS_GROUP(1, 1, BW_20),
-	MCS_GROUP(2, 1, BW_20),
+	MCS_GROUP(1, 1, 0),
+	MCS_GROUP(2, 1, 0),
 #if MINSTREL_MAX_STREAMS >= 3
-	MCS_GROUP(3, 1, BW_20),
+	MCS_GROUP(3, 1, 0),
 #endif
 
-	MCS_GROUP(1, 0, BW_40),
-	MCS_GROUP(2, 0, BW_40),
+	MCS_GROUP(1, 0, 1),
+	MCS_GROUP(2, 0, 1),
 #if MINSTREL_MAX_STREAMS >= 3
-	MCS_GROUP(3, 0, BW_40),
+	MCS_GROUP(3, 0, 1),
 #endif
 
-	MCS_GROUP(1, 1, BW_40),
-	MCS_GROUP(2, 1, BW_40),
+	MCS_GROUP(1, 1, 1),
+	MCS_GROUP(2, 1, 1),
 #if MINSTREL_MAX_STREAMS >= 3
-	MCS_GROUP(3, 1, BW_40),
+	MCS_GROUP(3, 1, 1),
 #endif
 
-	CCK_GROUP,
-
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-	VHT_GROUP(1, 0, BW_20),
-	VHT_GROUP(2, 0, BW_20),
-#if MINSTREL_MAX_STREAMS >= 3
-	VHT_GROUP(3, 0, BW_20),
-#endif
-
-	VHT_GROUP(1, 1, BW_20),
-	VHT_GROUP(2, 1, BW_20),
-#if MINSTREL_MAX_STREAMS >= 3
-	VHT_GROUP(3, 1, BW_20),
-#endif
-
-	VHT_GROUP(1, 0, BW_40),
-	VHT_GROUP(2, 0, BW_40),
-#if MINSTREL_MAX_STREAMS >= 3
-	VHT_GROUP(3, 0, BW_40),
-#endif
-
-	VHT_GROUP(1, 1, BW_40),
-	VHT_GROUP(2, 1, BW_40),
-#if MINSTREL_MAX_STREAMS >= 3
-	VHT_GROUP(3, 1, BW_40),
-#endif
-
-	VHT_GROUP(1, 0, BW_80),
-	VHT_GROUP(2, 0, BW_80),
-#if MINSTREL_MAX_STREAMS >= 3
-	VHT_GROUP(3, 0, BW_80),
-#endif
-
-	VHT_GROUP(1, 1, BW_80),
-	VHT_GROUP(2, 1, BW_80),
-#if MINSTREL_MAX_STREAMS >= 3
-	VHT_GROUP(3, 1, BW_80),
-#endif
-#endif
+	/* must be last */
+	CCK_GROUP
 };
 
+#define MINSTREL_CCK_GROUP	(ARRAY_SIZE(minstrel_mcs_groups) - 1)
+
 static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
 
 static void
 minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
 
 /*
- * Some VHT MCSes are invalid (when Ndbps / Nes is not an integer)
- * e.g for MCS9@20MHzx1Nss: Ndbps=8x52*(5/6) Nes=1
- *
- * Returns the valid mcs map for struct minstrel_mcs_group_data.supported
- */
-static u16
-minstrel_get_valid_vht_rates(int bw, int nss, __le16 mcs_map)
-{
-	u16 mask = 0;
-
-	if (bw == BW_20) {
-		if (nss != 3 && nss != 6)
-			mask = BIT(9);
-	} else if (bw == BW_80) {
-		if (nss == 3 || nss == 7)
-			mask = BIT(6);
-		else if (nss == 6)
-			mask = BIT(9);
-	} else {
-		WARN_ON(bw != BW_40);
-	}
-
-	switch ((le16_to_cpu(mcs_map) >> (2 * (nss - 1))) & 3) {
-	case IEEE80211_VHT_MCS_SUPPORT_0_7:
-		mask |= 0x300;
-		break;
-	case IEEE80211_VHT_MCS_SUPPORT_0_8:
-		mask |= 0x200;
-		break;
-	case IEEE80211_VHT_MCS_SUPPORT_0_9:
-		break;
-	default:
-		mask = 0x3ff;
-	}
-
-	return 0x3ff & ~mask;
-}
-
-/*
  * Look up an MCS group index based on mac80211 rate information
  */
 static int
 minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
 {
-	return GROUP_IDX((rate->idx / 8) + 1,
+	return GROUP_IDX((rate->idx / MCS_GROUP_RATES) + 1,
 			 !!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
 			 !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
 }
 
-static int
-minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
-{
-	return VHT_GROUP_IDX(ieee80211_rate_get_vht_nss(rate),
-			     !!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
-			     !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) +
-			     2*!!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH));
-}
-
 static struct minstrel_rate_stats *
 minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 		      struct ieee80211_tx_rate *rate)
@@ -288,9 +149,6 @@
 	if (rate->flags & IEEE80211_TX_RC_MCS) {
 		group = minstrel_ht_get_group_idx(rate);
 		idx = rate->idx % 8;
-	} else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
-		group = minstrel_vht_get_group_idx(rate);
-		idx = ieee80211_rate_get_vht_mcs(rate);
 	} else {
 		group = MINSTREL_CCK_GROUP;
 
@@ -382,8 +240,8 @@
  * MCS groups, CCK rates do not provide aggregation and are therefore at last.
  */
 static void
-minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index,
-			       u16 *tp_list)
+minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u8 index,
+			       u8 *tp_list)
 {
 	int cur_group, cur_idx, cur_thr, cur_prob;
 	int tmp_group, tmp_idx, tmp_thr, tmp_prob;
@@ -394,16 +252,19 @@
 	cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp;
 	cur_prob = mi->groups[cur_group].rates[cur_idx].probability;
 
-	do {
+	tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
+	tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
+	tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
+	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
+
+	while (j > 0 && (cur_thr > tmp_thr ||
+	      (cur_thr == tmp_thr && cur_prob > tmp_prob))) {
+		j--;
 		tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
 		tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
 		tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
 		tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
-		if (cur_thr < tmp_thr ||
-		    (cur_thr == tmp_thr && cur_prob <= tmp_prob))
-			break;
-		j--;
-	} while (j > 0);
+	}
 
 	if (j < MAX_THR_RATES - 1) {
 		memmove(&tp_list[j + 1], &tp_list[j], (sizeof(*tp_list) *
@@ -417,7 +278,7 @@
  * Find and set the topmost probability rate per sta and per group
  */
 static void
-minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
+minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u8 index)
 {
 	struct minstrel_mcs_group_data *mg;
 	struct minstrel_rate_stats *mr;
@@ -460,8 +321,8 @@
  */
 static void
 minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
-				 u16 tmp_mcs_tp_rate[MAX_THR_RATES],
-				 u16 tmp_cck_tp_rate[MAX_THR_RATES])
+				 u8 tmp_mcs_tp_rate[MAX_THR_RATES],
+				 u8 tmp_cck_tp_rate[MAX_THR_RATES])
 {
 	unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp;
 	int i;
@@ -525,8 +386,8 @@
 	struct minstrel_mcs_group_data *mg;
 	struct minstrel_rate_stats *mr;
 	int group, i, j;
-	u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
-	u16 tmp_cck_tp_rate[MAX_THR_RATES], index;
+	u8 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
+	u8 tmp_cck_tp_rate[MAX_THR_RATES], index;
 
 	if (mi->ampdu_packets > 0) {
 		mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
@@ -624,8 +485,7 @@
 	if (!rate->count)
 		return false;
 
-	if (rate->flags & IEEE80211_TX_RC_MCS ||
-	    rate->flags & IEEE80211_TX_RC_VHT_MCS)
+	if (rate->flags & IEEE80211_TX_RC_MCS)
 		return true;
 
 	return rate->idx == mp->cck_rates[0] ||
@@ -657,7 +517,7 @@
 }
 
 static void
-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
+minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u8 *idx, bool primary)
 {
 	int group, orig_group;
 
@@ -687,9 +547,6 @@
 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
 	u16 tid;
 
-	if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
-		return;
-
 	if (unlikely(!ieee80211_is_data_qos(hdr->frame_control)))
 		return;
 
@@ -700,16 +557,20 @@
 	if (likely(sta->ampdu_mlme.tid_tx[tid]))
 		return;
 
+	if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
+		return;
+
 	ieee80211_start_tx_ba_session(pubsta, tid, 5000);
 }
 
 static void
 minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
                       struct ieee80211_sta *sta, void *priv_sta,
-                      struct ieee80211_tx_info *info)
+                      struct sk_buff *skb)
 {
 	struct minstrel_ht_sta_priv *msp = priv_sta;
 	struct minstrel_ht_sta *mi = &msp->ht;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_tx_rate *ar = info->status.rates;
 	struct minstrel_rate_stats *rate, *rate2;
 	struct minstrel_priv *mp = priv;
@@ -717,8 +578,7 @@
 	int i;
 
 	if (!msp->is_ht)
-		return mac80211_minstrel.tx_status_noskb(priv, sband, sta,
-							 &msp->legacy, info);
+		return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb);
 
 	/* This packet was aggregated but doesn't carry status info */
 	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
@@ -779,6 +639,9 @@
 	if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
 		update = true;
 		minstrel_ht_update_stats(mp, mi);
+		if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
+		    mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
+			minstrel_aggr_check(sta, skb);
 	}
 
 	if (update)
@@ -851,7 +714,7 @@
 	const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
 	struct minstrel_rate_stats *mr;
 	u8 idx;
-	u16 flags = group->flags;
+	u16 flags;
 
 	mr = minstrel_get_ratestats(mi, index);
 	if (!mr->retry_updated)
@@ -867,13 +730,13 @@
 		ratetbl->rate[offset].count_rts = mr->retry_count_rtscts;
 	}
 
-	if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP)
+	if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
 		idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
-	else if (flags & IEEE80211_TX_RC_VHT_MCS)
-		idx = ((group->streams - 1) << 4) |
-		      ((index % MCS_GROUP_RATES) & 0xF);
-	else
+		flags = 0;
+	} else {
 		idx = index % MCS_GROUP_RATES + (group->streams - 1) * 8;
+		flags = IEEE80211_TX_RC_MCS | group->flags;
+	}
 
 	if (offset > 0) {
 		ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
@@ -1020,10 +883,6 @@
 	if (!msp->is_ht)
 		return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc);
 
-	if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
-	    mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
-		minstrel_aggr_check(sta, txrc->skb);
-
 	info->flags |= mi->tx_flags;
 	minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble);
 
@@ -1057,15 +916,13 @@
 	if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
 		int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
 		rate->idx = mp->cck_rates[idx];
-	} else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) {
-		ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES,
-				       sample_group->streams);
-	} else {
-		rate->idx = sample_idx % MCS_GROUP_RATES +
-			    (sample_group->streams - 1) * 8;
+		rate->flags = 0;
+		return;
 	}
 
-	rate->flags = sample_group->flags;
+	rate->idx = sample_idx % MCS_GROUP_RATES +
+		    (sample_group->streams - 1) * 8;
+	rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
 }
 
 static void
@@ -1105,8 +962,6 @@
 	struct minstrel_ht_sta *mi = &msp->ht;
 	struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
 	u16 sta_cap = sta->ht_cap.cap;
-	struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
-	int use_vht;
 	int n_supported = 0;
 	int ack_dur;
 	int stbc;
@@ -1116,14 +971,8 @@
 	if (!sta->ht_cap.ht_supported)
 		goto use_legacy;
 
-	BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB);
-
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-	if (vht_cap->vht_supported)
-		use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0);
-	else
-#endif
-	use_vht = 0;
+	BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) !=
+		MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS + 1);
 
 	msp->is_ht = true;
 	memset(mi, 0, sizeof(*mi));
@@ -1148,28 +997,22 @@
 	}
 	mi->sample_tries = 4;
 
-	/* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */
-	if (!use_vht) {
-		stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
-			IEEE80211_HT_CAP_RX_STBC_SHIFT;
-		mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
+	stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
+		IEEE80211_HT_CAP_RX_STBC_SHIFT;
+	mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
 
-		if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
-			mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
-	}
+	if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
+		mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
 
 	for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
-		u32 gflags = minstrel_mcs_groups[i].flags;
-		int bw, nss;
-
 		mi->groups[i].supported = 0;
 		if (i == MINSTREL_CCK_GROUP) {
 			minstrel_ht_update_cck(mp, mi, sband, sta);
 			continue;
 		}
 
-		if (gflags & IEEE80211_TX_RC_SHORT_GI) {
-			if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+		if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_SHORT_GI) {
+			if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
 				if (!(sta_cap & IEEE80211_HT_CAP_SGI_40))
 					continue;
 			} else {
@@ -1178,51 +1021,17 @@
 			}
 		}
 
-		if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH &&
+		if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH &&
 		    sta->bandwidth < IEEE80211_STA_RX_BW_40)
 			continue;
 
-		nss = minstrel_mcs_groups[i].streams;
-
 		/* Mark MCS > 7 as unsupported if STA is in static SMPS mode */
-		if (sta->smps_mode == IEEE80211_SMPS_STATIC && nss > 1)
+		if (sta->smps_mode == IEEE80211_SMPS_STATIC &&
+		    minstrel_mcs_groups[i].streams > 1)
 			continue;
 
-		/* HT rate */
-		if (gflags & IEEE80211_TX_RC_MCS) {
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-			if (use_vht && minstrel_vht_only)
-				continue;
-#endif
-			mi->groups[i].supported = mcs->rx_mask[nss - 1];
-			if (mi->groups[i].supported)
-				n_supported++;
-			continue;
-		}
-
-		/* VHT rate */
-		if (!vht_cap->vht_supported ||
-		    WARN_ON(!(gflags & IEEE80211_TX_RC_VHT_MCS)) ||
-		    WARN_ON(gflags & IEEE80211_TX_RC_160_MHZ_WIDTH))
-			continue;
-
-		if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH) {
-			if (sta->bandwidth < IEEE80211_STA_RX_BW_80 ||
-			    ((gflags & IEEE80211_TX_RC_SHORT_GI) &&
-			     !(vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80))) {
-				continue;
-			}
-		}
-
-		if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-			bw = BW_40;
-		else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-			bw = BW_80;
-		else
-			bw = BW_20;
-
-		mi->groups[i].supported = minstrel_get_valid_vht_rates(bw, nss,
-				vht_cap->vht_mcs.tx_mcs_map);
+		mi->groups[i].supported =
+			mcs->rx_mask[minstrel_mcs_groups[i].streams - 1];
 
 		if (mi->groups[i].supported)
 			n_supported++;
@@ -1340,7 +1149,7 @@
 
 static const struct rate_control_ops mac80211_minstrel_ht = {
 	.name = "minstrel_ht",
-	.tx_status_noskb = minstrel_ht_tx_status,
+	.tx_status = minstrel_ht_tx_status,
 	.get_rate = minstrel_ht_get_rate,
 	.rate_init = minstrel_ht_rate_init,
 	.rate_update = minstrel_ht_rate_update,
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index a1f74f5..0a76823 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -13,32 +13,10 @@
  * The number of streams can be changed to 2 to reduce code
  * size and memory footprint.
  */
-#define MINSTREL_MAX_STREAMS		3
-#define MINSTREL_HT_STREAM_GROUPS	4 /* BW(=2) * SGI(=2) */
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-#define MINSTREL_VHT_STREAM_GROUPS	6 /* BW(=3) * SGI(=2) */
-#else
-#define MINSTREL_VHT_STREAM_GROUPS	0
-#endif
+#define MINSTREL_MAX_STREAMS	3
+#define MINSTREL_STREAM_GROUPS	4
 
-#define MINSTREL_HT_GROUPS_NB	(MINSTREL_MAX_STREAMS *		\
-				 MINSTREL_HT_STREAM_GROUPS)
-#define MINSTREL_VHT_GROUPS_NB	(MINSTREL_MAX_STREAMS *		\
-				 MINSTREL_VHT_STREAM_GROUPS)
-#define MINSTREL_CCK_GROUPS_NB	1
-#define MINSTREL_GROUPS_NB	(MINSTREL_HT_GROUPS_NB +	\
-				 MINSTREL_VHT_GROUPS_NB +	\
-				 MINSTREL_CCK_GROUPS_NB)
-
-#define MINSTREL_HT_GROUP_0	0
-#define MINSTREL_CCK_GROUP	(MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB)
-#define MINSTREL_VHT_GROUP_0	(MINSTREL_CCK_GROUP + 1)
-
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-#define MCS_GROUP_RATES		10
-#else
-#define MCS_GROUP_RATES		8
-#endif
+#define MCS_GROUP_RATES	8
 
 struct mcs_group {
 	u32 flags;
@@ -53,11 +31,11 @@
 	u8 column;
 
 	/* bitfield of supported MCS rates of this group */
-	u16 supported;
+	u8 supported;
 
 	/* sorted rate set within a MCS group*/
-	u16 max_group_tp_rate[MAX_THR_RATES];
-	u16 max_group_prob_rate;
+	u8 max_group_tp_rate[MAX_THR_RATES];
+	u8 max_group_prob_rate;
 
 	/* MCS rate statistics */
 	struct minstrel_rate_stats rates[MCS_GROUP_RATES];
@@ -74,8 +52,8 @@
 	unsigned int avg_ampdu_len;
 
 	/* overall sorted rate set */
-	u16 max_tp_rate[MAX_THR_RATES];
-	u16 max_prob_rate;
+	u8 max_tp_rate[MAX_THR_RATES];
+	u8 max_prob_rate;
 
 	/* time of last status update */
 	unsigned long stats_update;
@@ -102,7 +80,7 @@
 	u8 cck_supported_short;
 
 	/* MCS rate group info and statistics */
-	struct minstrel_mcs_group_data groups[MINSTREL_GROUPS_NB];
+	struct minstrel_mcs_group_data groups[MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS + 1];
 };
 
 struct minstrel_ht_sta_priv {
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 20c676b..a72ad46 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -18,23 +18,19 @@
 static char *
 minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
 {
+	unsigned int max_mcs = MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS;
 	const struct mcs_group *mg;
 	unsigned int j, tp, prob, eprob;
 	char htmode = '2';
 	char gimode = 'L';
-	u32 gflags;
 
 	if (!mi->groups[i].supported)
 		return p;
 
 	mg = &minstrel_mcs_groups[i];
-	gflags = mg->flags;
-
-	if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+	if (mg->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
 		htmode = '4';
-	else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-		htmode = '8';
-	if (gflags & IEEE80211_TX_RC_SHORT_GI)
+	if (mg->flags & IEEE80211_TX_RC_SHORT_GI)
 		gimode = 'S';
 
 	for (j = 0; j < MCS_GROUP_RATES; j++) {
@@ -45,12 +41,10 @@
 		if (!(mi->groups[i].supported & BIT(j)))
 			continue;
 
-		if (gflags & IEEE80211_TX_RC_MCS)
-			p += sprintf(p, " HT%c0/%cGI ", htmode, gimode);
-		else if (gflags & IEEE80211_TX_RC_VHT_MCS)
-			p += sprintf(p, "VHT%c0/%cGI ", htmode, gimode);
+		if (i == max_mcs)
+			p += sprintf(p, "CCK/%cP   ", j < 4 ? 'L' : 'S');
 		else
-			p += sprintf(p, " CCK/%cP   ", j < 4 ? 'L' : 'S');
+			p += sprintf(p, "HT%c0/%cGI ", htmode, gimode);
 
 		*(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' ';
 		*(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' ';
@@ -58,22 +52,19 @@
 		*(p++) = (idx == mi->max_tp_rate[3]) ? 'D' : ' ';
 		*(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
 
-		if (gflags & IEEE80211_TX_RC_MCS) {
-			p += sprintf(p, " MCS%-2u ", (mg->streams - 1) * 8 + j);
-		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
-			p += sprintf(p, " MCS%-1u/%1u", j, mg->streams);
-		} else {
+		if (i == max_mcs) {
 			int r = bitrates[j % 4];
-
-			p += sprintf(p, " %2u.%1uM ", r / 10, r % 10);
+			p += sprintf(p, " %2u.%1uM", r / 10, r % 10);
+		} else {
+			p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j);
 		}
 
 		tp = mr->cur_tp / 10;
 		prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
 		eprob = MINSTREL_TRUNC(mr->probability * 1000);
 
-		p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u "
-				"%3u %4u(%4u) %9llu(%9llu)\n",
+		p += sprintf(p, "      %6u.%1u   %6u.%1u    %6u.%1u    "
+				"%3u            %3u(%3u)  %8llu    %8llu\n",
 				tp / 10, tp % 10,
 				eprob / 10, eprob % 10,
 				prob / 10, prob % 10,
@@ -94,6 +85,7 @@
 	struct minstrel_ht_sta *mi = &msp->ht;
 	struct minstrel_debugfs_info *ms;
 	unsigned int i;
+	unsigned int max_mcs = MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS;
 	char *p;
 	int ret;
 
@@ -104,19 +96,17 @@
 		return ret;
 	}
 
-	ms = kmalloc(32768, GFP_KERNEL);
+	ms = kmalloc(sizeof(*ms) + 8192, GFP_KERNEL);
 	if (!ms)
 		return -ENOMEM;
 
 	file->private_data = ms;
 	p = ms->buf;
-	p += sprintf(p, " type           rate      tpt eprob *prob "
-			"ret  *ok(*cum)        ok(      cum)\n");
+	p += sprintf(p, "type           rate     throughput  ewma prob   "
+		     "this prob  retry   this succ/attempt   success    attempts\n");
 
-	p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
-	for (i = 0; i < MINSTREL_CCK_GROUP; i++)
-		p = minstrel_ht_stats_dump(mi, i, p);
-	for (i++; i < ARRAY_SIZE(mi->groups); i++)
+	p = minstrel_ht_stats_dump(mi, max_mcs, p);
+	for (i = 0; i < max_mcs; i++)
 		p = minstrel_ht_stats_dump(mi, i, p);
 
 	p += sprintf(p, "\nTotal packet count::    ideal %d      "
@@ -128,8 +118,6 @@
 		MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
 	ms->len = p - ms->buf;
 
-	WARN_ON(ms->len + sizeof(*ms) > 32768);
-
 	return nonseekable_open(inode, file);
 }
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7560231..21d7259 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -39,8 +39,7 @@
  * only useful for monitoring.
  */
 static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
-					   struct sk_buff *skb,
-					   unsigned int rtap_vendor_space)
+					   struct sk_buff *skb)
 {
 	if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
 		if (likely(skb->len > FCS_LEN))
@@ -53,25 +52,20 @@
 		}
 	}
 
-	__pskb_pull(skb, rtap_vendor_space);
-
 	return skb;
 }
 
-static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len,
-				     unsigned int rtap_vendor_space)
+static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len)
 {
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-	struct ieee80211_hdr *hdr;
-
-	hdr = (void *)(skb->data + rtap_vendor_space);
+	struct ieee80211_hdr *hdr = (void *)skb->data;
 
 	if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
 			    RX_FLAG_FAILED_PLCP_CRC |
 			    RX_FLAG_AMPDU_IS_ZEROLEN))
 		return true;
 
-	if (unlikely(skb->len < 16 + present_fcs_len + rtap_vendor_space))
+	if (unlikely(skb->len < 16 + present_fcs_len))
 		return true;
 
 	if (ieee80211_is_ctl(hdr->frame_control) &&
@@ -83,9 +77,8 @@
 }
 
 static int
-ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
-			     struct ieee80211_rx_status *status,
-			     struct sk_buff *skb)
+ieee80211_rx_radiotap_space(struct ieee80211_local *local,
+			    struct ieee80211_rx_status *status)
 {
 	int len;
 
@@ -128,21 +121,6 @@
 		len += 2 * hweight8(status->chains);
 	}
 
-	if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
-		struct ieee80211_vendor_radiotap *rtap = (void *)skb->data;
-
-		/* vendor presence bitmap */
-		len += 4;
-		/* alignment for fixed 6-byte vendor data header */
-		len = ALIGN(len, 2);
-		/* vendor data header */
-		len += 6;
-		if (WARN_ON(rtap->align == 0))
-			rtap->align = 1;
-		len = ALIGN(len, rtap->align);
-		len += rtap->len + rtap->pad;
-	}
-
 	return len;
 }
 
@@ -166,20 +144,13 @@
 	u16 channel_flags = 0;
 	int mpdulen, chain;
 	unsigned long chains = status->chains;
-	struct ieee80211_vendor_radiotap rtap = {};
-
-	if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
-		rtap = *(struct ieee80211_vendor_radiotap *)skb->data;
-		/* rtap.len and rtap.pad are undone immediately */
-		skb_pull(skb, sizeof(rtap) + rtap.len + rtap.pad);
-	}
 
 	mpdulen = skb->len;
 	if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)))
 		mpdulen += FCS_LEN;
 
 	rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
-	memset(rthdr, 0, rtap_len - rtap.len - rtap.pad);
+	memset(rthdr, 0, rtap_len);
 	it_present = &rthdr->it_present;
 
 	/* radiotap header, set always present flags */
@@ -201,14 +172,6 @@
 				 BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
 	}
 
-	if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
-		it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
-				  BIT(IEEE80211_RADIOTAP_EXT);
-		put_unaligned_le32(it_present_val, it_present);
-		it_present++;
-		it_present_val = rtap.present;
-	}
-
 	put_unaligned_le32(it_present_val, it_present);
 
 	pos = (void *)(it_present + 1);
@@ -403,22 +366,6 @@
 		*pos++ = status->chain_signal[chain];
 		*pos++ = chain;
 	}
-
-	if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
-		/* ensure 2 byte alignment for the vendor field as required */
-		if ((pos - (u8 *)rthdr) & 1)
-			*pos++ = 0;
-		*pos++ = rtap.oui[0];
-		*pos++ = rtap.oui[1];
-		*pos++ = rtap.oui[2];
-		*pos++ = rtap.subns;
-		put_unaligned_le16(rtap.len, pos);
-		pos += 2;
-		/* align the actual payload as requested */
-		while ((pos - (u8 *)rthdr) & (rtap.align - 1))
-			*pos++ = 0;
-		/* data (and possible padding) already follows */
-	}
 }
 
 /*
@@ -432,17 +379,10 @@
 {
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
 	struct ieee80211_sub_if_data *sdata;
-	int rt_hdrlen, needed_headroom;
+	int needed_headroom;
 	struct sk_buff *skb, *skb2;
 	struct net_device *prev_dev = NULL;
 	int present_fcs_len = 0;
-	unsigned int rtap_vendor_space = 0;
-
-	if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) {
-		struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data;
-
-		rtap_vendor_space = sizeof(*rtap) + rtap->len + rtap->pad;
-	}
 
 	/*
 	 * First, we may need to make a copy of the skb because
@@ -456,27 +396,25 @@
 	if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
 		present_fcs_len = FCS_LEN;
 
-	/* ensure hdr->frame_control and vendor radiotap data are in skb head */
-	if (!pskb_may_pull(origskb, 2 + rtap_vendor_space)) {
+	/* ensure hdr->frame_control is in skb head */
+	if (!pskb_may_pull(origskb, 2)) {
 		dev_kfree_skb(origskb);
 		return NULL;
 	}
 
 	if (!local->monitors) {
-		if (should_drop_frame(origskb, present_fcs_len,
-				      rtap_vendor_space)) {
+		if (should_drop_frame(origskb, present_fcs_len)) {
 			dev_kfree_skb(origskb);
 			return NULL;
 		}
 
-		return remove_monitor_info(local, origskb, rtap_vendor_space);
+		return remove_monitor_info(local, origskb);
 	}
 
 	/* room for the radiotap header based on driver features */
-	rt_hdrlen = ieee80211_rx_radiotap_hdrlen(local, status, origskb);
-	needed_headroom = rt_hdrlen - rtap_vendor_space;
+	needed_headroom = ieee80211_rx_radiotap_space(local, status);
 
-	if (should_drop_frame(origskb, present_fcs_len, rtap_vendor_space)) {
+	if (should_drop_frame(origskb, present_fcs_len)) {
 		/* only need to expand headroom if necessary */
 		skb = origskb;
 		origskb = NULL;
@@ -500,15 +438,15 @@
 		 */
 		skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC);
 
-		origskb = remove_monitor_info(local, origskb,
-					      rtap_vendor_space);
+		origskb = remove_monitor_info(local, origskb);
 
 		if (!skb)
 			return origskb;
 	}
 
 	/* prepend radiotap information */
-	ieee80211_add_rx_radiotap_header(local, skb, rate, rt_hdrlen, true);
+	ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
+					 true);
 
 	skb_reset_mac_header(skb);
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1047,7 +985,7 @@
 }
 
 static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
+ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
@@ -1056,16 +994,10 @@
 	 * Drop duplicate 802.11 retransmissions
 	 * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
 	 */
-
-	if (rx->skb->len < 24)
-		return RX_CONTINUE;
-
-	if (ieee80211_is_ctl(hdr->frame_control) ||
-	    ieee80211_is_qos_nullfunc(hdr->frame_control) ||
-	    is_multicast_ether_addr(hdr->addr1))
-		return RX_CONTINUE;
-
-	if (rx->sta) {
+	if (rx->skb->len >= 24 && rx->sta &&
+	    !ieee80211_is_ctl(hdr->frame_control) &&
+	    !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
+	    !is_multicast_ether_addr(hdr->addr1)) {
 		if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
 			     rx->sta->last_seq_ctrl[rx->seqno_idx] ==
 			     hdr->seq_ctrl)) {
@@ -1079,14 +1011,6 @@
 		}
 	}
 
-	return RX_CONTINUE;
-}
-
-static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
-{
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-
 	if (unlikely(rx->skb->len < 16)) {
 		I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
 		return RX_DROP_MONITOR;
@@ -1108,7 +1032,6 @@
 		      ieee80211_is_pspoll(hdr->frame_control)) &&
 		     rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
 		     rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
-		     rx->sdata->vif.type != NL80211_IFTYPE_OCB &&
 		     (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
 		/*
 		 * accept port control frames from the AP even when it's not
@@ -1349,12 +1272,6 @@
 				sta->last_rx_rate_vht_nss = status->vht_nss;
 			}
 		}
-	} else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
-		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
-						NL80211_IFTYPE_OCB);
-		/* OCB uses wild-card BSSID */
-		if (is_broadcast_ether_addr(bssid))
-			sta->last_rx = jiffies;
 	} else if (!is_multicast_ether_addr(hdr->addr1)) {
 		/*
 		 * Mesh beacons will update last_rx when if they are found to
@@ -1761,14 +1678,11 @@
 	sc = le16_to_cpu(hdr->seq_ctrl);
 	frag = sc & IEEE80211_SCTL_FRAG;
 
-	if (is_multicast_ether_addr(hdr->addr1)) {
-		rx->local->dot11MulticastReceivedFrameCount++;
-		goto out_no_led;
-	}
-
-	if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
+	if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
+		   is_multicast_ether_addr(hdr->addr1))) {
+		/* not fragmented */
 		goto out;
-
+	}
 	I802_DEBUG_INC(rx->local->rx_handlers_fragments);
 
 	if (skb_linearize(rx->skb))
@@ -1859,10 +1773,12 @@
 	status->rx_flags |= IEEE80211_RX_FRAGMENTED;
 
  out:
-	ieee80211_led_rx(rx->local);
- out_no_led:
 	if (rx->sta)
 		rx->sta->rx_packets++;
+	if (is_multicast_ether_addr(hdr->addr1))
+		rx->local->dot11MulticastReceivedFrameCount++;
+	else
+		ieee80211_led_rx(rx->local);
 	return RX_CONTINUE;
 }
 
@@ -2345,27 +2261,6 @@
 	if (!ieee80211_frame_allowed(rx, fc))
 		return RX_DROP_MONITOR;
 
-	/* directly handle TDLS channel switch requests/responses */
-	if (unlikely(((struct ethhdr *)rx->skb->data)->h_proto ==
-						cpu_to_be16(ETH_P_TDLS))) {
-		struct ieee80211_tdls_data *tf = (void *)rx->skb->data;
-
-		if (pskb_may_pull(rx->skb,
-				  offsetof(struct ieee80211_tdls_data, u)) &&
-		    tf->payload_type == WLAN_TDLS_SNAP_RFTYPE &&
-		    tf->category == WLAN_CATEGORY_TDLS &&
-		    (tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST ||
-		     tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE)) {
-			rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TDLS_CHSW;
-			skb_queue_tail(&sdata->skb_queue, rx->skb);
-			ieee80211_queue_work(&rx->local->hw, &sdata->work);
-			if (rx->sta)
-				rx->sta->rx_packets++;
-
-			return RX_QUEUED;
-		}
-	}
-
 	if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
 	    unlikely(port_control) && sdata->bss) {
 		sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
@@ -2936,7 +2831,6 @@
 
 	if (!ieee80211_vif_is_mesh(&sdata->vif) &&
 	    sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-	    sdata->vif.type != NL80211_IFTYPE_OCB &&
 	    sdata->vif.type != NL80211_IFTYPE_STATION)
 		return RX_DROP_MONITOR;
 
@@ -3001,10 +2895,8 @@
 	if (!local->cooked_mntrs)
 		goto out_free_skb;
 
-	/* vendor data is long removed here */
-	status->flag &= ~RX_FLAG_RADIOTAP_VENDOR_DATA;
 	/* room for the radiotap header based on driver features */
-	needed_headroom = ieee80211_rx_radiotap_hdrlen(local, status, skb);
+	needed_headroom = ieee80211_rx_radiotap_space(local, status);
 
 	if (skb_headroom(skb) < needed_headroom &&
 	    pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC))
@@ -3157,7 +3049,6 @@
 			goto rxh_next;  \
 	} while (0);
 
-	CALL_RXH(ieee80211_rx_h_check_dup)
 	CALL_RXH(ieee80211_rx_h_check)
 
 	ieee80211_rx_reorder_ampdu(rx, &reorder_release);
@@ -3250,33 +3141,6 @@
 						 BIT(rate_idx));
 		}
 		break;
-	case NL80211_IFTYPE_OCB:
-		if (!bssid)
-			return false;
-		if (ieee80211_is_beacon(hdr->frame_control)) {
-			return false;
-		} else if (!is_broadcast_ether_addr(bssid)) {
-			ocb_dbg(sdata, "BSSID mismatch in OCB mode!\n");
-			return false;
-		} else if (!multicast &&
-			   !ether_addr_equal(sdata->dev->dev_addr,
-					     hdr->addr1)) {
-			/* if we are in promisc mode we also accept
-			 * packets not destined for us
-			 */
-			if (!(sdata->dev->flags & IFF_PROMISC))
-				return false;
-			rx->flags &= ~IEEE80211_RX_RA_MATCH;
-		} else if (!rx->sta) {
-			int rate_idx;
-			if (status->flag & RX_FLAG_HT)
-				rate_idx = 0; /* TODO: HT rates */
-			else
-				rate_idx = status->rate_idx;
-			ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2,
-						BIT(rate_idx));
-		}
-		break;
 	case NL80211_IFTYPE_MESH_POINT:
 		if (!multicast &&
 		    !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index ae84267..af0d094 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -184,21 +184,9 @@
 		return;
 
 	if (ieee80211_is_probe_resp(mgmt->frame_control)) {
-		struct cfg80211_scan_request *scan_req;
-		struct cfg80211_sched_scan_request *sched_scan_req;
-
-		scan_req = rcu_dereference(local->scan_req);
-		sched_scan_req = rcu_dereference(local->sched_scan_req);
-
-		/* ignore ProbeResp to foreign address unless scanning
-		 * with randomised address
-		 */
-		if (!(sdata1 &&
-		      (ether_addr_equal(mgmt->da, sdata1->vif.addr) ||
-		       scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) &&
-		    !(sdata2 &&
-		      (ether_addr_equal(mgmt->da, sdata2->vif.addr) ||
-		       sched_scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)))
+		/* ignore ProbeResp to foreign address */
+		if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) &&
+		    (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr)))
 			return;
 
 		elements = mgmt->u.probe_resp.variable;
@@ -246,14 +234,11 @@
 /* return false if no more work */
 static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 {
-	struct cfg80211_scan_request *req;
+	struct cfg80211_scan_request *req = local->scan_req;
 	struct cfg80211_chan_def chandef;
 	u8 bands_used = 0;
 	int i, ielen, n_chans;
 
-	req = rcu_dereference_protected(local->scan_req,
-					lockdep_is_held(&local->mtx));
-
 	if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
 		return false;
 
@@ -296,9 +281,6 @@
 					 bands_used, req->rates, &chandef);
 	local->hw_scan_req->req.ie_len = ielen;
 	local->hw_scan_req->req.no_cck = req->no_cck;
-	ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr);
-	ether_addr_copy(local->hw_scan_req->req.mac_addr_mask,
-			req->mac_addr_mask);
 
 	return true;
 }
@@ -308,8 +290,6 @@
 	struct ieee80211_local *local = hw_to_local(hw);
 	bool hw_scan = local->ops->hw_scan;
 	bool was_scanning = local->scanning;
-	struct cfg80211_scan_request *scan_req;
-	struct ieee80211_sub_if_data *scan_sdata;
 
 	lockdep_assert_held(&local->mtx);
 
@@ -342,15 +322,9 @@
 	kfree(local->hw_scan_req);
 	local->hw_scan_req = NULL;
 
-	scan_req = rcu_dereference_protected(local->scan_req,
-					     lockdep_is_held(&local->mtx));
-
-	if (scan_req != local->int_scan_req)
-		cfg80211_scan_done(scan_req, aborted);
-	RCU_INIT_POINTER(local->scan_req, NULL);
-
-	scan_sdata = rcu_dereference_protected(local->scan_sdata,
-					       lockdep_is_held(&local->mtx));
+	if (local->scan_req != local->int_scan_req)
+		cfg80211_scan_done(local->scan_req, aborted);
+	local->scan_req = NULL;
 	RCU_INIT_POINTER(local->scan_sdata, NULL);
 
 	local->scanning = 0;
@@ -361,7 +335,7 @@
 
 	if (!hw_scan) {
 		ieee80211_configure_filter(local);
-		drv_sw_scan_complete(local, scan_sdata);
+		drv_sw_scan_complete(local);
 		ieee80211_offchannel_return(local);
 	}
 
@@ -387,8 +361,7 @@
 }
 EXPORT_SYMBOL(ieee80211_scan_completed);
 
-static int ieee80211_start_sw_scan(struct ieee80211_local *local,
-				   struct ieee80211_sub_if_data *sdata)
+static int ieee80211_start_sw_scan(struct ieee80211_local *local)
 {
 	/* Software scan is not supported in multi-channel cases */
 	if (local->use_chanctx)
@@ -407,7 +380,7 @@
 	 * nullfunc frames and probe requests will be dropped in
 	 * ieee80211_tx_h_check_assoc().
 	 */
-	drv_sw_scan_start(local, sdata, local->scan_addr);
+	drv_sw_scan_start(local);
 
 	local->leave_oper_channel_time = jiffies;
 	local->next_scan_state = SCAN_DECISION;
@@ -467,26 +440,23 @@
 {
 	int i;
 	struct ieee80211_sub_if_data *sdata;
-	struct cfg80211_scan_request *scan_req;
 	enum ieee80211_band band = local->hw.conf.chandef.chan->band;
 	u32 tx_flags;
 
-	scan_req = rcu_dereference_protected(local->scan_req,
-					     lockdep_is_held(&local->mtx));
-
 	tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
-	if (scan_req->no_cck)
+	if (local->scan_req->no_cck)
 		tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
 
 	sdata = rcu_dereference_protected(local->scan_sdata,
 					  lockdep_is_held(&local->mtx));
 
-	for (i = 0; i < scan_req->n_ssids; i++)
+	for (i = 0; i < local->scan_req->n_ssids; i++)
 		ieee80211_send_probe_req(
-			sdata, local->scan_addr, NULL,
-			scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len,
-			scan_req->ie, scan_req->ie_len,
-			scan_req->rates[band], false,
+			sdata, NULL,
+			local->scan_req->ssids[i].ssid,
+			local->scan_req->ssids[i].ssid_len,
+			local->scan_req->ie, local->scan_req->ie_len,
+			local->scan_req->rates[band], false,
 			tx_flags, local->hw.conf.chandef.chan, true);
 
 	/*
@@ -510,7 +480,7 @@
 
 	if (!ieee80211_can_scan(local, sdata)) {
 		/* wait for the work to finish/time out */
-		rcu_assign_pointer(local->scan_req, req);
+		local->scan_req = req;
 		rcu_assign_pointer(local->scan_sdata, sdata);
 		return 0;
 	}
@@ -560,16 +530,9 @@
 		 */
 	}
 
-	rcu_assign_pointer(local->scan_req, req);
+	local->scan_req = req;
 	rcu_assign_pointer(local->scan_sdata, sdata);
 
-	if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
-		get_random_mask_addr(local->scan_addr,
-				     req->mac_addr,
-				     req->mac_addr_mask);
-	else
-		memcpy(local->scan_addr, sdata->vif.addr, ETH_ALEN);
-
 	if (local->ops->hw_scan) {
 		__set_bit(SCAN_HW_SCANNING, &local->scanning);
 	} else if ((req->n_channels == 1) &&
@@ -586,7 +549,7 @@
 
 		/* Notify driver scan is starting, keep order of operations
 		 * same as normal software scan, in case that matters. */
-		drv_sw_scan_start(local, sdata, local->scan_addr);
+		drv_sw_scan_start(local);
 
 		ieee80211_configure_filter(local); /* accept probe-responses */
 
@@ -595,7 +558,7 @@
 
 		if ((req->channels[0]->flags &
 		     IEEE80211_CHAN_NO_IR) ||
-		    !req->n_ssids) {
+		    !local->scan_req->n_ssids) {
 			next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
 		} else {
 			ieee80211_scan_state_send_probe(local, &next_delay);
@@ -616,9 +579,8 @@
 	if (local->ops->hw_scan) {
 		WARN_ON(!ieee80211_prep_hw_scan(local));
 		rc = drv_hw_scan(local, sdata, local->hw_scan_req);
-	} else {
-		rc = ieee80211_start_sw_scan(local, sdata);
-	}
+	} else
+		rc = ieee80211_start_sw_scan(local);
 
 	if (rc) {
 		kfree(local->hw_scan_req);
@@ -655,7 +617,6 @@
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_channel *next_chan;
 	enum mac80211_scan_state next_scan_state;
-	struct cfg80211_scan_request *scan_req;
 
 	/*
 	 * check if at least one STA interface is associated,
@@ -680,10 +641,7 @@
 	}
 	mutex_unlock(&local->iflist_mtx);
 
-	scan_req = rcu_dereference_protected(local->scan_req,
-					     lockdep_is_held(&local->mtx));
-
-	next_chan = scan_req->channels[local->scan_channel_idx];
+	next_chan = local->scan_req->channels[local->scan_channel_idx];
 
 	/*
 	 * we're currently scanning a different channel, let's
@@ -698,7 +656,7 @@
 				 local->leave_oper_channel_time + HZ / 8);
 
 	if (associated && !tx_empty) {
-		if (scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+		if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
 			next_scan_state = SCAN_ABORT;
 		else
 			next_scan_state = SCAN_SUSPEND;
@@ -719,18 +677,14 @@
 	int skip;
 	struct ieee80211_channel *chan;
 	enum nl80211_bss_scan_width oper_scan_width;
-	struct cfg80211_scan_request *scan_req;
-
-	scan_req = rcu_dereference_protected(local->scan_req,
-					     lockdep_is_held(&local->mtx));
 
 	skip = 0;
-	chan = scan_req->channels[local->scan_channel_idx];
+	chan = local->scan_req->channels[local->scan_channel_idx];
 
 	local->scan_chandef.chan = chan;
 	local->scan_chandef.center_freq1 = chan->center_freq;
 	local->scan_chandef.center_freq2 = 0;
-	switch (scan_req->scan_width) {
+	switch (local->scan_req->scan_width) {
 	case NL80211_BSS_CHAN_WIDTH_5:
 		local->scan_chandef.width = NL80211_CHAN_WIDTH_5;
 		break;
@@ -744,7 +698,7 @@
 		oper_scan_width = cfg80211_chandef_to_scan_width(
 					&local->_oper_chandef);
 		if (chan == local->_oper_chandef.chan &&
-		    oper_scan_width == scan_req->scan_width)
+		    oper_scan_width == local->scan_req->scan_width)
 			local->scan_chandef = local->_oper_chandef;
 		else
 			local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
@@ -773,7 +727,8 @@
 	 *
 	 * In any case, it is not necessary for a passive scan.
 	 */
-	if (chan->flags & IEEE80211_CHAN_NO_IR || !scan_req->n_ssids) {
+	if (chan->flags & IEEE80211_CHAN_NO_IR ||
+	    !local->scan_req->n_ssids) {
 		*next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
 		local->next_scan_state = SCAN_DECISION;
 		return;
@@ -822,7 +777,6 @@
 	struct ieee80211_local *local =
 		container_of(work, struct ieee80211_local, scan_work.work);
 	struct ieee80211_sub_if_data *sdata;
-	struct cfg80211_scan_request *scan_req;
 	unsigned long next_delay = 0;
 	bool aborted;
 
@@ -830,8 +784,6 @@
 
 	sdata = rcu_dereference_protected(local->scan_sdata,
 					  lockdep_is_held(&local->mtx));
-	scan_req = rcu_dereference_protected(local->scan_req,
-					     lockdep_is_held(&local->mtx));
 
 	/* When scanning on-channel, the first-callback means completed. */
 	if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
@@ -844,19 +796,20 @@
 		goto out_complete;
 	}
 
-	if (!sdata || !scan_req)
+	if (!sdata || !local->scan_req)
 		goto out;
 
-	if (!local->scanning) {
+	if (local->scan_req && !local->scanning) {
+		struct cfg80211_scan_request *req = local->scan_req;
 		int rc;
 
-		RCU_INIT_POINTER(local->scan_req, NULL);
+		local->scan_req = NULL;
 		RCU_INIT_POINTER(local->scan_sdata, NULL);
 
-		rc = __ieee80211_start_scan(sdata, scan_req);
+		rc = __ieee80211_start_scan(sdata, req);
 		if (rc) {
 			/* need to complete scan in cfg80211 */
-			rcu_assign_pointer(local->scan_req, scan_req);
+			local->scan_req = req;
 			aborted = true;
 			goto out_complete;
 		} else
@@ -876,7 +829,7 @@
 		switch (local->next_scan_state) {
 		case SCAN_DECISION:
 			/* if no more bands/channels left, complete scan */
-			if (local->scan_channel_idx >= scan_req->n_channels) {
+			if (local->scan_channel_idx >= local->scan_req->n_channels) {
 				aborted = false;
 				goto out_complete;
 			}
@@ -1090,7 +1043,7 @@
 	ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
 	if (ret == 0) {
 		rcu_assign_pointer(local->sched_scan_sdata, sdata);
-		rcu_assign_pointer(local->sched_scan_req, req);
+		local->sched_scan_req = req;
 	}
 
 	kfree(ie);
@@ -1099,7 +1052,7 @@
 	if (ret) {
 		/* Clean in case of failure after HW restart or upon resume. */
 		RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
-		RCU_INIT_POINTER(local->sched_scan_req, NULL);
+		local->sched_scan_req = NULL;
 	}
 
 	return ret;
@@ -1137,7 +1090,7 @@
 	}
 
 	/* We don't want to restart sched scan anymore. */
-	RCU_INIT_POINTER(local->sched_scan_req, NULL);
+	local->sched_scan_req = NULL;
 
 	if (rcu_access_pointer(local->sched_scan_sdata)) {
 		ret = drv_sched_scan_stop(local, sdata);
@@ -1172,7 +1125,7 @@
 	RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
 
 	/* If sched scan was aborted by the driver. */
-	RCU_INIT_POINTER(local->sched_scan_req, NULL);
+	local->sched_scan_req = NULL;
 
 	mutex_unlock(&local->mtx);
 
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index efeba56..6ab0090 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -22,7 +22,7 @@
 #include "wme.h"
 
 int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
-				 struct ieee802_11_elems *elems,
+				 struct ieee802_11_elems *elems, bool beacon,
 				 enum ieee80211_band current_band,
 				 u32 sta_flags, u8 *bssid,
 				 struct ieee80211_csa_ie *csa_ie)
@@ -91,13 +91,19 @@
 		return -EINVAL;
 	}
 
-	if (sec_chan_offs) {
+	if (!beacon && sec_chan_offs) {
 		secondary_channel_offset = sec_chan_offs->sec_chan_offs;
+	} else if (beacon && ht_oper) {
+		secondary_channel_offset =
+			ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
 	} else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) {
-		/* If the secondary channel offset IE is not present,
-		 * we can't know what's the post-CSA offset, so the
-		 * best we can do is use 20MHz.
-		*/
+		/* If it's not a beacon, HT is enabled and the IE not present,
+		 * it's 20 MHz, 802.11-2012 8.5.2.6:
+		 *	This element [the Secondary Channel Offset Element] is
+		 *	present when switching to a 40 MHz channel. It may be
+		 *	present when switching to a 20 MHz channel (in which
+		 *	case the secondary channel offset is set to SCN).
+		 */
 		secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
 	}
 
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index ca80ce0..9cefdbd 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -351,9 +351,6 @@
 
 	sta->sta_state = IEEE80211_STA_NONE;
 
-	/* Mark TID as unreserved */
-	sta->reserved_tid = IEEE80211_TID_UNRESERVED;
-
 	ktime_get_ts(&uptime);
 	sta->last_connected = uptime.tv_sec;
 	ewma_init(&sta->avg_signal, 1024, 8);
@@ -504,7 +501,7 @@
 	/* make the station visible */
 	sta_info_hash_add(local, sta);
 
-	list_add_tail_rcu(&sta->list, &local->sta_list);
+	list_add_rcu(&sta->list, &local->sta_list);
 
 	/* notify driver */
 	err = sta_info_insert_drv_state(local, sdata, sta);
@@ -850,15 +847,6 @@
 	if (WARN_ON(ret))
 		return ret;
 
-	/*
-	 * for TDLS peers, make sure to return to the base channel before
-	 * removal.
-	 */
-	if (test_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL)) {
-		drv_tdls_cancel_channel_switch(local, sdata, &sta->sta);
-		clear_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
-	}
-
 	list_del_rcu(&sta->list);
 
 	drv_sta_pre_rcu_remove(local, sta->sdata, sta);
@@ -1261,8 +1249,7 @@
 		return;
 	}
 
-	info->band = chanctx_conf->def.chan->band;
-	ieee80211_xmit(sdata, skb);
+	ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band);
 	rcu_read_unlock();
 }
 
@@ -1544,7 +1531,7 @@
 		break;
 	case 0:
 		/* XXX: what is a good value? */
-		n_frames = 128;
+		n_frames = 8;
 		break;
 	}
 
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 4370931..3aabd74 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -49,9 +49,6 @@
  *	packets. This means the link is enabled.
  * @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this
  *	station.
- * @WLAN_STA_TDLS_CHAN_SWITCH: This TDLS peer supports TDLS channel-switching
- * @WLAN_STA_TDLS_OFF_CHANNEL: The local STA is currently off-channel with this
- *	TDLS peer
  * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was
  *	keeping station in power-save mode, reply when the driver
  *	unblocks the station.
@@ -81,8 +78,6 @@
 	WLAN_STA_TDLS_PEER,
 	WLAN_STA_TDLS_PEER_AUTH,
 	WLAN_STA_TDLS_INITIATOR,
-	WLAN_STA_TDLS_CHAN_SWITCH,
-	WLAN_STA_TDLS_OFF_CHANNEL,
 	WLAN_STA_UAPSD,
 	WLAN_STA_SP,
 	WLAN_STA_4ADDR_EVENT,
@@ -254,9 +249,6 @@
 	u32 bin_count;
 };
 
-/* Value to indicate no TID reservation */
-#define IEEE80211_TID_UNRESERVED	0xff
-
 /**
  * struct sta_info - STA information
  *
@@ -344,8 +336,6 @@
  * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
  *	AP only.
  * @cipher_scheme: optional cipher scheme for this station
- * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed
- * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
  */
 struct sta_info {
 	/* General information, mostly static */
@@ -463,8 +453,6 @@
 	/* TDLS timeout data */
 	unsigned long last_tdls_pkt_time;
 
-	u8 reserved_tid;
-
 	/* keep last! */
 	struct ieee80211_sta sta;
 };
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index bb146f3..89290e3 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -390,46 +390,6 @@
 	}
 }
 
-/*
- * Handles the tx for TDLS teardown frames.
- * If the frame wasn't ACKed by the peer - it will be re-sent through the AP
- */
-static void ieee80211_tdls_td_tx_handle(struct ieee80211_local *local,
-					struct ieee80211_sub_if_data *sdata,
-					struct sk_buff *skb, u32 flags)
-{
-	struct sk_buff *teardown_skb;
-	struct sk_buff *orig_teardown_skb;
-	bool is_teardown = false;
-
-	/* Get the teardown data we need and free the lock */
-	spin_lock(&sdata->u.mgd.teardown_lock);
-	teardown_skb = sdata->u.mgd.teardown_skb;
-	orig_teardown_skb = sdata->u.mgd.orig_teardown_skb;
-	if ((skb == orig_teardown_skb) && teardown_skb) {
-		sdata->u.mgd.teardown_skb = NULL;
-		sdata->u.mgd.orig_teardown_skb = NULL;
-		is_teardown = true;
-	}
-	spin_unlock(&sdata->u.mgd.teardown_lock);
-
-	if (is_teardown) {
-		/* This mechanism relies on being able to get ACKs */
-		WARN_ON(!(local->hw.flags &
-			  IEEE80211_HW_REPORTS_TX_ACK_STATUS));
-
-		/* Check if peer has ACKed */
-		if (flags & IEEE80211_TX_STAT_ACK) {
-			dev_kfree_skb_any(teardown_skb);
-		} else {
-			tdls_dbg(sdata,
-				 "TDLS Resending teardown through AP\n");
-
-			ieee80211_subif_start_xmit(teardown_skb, skb->dev);
-		}
-	}
-}
-
 static void ieee80211_report_used_skb(struct ieee80211_local *local,
 				      struct sk_buff *skb, bool dropped)
 {
@@ -466,19 +426,8 @@
 		if (!sdata) {
 			skb->dev = NULL;
 		} else if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) {
-			unsigned int hdr_size =
-				ieee80211_hdrlen(hdr->frame_control);
-
-			/* Check to see if packet is a TDLS teardown packet */
-			if (ieee80211_is_data(hdr->frame_control) &&
-			    (ieee80211_get_tdls_action(skb, hdr_size) ==
-			     WLAN_TDLS_TEARDOWN))
-				ieee80211_tdls_td_tx_handle(local, sdata, skb,
-							    info->flags);
-			else
-				ieee80211_mgd_conn_tx_status(sdata,
-							     hdr->frame_control,
-							     acked);
+			ieee80211_mgd_conn_tx_status(sdata, hdr->frame_control,
+						     acked);
 		} else if (ieee80211_is_nullfunc(hdr->frame_control) ||
 			   ieee80211_is_qos_nullfunc(hdr->frame_control)) {
 			cfg80211_probe_status(sdata->dev, hdr->addr1,
@@ -592,9 +541,10 @@
 #define STA_LOST_TDLS_PKT_THRESHOLD	10
 #define STA_LOST_TDLS_PKT_TIME		(10*HZ) /* 10secs since last ACK */
 
-static void ieee80211_lost_packet(struct sta_info *sta,
-				  struct ieee80211_tx_info *info)
+static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
 {
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
 	/* This packet was aggregated but doesn't carry status info */
 	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
 	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
@@ -621,13 +571,24 @@
 	sta->lost_packets = 0;
 }
 
-static int ieee80211_tx_get_rates(struct ieee80211_hw *hw,
-				  struct ieee80211_tx_info *info,
-				  int *retry_count)
+void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
+	struct sk_buff *skb2;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	__le16 fc;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_sub_if_data *sdata;
+	struct net_device *prev_dev = NULL;
+	struct sta_info *sta, *tmp;
+	int retry_count = -1, i;
 	int rates_idx = -1;
-	int count = -1;
-	int i;
+	bool send_to_cooked;
+	bool acked;
+	struct ieee80211_bar *bar;
+	int rtap_len;
+	int shift = 0;
 
 	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
 		if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
@@ -645,91 +606,12 @@
 			break;
 		}
 
-		count += info->status.rates[i].count;
+		retry_count += info->status.rates[i].count;
 	}
 	rates_idx = i - 1;
 
-	if (count < 0)
-		count = 0;
-
-	*retry_count = count;
-	return rates_idx;
-}
-
-void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
-			       struct ieee80211_sta *pubsta,
-			       struct ieee80211_tx_info *info)
-{
-	struct ieee80211_local *local = hw_to_local(hw);
-	struct ieee80211_supported_band *sband;
-	int retry_count;
-	int rates_idx;
-	bool acked;
-
-	rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
-
-	sband = hw->wiphy->bands[info->band];
-
-	acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
-	if (pubsta) {
-		struct sta_info *sta;
-
-		sta = container_of(pubsta, struct sta_info, sta);
-
-		if (!acked)
-			sta->tx_retry_failed++;
-		sta->tx_retry_count += retry_count;
-
-		if (acked) {
-			sta->last_rx = jiffies;
-
-			if (sta->lost_packets)
-				sta->lost_packets = 0;
-
-			/* Track when last TDLS packet was ACKed */
-			if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
-				sta->last_tdls_pkt_time = jiffies;
-		} else {
-			ieee80211_lost_packet(sta, info);
-		}
-
-		rate_control_tx_status_noskb(local, sband, sta, info);
-	}
-
-	if (acked) {
-		    local->dot11TransmittedFrameCount++;
-		    if (!pubsta)
-			    local->dot11MulticastTransmittedFrameCount++;
-		    if (retry_count > 0)
-			    local->dot11RetryCount++;
-		    if (retry_count > 1)
-			    local->dot11MultipleRetryCount++;
-	} else {
-		local->dot11FailedCount++;
-	}
-}
-EXPORT_SYMBOL(ieee80211_tx_status_noskb);
-
-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct sk_buff *skb2;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	struct ieee80211_local *local = hw_to_local(hw);
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	__le16 fc;
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_sub_if_data *sdata;
-	struct net_device *prev_dev = NULL;
-	struct sta_info *sta, *tmp;
-	int retry_count;
-	int rates_idx;
-	bool send_to_cooked;
-	bool acked;
-	struct ieee80211_bar *bar;
-	int rtap_len;
-	int shift = 0;
-
-	rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+	if (retry_count < 0)
+		retry_count = 0;
 
 	rcu_read_lock();
 
@@ -822,8 +704,7 @@
 
 		if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) &&
 		    (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
-			ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
-						acked, info->status.tx_time);
+			ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, acked);
 
 		if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
 			if (info->flags & IEEE80211_TX_STAT_ACK) {
@@ -834,7 +715,7 @@
 				if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
 					sta->last_tdls_pkt_time = jiffies;
 			} else {
-				ieee80211_lost_packet(sta, info);
+				ieee80211_lost_packet(sta, skb);
 			}
 		}
 
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 55ddd77..4ea25de 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -35,101 +35,19 @@
 	mutex_unlock(&local->mtx);
 }
 
-static void ieee80211_tdls_add_ext_capab(struct ieee80211_local *local,
-					 struct sk_buff *skb)
+static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
 {
 	u8 *pos = (void *)skb_put(skb, 7);
-	bool chan_switch = local->hw.wiphy->features &
-			   NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
 
 	*pos++ = WLAN_EID_EXT_CAPABILITY;
 	*pos++ = 5; /* len */
 	*pos++ = 0x0;
 	*pos++ = 0x0;
 	*pos++ = 0x0;
-	*pos++ = chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0;
+	*pos++ = 0x0;
 	*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
 }
 
-static u8
-ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
-			   struct sk_buff *skb, u16 start, u16 end,
-			   u16 spacing)
-{
-	u8 subband_cnt = 0, ch_cnt = 0;
-	struct ieee80211_channel *ch;
-	struct cfg80211_chan_def chandef;
-	int i, subband_start;
-
-	for (i = start; i <= end; i += spacing) {
-		if (!ch_cnt)
-			subband_start = i;
-
-		ch = ieee80211_get_channel(sdata->local->hw.wiphy, i);
-		if (ch) {
-			/* we will be active on the channel */
-			u32 flags = IEEE80211_CHAN_DISABLED |
-				    IEEE80211_CHAN_NO_IR;
-			cfg80211_chandef_create(&chandef, ch,
-						NL80211_CHAN_HT20);
-			if (cfg80211_chandef_usable(sdata->local->hw.wiphy,
-						    &chandef, flags)) {
-				ch_cnt++;
-				continue;
-			}
-		}
-
-		if (ch_cnt) {
-			u8 *pos = skb_put(skb, 2);
-			*pos++ = ieee80211_frequency_to_channel(subband_start);
-			*pos++ = ch_cnt;
-
-			subband_cnt++;
-			ch_cnt = 0;
-		}
-	}
-
-	return subband_cnt;
-}
-
-static void
-ieee80211_tdls_add_supp_channels(struct ieee80211_sub_if_data *sdata,
-				 struct sk_buff *skb)
-{
-	/*
-	 * Add possible channels for TDLS. These are channels that are allowed
-	 * to be active.
-	 */
-	u8 subband_cnt;
-	u8 *pos = skb_put(skb, 2);
-
-	*pos++ = WLAN_EID_SUPPORTED_CHANNELS;
-
-	/*
-	 * 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as
-	 * this doesn't happen in real world scenarios.
-	 */
-
-	/* 2GHz, with 5MHz spacing */
-	subband_cnt = ieee80211_tdls_add_subband(sdata, skb, 2412, 2472, 5);
-
-	/* 5GHz, with 20MHz spacing */
-	subband_cnt += ieee80211_tdls_add_subband(sdata, skb, 5000, 5825, 20);
-
-	/* length */
-	*pos = 2 * subband_cnt;
-}
-
-static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb)
-{
-	u8 *pos = (void *)skb_put(skb, 3);
-
-	*pos++ = WLAN_EID_BSS_COEX_2040;
-	*pos++ = 1; /* len */
-
-	*pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST;
-}
-
 static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
 					u16 status_code)
 {
@@ -272,7 +190,6 @@
 
 	ieee80211_add_srates_ie(sdata, skb, false, band);
 	ieee80211_add_ext_srates_ie(sdata, skb, false, band);
-	ieee80211_tdls_add_supp_channels(sdata, skb);
 
 	/* add any custom IEs that go before Extended Capabilities */
 	if (extra_ies_len) {
@@ -292,7 +209,7 @@
 		offset = noffset;
 	}
 
-	ieee80211_tdls_add_ext_capab(local, skb);
+	ieee80211_tdls_add_ext_capab(skb);
 
 	/* add the QoS element if we support it */
 	if (local->hw.queues >= IEEE80211_NUM_ACS &&
@@ -354,10 +271,6 @@
 
 	rcu_read_unlock();
 
-	if (ht_cap.ht_supported &&
-	    (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
-		ieee80211_tdls_add_bss_coex_ie(skb);
-
 	/* add any remaining IEs */
 	if (extra_ies_len) {
 		noffset = extra_ies_len;
@@ -449,68 +362,11 @@
 	ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
 }
 
-static void
-ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
-				       struct sk_buff *skb, const u8 *peer,
-				       bool initiator, const u8 *extra_ies,
-				       size_t extra_ies_len, u8 oper_class,
-				       struct cfg80211_chan_def *chandef)
-{
-	struct ieee80211_tdls_data *tf;
-	size_t offset = 0, noffset;
-	u8 *pos;
-
-	if (WARN_ON_ONCE(!chandef))
-		return;
-
-	tf = (void *)skb->data;
-	tf->u.chan_switch_req.target_channel =
-		ieee80211_frequency_to_channel(chandef->chan->center_freq);
-	tf->u.chan_switch_req.oper_class = oper_class;
-
-	if (extra_ies_len) {
-		static const u8 before_lnkie[] = {
-			WLAN_EID_SECONDARY_CHANNEL_OFFSET,
-		};
-		noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
-					     before_lnkie,
-					     ARRAY_SIZE(before_lnkie),
-					     offset);
-		pos = skb_put(skb, noffset - offset);
-		memcpy(pos, extra_ies + offset, noffset - offset);
-		offset = noffset;
-	}
-
-	ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
-
-	/* add any remaining IEs */
-	if (extra_ies_len) {
-		noffset = extra_ies_len;
-		pos = skb_put(skb, noffset - offset);
-		memcpy(pos, extra_ies + offset, noffset - offset);
-	}
-}
-
-static void
-ieee80211_tdls_add_chan_switch_resp_ies(struct ieee80211_sub_if_data *sdata,
-					struct sk_buff *skb, const u8 *peer,
-					u16 status_code, bool initiator,
-					const u8 *extra_ies,
-					size_t extra_ies_len)
-{
-	if (status_code == 0)
-		ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
-
-	if (extra_ies_len)
-		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
-}
-
 static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
 				   struct sk_buff *skb, const u8 *peer,
 				   u8 action_code, u16 status_code,
 				   bool initiator, const u8 *extra_ies,
-				   size_t extra_ies_len, u8 oper_class,
-				   struct cfg80211_chan_def *chandef)
+				   size_t extra_ies_len)
 {
 	switch (action_code) {
 	case WLAN_TDLS_SETUP_REQUEST:
@@ -537,18 +393,6 @@
 		if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
 			ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
 		break;
-	case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
-		ieee80211_tdls_add_chan_switch_req_ies(sdata, skb, peer,
-						       initiator, extra_ies,
-						       extra_ies_len,
-						       oper_class, chandef);
-		break;
-	case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
-		ieee80211_tdls_add_chan_switch_resp_ies(sdata, skb, peer,
-							status_code,
-							initiator, extra_ies,
-							extra_ies_len);
-		break;
 	}
 
 }
@@ -615,19 +459,6 @@
 		skb_put(skb, sizeof(tf->u.discover_req));
 		tf->u.discover_req.dialog_token = dialog_token;
 		break;
-	case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
-		tf->category = WLAN_CATEGORY_TDLS;
-		tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST;
-
-		skb_put(skb, sizeof(tf->u.chan_switch_req));
-		break;
-	case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
-		tf->category = WLAN_CATEGORY_TDLS;
-		tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE;
-
-		skb_put(skb, sizeof(tf->u.chan_switch_resp));
-		tf->u.chan_switch_resp.status_code = cpu_to_le16(status_code);
-		break;
 	default:
 		return -EINVAL;
 	}
@@ -671,33 +502,32 @@
 	return 0;
 }
 
-static struct sk_buff *
-ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
-				      const u8 *peer, u8 action_code,
-				      u8 dialog_token, u16 status_code,
-				      bool initiator, const u8 *extra_ies,
-				      size_t extra_ies_len, u8 oper_class,
-				      struct cfg80211_chan_def *chandef)
+static int
+ieee80211_tdls_prep_mgmt_packet(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 *extra_ies, size_t extra_ies_len)
 {
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
+	bool send_direct;
+	struct sta_info *sta;
 	int ret;
 
-	skb = netdev_alloc_skb(sdata->dev,
-			       local->hw.extra_tx_headroom +
-			       max(sizeof(struct ieee80211_mgmt),
-				   sizeof(struct ieee80211_tdls_data)) +
-			       50 + /* supported rates */
-			       7 + /* ext capab */
-			       26 + /* max(WMM-info, WMM-param) */
-			       2 + max(sizeof(struct ieee80211_ht_cap),
-				       sizeof(struct ieee80211_ht_operation)) +
-			       50 + /* supported channels */
-			       3 + /* 40/20 BSS coex */
-			       extra_ies_len +
-			       sizeof(struct ieee80211_tdls_lnkie));
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+			    max(sizeof(struct ieee80211_mgmt),
+				sizeof(struct ieee80211_tdls_data)) +
+			    50 + /* supported rates */
+			    7 + /* ext capab */
+			    26 + /* max(WMM-info, WMM-param) */
+			    2 + max(sizeof(struct ieee80211_ht_cap),
+				    sizeof(struct ieee80211_ht_operation)) +
+			    extra_ies_len +
+			    sizeof(struct ieee80211_tdls_lnkie));
 	if (!skb)
-		return NULL;
+		return -ENOMEM;
 
 	skb_reserve(skb, local->hw.extra_tx_headroom);
 
@@ -707,18 +537,16 @@
 	case WLAN_TDLS_SETUP_CONFIRM:
 	case WLAN_TDLS_TEARDOWN:
 	case WLAN_TDLS_DISCOVERY_REQUEST:
-	case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
-	case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
-		ret = ieee80211_prep_tdls_encap_data(local->hw.wiphy,
-						     sdata->dev, peer,
+		ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
 						     action_code, dialog_token,
 						     status_code, skb);
+		send_direct = false;
 		break;
 	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
-		ret = ieee80211_prep_tdls_direct(local->hw.wiphy, sdata->dev,
-						 peer, action_code,
+		ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
 						 dialog_token, status_code,
 						 skb);
+		send_direct = true;
 		break;
 	default:
 		ret = -ENOTSUPP;
@@ -728,40 +556,14 @@
 	if (ret < 0)
 		goto fail;
 
-	ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code,
-			       initiator, extra_ies, extra_ies_len, oper_class,
-			       chandef);
-	return skb;
-
-fail:
-	dev_kfree_skb(skb);
-	return NULL;
-}
-
-static int
-ieee80211_tdls_prep_mgmt_packet(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 *extra_ies,
-				size_t extra_ies_len, u8 oper_class,
-				struct cfg80211_chan_def *chandef)
-{
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct sk_buff *skb = NULL;
-	struct sta_info *sta;
-	u32 flags = 0;
-	int ret = 0;
-
 	rcu_read_lock();
 	sta = sta_info_get(sdata, peer);
 
 	/* infer the initiator if we can, to support old userspace */
 	switch (action_code) {
 	case WLAN_TDLS_SETUP_REQUEST:
-		if (sta) {
+		if (sta)
 			set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
-			sta->sta.tdls_initiator = false;
-		}
 		/* fall-through */
 	case WLAN_TDLS_SETUP_CONFIRM:
 	case WLAN_TDLS_DISCOVERY_REQUEST:
@@ -773,17 +575,13 @@
 		 * Make the last packet sent take effect for the initiator
 		 * value.
 		 */
-		if (sta) {
+		if (sta)
 			clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
-			sta->sta.tdls_initiator = true;
-		}
 		/* fall-through */
 	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
 		initiator = false;
 		break;
 	case WLAN_TDLS_TEARDOWN:
-	case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
-	case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
 		/* any value is ok */
 		break;
 	default:
@@ -798,17 +596,9 @@
 	if (ret < 0)
 		goto fail;
 
-	skb = ieee80211_tdls_build_mgmt_packet_data(sdata, peer, action_code,
-						    dialog_token, status_code,
-						    initiator, extra_ies,
-						    extra_ies_len, oper_class,
-						    chandef);
-	if (!skb) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
+	ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code,
+			       initiator, extra_ies, extra_ies_len);
+	if (send_direct) {
 		ieee80211_tx_skb(sdata, skb);
 		return 0;
 	}
@@ -829,44 +619,9 @@
 		break;
 	}
 
-	/*
-	 * Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress.
-	 * Later, if no ACK is returned from peer, we will re-send the teardown
-	 * packet through the AP.
-	 */
-	if ((action_code == WLAN_TDLS_TEARDOWN) &&
-	    (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
-		struct sta_info *sta = NULL;
-		bool try_resend; /* Should we keep skb for possible resend */
-
-		/* If not sending directly to peer - no point in keeping skb */
-		rcu_read_lock();
-		sta = sta_info_get(sdata, peer);
-		try_resend = sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
-		rcu_read_unlock();
-
-		spin_lock_bh(&sdata->u.mgd.teardown_lock);
-		if (try_resend && !sdata->u.mgd.teardown_skb) {
-			/* Mark it as requiring TX status callback  */
-			flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
-				 IEEE80211_TX_INTFL_MLME_CONN_TX;
-
-			/*
-			 * skb is copied since mac80211 will later set
-			 * properties that might not be the same as the AP,
-			 * such as encryption, QoS, addresses, etc.
-			 *
-			 * No problem if skb_copy() fails, so no need to check.
-			 */
-			sdata->u.mgd.teardown_skb = skb_copy(skb, GFP_ATOMIC);
-			sdata->u.mgd.orig_teardown_skb = skb;
-		}
-		spin_unlock_bh(&sdata->u.mgd.teardown_lock);
-	}
-
 	/* disable bottom halves when entering the Tx path */
 	local_bh_disable();
-	__ieee80211_subif_start_xmit(skb, dev, flags);
+	ret = ieee80211_subif_start_xmit(skb, dev);
 	local_bh_enable();
 
 	return ret;
@@ -917,8 +672,7 @@
 	ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
 					      dialog_token, status_code,
 					      peer_capability, initiator,
-					      extra_ies, extra_ies_len, 0,
-					      NULL);
+					      extra_ies, extra_ies_len);
 	if (ret < 0)
 		goto exit;
 
@@ -957,8 +711,7 @@
 	ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
 					      dialog_token, status_code,
 					      peer_capability, initiator,
-					      extra_ies, extra_ies_len, 0,
-					      NULL);
+					      extra_ies, extra_ies_len);
 	if (ret < 0)
 		sdata_err(sdata, "Failed sending TDLS teardown packet %d\n",
 			  ret);
@@ -1028,7 +781,7 @@
 						      status_code,
 						      peer_capability,
 						      initiator, extra_ies,
-						      extra_ies_len, 0, NULL);
+						      extra_ies_len);
 		break;
 	default:
 		ret = -EOPNOTSUPP;
@@ -1131,480 +884,3 @@
 	cfg80211_tdls_oper_request(sdata->dev, peer, oper, reason_code, gfp);
 }
 EXPORT_SYMBOL(ieee80211_tdls_oper_request);
-
-static void
-iee80211_tdls_add_ch_switch_timing(u8 *buf, u16 switch_time, u16 switch_timeout)
-{
-	struct ieee80211_ch_switch_timing *ch_sw;
-
-	*buf++ = WLAN_EID_CHAN_SWITCH_TIMING;
-	*buf++ = sizeof(struct ieee80211_ch_switch_timing);
-
-	ch_sw = (void *)buf;
-	ch_sw->switch_time = cpu_to_le16(switch_time);
-	ch_sw->switch_timeout = cpu_to_le16(switch_timeout);
-}
-
-/* find switch timing IE in SKB ready for Tx */
-static const u8 *ieee80211_tdls_find_sw_timing_ie(struct sk_buff *skb)
-{
-	struct ieee80211_tdls_data *tf;
-	const u8 *ie_start;
-
-	/*
-	 * Get the offset for the new location of the switch timing IE.
-	 * The SKB network header will now point to the "payload_type"
-	 * element of the TDLS data frame struct.
-	 */
-	tf = container_of(skb->data + skb_network_offset(skb),
-			  struct ieee80211_tdls_data, payload_type);
-	ie_start = tf->u.chan_switch_req.variable;
-	return cfg80211_find_ie(WLAN_EID_CHAN_SWITCH_TIMING, ie_start,
-				skb->len - (ie_start - skb->data));
-}
-
-static struct sk_buff *
-ieee80211_tdls_ch_sw_tmpl_get(struct sta_info *sta, u8 oper_class,
-			      struct cfg80211_chan_def *chandef,
-			      u32 *ch_sw_tm_ie_offset)
-{
-	struct ieee80211_sub_if_data *sdata = sta->sdata;
-	u8 extra_ies[2 + sizeof(struct ieee80211_sec_chan_offs_ie) +
-		     2 + sizeof(struct ieee80211_ch_switch_timing)];
-	int extra_ies_len = 2 + sizeof(struct ieee80211_ch_switch_timing);
-	u8 *pos = extra_ies;
-	struct sk_buff *skb;
-
-	/*
-	 * if chandef points to a wide channel add a Secondary-Channel
-	 * Offset information element
-	 */
-	if (chandef->width == NL80211_CHAN_WIDTH_40) {
-		struct ieee80211_sec_chan_offs_ie *sec_chan_ie;
-		bool ht40plus;
-
-		*pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
-		*pos++ = sizeof(*sec_chan_ie);
-		sec_chan_ie = (void *)pos;
-
-		ht40plus = cfg80211_get_chandef_type(chandef) ==
-							NL80211_CHAN_HT40PLUS;
-		sec_chan_ie->sec_chan_offs = ht40plus ?
-					     IEEE80211_HT_PARAM_CHA_SEC_ABOVE :
-					     IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-		pos += sizeof(*sec_chan_ie);
-
-		extra_ies_len += 2 + sizeof(struct ieee80211_sec_chan_offs_ie);
-	}
-
-	/* just set the values to 0, this is a template */
-	iee80211_tdls_add_ch_switch_timing(pos, 0, 0);
-
-	skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr,
-					      WLAN_TDLS_CHANNEL_SWITCH_REQUEST,
-					      0, 0, !sta->sta.tdls_initiator,
-					      extra_ies, extra_ies_len,
-					      oper_class, chandef);
-	if (!skb)
-		return NULL;
-
-	skb = ieee80211_build_data_template(sdata, skb, 0);
-	if (IS_ERR(skb)) {
-		tdls_dbg(sdata, "Failed building TDLS channel switch frame\n");
-		return NULL;
-	}
-
-	if (ch_sw_tm_ie_offset) {
-		const u8 *tm_ie = ieee80211_tdls_find_sw_timing_ie(skb);
-
-		if (!tm_ie) {
-			tdls_dbg(sdata, "No switch timing IE in TDLS switch\n");
-			dev_kfree_skb_any(skb);
-			return NULL;
-		}
-
-		*ch_sw_tm_ie_offset = tm_ie - skb->data;
-	}
-
-	tdls_dbg(sdata,
-		 "TDLS channel switch request template for %pM ch %d width %d\n",
-		 sta->sta.addr, chandef->chan->center_freq, chandef->width);
-	return skb;
-}
-
-int
-ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
-			      const u8 *addr, u8 oper_class,
-			      struct cfg80211_chan_def *chandef)
-{
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_local *local = sdata->local;
-	struct sta_info *sta;
-	struct sk_buff *skb = NULL;
-	u32 ch_sw_tm_ie;
-	int ret;
-
-	mutex_lock(&local->sta_mtx);
-	sta = sta_info_get(sdata, addr);
-	if (!sta) {
-		tdls_dbg(sdata,
-			 "Invalid TDLS peer %pM for channel switch request\n",
-			 addr);
-		ret = -ENOENT;
-		goto out;
-	}
-
-	if (!test_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH)) {
-		tdls_dbg(sdata, "TDLS channel switch unsupported by %pM\n",
-			 addr);
-		ret = -ENOTSUPP;
-		goto out;
-	}
-
-	skb = ieee80211_tdls_ch_sw_tmpl_get(sta, oper_class, chandef,
-					    &ch_sw_tm_ie);
-	if (!skb) {
-		ret = -ENOENT;
-		goto out;
-	}
-
-	ret = drv_tdls_channel_switch(local, sdata, &sta->sta, oper_class,
-				      chandef, skb, ch_sw_tm_ie);
-	if (!ret)
-		set_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
-
-out:
-	mutex_unlock(&local->sta_mtx);
-	dev_kfree_skb_any(skb);
-	return ret;
-}
-
-void
-ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
-				     struct net_device *dev,
-				     const u8 *addr)
-{
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_local *local = sdata->local;
-	struct sta_info *sta;
-
-	mutex_lock(&local->sta_mtx);
-	sta = sta_info_get(sdata, addr);
-	if (!sta) {
-		tdls_dbg(sdata,
-			 "Invalid TDLS peer %pM for channel switch cancel\n",
-			 addr);
-		goto out;
-	}
-
-	if (!test_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL)) {
-		tdls_dbg(sdata, "TDLS channel switch not initiated by %pM\n",
-			 addr);
-		goto out;
-	}
-
-	drv_tdls_cancel_channel_switch(local, sdata, &sta->sta);
-	clear_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
-
-out:
-	mutex_unlock(&local->sta_mtx);
-}
-
-static struct sk_buff *
-ieee80211_tdls_ch_sw_resp_tmpl_get(struct sta_info *sta,
-				   u32 *ch_sw_tm_ie_offset)
-{
-	struct ieee80211_sub_if_data *sdata = sta->sdata;
-	struct sk_buff *skb;
-	u8 extra_ies[2 + sizeof(struct ieee80211_ch_switch_timing)];
-
-	/* initial timing are always zero in the template */
-	iee80211_tdls_add_ch_switch_timing(extra_ies, 0, 0);
-
-	skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr,
-					WLAN_TDLS_CHANNEL_SWITCH_RESPONSE,
-					0, 0, !sta->sta.tdls_initiator,
-					extra_ies, sizeof(extra_ies), 0, NULL);
-	if (!skb)
-		return NULL;
-
-	skb = ieee80211_build_data_template(sdata, skb, 0);
-	if (IS_ERR(skb)) {
-		tdls_dbg(sdata,
-			 "Failed building TDLS channel switch resp frame\n");
-		return NULL;
-	}
-
-	if (ch_sw_tm_ie_offset) {
-		const u8 *tm_ie = ieee80211_tdls_find_sw_timing_ie(skb);
-
-		if (!tm_ie) {
-			tdls_dbg(sdata,
-				 "No switch timing IE in TDLS switch resp\n");
-			dev_kfree_skb_any(skb);
-			return NULL;
-		}
-
-		*ch_sw_tm_ie_offset = tm_ie - skb->data;
-	}
-
-	tdls_dbg(sdata, "TDLS get channel switch response template for %pM\n",
-		 sta->sta.addr);
-	return skb;
-}
-
-static int
-ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
-					   struct sk_buff *skb)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee802_11_elems elems;
-	struct sta_info *sta;
-	struct ieee80211_tdls_data *tf = (void *)skb->data;
-	bool local_initiator;
-	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
-	int baselen = offsetof(typeof(*tf), u.chan_switch_resp.variable);
-	struct ieee80211_tdls_ch_sw_params params = {};
-	int ret;
-
-	params.action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE;
-	params.timestamp = rx_status->device_timestamp;
-
-	if (skb->len < baselen) {
-		tdls_dbg(sdata, "TDLS channel switch resp too short: %d\n",
-			 skb->len);
-		return -EINVAL;
-	}
-
-	mutex_lock(&local->sta_mtx);
-	sta = sta_info_get(sdata, tf->sa);
-	if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) {
-		tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n",
-			 tf->sa);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	params.sta = &sta->sta;
-	params.status = le16_to_cpu(tf->u.chan_switch_resp.status_code);
-	if (params.status != 0) {
-		ret = 0;
-		goto call_drv;
-	}
-
-	ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
-			       skb->len - baselen, false, &elems);
-	if (elems.parse_error) {
-		tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (!elems.ch_sw_timing || !elems.lnk_id) {
-		tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* validate the initiator is set correctly */
-	local_initiator =
-		!memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
-	if (local_initiator == sta->sta.tdls_initiator) {
-		tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
-	params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
-
-	params.tmpl_skb =
-		ieee80211_tdls_ch_sw_resp_tmpl_get(sta, &params.ch_sw_tm_ie);
-	if (!params.tmpl_skb) {
-		ret = -ENOENT;
-		goto out;
-	}
-
-call_drv:
-	drv_tdls_recv_channel_switch(sdata->local, sdata, &params);
-
-	tdls_dbg(sdata,
-		 "TDLS channel switch response received from %pM status %d\n",
-		 tf->sa, params.status);
-
-out:
-	mutex_unlock(&local->sta_mtx);
-	dev_kfree_skb_any(params.tmpl_skb);
-	return ret;
-}
-
-static int
-ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
-					  struct sk_buff *skb)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee802_11_elems elems;
-	struct cfg80211_chan_def chandef;
-	struct ieee80211_channel *chan;
-	enum nl80211_channel_type chan_type;
-	int freq;
-	u8 target_channel, oper_class;
-	bool local_initiator;
-	struct sta_info *sta;
-	enum ieee80211_band band;
-	struct ieee80211_tdls_data *tf = (void *)skb->data;
-	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
-	int baselen = offsetof(typeof(*tf), u.chan_switch_req.variable);
-	struct ieee80211_tdls_ch_sw_params params = {};
-	int ret = 0;
-
-	params.action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST;
-	params.timestamp = rx_status->device_timestamp;
-
-	if (skb->len < baselen) {
-		tdls_dbg(sdata, "TDLS channel switch req too short: %d\n",
-			 skb->len);
-		return -EINVAL;
-	}
-
-	target_channel = tf->u.chan_switch_req.target_channel;
-	oper_class = tf->u.chan_switch_req.oper_class;
-
-	/*
-	 * We can't easily infer the channel band. The operating class is
-	 * ambiguous - there are multiple tables (US/Europe/JP/Global). The
-	 * solution here is to treat channels with number >14 as 5GHz ones,
-	 * and specifically check for the (oper_class, channel) combinations
-	 * where this doesn't hold. These are thankfully unique according to
-	 * IEEE802.11-2012.
-	 * We consider only the 2GHz and 5GHz bands and 20MHz+ channels as
-	 * valid here.
-	 */
-	if ((oper_class == 112 || oper_class == 2 || oper_class == 3 ||
-	     oper_class == 4 || oper_class == 5 || oper_class == 6) &&
-	     target_channel < 14)
-		band = IEEE80211_BAND_5GHZ;
-	else
-		band = target_channel < 14 ? IEEE80211_BAND_2GHZ :
-					     IEEE80211_BAND_5GHZ;
-
-	freq = ieee80211_channel_to_frequency(target_channel, band);
-	if (freq == 0) {
-		tdls_dbg(sdata, "Invalid channel in TDLS chan switch: %d\n",
-			 target_channel);
-		return -EINVAL;
-	}
-
-	chan = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
-	if (!chan) {
-		tdls_dbg(sdata,
-			 "Unsupported channel for TDLS chan switch: %d\n",
-			 target_channel);
-		return -EINVAL;
-	}
-
-	ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
-			       skb->len - baselen, false, &elems);
-	if (elems.parse_error) {
-		tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n");
-		return -EINVAL;
-	}
-
-	if (!elems.ch_sw_timing || !elems.lnk_id) {
-		tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n");
-		return -EINVAL;
-	}
-
-	mutex_lock(&local->sta_mtx);
-	sta = sta_info_get(sdata, tf->sa);
-	if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) {
-		tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n",
-			 tf->sa);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	params.sta = &sta->sta;
-
-	/* validate the initiator is set correctly */
-	local_initiator =
-		!memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
-	if (local_initiator == sta->sta.tdls_initiator) {
-		tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (!sta->sta.ht_cap.ht_supported) {
-		chan_type = NL80211_CHAN_NO_HT;
-	} else if (!elems.sec_chan_offs) {
-		chan_type = NL80211_CHAN_HT20;
-	} else {
-		switch (elems.sec_chan_offs->sec_chan_offs) {
-		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-			chan_type = NL80211_CHAN_HT40PLUS;
-			break;
-		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-			chan_type = NL80211_CHAN_HT40MINUS;
-			break;
-		default:
-			chan_type = NL80211_CHAN_HT20;
-			break;
-		}
-	}
-
-	cfg80211_chandef_create(&chandef, chan, chan_type);
-	params.chandef = &chandef;
-
-	params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
-	params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
-
-	params.tmpl_skb =
-		ieee80211_tdls_ch_sw_resp_tmpl_get(sta,
-						   &params.ch_sw_tm_ie);
-	if (!params.tmpl_skb) {
-		ret = -ENOENT;
-		goto out;
-	}
-
-	drv_tdls_recv_channel_switch(sdata->local, sdata, &params);
-
-	tdls_dbg(sdata,
-		 "TDLS ch switch request received from %pM ch %d width %d\n",
-		 tf->sa, params.chandef->chan->center_freq,
-		 params.chandef->width);
-out:
-	mutex_unlock(&local->sta_mtx);
-	dev_kfree_skb_any(params.tmpl_skb);
-	return ret;
-}
-
-void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata,
-					   struct sk_buff *skb)
-{
-	struct ieee80211_tdls_data *tf = (void *)skb->data;
-	struct wiphy *wiphy = sdata->local->hw.wiphy;
-
-	/* make sure the driver supports it */
-	if (!(wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
-		return;
-
-	/* we want to access the entire packet */
-	if (skb_linearize(skb))
-		return;
-	/*
-	 * The packet/size was already validated by mac80211 Rx path, only look
-	 * at the action type.
-	 */
-	switch (tf->action_code) {
-	case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
-		ieee80211_process_tdls_channel_switch_req(sdata, skb);
-		break;
-	case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
-		ieee80211_process_tdls_channel_switch_resp(sdata, skb);
-		break;
-	default:
-		WARN_ON_ONCE(1);
-		return;
-	}
-}
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 3991437..5153d12 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -16,7 +16,6 @@
 
 #define STA_ENTRY	__array(char, sta_addr, ETH_ALEN)
 #define STA_ASSIGN	(sta ? memcpy(__entry->sta_addr, sta->addr, ETH_ALEN) : memset(__entry->sta_addr, 0, ETH_ALEN))
-#define STA_NAMED_ASSIGN(s)	memcpy(__entry->sta_addr, (s)->addr, ETH_ALEN)
 #define STA_PR_FMT	" sta:%pM"
 #define STA_PR_ARG	__entry->sta_addr
 
@@ -596,33 +595,14 @@
 	TP_ARGS(local, sdata)
 );
 
-TRACE_EVENT(drv_sw_scan_start,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 const u8 *mac_addr),
-
-	TP_ARGS(local, sdata, mac_addr),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		__array(char, mac_addr, ETH_ALEN)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		memcpy(__entry->mac_addr, mac_addr, ETH_ALEN);
-	),
-
-	TP_printk(LOCAL_PR_FMT ", " VIF_PR_FMT ", addr:%pM",
-		  LOCAL_PR_ARG, VIF_PR_ARG, __entry->mac_addr)
+DEFINE_EVENT(local_only_evt, drv_sw_scan_start,
+	TP_PROTO(struct ieee80211_local *local),
+	TP_ARGS(local)
 );
 
-DEFINE_EVENT(local_sdata_evt, drv_sw_scan_complete,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata),
-	TP_ARGS(local, sdata)
+DEFINE_EVENT(local_only_evt, drv_sw_scan_complete,
+	TP_PROTO(struct ieee80211_local *local),
+	TP_ARGS(local)
 );
 
 TRACE_EVENT(drv_get_stats,
@@ -846,13 +826,6 @@
 	TP_ARGS(local, sdata, sta)
 );
 
-DEFINE_EVENT(sta_event, drv_sta_rate_tbl_update,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct ieee80211_sta *sta),
-	TP_ARGS(local, sdata, sta)
-);
-
 TRACE_EVENT(drv_conf_tx,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
@@ -1014,34 +987,29 @@
 
 TRACE_EVENT(drv_channel_switch,
 	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
 		 struct ieee80211_channel_switch *ch_switch),
 
-	TP_ARGS(local, sdata, ch_switch),
+	TP_ARGS(local, ch_switch),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
-		VIF_ENTRY
 		CHANDEF_ENTRY
 		__field(u64, timestamp)
-		__field(u32, device_timestamp)
 		__field(bool, block_tx)
 		__field(u8, count)
 	),
 
 	TP_fast_assign(
 		LOCAL_ASSIGN;
-		VIF_ASSIGN;
 		CHANDEF_ASSIGN(&ch_switch->chandef)
 		__entry->timestamp = ch_switch->timestamp;
-		__entry->device_timestamp = ch_switch->device_timestamp;
 		__entry->block_tx = ch_switch->block_tx;
 		__entry->count = ch_switch->count;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT " new " CHANDEF_PR_FMT " count:%d",
-		LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG, __entry->count
+		LOCAL_PR_FMT " new " CHANDEF_PR_FMT " count:%d",
+		LOCAL_PR_ARG, CHANDEF_PR_ARG, __entry->count
 	)
 );
 
@@ -1589,26 +1557,9 @@
 	TP_ARGS(local, sdata)
 );
 
-TRACE_EVENT(drv_reconfig_complete,
-	TP_PROTO(struct ieee80211_local *local,
-		 enum ieee80211_reconfig_type reconfig_type),
-	TP_ARGS(local, reconfig_type),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		__field(u8, reconfig_type)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		__entry->reconfig_type = reconfig_type;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT  " reconfig_type:%d",
-		LOCAL_PR_ARG, __entry->reconfig_type
-	)
-
+DEFINE_EVENT(local_only_evt, drv_restart_complete,
+	TP_PROTO(struct ieee80211_local *local),
+	TP_ARGS(local)
 );
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -1829,12 +1780,6 @@
 	)
 );
 
-DEFINE_EVENT(local_sdata_evt, api_cqm_beacon_loss_notify,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata),
-	TP_ARGS(local, sdata)
-);
-
 TRACE_EVENT(api_scan_completed,
 	TP_PROTO(struct ieee80211_local *local, bool aborted),
 
@@ -2161,175 +2106,6 @@
 	)
 );
 
-TRACE_EVENT(drv_pre_channel_switch,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct ieee80211_channel_switch *ch_switch),
-
-	TP_ARGS(local, sdata, ch_switch),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		CHANDEF_ENTRY
-		__field(u64, timestamp)
-		__field(u32, device_timestamp)
-		__field(bool, block_tx)
-		__field(u8, count)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		CHANDEF_ASSIGN(&ch_switch->chandef)
-		__entry->timestamp = ch_switch->timestamp;
-		__entry->device_timestamp = ch_switch->device_timestamp;
-		__entry->block_tx = ch_switch->block_tx;
-		__entry->count = ch_switch->count;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT " prepare channel switch to "
-		CHANDEF_PR_FMT  " count:%d block_tx:%d timestamp:%llu",
-		LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG, __entry->count,
-		__entry->block_tx, __entry->timestamp
-	)
-);
-
-DEFINE_EVENT(local_sdata_evt, drv_post_channel_switch,
-	     TP_PROTO(struct ieee80211_local *local,
-		      struct ieee80211_sub_if_data *sdata),
-	     TP_ARGS(local, sdata)
-);
-
-TRACE_EVENT(drv_get_txpower,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 int dbm, int ret),
-
-	TP_ARGS(local, sdata, dbm, ret),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		__field(int, dbm)
-		__field(int, ret)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		__entry->dbm = dbm;
-		__entry->ret = ret;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT " dbm:%d ret:%d",
-		LOCAL_PR_ARG, VIF_PR_ARG, __entry->dbm, __entry->ret
-	)
-);
-
-TRACE_EVENT(drv_tdls_channel_switch,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct ieee80211_sta *sta, u8 oper_class,
-		 struct cfg80211_chan_def *chandef),
-
-	TP_ARGS(local, sdata, sta, oper_class, chandef),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		STA_ENTRY
-		__field(u8, oper_class)
-		CHANDEF_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		STA_ASSIGN;
-		__entry->oper_class = oper_class;
-		CHANDEF_ASSIGN(chandef)
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT " tdls channel switch to"
-		CHANDEF_PR_FMT  " oper_class:%d " STA_PR_FMT,
-		LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG, __entry->oper_class,
-		STA_PR_ARG
-	)
-);
-
-TRACE_EVENT(drv_tdls_cancel_channel_switch,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct ieee80211_sta *sta),
-
-	TP_ARGS(local, sdata, sta),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		STA_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		STA_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT
-		" tdls cancel channel switch with " STA_PR_FMT,
-		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG
-	)
-);
-
-TRACE_EVENT(drv_tdls_recv_channel_switch,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct ieee80211_tdls_ch_sw_params *params),
-
-	TP_ARGS(local, sdata, params),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		__field(u8, action_code)
-		STA_ENTRY
-		CHANDEF_ENTRY
-		__field(u32, status)
-		__field(bool, peer_initiator)
-		__field(u32, timestamp)
-		__field(u16, switch_time)
-		__field(u16, switch_timeout)
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		STA_NAMED_ASSIGN(params->sta);
-		CHANDEF_ASSIGN(params->chandef)
-		__entry->peer_initiator = params->sta->tdls_initiator;
-		__entry->action_code = params->action_code;
-		__entry->status = params->status;
-		__entry->timestamp = params->timestamp;
-		__entry->switch_time = params->switch_time;
-		__entry->switch_timeout = params->switch_timeout;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT " received tdls channel switch packet"
-		" action:%d status:%d time:%d switch time:%d switch"
-		" timeout:%d initiator: %d chan:" CHANDEF_PR_FMT STA_PR_FMT,
-		LOCAL_PR_ARG, VIF_PR_ARG, __entry->action_code, __entry->status,
-		__entry->timestamp, __entry->switch_time,
-		__entry->switch_timeout, __entry->peer_initiator,
-		CHANDEF_PR_ARG, STA_PR_ARG
-	)
-);
 
 #ifdef CPTCFG_MAC80211_MESSAGE_TRACING
 #undef TRACE_SYSTEM
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 002f28d..86ea121 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -60,7 +60,7 @@
 	rcu_read_unlock();
 
 	/* assume HW handles this */
-	if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
+	if (tx->rate.flags & IEEE80211_TX_RC_MCS)
 		return 0;
 
 	/* uh huh? */
@@ -296,9 +296,6 @@
 		 */
 		return TX_DROP;
 
-	if (tx->sdata->vif.type == NL80211_IFTYPE_OCB)
-		return TX_CONTINUE;
-
 	if (tx->sdata->vif.type == NL80211_IFTYPE_WDS)
 		return TX_CONTINUE;
 
@@ -1426,7 +1423,8 @@
  * Returns false if the frame couldn't be transmitted but was queued instead.
  */
 static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
-			 struct sk_buff *skb, bool txpending)
+			 struct sk_buff *skb, bool txpending,
+			 enum ieee80211_band band)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_tx_data tx;
@@ -1451,6 +1449,8 @@
 		return true;
 	}
 
+	info->band = band;
+
 	/* set up hw_queue value early */
 	if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
 	    !(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL))
@@ -1498,7 +1498,8 @@
 	return 0;
 }
 
-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+		    enum ieee80211_band band)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1533,7 +1534,7 @@
 	}
 
 	ieee80211_set_qos_hdr(sdata, skb);
-	ieee80211_tx(sdata, skb, false);
+	ieee80211_tx(sdata, skb, false, band);
 }
 
 static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
@@ -1753,8 +1754,7 @@
 				     sdata->vif.type))
 		goto fail_rcu;
 
-	info->band = chandef->chan->band;
-	ieee80211_xmit(sdata, skb);
+	ieee80211_xmit(sdata, skb, chandef->chan->band);
 	rcu_read_unlock();
 
 	return NETDEV_TX_OK;
@@ -1784,26 +1784,23 @@
 }
 
 /**
- * ieee80211_build_hdr - build 802.11 header in the given frame
- * @sdata: virtual interface to build the header for
- * @skb: the skb to build the header in
- * @info_flags: skb flags to set
+ * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
+ * subinterfaces (wlan#, WDS, and VLAN interfaces)
+ * @skb: packet to be sent
+ * @dev: incoming interface
  *
- * This function takes the skb with 802.3 header and reformats the header to
- * the appropriate IEEE 802.11 header based on which interface the packet is
- * being transmitted on.
+ * Returns: NETDEV_TX_OK both on success and on failure. On failure skb will
+ *	be freed.
  *
- * Note that this function also takes care of the TX status request and
- * potential unsharing of the SKB - this needs to be interleaved with the
- * header building.
- *
- * The function requires the read-side RCU lock held
- *
- * Returns: the (possibly reallocated) skb or an ERR_PTR() code
+ * This function takes in an Ethernet header and encapsulates it with suitable
+ * IEEE 802.11 header based on which interface the packet is coming in. The
+ * encapsulated packet will then be passed to master interface, wlan#.11, for
+ * transmission (through low-level driver).
  */
-static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
-					   struct sk_buff *skb, u32 info_flags)
+netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
+				    struct net_device *dev)
 {
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_tx_info *info;
 	int head_need;
@@ -1819,17 +1816,25 @@
 	bool wme_sta = false, authorized = false, tdls_auth = false;
 	bool tdls_peer = false, tdls_setup_frame = false;
 	bool multicast;
+	u32 info_flags = 0;
 	u16 info_id = 0;
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	struct ieee80211_sub_if_data *ap_sdata;
 	enum ieee80211_band band;
-	int ret;
+
+	if (unlikely(skb->len < ETH_HLEN))
+		goto fail;
 
 	/* convert Ethernet header to proper 802.11 header (based on
 	 * operation mode) */
 	ethertype = (skb->data[12] << 8) | skb->data[13];
 	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
 
+	rcu_read_lock();
+
+	/* Measure frame arrival for Tx latency statistics calculation */
+	ieee80211_tx_latency_start_msrmnt(local, skb);
+
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_AP_VLAN:
 		sta = rcu_dereference(sdata->u.vlan.sta);
@@ -1847,10 +1852,8 @@
 		ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
 					u.ap);
 		chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf);
-		if (!chanctx_conf) {
-			ret = -ENOTCONN;
-			goto free;
-		}
+		if (!chanctx_conf)
+			goto fail_rcu;
 		band = chanctx_conf->def.chan->band;
 		if (sta)
 			break;
@@ -1858,10 +1861,8 @@
 	case NL80211_IFTYPE_AP:
 		if (sdata->vif.type == NL80211_IFTYPE_AP)
 			chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-		if (!chanctx_conf) {
-			ret = -ENOTCONN;
-			goto free;
-		}
+		if (!chanctx_conf)
+			goto fail_rcu;
 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
 		/* DA BSSID SA */
 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -1948,10 +1949,8 @@
 
 		}
 		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-		if (!chanctx_conf) {
-			ret = -ENOTCONN;
-			goto free;
-		}
+		if (!chanctx_conf)
+			goto fail_rcu;
 		band = chanctx_conf->def.chan->band;
 		break;
 #endif
@@ -1981,10 +1980,8 @@
 		 * of a link teardown after a TDLS sta is removed due to being
 		 * unreachable.
 		 */
-		if (tdls_peer && !tdls_auth && !tdls_setup_frame) {
-			ret = -EINVAL;
-			goto free;
-		}
+		if (tdls_peer && !tdls_auth && !tdls_setup_frame)
+			goto fail_rcu;
 
 		/* send direct packets to authorized TDLS peers */
 		if (tdls_peer && tdls_auth) {
@@ -2012,23 +2009,8 @@
 			hdrlen = 24;
 		}
 		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-		if (!chanctx_conf) {
-			ret = -ENOTCONN;
-			goto free;
-		}
-		band = chanctx_conf->def.chan->band;
-		break;
-	case NL80211_IFTYPE_OCB:
-		/* DA SA BSSID */
-		memcpy(hdr.addr1, skb->data, ETH_ALEN);
-		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-		eth_broadcast_addr(hdr.addr3);
-		hdrlen = 24;
-		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-		if (!chanctx_conf) {
-			ret = -ENOTCONN;
-			goto free;
-		}
+		if (!chanctx_conf)
+			goto fail_rcu;
 		band = chanctx_conf->def.chan->band;
 		break;
 	case NL80211_IFTYPE_ADHOC:
@@ -2038,15 +2020,12 @@
 		memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN);
 		hdrlen = 24;
 		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-		if (!chanctx_conf) {
-			ret = -ENOTCONN;
-			goto free;
-		}
+		if (!chanctx_conf)
+			goto fail_rcu;
 		band = chanctx_conf->def.chan->band;
 		break;
 	default:
-		ret = -EINVAL;
-		goto free;
+		goto fail_rcu;
 	}
 
 	/*
@@ -2078,19 +2057,17 @@
 	 * EAPOL frames from the local station.
 	 */
 	if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
-		     (sdata->vif.type != NL80211_IFTYPE_OCB) &&
 		     !multicast && !authorized &&
 		     (cpu_to_be16(ethertype) != sdata->control_port_protocol ||
 		      !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) {
 #ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
 		net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n",
-				    sdata->name, hdr.addr1);
+				    dev->name, hdr.addr1);
 #endif
 
 		I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
 
-		ret = -EPERM;
-		goto free;
+		goto fail_rcu;
 	}
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
@@ -2129,10 +2106,8 @@
 		skb = skb_clone(skb, GFP_ATOMIC);
 		kfree_skb(tmp_skb);
 
-		if (!skb) {
-			ret = -ENOMEM;
-			goto free;
-		}
+		if (!skb)
+			goto fail_rcu;
 	}
 
 	hdr.frame_control = fc;
@@ -2181,7 +2156,7 @@
 		if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
 			ieee80211_free_txskb(&local->hw, skb);
 			skb = NULL;
-			return ERR_PTR(-ENOMEM);
+			goto fail_rcu;
 		}
 	}
 
@@ -2215,6 +2190,9 @@
 	nh_pos += hdrlen;
 	h_pos += hdrlen;
 
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
 	/* Update skb pointers to various headers since this modified frame
 	 * is going to go through Linux networking code that may potentially
 	 * need things like pointer to IP header. */
@@ -2225,90 +2203,23 @@
 	info = IEEE80211_SKB_CB(skb);
 	memset(info, 0, sizeof(*info));
 
-	info->flags = info_flags;
-	info->ack_frame_id = info_id;
-	info->band = band;
-
-	return skb;
- free:
-	kfree_skb(skb);
-	return ERR_PTR(ret);
-}
-
-void __ieee80211_subif_start_xmit(struct sk_buff *skb,
-				  struct net_device *dev,
-				  u32 info_flags)
-{
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_local *local = sdata->local;
-
-	if (unlikely(skb->len < ETH_HLEN)) {
-		kfree_skb(skb);
-		return;
-	}
-
-	rcu_read_lock();
-
-	/* Measure frame arrival for Tx latency statistics calculation */
-	ieee80211_tx_latency_start_msrmnt(local, skb);
-
-	skb = ieee80211_build_hdr(sdata, skb, info_flags);
-	if (IS_ERR(skb))
-		goto out;
-
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
 	dev->trans_start = jiffies;
 
-	ieee80211_xmit(sdata, skb);
- out:
-	rcu_read_unlock();
-}
+	info->flags = info_flags;
+	info->ack_frame_id = info_id;
 
-/**
- * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs
- * @skb: packet to be sent
- * @dev: incoming interface
- *
- * On failure skb will be freed.
- */
-netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
-				       struct net_device *dev)
-{
-	__ieee80211_subif_start_xmit(skb, dev, 0);
+	ieee80211_xmit(sdata, skb, band);
+	rcu_read_unlock();
+
+	return NETDEV_TX_OK;
+
+ fail_rcu:
+	rcu_read_unlock();
+ fail:
+	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
 
-struct sk_buff *
-ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
-			      struct sk_buff *skb, u32 info_flags)
-{
-	struct ieee80211_hdr *hdr;
-	struct ieee80211_tx_data tx = {
-		.local = sdata->local,
-		.sdata = sdata,
-	};
-
-	rcu_read_lock();
-
-	skb = ieee80211_build_hdr(sdata, skb, info_flags);
-	if (IS_ERR(skb))
-		goto out;
-
-	hdr = (void *)skb->data;
-	tx.sta = sta_info_get(sdata, hdr->addr1);
-	tx.skb = skb;
-
-	if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) {
-		rcu_read_unlock();
-		kfree_skb(skb);
-		return ERR_PTR(-EINVAL);
-	}
-
-out:
-	rcu_read_unlock();
-	return skb;
-}
 
 /*
  * ieee80211_clear_tx_pending may not be called in a context where
@@ -2348,8 +2259,8 @@
 			dev_kfree_skb(skb);
 			return true;
 		}
-		info->band = chanctx_conf->def.chan->band;
-		result = ieee80211_tx(sdata, skb, true);
+		result = ieee80211_tx(sdata, skb, true,
+				      chanctx_conf->def.chan->band);
 	} else {
 		struct sk_buff_head skbs;
 
@@ -2963,16 +2874,19 @@
 EXPORT_SYMBOL(ieee80211_nullfunc_get);
 
 struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
-				       const u8 *src_addr,
+				       struct ieee80211_vif *vif,
 				       const u8 *ssid, size_t ssid_len,
 				       size_t tailroom)
 {
-	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_local *local;
 	struct ieee80211_hdr_3addr *hdr;
 	struct sk_buff *skb;
 	size_t ie_ssid_len;
 	u8 *pos;
 
+	sdata = vif_to_sdata(vif);
+	local = sdata->local;
 	ie_ssid_len = 2 + ssid_len;
 
 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
@@ -2987,7 +2901,7 @@
 	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 					 IEEE80211_STYPE_PROBE_REQ);
 	eth_broadcast_addr(hdr->addr1);
-	memcpy(hdr->addr2, src_addr, ETH_ALEN);
+	memcpy(hdr->addr2, vif->addr, ETH_ALEN);
 	eth_broadcast_addr(hdr->addr3);
 
 	pos = skb_put(skb, ie_ssid_len);
@@ -3106,97 +3020,6 @@
 }
 EXPORT_SYMBOL(ieee80211_get_buffered_bc);
 
-int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
-{
-	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
-	struct ieee80211_sub_if_data *sdata = sta->sdata;
-	struct ieee80211_local *local = sdata->local;
-	int ret;
-	u32 queues;
-
-	lockdep_assert_held(&local->sta_mtx);
-
-	/* only some cases are supported right now */
-	switch (sdata->vif.type) {
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_AP_VLAN:
-		break;
-	default:
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	if (WARN_ON(tid >= IEEE80211_NUM_UPS))
-		return -EINVAL;
-
-	if (sta->reserved_tid == tid) {
-		ret = 0;
-		goto out;
-	}
-
-	if (sta->reserved_tid != IEEE80211_TID_UNRESERVED) {
-		sdata_err(sdata, "TID reservation already active\n");
-		ret = -EALREADY;
-		goto out;
-	}
-
-	ieee80211_stop_vif_queues(sdata->local, sdata,
-				  IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
-
-	synchronize_net();
-
-	/* Tear down BA sessions so we stop aggregating on this TID */
-	if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) {
-		set_sta_flag(sta, WLAN_STA_BLOCK_BA);
-		__ieee80211_stop_tx_ba_session(sta, tid,
-					       AGG_STOP_LOCAL_REQUEST);
-	}
-
-	queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]);
-	__ieee80211_flush_queues(local, sdata, queues);
-
-	sta->reserved_tid = tid;
-
-	ieee80211_wake_vif_queues(local, sdata,
-				  IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
-
-	if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)
-		clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
-
-	ret = 0;
- out:
-	return ret;
-}
-EXPORT_SYMBOL(ieee80211_reserve_tid);
-
-void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid)
-{
-	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
-	struct ieee80211_sub_if_data *sdata = sta->sdata;
-
-	lockdep_assert_held(&sdata->local->sta_mtx);
-
-	/* only some cases are supported right now */
-	switch (sdata->vif.type) {
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_AP_VLAN:
-		break;
-	default:
-		WARN_ON(1);
-		return;
-	}
-
-	if (tid != sta->reserved_tid) {
-		sdata_err(sdata, "TID to unreserve (%d) isn't reserved\n", tid);
-		return;
-	}
-
-	sta->reserved_tid = IEEE80211_TID_UNRESERVED;
-}
-EXPORT_SYMBOL(ieee80211_unreserve_tid);
-
 void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
 				 struct sk_buff *skb, int tid,
 				 enum ieee80211_band band)
@@ -3218,7 +3041,6 @@
 	 * requirements are that we do not come into tx with bhs on.
 	 */
 	local_bh_disable();
-	IEEE80211_SKB_CB(skb)->band = band;
-	ieee80211_xmit(sdata, skb);
+	ieee80211_xmit(sdata, skb, band);
 	local_bh_enable();
 }
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 974ebe7..3c61060 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -576,19 +576,15 @@
 	return queues;
 }
 
-void __ieee80211_flush_queues(struct ieee80211_local *local,
-			      struct ieee80211_sub_if_data *sdata,
-			      unsigned int queues)
+void ieee80211_flush_queues(struct ieee80211_local *local,
+			    struct ieee80211_sub_if_data *sdata)
 {
+	unsigned int queues;
+
 	if (!local->ops->flush)
 		return;
 
-	/*
-	 * If no queue was set, or if the HW doesn't support
-	 * IEEE80211_HW_QUEUE_CONTROL - flush all queues
-	 */
-	if (!queues || !(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL))
-		queues = ieee80211_get_vif_queues(local, sdata);
+	queues = ieee80211_get_vif_queues(local, sdata);
 
 	ieee80211_stop_queues_by_reason(&local->hw, queues,
 					IEEE80211_QUEUE_STOP_REASON_FLUSH,
@@ -601,12 +597,6 @@
 					false);
 }
 
-void ieee80211_flush_queues(struct ieee80211_local *local,
-			    struct ieee80211_sub_if_data *sdata)
-{
-	__ieee80211_flush_queues(local, sdata, 0);
-}
-
 void ieee80211_stop_vif_queues(struct ieee80211_local *local,
 			       struct ieee80211_sub_if_data *sdata,
 			       enum queue_stop_reason reason)
@@ -703,34 +693,6 @@
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
 
-static void __iterate_stations(struct ieee80211_local *local,
-			       void (*iterator)(void *data,
-						struct ieee80211_sta *sta),
-			       void *data)
-{
-	struct sta_info *sta;
-
-	list_for_each_entry_rcu(sta, &local->sta_list, list) {
-		if (!sta->uploaded)
-			continue;
-
-		iterator(data, &sta->sta);
-	}
-}
-
-void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
-			void (*iterator)(void *data,
-					 struct ieee80211_sta *sta),
-			void *data)
-{
-	struct ieee80211_local *local = hw_to_local(hw);
-
-	rcu_read_lock();
-	__iterate_stations(local, iterator, data);
-	rcu_read_unlock();
-}
-EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_atomic);
-
 struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
@@ -841,9 +803,6 @@
 		case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
 		case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
 		case WLAN_EID_CHAN_SWITCH_PARAM:
-		case WLAN_EID_EXT_CAPABILITY:
-		case WLAN_EID_CHAN_SWITCH_TIMING:
-		case WLAN_EID_LINK_ID:
 		/*
 		 * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
 		 * that if the content gets bigger it might be needed more than once
@@ -863,24 +822,6 @@
 		elem_parse_failed = false;
 
 		switch (id) {
-		case WLAN_EID_LINK_ID:
-			if (elen + 2 != sizeof(struct ieee80211_tdls_lnkie)) {
-				elem_parse_failed = true;
-				break;
-			}
-			elems->lnk_id = (void *)(pos - 2);
-			break;
-		case WLAN_EID_CHAN_SWITCH_TIMING:
-			if (elen != sizeof(struct ieee80211_ch_switch_timing)) {
-				elem_parse_failed = true;
-				break;
-			}
-			elems->ch_sw_timing = (void *)pos;
-			break;
-		case WLAN_EID_EXT_CAPABILITY:
-			elems->ext_capab = pos;
-			elems->ext_capab_len = elen;
-			break;
 		case WLAN_EID_SSID:
 			elems->ssid = pos;
 			elems->ssid_len = elen;
@@ -1132,7 +1073,6 @@
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	int ac;
 	bool use_11b, enable_qos;
-	bool is_ocb; /* Use another EDCA parameters if dot11OCBActivated=true */
 	int aCWmin, aCWmax;
 
 	if (!local->ops->conf_tx)
@@ -1157,8 +1097,6 @@
 	 */
 	enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION);
 
-	is_ocb = (sdata->vif.type == NL80211_IFTYPE_OCB);
-
 	/* Set defaults according to 802.11-2007 Table 7-37 */
 	aCWmax = 1023;
 	if (use_11b)
@@ -1180,10 +1118,7 @@
 				qparam.cw_max = aCWmax;
 				qparam.cw_min = aCWmin;
 				qparam.txop = 0;
-				if (is_ocb)
-					qparam.aifs = 9;
-				else
-					qparam.aifs = 7;
+				qparam.aifs = 7;
 				break;
 			/* never happens but let's not leave undefined */
 			default:
@@ -1191,32 +1126,21 @@
 				qparam.cw_max = aCWmax;
 				qparam.cw_min = aCWmin;
 				qparam.txop = 0;
-				if (is_ocb)
-					qparam.aifs = 6;
-				else
-					qparam.aifs = 3;
+				qparam.aifs = 3;
 				break;
 			case IEEE80211_AC_VI:
 				qparam.cw_max = aCWmin;
 				qparam.cw_min = (aCWmin + 1) / 2 - 1;
-				if (is_ocb)
-					qparam.txop = 0;
-				else if (use_11b)
+				if (use_11b)
 					qparam.txop = 6016/32;
 				else
 					qparam.txop = 3008/32;
-
-				if (is_ocb)
-					qparam.aifs = 3;
-				else
-					qparam.aifs = 2;
+				qparam.aifs = 2;
 				break;
 			case IEEE80211_AC_VO:
 				qparam.cw_max = (aCWmin + 1) / 2 - 1;
 				qparam.cw_min = (aCWmin + 1) / 4 - 1;
-				if (is_ocb)
-					qparam.txop = 0;
-				else if (use_11b)
+				if (use_11b)
 					qparam.txop = 3264/32;
 				else
 					qparam.txop = 1504/32;
@@ -1339,7 +1263,6 @@
 	int ext_rates_len;
 	int shift;
 	u32 rate_flags;
-	bool have_80mhz = false;
 
 	*offset = 0;
 
@@ -1468,15 +1391,7 @@
 		*offset = noffset;
 	}
 
-	/* Check if any channel in this sband supports at least 80 MHz */
-	for (i = 0; i < sband->n_channels; i++) {
-		if (!(sband->channels[i].flags & IEEE80211_CHAN_NO_80MHZ)) {
-			have_80mhz = true;
-			break;
-		}
-	}
-
-	if (sband->vht_cap.vht_supported && have_80mhz) {
+	if (sband->vht_cap.vht_supported) {
 		if (end - pos < 2 + sizeof(struct ieee80211_vht_cap))
 			goto out_err;
 		pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
@@ -1532,8 +1447,7 @@
 };
 
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-					  const u8 *src, const u8 *dst,
-					  u32 ratemask,
+					  u8 *dst, u32 ratemask,
 					  struct ieee80211_channel *chan,
 					  const u8 *ssid, size_t ssid_len,
 					  const u8 *ie, size_t ie_len,
@@ -1558,8 +1472,8 @@
 	else
 		chandef.chan = chan;
 
-	skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len,
-				     100 + ie_len);
+	skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
+				     ssid, ssid_len, 100 + ie_len);
 	if (!skb)
 		return NULL;
 
@@ -1581,8 +1495,7 @@
 	return skb;
 }
 
-void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
-			      const u8 *src, const u8 *dst,
+void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 			      const u8 *ssid, size_t ssid_len,
 			      const u8 *ie, size_t ie_len,
 			      u32 ratemask, bool directed, u32 tx_flags,
@@ -1590,7 +1503,7 @@
 {
 	struct sk_buff *skb;
 
-	skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel,
+	skb = ieee80211_build_probe_req(sdata, dst, ratemask, channel,
 					ssid, ssid_len,
 					ie, ie_len, directed);
 	if (skb) {
@@ -1732,7 +1645,6 @@
 	int res, i;
 	bool reconfig_due_to_wowlan = false;
 	struct ieee80211_sub_if_data *sched_scan_sdata;
-	struct cfg80211_sched_scan_request *sched_scan_req;
 	bool sched_scan_stopped = false;
 
 #ifdef CONFIG_PM
@@ -1901,10 +1813,6 @@
 			ieee80211_bss_info_change_notify(sdata, changed);
 			sdata_unlock(sdata);
 			break;
-		case NL80211_IFTYPE_OCB:
-			changed |= BSS_CHANGED_OCB;
-			ieee80211_bss_info_change_notify(sdata, changed);
-			break;
 		case NL80211_IFTYPE_ADHOC:
 			changed |= BSS_CHANGED_IBSS;
 			/* fall through */
@@ -2023,15 +1931,13 @@
 	mutex_lock(&local->mtx);
 	sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
 						lockdep_is_held(&local->mtx));
-	sched_scan_req = rcu_dereference_protected(local->sched_scan_req,
-						lockdep_is_held(&local->mtx));
-	if (sched_scan_sdata && sched_scan_req)
+	if (sched_scan_sdata && local->sched_scan_req)
 		/*
 		 * Sched scan stopped, but we don't want to report it. Instead,
 		 * we're trying to reschedule.
 		 */
 		if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
-							 sched_scan_req))
+							 local->sched_scan_req))
 			sched_scan_stopped = true;
 	mutex_unlock(&local->mtx);
 
@@ -2043,7 +1949,7 @@
 	 * We may want to change that later, however.
 	 */
 	if (!local->suspended || reconfig_due_to_wowlan)
-		drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
+		drv_restart_complete(local);
 
 	if (!local->suspended)
 		return 0;
@@ -2054,9 +1960,6 @@
 	mb();
 	local->resuming = false;
 
-	if (!reconfig_due_to_wowlan)
-		drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
-
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (!ieee80211_sdata_running(sdata))
 			continue;
@@ -2149,35 +2052,41 @@
 	return false;
 }
 
-size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
-			      const u8 *ids, int n_ids,
-			      const u8 *after_ric, int n_after_ric,
-			      size_t offset)
-{
-	size_t pos = offset;
-
-	while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
-		if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
-			pos += 2 + ies[pos + 1];
-
-			while (pos < ielen &&
-			       !ieee80211_id_in_list(after_ric, n_after_ric,
-						     ies[pos]))
-				pos += 2 + ies[pos + 1];
-		} else {
-			pos += 2 + ies[pos + 1];
-		}
-	}
-
-	return pos;
-}
-
+/**
+ * ieee80211_ie_split - split an IE buffer according to ordering
+ *
+ * @ies: the IE buffer
+ * @ielen: the length of the IE buffer
+ * @ids: an array with element IDs that are allowed before
+ *	the split
+ * @n_ids: the size of the element ID array
+ * @offset: offset where to start splitting in the buffer
+ *
+ * This function splits an IE buffer by updating the @offset
+ * variable to point to the location where the buffer should be
+ * split.
+ *
+ * It assumes that the given IE buffer is well-formed, this
+ * has to be guaranteed by the caller!
+ *
+ * It also assumes that the IEs in the buffer are ordered
+ * correctly, if not the result of using this function will not
+ * be ordered correctly either, i.e. it does no reordering.
+ *
+ * The function returns the offset where the next part of the
+ * buffer starts, which may be @ielen if the entire (remainder)
+ * of the buffer should be used.
+ */
 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
 			  const u8 *ids, int n_ids, size_t offset)
 {
-	return ieee80211_ie_split_ric(ies, ielen, ids, n_ids, NULL, 0, offset);
+	size_t pos = offset;
+
+	while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
+		pos += 2 + ies[pos + 1];
+
+	return pos;
 }
-EXPORT_SYMBOL(ieee80211_ie_split);
 
 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
 {
@@ -2617,23 +2526,11 @@
 	struct ieee80211_local *local =
 		container_of(work, struct ieee80211_local, radar_detected_work);
 	struct cfg80211_chan_def chandef = local->hw.conf.chandef;
-	struct ieee80211_chanctx *ctx;
-	int num_chanctx = 0;
-
-	mutex_lock(&local->chanctx_mtx);
-	list_for_each_entry(ctx, &local->chanctx_list, list) {
-		if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
-			continue;
-
-		num_chanctx++;
-		chandef = ctx->conf.def;
-	}
-	mutex_unlock(&local->chanctx_mtx);
 
 	ieee80211_dfs_cac_cancel(local);
 
-	if (num_chanctx > 1)
-		/* XXX: multi-channel is not supported yet */
+	if (local->use_chanctx)
+		/* currently not handled */
 		WARN_ON(1);
 	else
 		cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index bc9e8fc..671ce0d 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -287,8 +287,6 @@
 		/* fall through */
 	case NL80211_CHAN_WIDTH_20_NOHT:
 	case NL80211_CHAN_WIDTH_20:
-		bw = IEEE80211_STA_RX_BW_20;
-		break;
 	case NL80211_CHAN_WIDTH_40:
 		bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
 				IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index a4220e9..9181fb6 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -111,6 +111,8 @@
 	    (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
 		return newhdr + hdrlen;
 
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_WEP_IV_LEN);
 	ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
 	return newhdr + hdrlen;
 }
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index c04e74d..77509d8 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -53,49 +53,11 @@
 	}
 }
 
-/**
- * ieee80211_fix_reserved_tid - return the TID to use if this one is reserved
- * @tid: the assumed-reserved TID
- *
- * Returns: the alternative TID to use, or 0 on error
- */
-static inline u8 ieee80211_fix_reserved_tid(u8 tid)
-{
-	switch (tid) {
-	case 0:
-		return 3;
-	case 1:
-		return 2;
-	case 2:
-		return 1;
-	case 3:
-		return 0;
-	case 4:
-		return 5;
-	case 5:
-		return 4;
-	case 6:
-		return 7;
-	case 7:
-		return 6;
-	}
-
-	return 0;
-}
-
 static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
-				     struct sta_info *sta, struct sk_buff *skb)
+				     struct sk_buff *skb)
 {
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-
 	/* in case we are a client verify acm is not set for this ac */
-	while (sdata->wmm_acm & BIT(skb->priority)) {
-		int ac = ieee802_1d_to_ac[skb->priority];
-
-		if (ifmgd->tx_tspec[ac].admitted_time &&
-		    skb->priority == ifmgd->tx_tspec[ac].up)
-			return ac;
-
+	while (unlikely(sdata->wmm_acm & BIT(skb->priority))) {
 		if (wme_downgrade_ac(skb)) {
 			/*
 			 * This should not really happen. The AP has marked all
@@ -107,10 +69,6 @@
 		}
 	}
 
-	/* Check to see if this is a reserved TID */
-	if (sta && sta->reserved_tid == skb->priority)
-		skb->priority = ieee80211_fix_reserved_tid(skb->priority);
-
 	/* look up which queue to use for frames with this 1d tag */
 	return ieee802_1d_to_ac[skb->priority];
 }
@@ -138,7 +96,7 @@
 	p = ieee80211_get_qos_ctl(hdr);
 	skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
 
-	return ieee80211_downgrade_queue(sdata, NULL, skb);
+	return ieee80211_downgrade_queue(sdata, skb);
 }
 
 /* Indicate which queue to use. */
@@ -150,7 +108,6 @@
 	const u8 *ra = NULL;
 	bool qos = false;
 	struct mac80211_qos_map *qos_map;
-	u16 ret;
 
 	if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
 		skb->priority = 0; /* required for correct WPA/11i MIC */
@@ -177,20 +134,11 @@
 		break;
 #endif
 	case NL80211_IFTYPE_STATION:
-		/* might be a TDLS station */
-		sta = sta_info_get(sdata, skb->data);
-		if (sta)
-			qos = sta->sta.wme;
-
 		ra = sdata->u.mgd.bssid;
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		ra = skb->data;
 		break;
-	case NL80211_IFTYPE_OCB:
-		/* all stations are required to support WME */
-		qos = true;
-		break;
 	default:
 		break;
 	}
@@ -200,29 +148,27 @@
 		if (sta)
 			qos = sta->sta.wme;
 	}
+	rcu_read_unlock();
 
 	if (!qos) {
 		skb->priority = 0; /* required for correct WPA/11i MIC */
-		ret = IEEE80211_AC_BE;
-		goto out;
+		return IEEE80211_AC_BE;
 	}
 
 	if (skb->protocol == sdata->control_port_protocol) {
 		skb->priority = 7;
-		goto downgrade;
+		return ieee80211_downgrade_queue(sdata, skb);
 	}
 
 	/* use the data classifier to determine what 802.1d tag the
 	 * data frame has */
+	rcu_read_lock();
 	qos_map = rcu_dereference(sdata->qos_map);
 	skb->priority = cfg80211_classify8021d(skb, qos_map ?
 					       &qos_map->qos_map : NULL);
-
- downgrade:
-	ret = ieee80211_downgrade_queue(sdata, sta, skb);
- out:
 	rcu_read_unlock();
-	return ret;
+
+	return ieee80211_downgrade_queue(sdata, skb);
 }
 
 /**
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index 80151ed..7fea4bb 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -13,6 +13,8 @@
 #include <linux/netdevice.h>
 #include "ieee80211_i.h"
 
+extern const int ieee802_1d_to_ac[8];
+
 u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
 				 struct sk_buff *skb,
 				 struct ieee80211_hdr *hdr);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 12398fd..983527a 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -209,6 +209,8 @@
 
 	pos = skb_push(skb, IEEE80211_TKIP_IV_LEN);
 	memmove(pos, pos + IEEE80211_TKIP_IV_LEN, hdrlen);
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_TKIP_IV_LEN);
 	pos += hdrlen;
 
 	/* the HW only needs room for the IV, but not the actual IV */
@@ -432,6 +434,8 @@
 
 	pos = skb_push(skb, IEEE80211_CCMP_HDR_LEN);
 	memmove(pos, pos + IEEE80211_CCMP_HDR_LEN, hdrlen);
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_CCMP_HDR_LEN);
 
 	/* the HW only needs room for the IV, but not the actual IV */
 	if (info->control.hw_key &&
@@ -571,6 +575,7 @@
 
 	pos = skb_push(skb, cs->hdr_len);
 	memmove(pos, pos + cs->hdr_len, hdrlen);
+	skb_set_network_header(skb, skb_network_offset(skb) + cs->hdr_len);
 
 	return TX_CONTINUE;
 }
diff --git a/net/mac802154/Kconfig b/net/mac802154/Kconfig
index 4621ecb..e62e73f 100644
--- a/net/mac802154/Kconfig
+++ b/net/mac802154/Kconfig
@@ -4,7 +4,7 @@
 	depends on IEEE802154
 	depends on CRC_CCITT
 	depends on CRYPTO_AUTHENC
-	select BPAUTO_CRYPTO_CCM
+	select BACKPORT_CRYPTO_CCM
 	depends on CRYPTO_CTR
 	depends on CRYPTO_AES
 	---help---
@@ -17,5 +17,5 @@
 	  been tested yet!
 
 	  If you plan to use HardMAC IEEE 802.15.4 devices, you can
-	  say N here. Alternatively you can say M to compile it as
+	  say N here. Alternatievly you can say M to compile it as
 	  module.
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
index 4ea25d0..562844a 100644
--- a/net/mac802154/Makefile
+++ b/net/mac802154/Makefile
@@ -1,5 +1,5 @@
 obj-$(CPTCFG_MAC802154)	+= mac802154.o
-mac802154-objs		:= main.o rx.o tx.o mac_cmd.o mib.o \
-			   iface.o llsec.o util.o cfg.o
+mac802154-objs		:= ieee802154_dev.o rx.o tx.o mac_cmd.o mib.o \
+			   monitor.o wpan.o llsec.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
deleted file mode 100644
index c035708..0000000
--- a/net/mac802154/cfg.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/* 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.
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- *
- * Based on: net/mac80211/cfg.c
- */
-
-#include <net/rtnetlink.h>
-#include <net/cfg802154.h>
-
-#include "ieee802154_i.h"
-#include "driver-ops.h"
-#include "cfg.h"
-
-static struct net_device *
-ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy,
-				const char *name, int type)
-{
-	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-	struct net_device *dev;
-
-	rtnl_lock();
-	dev = ieee802154_if_add(local, name, type,
-				cpu_to_le64(0x0000000000000000ULL));
-	rtnl_unlock();
-
-	return dev;
-}
-
-static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
-					    struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-
-	ieee802154_if_remove(sdata);
-}
-
-static int
-ieee802154_add_iface(struct wpan_phy *phy, const char *name,
-		     enum nl802154_iftype type, __le64 extended_addr)
-{
-	struct ieee802154_local *local = wpan_phy_priv(phy);
-	struct net_device *err;
-
-	err = ieee802154_if_add(local, name, type, extended_addr);
-	if (IS_ERR(err))
-		return PTR_ERR(err);
-
-	return 0;
-}
-
-static int
-ieee802154_del_iface(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev)
-{
-	ieee802154_if_remove(IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev));
-
-	return 0;
-}
-
-static int
-ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
-{
-	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-	int ret;
-
-	ASSERT_RTNL();
-
-	/* check if phy support this setting */
-	if (!(wpan_phy->channels_supported[page] & BIT(channel)))
-		return -EINVAL;
-
-	ret = drv_set_channel(local, page, channel);
-	if (!ret) {
-		wpan_phy->current_page = page;
-		wpan_phy->current_channel = channel;
-	}
-
-	return ret;
-}
-
-static int
-ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
-		      __le16 pan_id)
-{
-	ASSERT_RTNL();
-
-	/* TODO
-	 * I am not sure about to check here on broadcast pan_id.
-	 * Broadcast is a valid setting, comment from 802.15.4:
-	 * If this value is 0xffff, the device is not associated.
-	 *
-	 * This could useful to simple deassociate an device.
-	 */
-	if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
-		return -EINVAL;
-
-	wpan_dev->pan_id = pan_id;
-	return 0;
-}
-
-static int
-ieee802154_set_backoff_exponent(struct wpan_phy *wpan_phy,
-				struct wpan_dev *wpan_dev,
-				u8 min_be, u8 max_be)
-{
-	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-
-	ASSERT_RTNL();
-
-	if (!(local->hw.flags & IEEE802154_HW_CSMA_PARAMS))
-		return -EOPNOTSUPP;
-
-	wpan_dev->min_be = min_be;
-	wpan_dev->max_be = max_be;
-	return 0;
-}
-
-static int
-ieee802154_set_short_addr(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
-			  __le16 short_addr)
-{
-	ASSERT_RTNL();
-
-	/* TODO
-	 * I am not sure about to check here on broadcast short_addr.
-	 * Broadcast is a valid setting, comment from 802.15.4:
-	 * A value of 0xfffe indicates that the device has
-	 * associated but has not been allocated an address. A
-	 * value of 0xffff indicates that the device does not
-	 * have a short address.
-	 *
-	 * I think we should allow to set these settings but
-	 * don't allow to allow socket communication with it.
-	 */
-	if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) ||
-	    short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST))
-		return -EINVAL;
-
-	wpan_dev->short_addr = short_addr;
-	return 0;
-}
-
-static int
-ieee802154_set_max_csma_backoffs(struct wpan_phy *wpan_phy,
-				 struct wpan_dev *wpan_dev,
-				 u8 max_csma_backoffs)
-{
-	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-
-	ASSERT_RTNL();
-
-	if (!(local->hw.flags & IEEE802154_HW_CSMA_PARAMS))
-		return -EOPNOTSUPP;
-
-	wpan_dev->csma_retries = max_csma_backoffs;
-	return 0;
-}
-
-static int
-ieee802154_set_max_frame_retries(struct wpan_phy *wpan_phy,
-				 struct wpan_dev *wpan_dev,
-				 s8 max_frame_retries)
-{
-	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-
-	ASSERT_RTNL();
-
-	if (!(local->hw.flags & IEEE802154_HW_FRAME_RETRIES))
-		return -EOPNOTSUPP;
-
-	wpan_dev->frame_retries = max_frame_retries;
-	return 0;
-}
-
-static int
-ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
-			bool mode)
-{
-	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-
-	ASSERT_RTNL();
-
-	if (!(local->hw.flags & IEEE802154_HW_LBT))
-		return -EOPNOTSUPP;
-
-	wpan_dev->lbt = mode;
-	return 0;
-}
-
-const struct cfg802154_ops mac802154_config_ops = {
-	.add_virtual_intf_deprecated = ieee802154_add_iface_deprecated,
-	.del_virtual_intf_deprecated = ieee802154_del_iface_deprecated,
-	.add_virtual_intf = ieee802154_add_iface,
-	.del_virtual_intf = ieee802154_del_iface,
-	.set_channel = ieee802154_set_channel,
-	.set_pan_id = ieee802154_set_pan_id,
-	.set_short_addr = ieee802154_set_short_addr,
-	.set_backoff_exponent = ieee802154_set_backoff_exponent,
-	.set_max_csma_backoffs = ieee802154_set_max_csma_backoffs,
-	.set_max_frame_retries = ieee802154_set_max_frame_retries,
-	.set_lbt_mode = ieee802154_set_lbt_mode,
-};
diff --git a/net/mac802154/cfg.h b/net/mac802154/cfg.h
deleted file mode 100644
index e2718f9..0000000
--- a/net/mac802154/cfg.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* mac802154 configuration hooks for cfg802154
- */
-
-#ifndef __CFG_H
-#define __CFG_H
-
-extern const struct cfg802154_ops mac802154_config_ops;
-
-#endif /* __CFG_H */
diff --git a/net/mac802154/driver-ops.h b/net/mac802154/driver-ops.h
deleted file mode 100644
index f21e864..0000000
--- a/net/mac802154/driver-ops.h
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifndef __MAC802154_DRVIER_OPS
-#define __MAC802154_DRIVER_OPS
-
-#include <linux/types.h>
-#include <linux/rtnetlink.h>
-
-#include <net/mac802154.h>
-
-#include "ieee802154_i.h"
-
-static inline int
-drv_xmit_async(struct ieee802154_local *local, struct sk_buff *skb)
-{
-	return local->ops->xmit_async(&local->hw, skb);
-}
-
-static inline int
-drv_xmit_sync(struct ieee802154_local *local, struct sk_buff *skb)
-{
-	/* don't allow other operations while sync xmit */
-	ASSERT_RTNL();
-
-	might_sleep();
-
-	return local->ops->xmit_sync(&local->hw, skb);
-}
-
-static inline int drv_start(struct ieee802154_local *local)
-{
-	might_sleep();
-
-	local->started = true;
-	smp_mb();
-
-	return local->ops->start(&local->hw);
-}
-
-static inline void drv_stop(struct ieee802154_local *local)
-{
-	might_sleep();
-
-	local->ops->stop(&local->hw);
-
-	/* sync away all work on the tasklet before clearing started */
-	tasklet_disable(&local->tasklet);
-	tasklet_enable(&local->tasklet);
-
-	barrier();
-
-	local->started = false;
-}
-
-static inline int
-drv_set_channel(struct ieee802154_local *local, u8 page, u8 channel)
-{
-	might_sleep();
-
-	return local->ops->set_channel(&local->hw, page, channel);
-}
-
-static inline int drv_set_tx_power(struct ieee802154_local *local, s8 dbm)
-{
-	might_sleep();
-
-	if (!local->ops->set_txpower) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	return local->ops->set_txpower(&local->hw, dbm);
-}
-
-static inline int drv_set_cca_mode(struct ieee802154_local *local, u8 cca_mode)
-{
-	might_sleep();
-
-	if (!local->ops->set_cca_mode) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	return local->ops->set_cca_mode(&local->hw, cca_mode);
-}
-
-static inline int drv_set_lbt_mode(struct ieee802154_local *local, bool mode)
-{
-	might_sleep();
-
-	if (!local->ops->set_lbt) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	return local->ops->set_lbt(&local->hw, mode);
-}
-
-static inline int
-drv_set_cca_ed_level(struct ieee802154_local *local, s32 ed_level)
-{
-	might_sleep();
-
-	if (!local->ops->set_cca_ed_level) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	return local->ops->set_cca_ed_level(&local->hw, ed_level);
-}
-
-static inline int drv_set_pan_id(struct ieee802154_local *local, __le16 pan_id)
-{
-	struct ieee802154_hw_addr_filt filt;
-
-	might_sleep();
-
-	if (!local->ops->set_hw_addr_filt) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	filt.pan_id = pan_id;
-
-	return local->ops->set_hw_addr_filt(&local->hw, &filt,
-					    IEEE802154_AFILT_PANID_CHANGED);
-}
-
-static inline int
-drv_set_extended_addr(struct ieee802154_local *local, __le64 extended_addr)
-{
-	struct ieee802154_hw_addr_filt filt;
-
-	might_sleep();
-
-	if (!local->ops->set_hw_addr_filt) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	filt.ieee_addr = extended_addr;
-
-	return local->ops->set_hw_addr_filt(&local->hw, &filt,
-					    IEEE802154_AFILT_IEEEADDR_CHANGED);
-}
-
-static inline int
-drv_set_short_addr(struct ieee802154_local *local, __le16 short_addr)
-{
-	struct ieee802154_hw_addr_filt filt;
-
-	might_sleep();
-
-	if (!local->ops->set_hw_addr_filt) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	filt.short_addr = short_addr;
-
-	return local->ops->set_hw_addr_filt(&local->hw, &filt,
-					    IEEE802154_AFILT_SADDR_CHANGED);
-}
-
-static inline int
-drv_set_pan_coord(struct ieee802154_local *local, bool is_coord)
-{
-	struct ieee802154_hw_addr_filt filt;
-
-	might_sleep();
-
-	if (!local->ops->set_hw_addr_filt) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	filt.pan_coord = is_coord;
-
-	return local->ops->set_hw_addr_filt(&local->hw, &filt,
-					    IEEE802154_AFILT_PANC_CHANGED);
-}
-
-static inline int
-drv_set_csma_params(struct ieee802154_local *local, u8 min_be, u8 max_be,
-		    u8 max_csma_backoffs)
-{
-	might_sleep();
-
-	if (!local->ops->set_csma_params) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	return local->ops->set_csma_params(&local->hw, min_be, max_be,
-					   max_csma_backoffs);
-}
-
-static inline int
-drv_set_max_frame_retries(struct ieee802154_local *local, s8 max_frame_retries)
-{
-	might_sleep();
-
-	if (!local->ops->set_frame_retries) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	return local->ops->set_frame_retries(&local->hw, max_frame_retries);
-}
-
-static inline int
-drv_set_promiscuous_mode(struct ieee802154_local *local, bool on)
-{
-	might_sleep();
-
-	if (!local->ops->set_promiscuous_mode) {
-		WARN_ON(1);
-		return -EOPNOTSUPP;
-	}
-
-	return local->ops->set_promiscuous_mode(&local->hw, on);
-}
-
-#endif /* __MAC802154_DRVIER_OPS */
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
new file mode 100644
index 0000000..b36b2b9
--- /dev/null
+++ b/net/mac802154/ieee802154_dev.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2007-2012 Siemens AG
+ *
+ * Written by:
+ * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ *
+ * Based on the code from 'linux-zigbee.sourceforge.net' project.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+
+#include <net/netlink.h>
+#include <linux/nl802154.h>
+#include <net/mac802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/route.h>
+#include <net/wpan-phy.h>
+
+#include "mac802154.h"
+
+int mac802154_slave_open(struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct mac802154_sub_if_data *subif;
+	struct mac802154_priv *ipriv = priv->hw;
+	int res = 0;
+
+	ASSERT_RTNL();
+
+	if (priv->type == IEEE802154_DEV_WPAN) {
+		mutex_lock(&priv->hw->slaves_mtx);
+		list_for_each_entry(subif, &priv->hw->slaves, list) {
+			if (subif != priv && subif->type == priv->type &&
+			    subif->running) {
+				mutex_unlock(&priv->hw->slaves_mtx);
+				return -EBUSY;
+			}
+		}
+		mutex_unlock(&priv->hw->slaves_mtx);
+	}
+
+	mutex_lock(&priv->hw->slaves_mtx);
+	priv->running = true;
+	mutex_unlock(&priv->hw->slaves_mtx);
+
+	if (ipriv->open_count++ == 0) {
+		res = ipriv->ops->start(&ipriv->hw);
+		WARN_ON(res);
+		if (res)
+			goto err;
+	}
+
+	if (ipriv->ops->ieee_addr) {
+		__le64 addr = ieee802154_devaddr_from_raw(dev->dev_addr);
+
+		res = ipriv->ops->ieee_addr(&ipriv->hw, addr);
+		WARN_ON(res);
+		if (res)
+			goto err;
+		mac802154_dev_set_ieee_addr(dev);
+	}
+
+	netif_start_queue(dev);
+	return 0;
+err:
+	priv->hw->open_count--;
+
+	return res;
+}
+
+int mac802154_slave_close(struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct mac802154_priv *ipriv = priv->hw;
+
+	ASSERT_RTNL();
+
+	netif_stop_queue(dev);
+
+	mutex_lock(&priv->hw->slaves_mtx);
+	priv->running = false;
+	mutex_unlock(&priv->hw->slaves_mtx);
+
+	if (!--ipriv->open_count)
+		ipriv->ops->stop(&ipriv->hw);
+
+	return 0;
+}
+
+static int
+mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv;
+	struct mac802154_priv *ipriv;
+	int err;
+
+	ipriv = wpan_phy_priv(phy);
+
+	priv = netdev_priv(dev);
+	priv->dev = dev;
+	priv->hw = ipriv;
+
+	dev->needed_headroom = ipriv->hw.extra_tx_headroom;
+
+	SET_NETDEV_DEV(dev, &ipriv->phy->dev);
+
+	mutex_lock(&ipriv->slaves_mtx);
+	if (!ipriv->running) {
+		mutex_unlock(&ipriv->slaves_mtx);
+		return -ENODEV;
+	}
+	mutex_unlock(&ipriv->slaves_mtx);
+
+	err = register_netdev(dev);
+	if (err < 0)
+		return err;
+
+	rtnl_lock();
+	mutex_lock(&ipriv->slaves_mtx);
+	list_add_tail_rcu(&priv->list, &ipriv->slaves);
+	mutex_unlock(&ipriv->slaves_mtx);
+	rtnl_unlock();
+
+	return 0;
+}
+
+static void
+mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev)
+{
+	struct mac802154_sub_if_data *sdata;
+
+	ASSERT_RTNL();
+
+	sdata = netdev_priv(dev);
+
+	BUG_ON(sdata->hw->phy != phy);
+
+	mutex_lock(&sdata->hw->slaves_mtx);
+	list_del_rcu(&sdata->list);
+	mutex_unlock(&sdata->hw->slaves_mtx);
+
+	synchronize_rcu();
+	unregister_netdevice(sdata->dev);
+}
+
+static struct net_device *
+mac802154_add_iface(struct wpan_phy *phy, const char *name, int type)
+{
+	struct net_device *dev;
+	int err = -ENOMEM;
+
+	switch (type) {
+	case IEEE802154_DEV_MONITOR:
+		dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
+				   name, NET_NAME_UNKNOWN,
+				   mac802154_monitor_setup);
+		break;
+	case IEEE802154_DEV_WPAN:
+		dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
+				   name, NET_NAME_UNKNOWN,
+				   mac802154_wpan_setup);
+		break;
+	default:
+		dev = NULL;
+		err = -EINVAL;
+		break;
+	}
+	if (!dev)
+		goto err;
+
+	err = mac802154_netdev_register(phy, dev);
+	if (err)
+		goto err_free;
+
+	dev_hold(dev); /* we return an incremented device refcount */
+	return dev;
+
+err_free:
+	free_netdev(dev);
+err:
+	return ERR_PTR(err);
+}
+
+static int mac802154_set_txpower(struct wpan_phy *phy, int db)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	return priv->ops->set_txpower(&priv->hw, db);
+}
+
+static int mac802154_set_lbt(struct wpan_phy *phy, bool on)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	return priv->ops->set_lbt(&priv->hw, on);
+}
+
+static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	return priv->ops->set_cca_mode(&priv->hw, mode);
+}
+
+static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	return priv->ops->set_cca_ed_level(&priv->hw, level);
+}
+
+static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be,
+				     u8 max_be, u8 retries)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries);
+}
+
+static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	return priv->ops->set_frame_retries(&priv->hw, retries);
+}
+
+struct ieee802154_dev *
+ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
+{
+	struct wpan_phy *phy;
+	struct mac802154_priv *priv;
+	size_t priv_size;
+
+	if (!ops || !ops->xmit || !ops->ed || !ops->start ||
+	    !ops->stop || !ops->set_channel) {
+		pr_err("undefined IEEE802.15.4 device operations\n");
+		return NULL;
+	}
+
+	/* Ensure 32-byte alignment of our private data and hw private data.
+	 * We use the wpan_phy priv data for both our mac802154_priv and for
+	 * the driver's private data
+	 *
+	 * in memory it'll be like this:
+	 *
+	 * +-----------------------+
+	 * | struct wpan_phy       |
+	 * +-----------------------+
+	 * | struct mac802154_priv |
+	 * +-----------------------+
+	 * | driver's private data |
+	 * +-----------------------+
+	 *
+	 * Due to ieee802154 layer isn't aware of driver and MAC structures,
+	 * so lets allign them here.
+	 */
+
+	priv_size = ALIGN(sizeof(*priv), NETDEV_ALIGN) + priv_data_len;
+
+	phy = wpan_phy_alloc(priv_size);
+	if (!phy) {
+		pr_err("failure to allocate master IEEE802.15.4 device\n");
+		return NULL;
+	}
+
+	priv = wpan_phy_priv(phy);
+	priv->phy = phy;
+	priv->hw.phy = priv->phy;
+	priv->hw.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN);
+	priv->ops = ops;
+
+	INIT_LIST_HEAD(&priv->slaves);
+	mutex_init(&priv->slaves_mtx);
+
+	return &priv->hw;
+}
+EXPORT_SYMBOL(ieee802154_alloc_device);
+
+void ieee802154_free_device(struct ieee802154_dev *hw)
+{
+	struct mac802154_priv *priv = mac802154_to_priv(hw);
+
+	BUG_ON(!list_empty(&priv->slaves));
+
+	mutex_destroy(&priv->slaves_mtx);
+
+	wpan_phy_free(priv->phy);
+}
+EXPORT_SYMBOL(ieee802154_free_device);
+
+int ieee802154_register_device(struct ieee802154_dev *dev)
+{
+	struct mac802154_priv *priv = mac802154_to_priv(dev);
+	int rc = -ENOSYS;
+
+	if (dev->flags & IEEE802154_HW_TXPOWER) {
+		if (!priv->ops->set_txpower)
+			goto out;
+
+		priv->phy->set_txpower = mac802154_set_txpower;
+	}
+
+	if (dev->flags & IEEE802154_HW_LBT) {
+		if (!priv->ops->set_lbt)
+			goto out;
+
+		priv->phy->set_lbt = mac802154_set_lbt;
+	}
+
+	if (dev->flags & IEEE802154_HW_CCA_MODE) {
+		if (!priv->ops->set_cca_mode)
+			goto out;
+
+		priv->phy->set_cca_mode = mac802154_set_cca_mode;
+	}
+
+	if (dev->flags & IEEE802154_HW_CCA_ED_LEVEL) {
+		if (!priv->ops->set_cca_ed_level)
+			goto out;
+
+		priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
+	}
+
+	if (dev->flags & IEEE802154_HW_CSMA_PARAMS) {
+		if (!priv->ops->set_csma_params)
+			goto out;
+
+		priv->phy->set_csma_params = mac802154_set_csma_params;
+	}
+
+	if (dev->flags & IEEE802154_HW_FRAME_RETRIES) {
+		if (!priv->ops->set_frame_retries)
+			goto out;
+
+		priv->phy->set_frame_retries = mac802154_set_frame_retries;
+	}
+
+	priv->dev_workqueue =
+		create_singlethread_workqueue(wpan_phy_name(priv->phy));
+	if (!priv->dev_workqueue) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	wpan_phy_set_dev(priv->phy, priv->hw.parent);
+
+	priv->phy->add_iface = mac802154_add_iface;
+	priv->phy->del_iface = mac802154_del_iface;
+
+	rc = wpan_phy_register(priv->phy);
+	if (rc < 0)
+		goto out_wq;
+
+	rtnl_lock();
+
+	mutex_lock(&priv->slaves_mtx);
+	priv->running = MAC802154_DEVICE_RUN;
+	mutex_unlock(&priv->slaves_mtx);
+
+	rtnl_unlock();
+
+	return 0;
+
+out_wq:
+	destroy_workqueue(priv->dev_workqueue);
+out:
+	return rc;
+}
+EXPORT_SYMBOL(ieee802154_register_device);
+
+void ieee802154_unregister_device(struct ieee802154_dev *dev)
+{
+	struct mac802154_priv *priv = mac802154_to_priv(dev);
+	struct mac802154_sub_if_data *sdata, *next;
+
+	flush_workqueue(priv->dev_workqueue);
+	destroy_workqueue(priv->dev_workqueue);
+
+	rtnl_lock();
+
+	mutex_lock(&priv->slaves_mtx);
+	priv->running = MAC802154_DEVICE_STOPPED;
+	mutex_unlock(&priv->slaves_mtx);
+
+	list_for_each_entry_safe(sdata, next, &priv->slaves, list) {
+		mutex_lock(&sdata->hw->slaves_mtx);
+		list_del(&sdata->list);
+		mutex_unlock(&sdata->hw->slaves_mtx);
+
+		unregister_netdevice(sdata->dev);
+	}
+
+	rtnl_unlock();
+
+	wpan_phy_unregister(priv->phy);
+}
+EXPORT_SYMBOL(ieee802154_unregister_device);
+
+MODULE_DESCRIPTION("IEEE 802.15.4 implementation");
+MODULE_LICENSE("GPL v2");
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
deleted file mode 100644
index 9ae8930..0000000
--- a/net/mac802154/iface.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Copyright 2007-2012 Siemens AG
- *
- * 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.
- *
- * Written by:
- * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
- * Sergey Lapin <slapin@ossfans.org>
- * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
- * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
- */
-
-#include <linux/netdevice.h>
-#include <linux/module.h>
-#include <linux/if_arp.h>
-#include <linux/ieee802154.h>
-
-#include <net/nl802154.h>
-#include <net/mac802154.h>
-#include <net/ieee802154_netdev.h>
-#include <net/cfg802154.h>
-
-#include "ieee802154_i.h"
-#include "driver-ops.h"
-
-static int mac802154_wpan_update_llsec(struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
-	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-	int rc = 0;
-
-	if (ops->llsec) {
-		struct ieee802154_llsec_params params;
-		int changed = 0;
-
-		params.pan_id = wpan_dev->pan_id;
-		changed |= IEEE802154_LLSEC_PARAM_PAN_ID;
-
-		params.hwaddr = wpan_dev->extended_addr;
-		changed |= IEEE802154_LLSEC_PARAM_HWADDR;
-
-		rc = ops->llsec->set_params(dev, &params, changed);
-	}
-
-	return rc;
-}
-
-static int
-mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-	struct sockaddr_ieee802154 *sa =
-		(struct sockaddr_ieee802154 *)&ifr->ifr_addr;
-	int err = -ENOIOCTLCMD;
-
-	ASSERT_RTNL();
-
-	spin_lock_bh(&sdata->mib_lock);
-
-	switch (cmd) {
-	case SIOCGIFADDR:
-	{
-		u16 pan_id, short_addr;
-
-		pan_id = le16_to_cpu(wpan_dev->pan_id);
-		short_addr = le16_to_cpu(wpan_dev->short_addr);
-		if (pan_id == IEEE802154_PANID_BROADCAST ||
-		    short_addr == IEEE802154_ADDR_BROADCAST) {
-			err = -EADDRNOTAVAIL;
-			break;
-		}
-
-		sa->family = AF_IEEE802154;
-		sa->addr.addr_type = IEEE802154_ADDR_SHORT;
-		sa->addr.pan_id = pan_id;
-		sa->addr.short_addr = short_addr;
-
-		err = 0;
-		break;
-	}
-	case SIOCSIFADDR:
-		if (netif_running(dev)) {
-			spin_unlock_bh(&sdata->mib_lock);
-			return -EBUSY;
-		}
-
-		dev_warn(&dev->dev,
-			 "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n");
-		if (sa->family != AF_IEEE802154 ||
-		    sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
-		    sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
-		    sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
-		    sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
-			err = -EINVAL;
-			break;
-		}
-
-		wpan_dev->pan_id = cpu_to_le16(sa->addr.pan_id);
-		wpan_dev->short_addr = cpu_to_le16(sa->addr.short_addr);
-
-		err = mac802154_wpan_update_llsec(dev);
-		break;
-	}
-
-	spin_unlock_bh(&sdata->mib_lock);
-	return err;
-}
-
-static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct sockaddr *addr = p;
-	__le64 extended_addr;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	ieee802154_be64_to_le64(&extended_addr, addr->sa_data);
-	if (!ieee802154_is_valid_extended_addr(extended_addr))
-		return -EINVAL;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	sdata->wpan_dev.extended_addr = extended_addr;
-
-	return mac802154_wpan_update_llsec(dev);
-}
-
-static int mac802154_slave_open(struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct ieee802154_sub_if_data *subif;
-	struct ieee802154_local *local = sdata->local;
-	int res = 0;
-
-	ASSERT_RTNL();
-
-	if (sdata->vif.type == NL802154_IFTYPE_NODE) {
-		mutex_lock(&sdata->local->iflist_mtx);
-		list_for_each_entry(subif, &sdata->local->interfaces, list) {
-			if (subif != sdata &&
-			    subif->vif.type == sdata->vif.type &&
-			    ieee802154_sdata_running(subif)) {
-				mutex_unlock(&sdata->local->iflist_mtx);
-				return -EBUSY;
-			}
-		}
-		mutex_unlock(&sdata->local->iflist_mtx);
-	}
-
-	set_bit(SDATA_STATE_RUNNING, &sdata->state);
-
-	if (!local->open_count) {
-		res = drv_start(local);
-		WARN_ON(res);
-		if (res)
-			goto err;
-	}
-
-	local->open_count++;
-	netif_start_queue(dev);
-	return 0;
-err:
-	/* might already be clear but that doesn't matter */
-	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
-
-	return res;
-}
-
-static int mac802154_wpan_open(struct net_device *dev)
-{
-	int rc;
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct ieee802154_local *local = sdata->local;
-	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-	struct wpan_phy *phy = sdata->local->phy;
-
-	rc = mac802154_slave_open(dev);
-	if (rc < 0)
-		return rc;
-
-	mutex_lock(&phy->pib_lock);
-
-	if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) {
-		rc = drv_set_promiscuous_mode(local,
-					      wpan_dev->promiscuous_mode);
-		if (rc < 0)
-			goto out;
-	}
-
-	if (local->hw.flags & IEEE802154_HW_AFILT) {
-		rc = drv_set_pan_id(local, wpan_dev->pan_id);
-		if (rc < 0)
-			goto out;
-
-		rc = drv_set_extended_addr(local, wpan_dev->extended_addr);
-		if (rc < 0)
-			goto out;
-
-		rc = drv_set_short_addr(local, wpan_dev->short_addr);
-		if (rc < 0)
-			goto out;
-	}
-
-	if (local->hw.flags & IEEE802154_HW_LBT) {
-		rc = drv_set_lbt_mode(local, wpan_dev->lbt);
-		if (rc < 0)
-			goto out;
-	}
-
-	if (local->hw.flags & IEEE802154_HW_CSMA_PARAMS) {
-		rc = drv_set_csma_params(local, wpan_dev->min_be,
-					 wpan_dev->max_be,
-					 wpan_dev->csma_retries);
-		if (rc < 0)
-			goto out;
-	}
-
-	if (local->hw.flags & IEEE802154_HW_FRAME_RETRIES) {
-		rc = drv_set_max_frame_retries(local, wpan_dev->frame_retries);
-		if (rc < 0)
-			goto out;
-	}
-
-	mutex_unlock(&phy->pib_lock);
-	return 0;
-
-out:
-	mutex_unlock(&phy->pib_lock);
-	return rc;
-}
-
-static int mac802154_slave_close(struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct ieee802154_local *local = sdata->local;
-
-	ASSERT_RTNL();
-
-	hrtimer_cancel(&local->ifs_timer);
-
-	netif_stop_queue(dev);
-	local->open_count--;
-
-	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
-
-	if (!local->open_count)
-		drv_stop(local);
-
-	return 0;
-}
-
-static int mac802154_set_header_security(struct ieee802154_sub_if_data *sdata,
-					 struct ieee802154_hdr *hdr,
-					 const struct ieee802154_mac_cb *cb)
-{
-	struct ieee802154_llsec_params params;
-	u8 level;
-
-	mac802154_llsec_get_params(&sdata->sec, &params);
-
-	if (!params.enabled && cb->secen_override && cb->secen)
-		return -EINVAL;
-	if (!params.enabled ||
-	    (cb->secen_override && !cb->secen) ||
-	    !params.out_level)
-		return 0;
-	if (cb->seclevel_override && !cb->seclevel)
-		return -EINVAL;
-
-	level = cb->seclevel_override ? cb->seclevel : params.out_level;
-
-	hdr->fc.security_enabled = 1;
-	hdr->sec.level = level;
-	hdr->sec.key_id_mode = params.out_key.mode;
-	if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX)
-		hdr->sec.short_src = params.out_key.short_source;
-	else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX)
-		hdr->sec.extended_src = params.out_key.extended_source;
-	hdr->sec.key_id = params.out_key.id;
-
-	return 0;
-}
-
-static int mac802154_header_create(struct sk_buff *skb,
-				   struct net_device *dev,
-				   unsigned short type,
-				   const void *daddr,
-				   const void *saddr,
-				   unsigned len)
-{
-	struct ieee802154_hdr hdr;
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-	struct ieee802154_mac_cb *cb = mac_cb(skb);
-	int hlen;
-
-	if (!daddr)
-		return -EINVAL;
-
-	memset(&hdr.fc, 0, sizeof(hdr.fc));
-	hdr.fc.type = cb->type;
-	hdr.fc.security_enabled = cb->secen;
-	hdr.fc.ack_request = cb->ackreq;
-	hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
-
-	if (mac802154_set_header_security(sdata, &hdr, cb) < 0)
-		return -EINVAL;
-
-	if (!saddr) {
-		spin_lock_bh(&sdata->mib_lock);
-
-		if (wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) ||
-		    wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
-		    wpan_dev->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) {
-			hdr.source.mode = IEEE802154_ADDR_LONG;
-			hdr.source.extended_addr = wpan_dev->extended_addr;
-		} else {
-			hdr.source.mode = IEEE802154_ADDR_SHORT;
-			hdr.source.short_addr = wpan_dev->short_addr;
-		}
-
-		hdr.source.pan_id = wpan_dev->pan_id;
-
-		spin_unlock_bh(&sdata->mib_lock);
-	} else {
-		hdr.source = *(const struct ieee802154_addr *)saddr;
-	}
-
-	hdr.dest = *(const struct ieee802154_addr *)daddr;
-
-	hlen = ieee802154_hdr_push(skb, &hdr);
-	if (hlen < 0)
-		return -EINVAL;
-
-	skb_reset_mac_header(skb);
-	skb->mac_len = hlen;
-
-	if (len > ieee802154_max_payload(&hdr))
-		return -EMSGSIZE;
-
-	return hlen;
-}
-
-static int
-mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
-{
-	struct ieee802154_hdr hdr;
-	struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
-
-	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
-		pr_debug("malformed packet\n");
-		return 0;
-	}
-
-	*addr = hdr.source;
-	return sizeof(*addr);
-}
-
-static struct header_ops mac802154_header_ops = {
-	.create		= mac802154_header_create,
-	.parse		= mac802154_header_parse,
-};
-
-static const struct net_device_ops mac802154_wpan_ops = {
-	.ndo_open		= mac802154_wpan_open,
-	.ndo_stop		= mac802154_slave_close,
-	.ndo_start_xmit		= ieee802154_subif_start_xmit,
-	.ndo_do_ioctl		= mac802154_wpan_ioctl,
-	.ndo_set_mac_address	= mac802154_wpan_mac_addr,
-};
-
-static const struct net_device_ops mac802154_monitor_ops = {
-	.ndo_open		= mac802154_wpan_open,
-	.ndo_stop		= mac802154_slave_close,
-	.ndo_start_xmit		= ieee802154_monitor_start_xmit,
-};
-
-static void mac802154_wpan_free(struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-
-	mac802154_llsec_destroy(&sdata->sec);
-
-	free_netdev(dev);
-}
-
-static void ieee802154_if_setup(struct net_device *dev)
-{
-	dev->addr_len		= IEEE802154_EXTENDED_ADDR_LEN;
-	memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_ADDR_LEN);
-
-	dev->hard_header_len	= MAC802154_FRAME_HARD_HEADER_LEN;
-	dev->needed_tailroom	= 2 + 16; /* FCS + MIC */
-	dev->mtu		= IEEE802154_MTU;
-	dev->tx_queue_len	= 300;
-	dev->flags		= IFF_NOARP | IFF_BROADCAST;
-}
-
-static int
-ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
-		       enum nl802154_iftype type)
-{
-	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-
-	/* set some type-dependent values */
-	sdata->vif.type = type;
-	sdata->wpan_dev.iftype = type;
-
-	get_random_bytes(&wpan_dev->bsn, 1);
-	get_random_bytes(&wpan_dev->dsn, 1);
-
-	/* defaults per 802.15.4-2011 */
-	wpan_dev->min_be = 3;
-	wpan_dev->max_be = 5;
-	wpan_dev->csma_retries = 4;
-	/* for compatibility, actual default is 3 */
-	wpan_dev->frame_retries = -1;
-
-	wpan_dev->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
-	wpan_dev->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
-
-	switch (type) {
-	case NL802154_IFTYPE_NODE:
-		ieee802154_be64_to_le64(&wpan_dev->extended_addr,
-					sdata->dev->dev_addr);
-
-		sdata->dev->header_ops = &mac802154_header_ops;
-		sdata->dev->destructor = mac802154_wpan_free;
-		sdata->dev->netdev_ops = &mac802154_wpan_ops;
-		sdata->dev->ml_priv = &mac802154_mlme_wpan;
-		wpan_dev->promiscuous_mode = false;
-
-		spin_lock_init(&sdata->mib_lock);
-		mutex_init(&sdata->sec_mtx);
-
-		mac802154_llsec_init(&sdata->sec);
-		break;
-	case NL802154_IFTYPE_MONITOR:
-		sdata->dev->destructor = free_netdev;
-		sdata->dev->netdev_ops = &mac802154_monitor_ops;
-		wpan_dev->promiscuous_mode = true;
-		break;
-	default:
-		BUG();
-	}
-
-	return 0;
-}
-
-struct net_device *
-ieee802154_if_add(struct ieee802154_local *local, const char *name,
-		  enum nl802154_iftype type, __le64 extended_addr)
-{
-	struct net_device *ndev = NULL;
-	struct ieee802154_sub_if_data *sdata = NULL;
-	int ret = -ENOMEM;
-
-	ASSERT_RTNL();
-
-	ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name,
-			    NET_NAME_UNKNOWN, ieee802154_if_setup);
-	if (!ndev)
-		return ERR_PTR(-ENOMEM);
-
-	ndev->needed_headroom = local->hw.extra_tx_headroom;
-
-	ret = dev_alloc_name(ndev, ndev->name);
-	if (ret < 0)
-		goto err;
-
-	ieee802154_le64_to_be64(ndev->perm_addr,
-				&local->hw.phy->perm_extended_addr);
-	switch (type) {
-	case NL802154_IFTYPE_NODE:
-		ndev->type = ARPHRD_IEEE802154;
-		if (ieee802154_is_valid_extended_addr(extended_addr))
-			ieee802154_le64_to_be64(ndev->dev_addr, &extended_addr);
-		else
-			memcpy(ndev->dev_addr, ndev->perm_addr,
-			       IEEE802154_EXTENDED_ADDR_LEN);
-		break;
-	case NL802154_IFTYPE_MONITOR:
-		ndev->type = ARPHRD_IEEE802154_MONITOR;
-		break;
-	default:
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* TODO check this */
-	SET_NETDEV_DEV(ndev, &local->phy->dev);
-	sdata = netdev_priv(ndev);
-	ndev->ieee802154_ptr = &sdata->wpan_dev;
-	memcpy(sdata->name, ndev->name, IFNAMSIZ);
-	sdata->dev = ndev;
-	sdata->wpan_dev.wpan_phy = local->hw.phy;
-	sdata->local = local;
-
-	/* setup type-dependent data */
-	ret = ieee802154_setup_sdata(sdata, type);
-	if (ret)
-		goto err;
-
-	ret = register_netdevice(ndev);
-	if (ret < 0)
-		goto err;
-
-	mutex_lock(&local->iflist_mtx);
-	list_add_tail_rcu(&sdata->list, &local->interfaces);
-	mutex_unlock(&local->iflist_mtx);
-
-	return ndev;
-
-err:
-	free_netdev(ndev);
-	return ERR_PTR(ret);
-}
-
-void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata)
-{
-	ASSERT_RTNL();
-
-	mutex_lock(&sdata->local->iflist_mtx);
-	list_del_rcu(&sdata->list);
-	mutex_unlock(&sdata->local->iflist_mtx);
-
-	synchronize_rcu();
-	unregister_netdevice(sdata->dev);
-}
-
-void ieee802154_remove_interfaces(struct ieee802154_local *local)
-{
-	struct ieee802154_sub_if_data *sdata, *tmp;
-
-	mutex_lock(&local->iflist_mtx);
-	list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
-		list_del(&sdata->list);
-
-		unregister_netdevice(sdata->dev);
-	}
-	mutex_unlock(&local->iflist_mtx);
-}
-
-static int netdev_notify(struct notifier_block *nb,
-			 unsigned long state, void *ptr)
-{
-	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-	struct ieee802154_sub_if_data *sdata;
-
-	if (state != NETDEV_CHANGENAME)
-		return NOTIFY_DONE;
-
-	if (!dev->ieee802154_ptr || !dev->ieee802154_ptr->wpan_phy)
-		return NOTIFY_DONE;
-
-	if (dev->ieee802154_ptr->wpan_phy->privid != mac802154_wpan_phy_privid)
-		return NOTIFY_DONE;
-
-	sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	memcpy(sdata->name, dev->name, IFNAMSIZ);
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block mac802154_netdev_notifier = {
-	.notifier_call = netdev_notify,
-};
-
-int ieee802154_iface_init(void)
-{
-	return register_netdevice_notifier(&mac802154_netdev_notifier);
-}
-
-void ieee802154_iface_exit(void)
-{
-	unregister_netdevice_notifier(&mac802154_netdev_notifier);
-}
diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c
index dcf7395..4570581 100644
--- a/net/mac802154/llsec.c
+++ b/net/mac802154/llsec.c
@@ -17,10 +17,10 @@
 #include <linux/err.h>
 #include <linux/bug.h>
 #include <linux/completion.h>
-#include <linux/ieee802154.h>
+#include <net/ieee802154.h>
 #include <crypto/algapi.h>
 
-#include "ieee802154_i.h"
+#include "mac802154.h"
 #include "llsec.h"
 
 static void llsec_key_put(struct mac802154_llsec_key *key);
@@ -75,6 +75,8 @@
 	}
 }
 
+
+
 int mac802154_llsec_get_params(struct mac802154_llsec *sec,
 			       struct ieee802154_llsec_params *params)
 {
@@ -115,6 +117,8 @@
 	return 0;
 }
 
+
+
 static struct mac802154_llsec_key*
 llsec_key_alloc(const struct ieee802154_llsec_key *template)
 {
@@ -290,6 +294,8 @@
 	return -ENOENT;
 }
 
+
+
 static bool llsec_dev_use_shortaddr(__le16 short_addr)
 {
 	return short_addr != cpu_to_le16(IEEE802154_ADDR_UNDEF) &&
@@ -298,12 +304,12 @@
 
 static u32 llsec_dev_hash_short(__le16 short_addr, __le16 pan_id)
 {
-	return ((__force u16)short_addr) << 16 | (__force u16)pan_id;
+	return ((__force u16) short_addr) << 16 | (__force u16) pan_id;
 }
 
 static u64 llsec_dev_hash_long(__le64 hwaddr)
 {
-	return (__force u64)hwaddr;
+	return (__force u64) hwaddr;
 }
 
 static struct mac802154_llsec_device*
@@ -405,6 +411,8 @@
 	return 0;
 }
 
+
+
 static struct mac802154_llsec_device_key*
 llsec_devkey_find(struct mac802154_llsec_device *dev,
 		  const struct ieee802154_llsec_key_id *key)
@@ -467,6 +475,8 @@
 	return 0;
 }
 
+
+
 static struct mac802154_llsec_seclevel*
 llsec_find_seclevel(const struct mac802154_llsec *sec,
 		    const struct ieee802154_llsec_seclevel *sl)
@@ -522,6 +532,8 @@
 	return 0;
 }
 
+
+
 static int llsec_recover_addr(struct mac802154_llsec *sec,
 			      struct ieee802154_addr *addr)
 {
@@ -597,6 +609,7 @@
 	return llsec_key_get(key);
 }
 
+
 static void llsec_geniv(u8 iv[16], __le64 addr,
 			const struct ieee802154_sechdr *sec)
 {
@@ -773,6 +786,8 @@
 	return rc;
 }
 
+
+
 static struct mac802154_llsec_device*
 llsec_lookup_dev(struct mac802154_llsec *sec,
 		 const struct ieee802154_addr *addr)
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/mac802154.h
similarity index 63%
rename from net/mac802154/ieee802154_i.h
rename to net/mac802154/mac802154.h
index bebd70f..762a6f8 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/mac802154.h
@@ -10,28 +10,29 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
  */
-#ifndef __IEEE802154_I_H
-#define __IEEE802154_I_H
+#ifndef MAC802154_H
+#define MAC802154_H
 
 #include <linux/mutex.h>
-#include <linux/hrtimer.h>
-#include <net/cfg802154.h>
 #include <net/mac802154.h>
-#include <net/nl802154.h>
 #include <net/ieee802154_netdev.h>
 
 #include "llsec.h"
 
 /* mac802154 device private data */
-struct ieee802154_local {
-	struct ieee802154_hw hw;
-	const struct ieee802154_ops *ops;
+struct mac802154_priv {
+	struct ieee802154_dev hw;
+	struct ieee802154_ops *ops;
 
 	/* ieee802154 phy */
 	struct wpan_phy *phy;
@@ -45,29 +46,23 @@
 	 *
 	 * So atomic readers can use any of this protection methods.
 	 */
-	struct list_head	interfaces;
-	struct mutex		iflist_mtx;
+	struct list_head	slaves;
+	struct mutex		slaves_mtx;
 
 	/* This one is used for scanning and other jobs not to be interfered
 	 * with serial driver.
 	 */
-	struct workqueue_struct	*workqueue;
+	struct workqueue_struct	*dev_workqueue;
 
-	struct hrtimer ifs_timer;
-
-	bool started;
-
-	struct tasklet_struct tasklet;
-	struct sk_buff_head skb_queue;
+	/* SoftMAC device is registered and running. One can add subinterfaces.
+	 * This flag should be modified under slaves_mtx and RTNL, so you can
+	 * read them using any of protection methods.
+	 */
+	bool running;
 };
 
-enum {
-	IEEE802154_RX_MSG        = 1,
-};
-
-enum ieee802154_sdata_state_bits {
-	SDATA_STATE_RUNNING,
-};
+#define	MAC802154_DEVICE_STOPPED	0x00
+#define MAC802154_DEVICE_RUN		0x01
 
 /* Slave interface definition.
  *
@@ -75,74 +70,72 @@
  * Each ieee802154 device/transceiver may have several slaves and able
  * to be associated with several networks at the same time.
  */
-struct ieee802154_sub_if_data {
+struct mac802154_sub_if_data {
 	struct list_head list; /* the ieee802154_priv->slaves list */
 
-	struct wpan_dev wpan_dev;
-
-	struct ieee802154_local *local;
+	struct mac802154_priv *hw;
 	struct net_device *dev;
 
-	unsigned long state;
-	char name[IFNAMSIZ];
+	int type;
+	bool running;
 
 	spinlock_t mib_lock;
 
+	__le16 pan_id;
+	__le16 short_addr;
+	__le64 extended_addr;
+
+	u8 chan;
+	u8 page;
+
+	struct ieee802154_mac_params mac_params;
+
+	/* MAC BSN field */
+	u8 bsn;
+	/* MAC DSN field */
+	u8 dsn;
+
 	/* protects sec from concurrent access by netlink. access by
 	 * encrypt/decrypt/header_create safe without additional protection.
 	 */
 	struct mutex sec_mtx;
 
 	struct mac802154_llsec sec;
-	/* must be last, dynamically sized area in this! */
-	struct ieee802154_vif vif;
 };
 
+#define mac802154_to_priv(_hw)	container_of(_hw, struct mac802154_priv, hw)
+
 #define MAC802154_CHAN_NONE		0xff /* No channel is assigned */
 
-/* utility functions/constants */
-extern const void *const mac802154_wpan_phy_privid; /*  for wpan_phy privid */
-
-static inline struct ieee802154_local *
-hw_to_local(struct ieee802154_hw *hw)
-{
-	return container_of(hw, struct ieee802154_local, hw);
-}
-
-static inline struct ieee802154_sub_if_data *
-IEEE802154_DEV_TO_SUB_IF(const struct net_device *dev)
-{
-	return netdev_priv(dev);
-}
-
-static inline struct ieee802154_sub_if_data *
-IEEE802154_WPAN_DEV_TO_SUB_IF(struct wpan_dev *wpan_dev)
-{
-	return container_of(wpan_dev, struct ieee802154_sub_if_data, wpan_dev);
-}
-
-static inline bool
-ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata)
-{
-	return test_bit(SDATA_STATE_RUNNING, &sdata->state);
-}
-
+extern struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced;
 extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
 
-netdev_tx_t
-ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
-netdev_tx_t
-ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
-enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer);
+int mac802154_slave_open(struct net_device *dev);
+int mac802154_slave_close(struct net_device *dev);
+
+void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb);
+void mac802154_monitor_setup(struct net_device *dev);
+
+void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb);
+void mac802154_wpan_setup(struct net_device *dev);
+
+netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
+			 u8 page, u8 chan);
 
 /* MIB callbacks */
 void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val);
 __le16 mac802154_dev_get_short_addr(const struct net_device *dev);
+void mac802154_dev_set_ieee_addr(struct net_device *dev);
 __le16 mac802154_dev_get_pan_id(const struct net_device *dev);
 void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val);
 void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
 u8 mac802154_dev_get_dsn(const struct net_device *dev);
 
+int mac802154_set_mac_params(struct net_device *dev,
+			     const struct ieee802154_mac_params *params);
+void mac802154_get_mac_params(struct net_device *dev,
+			      struct ieee802154_mac_params *params);
+
 int mac802154_get_params(struct net_device *dev,
 			 struct ieee802154_llsec_params *params);
 int mac802154_set_params(struct net_device *dev,
@@ -176,13 +169,4 @@
 			 struct ieee802154_llsec_table **t);
 void mac802154_unlock_table(struct net_device *dev);
 
-/* interface handling */
-int ieee802154_iface_init(void);
-void ieee802154_iface_exit(void);
-void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata);
-struct net_device *
-ieee802154_if_add(struct ieee802154_local *local, const char *name,
-		  enum nl802154_iftype type, __le64 extended_addr);
-void ieee802154_remove_interfaces(struct ieee802154_local *local);
-
-#endif /* __IEEE802154_I_H */
+#endif /* MAC802154_H */
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
index 6aacb18..bf80913 100644
--- a/net/mac802154/mac_cmd.c
+++ b/net/mac802154/mac_cmd.c
@@ -12,6 +12,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Sergey Lapin <slapin@ossfans.org>
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -20,14 +24,14 @@
 
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
-#include <linux/ieee802154.h>
 
+#include <net/ieee802154.h>
 #include <net/ieee802154_netdev.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
 #include <net/mac802154.h>
+#include <net/nl802154.h>
 
-#include "ieee802154_i.h"
-#include "driver-ops.h"
+#include "mac802154.h"
 
 static int mac802154_mlme_start_req(struct net_device *dev,
 				    struct ieee802154_addr *addr,
@@ -39,12 +43,11 @@
 	struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
 	int rc = 0;
 
-	ASSERT_RTNL();
-
 	BUG_ON(addr->mode != IEEE802154_ADDR_SHORT);
 
 	mac802154_dev_set_pan_id(dev, addr->pan_id);
 	mac802154_dev_set_short_addr(dev, addr->short_addr);
+	mac802154_dev_set_ieee_addr(dev);
 	mac802154_dev_set_page_channel(dev, page, channel);
 
 	if (ops->llsec) {
@@ -66,71 +69,21 @@
 		rc = ops->llsec->set_params(dev, &params, changed);
 	}
 
+	/* FIXME: add validation for unused parameters to be sane
+	 * for SoftMAC
+	 */
+	ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
+
 	return rc;
 }
 
-static int mac802154_set_mac_params(struct net_device *dev,
-				    const struct ieee802154_mac_params *params)
+static struct wpan_phy *mac802154_get_phy(const struct net_device *dev)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct ieee802154_local *local = sdata->local;
-	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-	int ret;
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 
-	ASSERT_RTNL();
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	/* PHY */
-	wpan_dev->wpan_phy->transmit_power = params->transmit_power;
-	wpan_dev->wpan_phy->cca_mode = params->cca_mode;
-	wpan_dev->wpan_phy->cca_ed_level = params->cca_ed_level;
-
-	/* MAC */
-	wpan_dev->min_be = params->min_be;
-	wpan_dev->max_be = params->max_be;
-	wpan_dev->csma_retries = params->csma_retries;
-	wpan_dev->frame_retries = params->frame_retries;
-	wpan_dev->lbt = params->lbt;
-
-	if (local->hw.flags & IEEE802154_HW_TXPOWER) {
-		ret = drv_set_tx_power(local, params->transmit_power);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (local->hw.flags & IEEE802154_HW_CCA_MODE) {
-		ret = drv_set_cca_mode(local, params->cca_mode);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) {
-		ret = drv_set_cca_ed_level(local, params->cca_ed_level);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-static void mac802154_get_mac_params(struct net_device *dev,
-				     struct ieee802154_mac_params *params)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-
-	ASSERT_RTNL();
-
-	/* PHY */
-	params->transmit_power = wpan_dev->wpan_phy->transmit_power;
-	params->cca_mode = wpan_dev->wpan_phy->cca_mode;
-	params->cca_ed_level = wpan_dev->wpan_phy->cca_ed_level;
-
-	/* MAC */
-	params->min_be = wpan_dev->min_be;
-	params->max_be = wpan_dev->max_be;
-	params->csma_retries = wpan_dev->csma_retries;
-	params->frame_retries = wpan_dev->frame_retries;
-	params->lbt = wpan_dev->lbt;
+	return to_phy(get_device(&priv->hw->phy->dev));
 }
 
 static struct ieee802154_llsec_ops mac802154_llsec_ops = {
@@ -149,7 +102,12 @@
 	.unlock_table = mac802154_unlock_table,
 };
 
+struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced = {
+	.get_phy = mac802154_get_phy,
+};
+
 struct ieee802154_mlme_ops mac802154_mlme_wpan = {
+	.get_phy = mac802154_get_phy,
 	.start_req = mac802154_mlme_start_req,
 	.get_pan_id = mac802154_dev_get_pan_id,
 	.get_short_addr = mac802154_dev_get_short_addr,
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
deleted file mode 100644
index 8500378..0000000
--- a/net/mac802154/main.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Siemens AG
- *
- * Written by:
- * Alexander Smirnov <alex.bluesman.smirnov@gmail.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.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-
-#include <net/netlink.h>
-#include <net/nl802154.h>
-#include <net/mac802154.h>
-#include <net/ieee802154_netdev.h>
-#include <net/route.h>
-#include <net/cfg802154.h>
-
-#include "ieee802154_i.h"
-#include "cfg.h"
-
-static void ieee802154_tasklet_handler(unsigned long data)
-{
-	struct ieee802154_local *local = (struct ieee802154_local *)data;
-	struct sk_buff *skb;
-
-	while ((skb = skb_dequeue(&local->skb_queue))) {
-		switch (skb->pkt_type) {
-		case IEEE802154_RX_MSG:
-			/* Clear skb->pkt_type in order to not confuse kernel
-			 * netstack.
-			 */
-			skb->pkt_type = 0;
-			ieee802154_rx(&local->hw, skb);
-			break;
-		default:
-			WARN(1, "mac802154: Packet is of unknown type %d\n",
-			     skb->pkt_type);
-			kfree_skb(skb);
-			break;
-		}
-	}
-}
-
-struct ieee802154_hw *
-ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
-{
-	struct wpan_phy *phy;
-	struct ieee802154_local *local;
-	size_t priv_size;
-
-	if (!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed ||
-	    !ops->start || !ops->stop || !ops->set_channel) {
-		pr_err("undefined IEEE802.15.4 device operations\n");
-		return NULL;
-	}
-
-	/* Ensure 32-byte alignment of our private data and hw private data.
-	 * We use the wpan_phy priv data for both our ieee802154_local and for
-	 * the driver's private data
-	 *
-	 * in memory it'll be like this:
-	 *
-	 * +-------------------------+
-	 * | struct wpan_phy         |
-	 * +-------------------------+
-	 * | struct ieee802154_local |
-	 * +-------------------------+
-	 * | driver's private data   |
-	 * +-------------------------+
-	 *
-	 * Due to ieee802154 layer isn't aware of driver and MAC structures,
-	 * so lets align them here.
-	 */
-
-	priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
-
-	phy = wpan_phy_new(&mac802154_config_ops, priv_size);
-	if (!phy) {
-		pr_err("failure to allocate master IEEE802.15.4 device\n");
-		return NULL;
-	}
-
-	phy->privid = mac802154_wpan_phy_privid;
-
-	local = wpan_phy_priv(phy);
-	local->phy = phy;
-	local->hw.phy = local->phy;
-	local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
-	local->ops = ops;
-
-	INIT_LIST_HEAD(&local->interfaces);
-	mutex_init(&local->iflist_mtx);
-
-	tasklet_init(&local->tasklet,
-		     ieee802154_tasklet_handler,
-		     (unsigned long)local);
-
-	skb_queue_head_init(&local->skb_queue);
-
-	return &local->hw;
-}
-EXPORT_SYMBOL(ieee802154_alloc_hw);
-
-void ieee802154_free_hw(struct ieee802154_hw *hw)
-{
-	struct ieee802154_local *local = hw_to_local(hw);
-
-	BUG_ON(!list_empty(&local->interfaces));
-
-	mutex_destroy(&local->iflist_mtx);
-
-	wpan_phy_free(local->phy);
-}
-EXPORT_SYMBOL(ieee802154_free_hw);
-
-static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy)
-{
-	/* TODO warn on empty symbol_duration
-	 * Should be done when all drivers sets this value.
-	 */
-
-	wpan_phy->lifs_period = IEEE802154_LIFS_PERIOD *
-				wpan_phy->symbol_duration;
-	wpan_phy->sifs_period = IEEE802154_SIFS_PERIOD *
-				wpan_phy->symbol_duration;
-}
-
-int ieee802154_register_hw(struct ieee802154_hw *hw)
-{
-	struct ieee802154_local *local = hw_to_local(hw);
-	struct net_device *dev;
-	int rc = -ENOSYS;
-
-	local->workqueue =
-		create_singlethread_workqueue(wpan_phy_name(local->phy));
-	if (!local->workqueue) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	hrtimer_init(&local->ifs_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	local->ifs_timer.function = ieee802154_xmit_ifs_timer;
-
-	wpan_phy_set_dev(local->phy, local->hw.parent);
-
-	ieee802154_setup_wpan_phy_pib(local->phy);
-
-	rc = wpan_phy_register(local->phy);
-	if (rc < 0)
-		goto out_wq;
-
-	rtnl_lock();
-
-	dev = ieee802154_if_add(local, "wpan%d", NL802154_IFTYPE_NODE,
-				cpu_to_le64(0x0000000000000000ULL));
-	if (IS_ERR(dev)) {
-		rtnl_unlock();
-		rc = PTR_ERR(dev);
-		goto out_wq;
-	}
-
-	rtnl_unlock();
-
-	return 0;
-
-out_wq:
-	destroy_workqueue(local->workqueue);
-out:
-	return rc;
-}
-EXPORT_SYMBOL(ieee802154_register_hw);
-
-void ieee802154_unregister_hw(struct ieee802154_hw *hw)
-{
-	struct ieee802154_local *local = hw_to_local(hw);
-
-	tasklet_kill(&local->tasklet);
-	flush_workqueue(local->workqueue);
-	destroy_workqueue(local->workqueue);
-
-	rtnl_lock();
-
-	ieee802154_remove_interfaces(local);
-
-	rtnl_unlock();
-
-	wpan_phy_unregister(local->phy);
-}
-EXPORT_SYMBOL(ieee802154_unregister_hw);
-
-static int __init ieee802154_init(void)
-{
-	return ieee802154_iface_init();
-}
-
-static void __exit ieee802154_exit(void)
-{
-	ieee802154_iface_exit();
-
-	rcu_barrier();
-}
-
-subsys_initcall(ieee802154_init);
-module_exit(ieee802154_exit);
-
-MODULE_DESCRIPTION("IEEE 802.15.4 subsystem");
-MODULE_LICENSE("GPL v2");
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
index 5cf019a..868a040 100644
--- a/net/mac802154/mib.c
+++ b/net/mac802154/mib.c
@@ -10,6 +10,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  * Sergey Lapin <slapin@ossfans.org>
@@ -21,100 +25,208 @@
 
 #include <net/mac802154.h>
 #include <net/ieee802154_netdev.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
 
-#include "ieee802154_i.h"
-#include "driver-ops.h"
+#include "mac802154.h"
 
-void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
+struct phy_chan_notify_work {
+	struct work_struct work;
+	struct net_device *dev;
+};
+
+struct hw_addr_filt_notify_work {
+	struct work_struct work;
+	struct net_device *dev;
+	unsigned long changed;
+};
+
+static struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	spin_lock_bh(&sdata->mib_lock);
-	sdata->wpan_dev.short_addr = val;
-	spin_unlock_bh(&sdata->mib_lock);
+	return priv->hw;
+}
+
+static void hw_addr_notify(struct work_struct *work)
+{
+	struct hw_addr_filt_notify_work *nw = container_of(work,
+			struct hw_addr_filt_notify_work, work);
+	struct mac802154_priv *hw = mac802154_slave_get_priv(nw->dev);
+	int res;
+
+	res = hw->ops->set_hw_addr_filt(&hw->hw,
+					&hw->hw.hw_filt,
+					nw->changed);
+	if (res)
+		pr_debug("failed changed mask %lx\n", nw->changed);
+
+	kfree(nw);
+}
+
+static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct hw_addr_filt_notify_work *work;
+
+	work = kzalloc(sizeof(*work), GFP_ATOMIC);
+	if (!work)
+		return;
+
+	INIT_WORK(&work->work, hw_addr_notify);
+	work->dev = dev;
+	work->changed = changed;
+	queue_work(priv->hw->dev_workqueue, &work->work);
+}
+
+void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	spin_lock_bh(&priv->mib_lock);
+	priv->short_addr = val;
+	spin_unlock_bh(&priv->mib_lock);
+
+	if ((priv->hw->ops->set_hw_addr_filt) &&
+	    (priv->hw->hw.hw_filt.short_addr != priv->short_addr)) {
+		priv->hw->hw.hw_filt.short_addr = priv->short_addr;
+		set_hw_addr_filt(dev, IEEE802515_AFILT_SADDR_CHANGED);
+	}
 }
 
 __le16 mac802154_dev_get_short_addr(const struct net_device *dev)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	__le16 ret;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	spin_lock_bh(&sdata->mib_lock);
-	ret = sdata->wpan_dev.short_addr;
-	spin_unlock_bh(&sdata->mib_lock);
+	spin_lock_bh(&priv->mib_lock);
+	ret = priv->short_addr;
+	spin_unlock_bh(&priv->mib_lock);
 
 	return ret;
 }
 
+void mac802154_dev_set_ieee_addr(struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct mac802154_priv *mac = priv->hw;
+
+	priv->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
+
+	if (mac->ops->set_hw_addr_filt &&
+	    mac->hw.hw_filt.ieee_addr != priv->extended_addr) {
+		mac->hw.hw_filt.ieee_addr = priv->extended_addr;
+		set_hw_addr_filt(dev, IEEE802515_AFILT_IEEEADDR_CHANGED);
+	}
+}
+
 __le16 mac802154_dev_get_pan_id(const struct net_device *dev)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	__le16 ret;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	spin_lock_bh(&sdata->mib_lock);
-	ret = sdata->wpan_dev.pan_id;
-	spin_unlock_bh(&sdata->mib_lock);
+	spin_lock_bh(&priv->mib_lock);
+	ret = priv->pan_id;
+	spin_unlock_bh(&priv->mib_lock);
 
 	return ret;
 }
 
 void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	spin_lock_bh(&sdata->mib_lock);
-	sdata->wpan_dev.pan_id = val;
-	spin_unlock_bh(&sdata->mib_lock);
+	spin_lock_bh(&priv->mib_lock);
+	priv->pan_id = val;
+	spin_unlock_bh(&priv->mib_lock);
+
+	if ((priv->hw->ops->set_hw_addr_filt) &&
+	    (priv->hw->hw.hw_filt.pan_id != priv->pan_id)) {
+		priv->hw->hw.hw_filt.pan_id = priv->pan_id;
+		set_hw_addr_filt(dev, IEEE802515_AFILT_PANID_CHANGED);
+	}
 }
 
 u8 mac802154_dev_get_dsn(const struct net_device *dev)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	return sdata->wpan_dev.dsn++;
+	return priv->dsn++;
+}
+
+static void phy_chan_notify(struct work_struct *work)
+{
+	struct phy_chan_notify_work *nw = container_of(work,
+					  struct phy_chan_notify_work, work);
+	struct mac802154_priv *hw = mac802154_slave_get_priv(nw->dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(nw->dev);
+	int res;
+
+	mutex_lock(&priv->hw->phy->pib_lock);
+	res = hw->ops->set_channel(&hw->hw, priv->page, priv->chan);
+	if (res) {
+		pr_debug("set_channel failed\n");
+	} else {
+		priv->hw->phy->current_channel = priv->chan;
+		priv->hw->phy->current_page = priv->page;
+	}
+	mutex_unlock(&priv->hw->phy->pib_lock);
+
+	kfree(nw);
 }
 
 void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	struct ieee802154_local *local = sdata->local;
-	int res;
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct phy_chan_notify_work *work;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	res = drv_set_channel(local, page, chan);
-	if (res) {
-		pr_debug("set_channel failed\n");
+	spin_lock_bh(&priv->mib_lock);
+	priv->page = page;
+	priv->chan = chan;
+	spin_unlock_bh(&priv->mib_lock);
+
+	mutex_lock(&priv->hw->phy->pib_lock);
+	if (priv->hw->phy->current_channel != priv->chan ||
+	    priv->hw->phy->current_page != priv->page) {
+		mutex_unlock(&priv->hw->phy->pib_lock);
+
+		work = kzalloc(sizeof(*work), GFP_ATOMIC);
+		if (!work)
+			return;
+
+		INIT_WORK(&work->work, phy_chan_notify);
+		work->dev = dev;
+		queue_work(priv->hw->dev_workqueue, &work->work);
 	} else {
-		mutex_lock(&local->phy->pib_lock);
-		local->phy->current_channel = chan;
-		local->phy->current_page = page;
-		mutex_unlock(&local->phy->pib_lock);
+		mutex_unlock(&priv->hw->phy->pib_lock);
 	}
 }
 
+
 int mac802154_get_params(struct net_device *dev,
 			 struct ieee802154_llsec_params *params)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_get_params(&sdata->sec, params);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_get_params(&priv->sec, params);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
@@ -123,30 +235,31 @@
 			 const struct ieee802154_llsec_params *params,
 			 int changed)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_set_params(&sdata->sec, params, changed);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_set_params(&priv->sec, params, changed);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
 
+
 int mac802154_add_key(struct net_device *dev,
 		      const struct ieee802154_llsec_key_id *id,
 		      const struct ieee802154_llsec_key *key)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_key_add(&sdata->sec, id, key);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_key_add(&priv->sec, id, key);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
@@ -154,59 +267,61 @@
 int mac802154_del_key(struct net_device *dev,
 		      const struct ieee802154_llsec_key_id *id)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_key_del(&sdata->sec, id);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_key_del(&priv->sec, id);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
 
+
 int mac802154_add_dev(struct net_device *dev,
 		      const struct ieee802154_llsec_device *llsec_dev)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_dev_add(&sdata->sec, llsec_dev);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_dev_add(&priv->sec, llsec_dev);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
 
 int mac802154_del_dev(struct net_device *dev, __le64 dev_addr)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_dev_del(&sdata->sec, dev_addr);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_dev_del(&priv->sec, dev_addr);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
 
+
 int mac802154_add_devkey(struct net_device *dev,
 			 __le64 device_addr,
 			 const struct ieee802154_llsec_device_key *key)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_devkey_add(&sdata->sec, device_addr, key);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_devkey_add(&priv->sec, device_addr, key);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
@@ -215,29 +330,30 @@
 			 __le64 device_addr,
 			 const struct ieee802154_llsec_device_key *key)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_devkey_del(&sdata->sec, device_addr, key);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_devkey_del(&priv->sec, device_addr, key);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
 
+
 int mac802154_add_seclevel(struct net_device *dev,
 			   const struct ieee802154_llsec_seclevel *sl)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_seclevel_add(&sdata->sec, sl);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_seclevel_add(&priv->sec, sl);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
@@ -245,42 +361,43 @@
 int mac802154_del_seclevel(struct net_device *dev,
 			   const struct ieee802154_llsec_seclevel *sl)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int res;
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
-	res = mac802154_llsec_seclevel_del(&sdata->sec, sl);
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
+	res = mac802154_llsec_seclevel_del(&priv->sec, sl);
+	mutex_unlock(&priv->sec_mtx);
 
 	return res;
 }
 
+
 void mac802154_lock_table(struct net_device *dev)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_lock(&sdata->sec_mtx);
+	mutex_lock(&priv->sec_mtx);
 }
 
 void mac802154_get_table(struct net_device *dev,
 			 struct ieee802154_llsec_table **t)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	*t = &sdata->sec.table;
+	*t = &priv->sec.table;
 }
 
 void mac802154_unlock_table(struct net_device *dev)
 {
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 
 	BUG_ON(dev->type != ARPHRD_IEEE802154);
 
-	mutex_unlock(&sdata->sec_mtx);
+	mutex_unlock(&priv->sec_mtx);
 }
diff --git a/net/mac802154/monitor.c b/net/mac802154/monitor.c
new file mode 100644
index 0000000..a68230e
--- /dev/null
+++ b/net/mac802154/monitor.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007, 2008, 2009 Siemens AG
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ * Sergey Lapin <slapin@ossfans.org>
+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
+ * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/crc-ccitt.h>
+
+#include <net/ieee802154.h>
+#include <net/mac802154.h>
+#include <net/netlink.h>
+#include <net/wpan-phy.h>
+#include <linux/nl802154.h>
+
+#include "mac802154.h"
+
+static netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb,
+					  struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv;
+	u8 chan, page;
+
+	priv = netdev_priv(dev);
+
+	/* FIXME: locking */
+	chan = priv->hw->phy->current_channel;
+	page = priv->hw->phy->current_page;
+
+	if (chan == MAC802154_CHAN_NONE) /* not initialized */
+		return NETDEV_TX_OK;
+
+	if (WARN_ON(page >= WPAN_NUM_PAGES) ||
+	    WARN_ON(chan >= WPAN_NUM_CHANNELS))
+		return NETDEV_TX_OK;
+
+	skb->skb_iif = dev->ifindex;
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	return mac802154_tx(priv->hw, skb, page, chan);
+}
+
+
+void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb)
+{
+	struct sk_buff *skb2;
+	struct mac802154_sub_if_data *sdata;
+	u16 crc = crc_ccitt(0, skb->data, skb->len);
+	u8 *data;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(sdata, &priv->slaves, list) {
+		if (sdata->type != IEEE802154_DEV_MONITOR ||
+		    !netif_running(sdata->dev))
+			continue;
+
+		skb2 = skb_clone(skb, GFP_ATOMIC);
+		skb2->dev = sdata->dev;
+		skb2->pkt_type = PACKET_HOST;
+		data = skb_put(skb2, 2);
+		data[0] = crc & 0xff;
+		data[1] = crc >> 8;
+
+		netif_rx_ni(skb2);
+	}
+	rcu_read_unlock();
+}
+
+static const struct net_device_ops mac802154_monitor_ops = {
+	.ndo_open		= mac802154_slave_open,
+	.ndo_stop		= mac802154_slave_close,
+	.ndo_start_xmit		= mac802154_monitor_xmit,
+};
+
+void mac802154_monitor_setup(struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv;
+
+	dev->addr_len		= 0;
+	dev->hard_header_len	= 0;
+	dev->needed_tailroom	= 2; /* room for FCS */
+	dev->mtu		= IEEE802154_MTU;
+	dev->tx_queue_len	= 10;
+	dev->type		= ARPHRD_IEEE802154_MONITOR;
+	dev->flags		= IFF_NOARP | IFF_BROADCAST;
+	dev->watchdog_timeo	= 0;
+
+	dev->destructor		= free_netdev;
+	dev->netdev_ops		= &mac802154_monitor_ops;
+	dev->ml_priv		= &mac802154_mlme_reduced;
+
+	priv = netdev_priv(dev);
+	priv->type = IEEE802154_DEV_MONITOR;
+
+	priv->chan = MAC802154_CHAN_NONE; /* not initialized */
+	priv->page = 0;
+}
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index c0d67b2..a14cf9e 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -10,6 +10,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
@@ -19,284 +23,92 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/workqueue.h>
 #include <linux/netdevice.h>
 #include <linux/crc-ccitt.h>
-#include <asm/unaligned.h>
 
 #include <net/mac802154.h>
 #include <net/ieee802154_netdev.h>
-#include <net/nl802154.h>
 
-#include "ieee802154_i.h"
+#include "mac802154.h"
 
-static int ieee802154_deliver_skb(struct sk_buff *skb)
+/* The IEEE 802.15.4 standard defines 4 MAC packet types:
+ * - beacon frame
+ * - MAC command frame
+ * - acknowledgement frame
+ * - data frame
+ *
+ * and only the data frame should be pushed to the upper layers, other types
+ * are just internal MAC layer management information. So only data packets
+ * are going to be sent to the networking queue, all other will be processed
+ * right here by using the device workqueue.
+ */
+struct rx_work {
+	struct sk_buff *skb;
+	struct work_struct work;
+	struct ieee802154_dev *dev;
+	u8 lqi;
+};
+
+static void
+mac802154_subif_rx(struct ieee802154_dev *hw, struct sk_buff *skb, u8 lqi)
 {
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	struct mac802154_priv *priv = mac802154_to_priv(hw);
+
+	mac_cb(skb)->lqi = lqi;
 	skb->protocol = htons(ETH_P_IEEE802154);
+	skb_reset_mac_header(skb);
 
-	return netif_receive_skb(skb);
-}
+	if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
+		u16 crc;
 
-static int
-ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
-		       struct sk_buff *skb, const struct ieee802154_hdr *hdr)
-{
-	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-	__le16 span, sshort;
-	int rc;
-
-	pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
-
-	spin_lock_bh(&sdata->mib_lock);
-
-	span = wpan_dev->pan_id;
-	sshort = wpan_dev->short_addr;
-
-	switch (mac_cb(skb)->dest.mode) {
-	case IEEE802154_ADDR_NONE:
-		if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
-			/* FIXME: check if we are PAN coordinator */
-			skb->pkt_type = PACKET_OTHERHOST;
-		else
-			/* ACK comes with both addresses empty */
-			skb->pkt_type = PACKET_HOST;
-		break;
-	case IEEE802154_ADDR_LONG:
-		if (mac_cb(skb)->dest.pan_id != span &&
-		    mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
-			skb->pkt_type = PACKET_OTHERHOST;
-		else if (mac_cb(skb)->dest.extended_addr == wpan_dev->extended_addr)
-			skb->pkt_type = PACKET_HOST;
-		else
-			skb->pkt_type = PACKET_OTHERHOST;
-		break;
-	case IEEE802154_ADDR_SHORT:
-		if (mac_cb(skb)->dest.pan_id != span &&
-		    mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
-			skb->pkt_type = PACKET_OTHERHOST;
-		else if (mac_cb(skb)->dest.short_addr == sshort)
-			skb->pkt_type = PACKET_HOST;
-		else if (mac_cb(skb)->dest.short_addr ==
-			  cpu_to_le16(IEEE802154_ADDR_BROADCAST))
-			skb->pkt_type = PACKET_BROADCAST;
-		else
-			skb->pkt_type = PACKET_OTHERHOST;
-		break;
-	default:
-		spin_unlock_bh(&sdata->mib_lock);
-		pr_debug("invalid dest mode\n");
-		goto fail;
+		if (skb->len < 2) {
+			pr_debug("got invalid frame\n");
+			goto fail;
+		}
+		crc = crc_ccitt(0, skb->data, skb->len);
+		if (crc) {
+			pr_debug("CRC mismatch\n");
+			goto fail;
+		}
+		skb_trim(skb, skb->len - 2); /* CRC */
 	}
 
-	spin_unlock_bh(&sdata->mib_lock);
+	mac802154_monitors_rx(priv, skb);
+	mac802154_wpans_rx(priv, skb);
 
-	skb->dev = sdata->dev;
-
-	rc = mac802154_llsec_decrypt(&sdata->sec, skb);
-	if (rc) {
-		pr_debug("decryption failed: %i\n", rc);
-		goto fail;
-	}
-
-	sdata->dev->stats.rx_packets++;
-	sdata->dev->stats.rx_bytes += skb->len;
-
-	switch (mac_cb(skb)->type) {
-	case IEEE802154_FC_TYPE_DATA:
-		return ieee802154_deliver_skb(skb);
-	default:
-		pr_warn("ieee802154: bad frame received (type = %d)\n",
-			mac_cb(skb)->type);
-		goto fail;
-	}
+	return;
 
 fail:
 	kfree_skb(skb);
-	return NET_RX_DROP;
 }
 
-static void
-ieee802154_print_addr(const char *name, const struct ieee802154_addr *addr)
+static void mac802154_rx_worker(struct work_struct *work)
 {
-	if (addr->mode == IEEE802154_ADDR_NONE)
-		pr_debug("%s not present\n", name);
+	struct rx_work *rw = container_of(work, struct rx_work, work);
 
-	pr_debug("%s PAN ID: %04x\n", name, le16_to_cpu(addr->pan_id));
-	if (addr->mode == IEEE802154_ADDR_SHORT) {
-		pr_debug("%s is short: %04x\n", name,
-			 le16_to_cpu(addr->short_addr));
-	} else {
-		u64 hw = swab64((__force u64)addr->extended_addr);
-
-		pr_debug("%s is hardware: %8phC\n", name, &hw);
-	}
+	mac802154_subif_rx(rw->dev, rw->skb, rw->lqi);
+	kfree(rw);
 }
 
-static int
-ieee802154_parse_frame_start(struct sk_buff *skb, struct ieee802154_hdr *hdr)
-{
-	int hlen;
-	struct ieee802154_mac_cb *cb = mac_cb_init(skb);
-
-	skb_reset_mac_header(skb);
-
-	hlen = ieee802154_hdr_pull(skb, hdr);
-	if (hlen < 0)
-		return -EINVAL;
-
-	skb->mac_len = hlen;
-
-	pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc),
-		 hdr->seq);
-
-	cb->type = hdr->fc.type;
-	cb->ackreq = hdr->fc.ack_request;
-	cb->secen = hdr->fc.security_enabled;
-
-	ieee802154_print_addr("destination", &hdr->dest);
-	ieee802154_print_addr("source", &hdr->source);
-
-	cb->source = hdr->source;
-	cb->dest = hdr->dest;
-
-	if (hdr->fc.security_enabled) {
-		u64 key;
-
-		pr_debug("seclevel %i\n", hdr->sec.level);
-
-		switch (hdr->sec.key_id_mode) {
-		case IEEE802154_SCF_KEY_IMPLICIT:
-			pr_debug("implicit key\n");
-			break;
-
-		case IEEE802154_SCF_KEY_INDEX:
-			pr_debug("key %02x\n", hdr->sec.key_id);
-			break;
-
-		case IEEE802154_SCF_KEY_SHORT_INDEX:
-			pr_debug("key %04x:%04x %02x\n",
-				 le32_to_cpu(hdr->sec.short_src) >> 16,
-				 le32_to_cpu(hdr->sec.short_src) & 0xffff,
-				 hdr->sec.key_id);
-			break;
-
-		case IEEE802154_SCF_KEY_HW_INDEX:
-			key = swab64((__force u64)hdr->sec.extended_src);
-			pr_debug("key source %8phC %02x\n", &key,
-				 hdr->sec.key_id);
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static void
-__ieee802154_rx_handle_packet(struct ieee802154_local *local,
-			      struct sk_buff *skb)
-{
-	int ret;
-	struct ieee802154_sub_if_data *sdata;
-	struct ieee802154_hdr hdr;
-
-	ret = ieee802154_parse_frame_start(skb, &hdr);
-	if (ret) {
-		pr_debug("got invalid frame\n");
-		kfree_skb(skb);
-		return;
-	}
-
-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (sdata->vif.type != NL802154_IFTYPE_NODE ||
-		    !netif_running(sdata->dev))
-			continue;
-
-		ieee802154_subif_frame(sdata, skb, &hdr);
-		skb = NULL;
-		break;
-	}
-
-	if (skb)
-		kfree_skb(skb);
-}
-
-static void
-ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
-{
-	struct sk_buff *skb2;
-	struct ieee802154_sub_if_data *sdata;
-
-	skb_reset_mac_header(skb);
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-	skb->pkt_type = PACKET_OTHERHOST;
-	skb->protocol = htons(ETH_P_IEEE802154);
-
-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (sdata->vif.type != NL802154_IFTYPE_MONITOR)
-			continue;
-
-		if (!ieee802154_sdata_running(sdata))
-			continue;
-
-		skb2 = skb_clone(skb, GFP_ATOMIC);
-		if (skb2) {
-			skb2->dev = sdata->dev;
-			ieee802154_deliver_skb(skb2);
-
-			sdata->dev->stats.rx_packets++;
-			sdata->dev->stats.rx_bytes += skb->len;
-		}
-	}
-}
-
-void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
-{
-	struct ieee802154_local *local = hw_to_local(hw);
-	u16 crc;
-
-	WARN_ON_ONCE(softirq_count() == 0);
-
-	/* TODO: When a transceiver omits the checksum here, we
-	 * add an own calculated one. This is currently an ugly
-	 * solution because the monitor needs a crc here.
-	 */
-	if (local->hw.flags & IEEE802154_HW_RX_OMIT_CKSUM) {
-		crc = crc_ccitt(0, skb->data, skb->len);
-		put_unaligned_le16(crc, skb_put(skb, 2));
-	}
-
-	rcu_read_lock();
-
-	ieee802154_monitors_rx(local, skb);
-
-	/* Check if transceiver doesn't validate the checksum.
-	 * If not we validate the checksum here.
-	 */
-	if (local->hw.flags & IEEE802154_HW_RX_DROP_BAD_CKSUM) {
-		crc = crc_ccitt(0, skb->data, skb->len);
-		if (crc) {
-			rcu_read_unlock();
-			kfree_skb(skb);
-			return;
-		}
-	}
-	/* remove crc */
-	skb_trim(skb, skb->len - 2);
-
-	__ieee802154_rx_handle_packet(local, skb);
-
-	rcu_read_unlock();
-}
-EXPORT_SYMBOL(ieee802154_rx);
-
 void
-ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb, u8 lqi)
+ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi)
 {
-	struct ieee802154_local *local = hw_to_local(hw);
+	struct mac802154_priv *priv = mac802154_to_priv(dev);
+	struct rx_work *work;
 
-	mac_cb(skb)->lqi = lqi;
-	skb->pkt_type = IEEE802154_RX_MSG;
-	skb_queue_tail(&local->skb_queue, skb);
-	tasklet_schedule(&local->tasklet);
+	if (!skb)
+		return;
+
+	work = kzalloc(sizeof(*work), GFP_ATOMIC);
+	if (!work)
+		return;
+
+	INIT_WORK(&work->work, mac802154_rx_worker);
+	work->skb = skb;
+	work->dev = dev;
+	work->lqi = lqi;
+
+	queue_work(priv->dev_workqueue, &work->work);
 }
 EXPORT_SYMBOL(ieee802154_rx_irqsafe);
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index c62e956..fdf4c0e 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -10,6 +10,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
  * Written by:
  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  * Sergey Lapin <slapin@ossfans.org>
@@ -20,130 +24,110 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/crc-ccitt.h>
-#include <asm/unaligned.h>
 
-#include <net/rtnetlink.h>
 #include <net/ieee802154_netdev.h>
 #include <net/mac802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
 
-#include "ieee802154_i.h"
-#include "driver-ops.h"
+#include "mac802154.h"
 
 /* IEEE 802.15.4 transceivers can sleep during the xmit session, so process
  * packets through the workqueue.
  */
-struct ieee802154_xmit_cb {
+struct xmit_work {
 	struct sk_buff *skb;
 	struct work_struct work;
-	struct ieee802154_local *local;
+	struct mac802154_priv *priv;
+	u8 chan;
+	u8 page;
 };
 
-static struct ieee802154_xmit_cb ieee802154_xmit_cb;
-
-static void ieee802154_xmit_worker(struct work_struct *work)
+static void mac802154_xmit_worker(struct work_struct *work)
 {
-	struct ieee802154_xmit_cb *cb =
-		container_of(work, struct ieee802154_xmit_cb, work);
-	struct ieee802154_local *local = cb->local;
-	struct sk_buff *skb = cb->skb;
-	struct net_device *dev = skb->dev;
+	struct xmit_work *xw = container_of(work, struct xmit_work, work);
+	struct mac802154_sub_if_data *sdata;
 	int res;
 
-	rtnl_lock();
-
-	/* check if ifdown occurred while schedule */
-	if (!netif_running(dev))
-		goto err_tx;
-
-	res = drv_xmit_sync(local, skb);
-	if (res)
-		goto err_tx;
-
-	ieee802154_xmit_complete(&local->hw, skb, false);
-
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	rtnl_unlock();
-
-	return;
-
-err_tx:
-	/* Restart the netif queue on each sub_if_data object. */
-	ieee802154_wake_queue(&local->hw);
-	rtnl_unlock();
-	kfree_skb(skb);
-	netdev_dbg(dev, "transmission failed\n");
-}
-
-static netdev_tx_t
-ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
-{
-	struct net_device *dev = skb->dev;
-	int ret;
-
-	if (!(local->hw.flags & IEEE802154_HW_TX_OMIT_CKSUM)) {
-		u16 crc = crc_ccitt(0, skb->data, skb->len);
-
-		put_unaligned_le16(crc, skb_put(skb, 2));
-	}
-
-	if (skb_cow_head(skb, local->hw.extra_tx_headroom))
-		goto err_tx;
-
-	/* Stop the netif queue on each sub_if_data object. */
-	ieee802154_stop_queue(&local->hw);
-
-	/* async is priority, otherwise sync is fallback */
-	if (local->ops->xmit_async) {
-		ret = drv_xmit_async(local, skb);
-		if (ret) {
-			ieee802154_wake_queue(&local->hw);
-			goto err_tx;
+	mutex_lock(&xw->priv->phy->pib_lock);
+	if (xw->priv->phy->current_channel != xw->chan ||
+	    xw->priv->phy->current_page != xw->page) {
+		res = xw->priv->ops->set_channel(&xw->priv->hw,
+						  xw->page,
+						  xw->chan);
+		if (res) {
+			pr_debug("set_channel failed\n");
+			goto out;
 		}
 
-		dev->stats.tx_packets++;
-		dev->stats.tx_bytes += skb->len;
-	} else {
-		INIT_WORK(&ieee802154_xmit_cb.work, ieee802154_xmit_worker);
-		ieee802154_xmit_cb.skb = skb;
-		ieee802154_xmit_cb.local = local;
-
-		queue_work(local->workqueue, &ieee802154_xmit_cb.work);
+		xw->priv->phy->current_channel = xw->chan;
+		xw->priv->phy->current_page = xw->page;
 	}
 
+	res = xw->priv->ops->xmit(&xw->priv->hw, xw->skb);
+	if (res)
+		pr_debug("transmission failed\n");
+
+out:
+	mutex_unlock(&xw->priv->phy->pib_lock);
+
+	/* Restart the netif queue on each sub_if_data object. */
+	rcu_read_lock();
+	list_for_each_entry_rcu(sdata, &xw->priv->slaves, list)
+		netif_wake_queue(sdata->dev);
+	rcu_read_unlock();
+
+	dev_kfree_skb(xw->skb);
+
+	kfree(xw);
+}
+
+netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
+			 u8 page, u8 chan)
+{
+	struct xmit_work *work;
+	struct mac802154_sub_if_data *sdata;
+
+	if (!(priv->phy->channels_supported[page] & (1 << chan))) {
+		WARN_ON(1);
+		goto err_tx;
+	}
+
+	mac802154_monitors_rx(mac802154_to_priv(&priv->hw), skb);
+
+	if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
+		u16 crc = crc_ccitt(0, skb->data, skb->len);
+		u8 *data = skb_put(skb, 2);
+
+		data[0] = crc & 0xff;
+		data[1] = crc >> 8;
+	}
+
+	if (skb_cow_head(skb, priv->hw.extra_tx_headroom))
+		goto err_tx;
+
+	work = kzalloc(sizeof(*work), GFP_ATOMIC);
+	if (!work) {
+		kfree_skb(skb);
+		return NETDEV_TX_BUSY;
+	}
+
+	/* Stop the netif queue on each sub_if_data object. */
+	rcu_read_lock();
+	list_for_each_entry_rcu(sdata, &priv->slaves, list)
+		netif_stop_queue(sdata->dev);
+	rcu_read_unlock();
+
+	INIT_WORK(&work->work, mac802154_xmit_worker);
+	work->skb = skb;
+	work->priv = priv;
+	work->page = page;
+	work->chan = chan;
+
+	queue_work(priv->dev_workqueue, &work->work);
+
 	return NETDEV_TX_OK;
 
 err_tx:
 	kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
-
-netdev_tx_t
-ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-
-	skb->skb_iif = dev->ifindex;
-
-	return ieee802154_tx(sdata->local, skb);
-}
-
-netdev_tx_t
-ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-	int rc;
-
-	rc = mac802154_llsec_encrypt(&sdata->sec, skb);
-	if (rc) {
-		netdev_warn(dev, "encryption failed: %i\n", rc);
-		kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	skb->skb_iif = dev->ifindex;
-
-	return ieee802154_tx(sdata->local, skb);
-}
diff --git a/net/mac802154/util.c b/net/mac802154/util.c
deleted file mode 100644
index 5fc9790..0000000
--- a/net/mac802154/util.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* 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.
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- *
- * Based on: net/mac80211/util.c
- */
-
-#include "ieee802154_i.h"
-
-/* privid for wpan_phys to determine whether they belong to us or not */
-const void *const mac802154_wpan_phy_privid = &mac802154_wpan_phy_privid;
-
-void ieee802154_wake_queue(struct ieee802154_hw *hw)
-{
-	struct ieee802154_local *local = hw_to_local(hw);
-	struct ieee802154_sub_if_data *sdata;
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (!sdata->dev)
-			continue;
-
-		netif_wake_queue(sdata->dev);
-	}
-	rcu_read_unlock();
-}
-EXPORT_SYMBOL(ieee802154_wake_queue);
-
-void ieee802154_stop_queue(struct ieee802154_hw *hw)
-{
-	struct ieee802154_local *local = hw_to_local(hw);
-	struct ieee802154_sub_if_data *sdata;
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (!sdata->dev)
-			continue;
-
-		netif_stop_queue(sdata->dev);
-	}
-	rcu_read_unlock();
-}
-EXPORT_SYMBOL(ieee802154_stop_queue);
-
-enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer)
-{
-	struct ieee802154_local *local =
-		container_of(timer, struct ieee802154_local, ifs_timer);
-
-	ieee802154_wake_queue(&local->hw);
-
-	return HRTIMER_NORESTART;
-}
-
-void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
-			      bool ifs_handling)
-{
-	if (ifs_handling) {
-		struct ieee802154_local *local = hw_to_local(hw);
-
-		if (skb->len > 18)
-			hrtimer_start(&local->ifs_timer,
-				      ktime_set(0, hw->phy->lifs_period * NSEC_PER_USEC),
-				      HRTIMER_MODE_REL);
-		else
-			hrtimer_start(&local->ifs_timer,
-				      ktime_set(0, hw->phy->sifs_period * NSEC_PER_USEC),
-				      HRTIMER_MODE_REL);
-
-		consume_skb(skb);
-	} else {
-		ieee802154_wake_queue(hw);
-		consume_skb(skb);
-	}
-}
-EXPORT_SYMBOL(ieee802154_xmit_complete);
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
new file mode 100644
index 0000000..4ab86a5
--- /dev/null
+++ b/net/mac802154/wpan.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright 2007-2012 Siemens AG
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ * Sergey Lapin <slapin@ossfans.org>
+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
+ * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <linux/if_arp.h>
+
+#include <net/rtnetlink.h>
+#include <linux/nl802154.h>
+#include <net/af_ieee802154.h>
+#include <net/mac802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/ieee802154.h>
+#include <net/wpan-phy.h>
+
+#include "mac802154.h"
+
+static int mac802154_wpan_update_llsec(struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
+	int rc = 0;
+
+	if (ops->llsec) {
+		struct ieee802154_llsec_params params;
+		int changed = 0;
+
+		params.pan_id = priv->pan_id;
+		changed |= IEEE802154_LLSEC_PARAM_PAN_ID;
+
+		params.hwaddr = priv->extended_addr;
+		changed |= IEEE802154_LLSEC_PARAM_HWADDR;
+
+		rc = ops->llsec->set_params(dev, &params, changed);
+	}
+
+	return rc;
+}
+
+static int
+mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct sockaddr_ieee802154 *sa =
+		(struct sockaddr_ieee802154 *)&ifr->ifr_addr;
+	int err = -ENOIOCTLCMD;
+
+	spin_lock_bh(&priv->mib_lock);
+
+	switch (cmd) {
+	case SIOCGIFADDR:
+	{
+		u16 pan_id, short_addr;
+
+		pan_id = le16_to_cpu(priv->pan_id);
+		short_addr = le16_to_cpu(priv->short_addr);
+		if (pan_id == IEEE802154_PANID_BROADCAST ||
+		    short_addr == IEEE802154_ADDR_BROADCAST) {
+			err = -EADDRNOTAVAIL;
+			break;
+		}
+
+		sa->family = AF_IEEE802154;
+		sa->addr.addr_type = IEEE802154_ADDR_SHORT;
+		sa->addr.pan_id = pan_id;
+		sa->addr.short_addr = short_addr;
+
+		err = 0;
+		break;
+	}
+	case SIOCSIFADDR:
+		dev_warn(&dev->dev,
+			 "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n");
+		if (sa->family != AF_IEEE802154 ||
+		    sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
+		    sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
+		    sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
+		    sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
+			err = -EINVAL;
+			break;
+		}
+
+		priv->pan_id = cpu_to_le16(sa->addr.pan_id);
+		priv->short_addr = cpu_to_le16(sa->addr.short_addr);
+
+		err = mac802154_wpan_update_llsec(dev);
+		break;
+	}
+
+	spin_unlock_bh(&priv->mib_lock);
+	return err;
+}
+
+static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+
+	if (netif_running(dev))
+		return -EBUSY;
+
+	/* FIXME: validate addr */
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	mac802154_dev_set_ieee_addr(dev);
+	return mac802154_wpan_update_llsec(dev);
+}
+
+int mac802154_set_mac_params(struct net_device *dev,
+			     const struct ieee802154_mac_params *params)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+	mutex_lock(&priv->hw->slaves_mtx);
+	priv->mac_params = *params;
+	mutex_unlock(&priv->hw->slaves_mtx);
+
+	return 0;
+}
+
+void mac802154_get_mac_params(struct net_device *dev,
+			      struct ieee802154_mac_params *params)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+	mutex_lock(&priv->hw->slaves_mtx);
+	*params = priv->mac_params;
+	mutex_unlock(&priv->hw->slaves_mtx);
+}
+
+static int mac802154_wpan_open(struct net_device *dev)
+{
+	int rc;
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct wpan_phy *phy = priv->hw->phy;
+
+	rc = mac802154_slave_open(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&phy->pib_lock);
+
+	if (phy->set_txpower) {
+		rc = phy->set_txpower(phy, priv->mac_params.transmit_power);
+		if (rc < 0)
+			goto out;
+	}
+
+	if (phy->set_lbt) {
+		rc = phy->set_lbt(phy, priv->mac_params.lbt);
+		if (rc < 0)
+			goto out;
+	}
+
+	if (phy->set_cca_mode) {
+		rc = phy->set_cca_mode(phy, priv->mac_params.cca_mode);
+		if (rc < 0)
+			goto out;
+	}
+
+	if (phy->set_cca_ed_level) {
+		rc = phy->set_cca_ed_level(phy, priv->mac_params.cca_ed_level);
+		if (rc < 0)
+			goto out;
+	}
+
+	if (phy->set_csma_params) {
+		rc = phy->set_csma_params(phy, priv->mac_params.min_be,
+					  priv->mac_params.max_be,
+					  priv->mac_params.csma_retries);
+		if (rc < 0)
+			goto out;
+	}
+
+	if (phy->set_frame_retries) {
+		rc = phy->set_frame_retries(phy,
+					    priv->mac_params.frame_retries);
+		if (rc < 0)
+			goto out;
+	}
+
+	mutex_unlock(&phy->pib_lock);
+	return 0;
+
+out:
+	mutex_unlock(&phy->pib_lock);
+	return rc;
+}
+
+static int mac802154_set_header_security(struct mac802154_sub_if_data *priv,
+					 struct ieee802154_hdr *hdr,
+					 const struct ieee802154_mac_cb *cb)
+{
+	struct ieee802154_llsec_params params;
+	u8 level;
+
+	mac802154_llsec_get_params(&priv->sec, &params);
+
+	if (!params.enabled && cb->secen_override && cb->secen)
+		return -EINVAL;
+	if (!params.enabled ||
+	    (cb->secen_override && !cb->secen) ||
+	    !params.out_level)
+		return 0;
+	if (cb->seclevel_override && !cb->seclevel)
+		return -EINVAL;
+
+	level = cb->seclevel_override ? cb->seclevel : params.out_level;
+
+	hdr->fc.security_enabled = 1;
+	hdr->sec.level = level;
+	hdr->sec.key_id_mode = params.out_key.mode;
+	if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX)
+		hdr->sec.short_src = params.out_key.short_source;
+	else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX)
+		hdr->sec.extended_src = params.out_key.extended_source;
+	hdr->sec.key_id = params.out_key.id;
+
+	return 0;
+}
+
+static int mac802154_header_create(struct sk_buff *skb,
+				   struct net_device *dev,
+				   unsigned short type,
+				   const void *daddr,
+				   const void *saddr,
+				   unsigned len)
+{
+	struct ieee802154_hdr hdr;
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+	struct ieee802154_mac_cb *cb = mac_cb(skb);
+	int hlen;
+
+	if (!daddr)
+		return -EINVAL;
+
+	memset(&hdr.fc, 0, sizeof(hdr.fc));
+	hdr.fc.type = cb->type;
+	hdr.fc.security_enabled = cb->secen;
+	hdr.fc.ack_request = cb->ackreq;
+	hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+
+	if (mac802154_set_header_security(priv, &hdr, cb) < 0)
+		return -EINVAL;
+
+	if (!saddr) {
+		spin_lock_bh(&priv->mib_lock);
+
+		if (priv->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) ||
+		    priv->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
+		    priv->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) {
+			hdr.source.mode = IEEE802154_ADDR_LONG;
+			hdr.source.extended_addr = priv->extended_addr;
+		} else {
+			hdr.source.mode = IEEE802154_ADDR_SHORT;
+			hdr.source.short_addr = priv->short_addr;
+		}
+
+		hdr.source.pan_id = priv->pan_id;
+
+		spin_unlock_bh(&priv->mib_lock);
+	} else {
+		hdr.source = *(const struct ieee802154_addr *)saddr;
+	}
+
+	hdr.dest = *(const struct ieee802154_addr *)daddr;
+
+	hlen = ieee802154_hdr_push(skb, &hdr);
+	if (hlen < 0)
+		return -EINVAL;
+
+	skb_reset_mac_header(skb);
+	skb->mac_len = hlen;
+
+	if (len > ieee802154_max_payload(&hdr))
+		return -EMSGSIZE;
+
+	return hlen;
+}
+
+static int
+mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+{
+	struct ieee802154_hdr hdr;
+	struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
+
+	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
+		pr_debug("malformed packet\n");
+		return 0;
+	}
+
+	*addr = hdr.source;
+	return sizeof(*addr);
+}
+
+static netdev_tx_t
+mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv;
+	u8 chan, page;
+	int rc;
+
+	priv = netdev_priv(dev);
+
+	spin_lock_bh(&priv->mib_lock);
+	chan = priv->chan;
+	page = priv->page;
+	spin_unlock_bh(&priv->mib_lock);
+
+	if (chan == MAC802154_CHAN_NONE ||
+	    page >= WPAN_NUM_PAGES ||
+	    chan >= WPAN_NUM_CHANNELS) {
+		kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	rc = mac802154_llsec_encrypt(&priv->sec, skb);
+	if (rc) {
+		pr_warn("encryption failed: %i\n", rc);
+		kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	skb->skb_iif = dev->ifindex;
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	return mac802154_tx(priv->hw, skb, page, chan);
+}
+
+static struct header_ops mac802154_header_ops = {
+	.create		= mac802154_header_create,
+	.parse		= mac802154_header_parse,
+};
+
+static const struct net_device_ops mac802154_wpan_ops = {
+	.ndo_open		= mac802154_wpan_open,
+	.ndo_stop		= mac802154_slave_close,
+	.ndo_start_xmit		= mac802154_wpan_xmit,
+	.ndo_do_ioctl		= mac802154_wpan_ioctl,
+	.ndo_set_mac_address	= mac802154_wpan_mac_addr,
+};
+
+static void mac802154_wpan_free(struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+	mac802154_llsec_destroy(&priv->sec);
+
+	free_netdev(dev);
+}
+
+void mac802154_wpan_setup(struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv;
+
+	dev->addr_len		= IEEE802154_ADDR_LEN;
+	memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
+
+	dev->hard_header_len	= MAC802154_FRAME_HARD_HEADER_LEN;
+	dev->header_ops		= &mac802154_header_ops;
+	dev->needed_tailroom	= 2 + 16; /* FCS + MIC */
+	dev->mtu		= IEEE802154_MTU;
+	dev->tx_queue_len	= 300;
+	dev->type		= ARPHRD_IEEE802154;
+	dev->flags		= IFF_NOARP | IFF_BROADCAST;
+	dev->watchdog_timeo	= 0;
+
+	dev->destructor		= mac802154_wpan_free;
+	dev->netdev_ops		= &mac802154_wpan_ops;
+	dev->ml_priv		= &mac802154_mlme_wpan;
+
+	priv = netdev_priv(dev);
+	priv->type = IEEE802154_DEV_WPAN;
+
+	priv->chan = MAC802154_CHAN_NONE;
+	priv->page = 0;
+
+	spin_lock_init(&priv->mib_lock);
+	mutex_init(&priv->sec_mtx);
+
+	get_random_bytes(&priv->bsn, 1);
+	get_random_bytes(&priv->dsn, 1);
+
+	/* defaults per 802.15.4-2011 */
+	priv->mac_params.min_be = 3;
+	priv->mac_params.max_be = 5;
+	priv->mac_params.csma_retries = 4;
+	priv->mac_params.frame_retries = -1; /* for compatibility, actual default is 3 */
+
+	priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
+	priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
+
+	mac802154_llsec_init(&priv->sec);
+}
+
+static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
+{
+	return netif_rx_ni(skb);
+}
+
+static int
+mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb,
+		      const struct ieee802154_hdr *hdr)
+{
+	__le16 span, sshort;
+	int rc;
+
+	pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
+
+	spin_lock_bh(&sdata->mib_lock);
+
+	span = sdata->pan_id;
+	sshort = sdata->short_addr;
+
+	switch (mac_cb(skb)->dest.mode) {
+	case IEEE802154_ADDR_NONE:
+		if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
+			/* FIXME: check if we are PAN coordinator */
+			skb->pkt_type = PACKET_OTHERHOST;
+		else
+			/* ACK comes with both addresses empty */
+			skb->pkt_type = PACKET_HOST;
+		break;
+	case IEEE802154_ADDR_LONG:
+		if (mac_cb(skb)->dest.pan_id != span &&
+		    mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
+			skb->pkt_type = PACKET_OTHERHOST;
+		else if (mac_cb(skb)->dest.extended_addr == sdata->extended_addr)
+			skb->pkt_type = PACKET_HOST;
+		else
+			skb->pkt_type = PACKET_OTHERHOST;
+		break;
+	case IEEE802154_ADDR_SHORT:
+		if (mac_cb(skb)->dest.pan_id != span &&
+		    mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
+			skb->pkt_type = PACKET_OTHERHOST;
+		else if (mac_cb(skb)->dest.short_addr == sshort)
+			skb->pkt_type = PACKET_HOST;
+		else if (mac_cb(skb)->dest.short_addr ==
+			  cpu_to_le16(IEEE802154_ADDR_BROADCAST))
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_OTHERHOST;
+		break;
+	default:
+		spin_unlock_bh(&sdata->mib_lock);
+		pr_debug("invalid dest mode\n");
+		kfree_skb(skb);
+		return NET_RX_DROP;
+	}
+
+	spin_unlock_bh(&sdata->mib_lock);
+
+	skb->dev = sdata->dev;
+
+	rc = mac802154_llsec_decrypt(&sdata->sec, skb);
+	if (rc) {
+		pr_debug("decryption failed: %i\n", rc);
+		goto fail;
+	}
+
+	sdata->dev->stats.rx_packets++;
+	sdata->dev->stats.rx_bytes += skb->len;
+
+	switch (mac_cb(skb)->type) {
+	case IEEE802154_FC_TYPE_DATA:
+		return mac802154_process_data(sdata->dev, skb);
+	default:
+		pr_warn("ieee802154: bad frame received (type = %d)\n",
+			mac_cb(skb)->type);
+		goto fail;
+	}
+
+fail:
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
+
+static void mac802154_print_addr(const char *name,
+				 const struct ieee802154_addr *addr)
+{
+	if (addr->mode == IEEE802154_ADDR_NONE)
+		pr_debug("%s not present\n", name);
+
+	pr_debug("%s PAN ID: %04x\n", name, le16_to_cpu(addr->pan_id));
+	if (addr->mode == IEEE802154_ADDR_SHORT) {
+		pr_debug("%s is short: %04x\n", name,
+			 le16_to_cpu(addr->short_addr));
+	} else {
+		u64 hw = swab64((__force u64) addr->extended_addr);
+
+		pr_debug("%s is hardware: %8phC\n", name, &hw);
+	}
+}
+
+static int mac802154_parse_frame_start(struct sk_buff *skb,
+				       struct ieee802154_hdr *hdr)
+{
+	int hlen;
+	struct ieee802154_mac_cb *cb = mac_cb_init(skb);
+
+	hlen = ieee802154_hdr_pull(skb, hdr);
+	if (hlen < 0)
+		return -EINVAL;
+
+	skb->mac_len = hlen;
+
+	pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc),
+		 hdr->seq);
+
+	cb->type = hdr->fc.type;
+	cb->ackreq = hdr->fc.ack_request;
+	cb->secen = hdr->fc.security_enabled;
+
+	mac802154_print_addr("destination", &hdr->dest);
+	mac802154_print_addr("source", &hdr->source);
+
+	cb->source = hdr->source;
+	cb->dest = hdr->dest;
+
+	if (hdr->fc.security_enabled) {
+		u64 key;
+
+		pr_debug("seclevel %i\n", hdr->sec.level);
+
+		switch (hdr->sec.key_id_mode) {
+		case IEEE802154_SCF_KEY_IMPLICIT:
+			pr_debug("implicit key\n");
+			break;
+
+		case IEEE802154_SCF_KEY_INDEX:
+			pr_debug("key %02x\n", hdr->sec.key_id);
+			break;
+
+		case IEEE802154_SCF_KEY_SHORT_INDEX:
+			pr_debug("key %04x:%04x %02x\n",
+				 le32_to_cpu(hdr->sec.short_src) >> 16,
+				 le32_to_cpu(hdr->sec.short_src) & 0xffff,
+				 hdr->sec.key_id);
+			break;
+
+		case IEEE802154_SCF_KEY_HW_INDEX:
+			key = swab64((__force u64) hdr->sec.extended_src);
+			pr_debug("key source %8phC %02x\n", &key,
+				 hdr->sec.key_id);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
+{
+	int ret;
+	struct mac802154_sub_if_data *sdata;
+	struct ieee802154_hdr hdr;
+
+	ret = mac802154_parse_frame_start(skb, &hdr);
+	if (ret) {
+		pr_debug("got invalid frame\n");
+		kfree_skb(skb);
+		return;
+	}
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(sdata, &priv->slaves, list) {
+		if (sdata->type != IEEE802154_DEV_WPAN ||
+		    !netif_running(sdata->dev))
+			continue;
+
+		mac802154_subif_frame(sdata, skb, &hdr);
+		skb = NULL;
+		break;
+	}
+	rcu_read_unlock();
+
+	if (skb)
+		kfree_skb(skb);
+}
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig
index 5e54818..314f31c 100644
--- a/net/nfc/Kconfig
+++ b/net/nfc/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menuconfig NFC
-	depends on !KERNEL_3_1
+	depends on !BACKPORT_KERNEL_3_1
 	depends on NET
 	depends on RFKILL || !RFKILL
 	tristate "NFC subsystem support"
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index f72be74..b60aa35 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -17,9 +17,6 @@
 
 #include "digital.h"
 
-#define DIGITAL_NFC_DEP_N_RETRY_NACK	2
-#define DIGITAL_NFC_DEP_N_RETRY_ATN	2
-
 #define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4
 #define DIGITAL_NFC_DEP_FRAME_DIR_IN  0xD5
 
@@ -35,32 +32,20 @@
 #define DIGITAL_ATR_REQ_MIN_SIZE 16
 #define DIGITAL_ATR_REQ_MAX_SIZE 64
 
-#define DIGITAL_DID_MAX	14
-
-#define DIGITAL_PAYLOAD_SIZE_MAX	254
-#define DIGITAL_PAYLOAD_BITS_TO_PP(s)	(((s) & 0x3) << 4)
-#define DIGITAL_PAYLOAD_PP_TO_BITS(s)	(((s) >> 4) & 0x3)
-#define DIGITAL_PAYLOAD_BITS_TO_FSL(s)	((s) & 0x3)
-#define DIGITAL_PAYLOAD_FSL_TO_BITS(s)	((s) & 0x3)
-
+#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
+#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
+				(DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
 #define DIGITAL_GB_BIT	0x02
 
-#define DIGITAL_NFC_DEP_REQ_RES_HEADROOM	2 /* SoD: [SB (NFC-A)] + LEN */
-#define DIGITAL_NFC_DEP_REQ_RES_TAILROOM	2 /* EoD: 2-byte CRC */
-
 #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
 
 #define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
-#define DIGITAL_NFC_DEP_PFB_MI_BIT	0x10
-#define DIGITAL_NFC_DEP_PFB_NACK_BIT	0x10
-#define DIGITAL_NFC_DEP_PFB_DID_BIT	0x04
 
 #define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
 				((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
-#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb)  ((pfb) & DIGITAL_NFC_DEP_PFB_MI_BIT)
-#define DIGITAL_NFC_DEP_NACK_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_NACK_BIT)
+#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb)  ((pfb) & 0x10)
 #define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
-#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
+#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
 #define DIGITAL_NFC_DEP_PFB_PNI(pfb)     ((pfb) & 0x03)
 
 #define DIGITAL_NFC_DEP_PFB_I_PDU          0x00
@@ -112,34 +97,6 @@
 
 static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
 				    struct sk_buff *resp);
-static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
-				    struct sk_buff *resp);
-
-static const u8 digital_payload_bits_map[4] = {
-	[0] = 64,
-	[1] = 128,
-	[2] = 192,
-	[3] = 254
-};
-
-static u8 digital_payload_bits_to_size(u8 payload_bits)
-{
-	if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map))
-		return 0;
-
-	return digital_payload_bits_map[payload_bits];
-}
-
-static u8 digital_payload_size_to_bits(u8 payload_size)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(digital_payload_bits_map); i++)
-		if (digital_payload_bits_map[i] == payload_size)
-			return i;
-
-	return 0xff;
-}
 
 static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev,
 				     struct sk_buff *skb)
@@ -172,106 +129,6 @@
 	return 0;
 }
 
-static struct sk_buff *
-digital_send_dep_data_prep(struct nfc_digital_dev *ddev, struct sk_buff *skb,
-			   struct digital_dep_req_res *dep_req_res,
-			   struct digital_data_exch *data_exch)
-{
-	struct sk_buff *new_skb;
-
-	if (skb->len > ddev->remote_payload_max) {
-		dep_req_res->pfb |= DIGITAL_NFC_DEP_PFB_MI_BIT;
-
-		new_skb = digital_skb_alloc(ddev, ddev->remote_payload_max);
-		if (!new_skb) {
-			kfree_skb(ddev->chaining_skb);
-			ddev->chaining_skb = NULL;
-
-			return ERR_PTR(-ENOMEM);
-		}
-
-		skb_reserve(new_skb, ddev->tx_headroom + NFC_HEADER_SIZE +
-					DIGITAL_NFC_DEP_REQ_RES_HEADROOM);
-		memcpy(skb_put(new_skb, ddev->remote_payload_max), skb->data,
-		       ddev->remote_payload_max);
-		skb_pull(skb, ddev->remote_payload_max);
-
-		ddev->chaining_skb = skb;
-		ddev->data_exch = data_exch;
-	} else {
-		ddev->chaining_skb = NULL;
-		new_skb = skb;
-	}
-
-	return new_skb;
-}
-
-static struct sk_buff *
-digital_recv_dep_data_gather(struct nfc_digital_dev *ddev, u8 pfb,
-			     struct sk_buff *resp,
-			     int (*send_ack)(struct nfc_digital_dev *ddev,
-					     struct digital_data_exch
-							     *data_exch),
-			     struct digital_data_exch *data_exch)
-{
-	struct sk_buff *new_skb;
-	int rc;
-
-	if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb) && (!ddev->chaining_skb)) {
-		ddev->chaining_skb =
-			nfc_alloc_recv_skb(8 * ddev->local_payload_max,
-					   GFP_KERNEL);
-		if (!ddev->chaining_skb) {
-			rc = -ENOMEM;
-			goto error;
-		}
-	}
-
-	if (ddev->chaining_skb) {
-		if (resp->len > skb_tailroom(ddev->chaining_skb)) {
-			new_skb = skb_copy_expand(ddev->chaining_skb,
-						  skb_headroom(
-							  ddev->chaining_skb),
-						  8 * ddev->local_payload_max,
-						  GFP_KERNEL);
-			if (!new_skb) {
-				rc = -ENOMEM;
-				goto error;
-			}
-
-			kfree_skb(ddev->chaining_skb);
-			ddev->chaining_skb = new_skb;
-		}
-
-		memcpy(skb_put(ddev->chaining_skb, resp->len), resp->data,
-		       resp->len);
-
-		kfree_skb(resp);
-		resp = NULL;
-
-		if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
-			rc = send_ack(ddev, data_exch);
-			if (rc)
-				goto error;
-
-			return NULL;
-		}
-
-		resp = ddev->chaining_skb;
-		ddev->chaining_skb = NULL;
-	}
-
-	return resp;
-
-error:
-	kfree_skb(resp);
-
-	kfree_skb(ddev->chaining_skb);
-	ddev->chaining_skb = NULL;
-
-	return ERR_PTR(rc);
-}
-
 static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
 				    struct sk_buff *resp)
 {
@@ -341,8 +198,6 @@
 {
 	struct sk_buff *skb;
 	struct digital_psl_req *psl_req;
-	int rc;
-	u8 payload_size, payload_bits;
 
 	skb = digital_skb_alloc(ddev, sizeof(*psl_req));
 	if (!skb)
@@ -356,24 +211,14 @@
 	psl_req->cmd = DIGITAL_CMD_PSL_REQ;
 	psl_req->did = 0;
 	psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
-
-	payload_size = min(ddev->local_payload_max, ddev->remote_payload_max);
-	payload_bits = digital_payload_size_to_bits(payload_size);
-	psl_req->fsl = DIGITAL_PAYLOAD_BITS_TO_FSL(payload_bits);
-
-	ddev->local_payload_max = payload_size;
-	ddev->remote_payload_max = payload_size;
+	psl_req->fsl = DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B;
 
 	digital_skb_push_dep_sod(ddev, skb);
 
 	ddev->skb_add_crc(skb);
 
-	rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res,
-				 target);
-	if (rc)
-		kfree_skb(skb);
-
-	return rc;
+	return digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res,
+				   target);
 }
 
 static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
@@ -381,7 +226,7 @@
 {
 	struct nfc_target *target = arg;
 	struct digital_atr_res *atr_res;
-	u8 gb_len, payload_bits;
+	u8 gb_len;
 	int rc;
 
 	if (IS_ERR(resp)) {
@@ -411,14 +256,6 @@
 
 	atr_res = (struct digital_atr_res *)resp->data;
 
-	payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp);
-	ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
-
-	if (!ddev->remote_payload_max) {
-		rc = -EINVAL;
-		goto exit;
-	}
-
 	rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len);
 	if (rc)
 		goto exit;
@@ -449,8 +286,6 @@
 	struct sk_buff *skb;
 	struct digital_atr_req *atr_req;
 	uint size;
-	int rc;
-	u8 payload_bits;
 
 	size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len;
 
@@ -479,9 +314,7 @@
 	atr_req->bs = 0;
 	atr_req->br = 0;
 
-	ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
-	payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
-	atr_req->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
+	atr_req->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
 
 	if (gb_len) {
 		atr_req->pp |= DIGITAL_GB_BIT;
@@ -492,113 +325,8 @@
 
 	ddev->skb_add_crc(skb);
 
-	rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res,
-				 target);
-	if (rc)
-		kfree_skb(skb);
-
-	return rc;
-}
-
-static int digital_in_send_ack(struct nfc_digital_dev *ddev,
-			       struct digital_data_exch *data_exch)
-{
-	struct digital_dep_req_res *dep_req;
-	struct sk_buff *skb;
-	int rc;
-
-	skb = digital_skb_alloc(ddev, 1);
-	if (!skb)
-		return -ENOMEM;
-
-	skb_push(skb, sizeof(struct digital_dep_req_res));
-
-	dep_req = (struct digital_dep_req_res *)skb->data;
-
-	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
-	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
-	dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
-		       ddev->curr_nfc_dep_pni;
-
-	digital_skb_push_dep_sod(ddev, skb);
-
-	ddev->skb_add_crc(skb);
-
-	ddev->saved_skb = skb_get(skb);
-	ddev->saved_skb_len = skb->len;
-
-	rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
-				 data_exch);
-	if (rc) {
-		kfree_skb(skb);
-		kfree_skb(ddev->saved_skb);
-		ddev->saved_skb = NULL;
-	}
-
-	return rc;
-}
-
-static int digital_in_send_nack(struct nfc_digital_dev *ddev,
-				struct digital_data_exch *data_exch)
-{
-	struct digital_dep_req_res *dep_req;
-	struct sk_buff *skb;
-	int rc;
-
-	skb = digital_skb_alloc(ddev, 1);
-	if (!skb)
-		return -ENOMEM;
-
-	skb_push(skb, sizeof(struct digital_dep_req_res));
-
-	dep_req = (struct digital_dep_req_res *)skb->data;
-
-	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
-	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
-	dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
-		       DIGITAL_NFC_DEP_PFB_NACK_BIT | ddev->curr_nfc_dep_pni;
-
-	digital_skb_push_dep_sod(ddev, skb);
-
-	ddev->skb_add_crc(skb);
-
-	rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
-				 data_exch);
-	if (rc)
-		kfree_skb(skb);
-
-	return rc;
-}
-
-static int digital_in_send_atn(struct nfc_digital_dev *ddev,
-			       struct digital_data_exch *data_exch)
-{
-	struct digital_dep_req_res *dep_req;
-	struct sk_buff *skb;
-	int rc;
-
-	skb = digital_skb_alloc(ddev, 1);
-	if (!skb)
-		return -ENOMEM;
-
-	skb_push(skb, sizeof(struct digital_dep_req_res));
-
-	dep_req = (struct digital_dep_req_res *)skb->data;
-
-	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
-	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
-	dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
-
-	digital_skb_push_dep_sod(ddev, skb);
-
-	ddev->skb_add_crc(skb);
-
-	rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
-				 data_exch);
-	if (rc)
-		kfree_skb(skb);
-
-	return rc;
+	return digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res,
+				   target);
 }
 
 static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
@@ -627,30 +355,12 @@
 
 	ddev->skb_add_crc(skb);
 
-	ddev->saved_skb = skb_get(skb);
-	ddev->saved_skb_len = skb->len;
-
 	rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
 				 data_exch);
-	if (rc) {
-		kfree_skb(skb);
-		kfree_skb(ddev->saved_skb);
-		ddev->saved_skb = NULL;
-	}
 
 	return rc;
 }
 
-static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev,
-				     struct digital_data_exch *data_exch)
-{
-	skb_get(ddev->saved_skb);
-	skb_push(ddev->saved_skb, ddev->saved_skb_len);
-
-	return digital_in_send_cmd(ddev, ddev->saved_skb, 1500,
-				   digital_in_recv_dep_res, data_exch);
-}
-
 static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
 				    struct sk_buff *resp)
 {
@@ -663,67 +373,25 @@
 	if (IS_ERR(resp)) {
 		rc = PTR_ERR(resp);
 		resp = NULL;
-
-		if (((rc != -ETIMEDOUT) || ddev->nack_count) &&
-		    (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
-			ddev->atn_count = 0;
-
-			rc = digital_in_send_nack(ddev, data_exch);
-			if (rc)
-				goto error;
-
-			return;
-		} else if ((rc == -ETIMEDOUT) &&
-			   (ddev->atn_count++ < DIGITAL_NFC_DEP_N_RETRY_ATN)) {
-			ddev->nack_count = 0;
-
-			rc = digital_in_send_atn(ddev, data_exch);
-			if (rc)
-				goto error;
-
-			return;
-		}
-
 		goto exit;
 	}
 
+	rc = ddev->skb_check_crc(resp);
+	if (rc) {
+		PROTOCOL_ERR("14.4.1.6");
+		goto error;
+	}
+
 	rc = digital_skb_pull_dep_sod(ddev, resp);
 	if (rc) {
 		PROTOCOL_ERR("14.4.1.2");
 		goto exit;
 	}
 
-	rc = ddev->skb_check_crc(resp);
-	if (rc) {
-		if ((resp->len >= 4) &&
-		    (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
-			ddev->atn_count = 0;
-
-			rc = digital_in_send_nack(ddev, data_exch);
-			if (rc)
-				goto error;
-
-			kfree_skb(resp);
-
-			return;
-		}
-
-		PROTOCOL_ERR("14.4.1.6");
-		goto error;
-	}
-
-	ddev->atn_count = 0;
-	ddev->nack_count = 0;
-
-	if (resp->len > ddev->local_payload_max) {
-		rc = -EMSGSIZE;
-		goto exit;
-	}
-
-	size = sizeof(struct digital_dep_req_res);
 	dep_res = (struct digital_dep_req_res *)resp->data;
 
-	if (resp->len < size || dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
+	if (resp->len < sizeof(struct digital_dep_req_res) ||
+	    dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
 	    dep_res->cmd != DIGITAL_CMD_DEP_RES) {
 		rc = -EIO;
 		goto error;
@@ -731,24 +399,6 @@
 
 	pfb = dep_res->pfb;
 
-	if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
-		PROTOCOL_ERR("14.8.2.1");
-		rc = -EIO;
-		goto error;
-	}
-
-	if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
-		rc = -EIO;
-		goto exit;
-	}
-
-	if (size > resp->len) {
-		rc = -EIO;
-		goto error;
-	}
-
-	skb_pull(resp, size);
-
 	switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
 	case DIGITAL_NFC_DEP_PFB_I_PDU:
 		if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
@@ -759,71 +409,21 @@
 
 		ddev->curr_nfc_dep_pni =
 			DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
-
-		kfree_skb(ddev->saved_skb);
-		ddev->saved_skb = NULL;
-
-		resp = digital_recv_dep_data_gather(ddev, pfb, resp,
-						    digital_in_send_ack,
-						    data_exch);
-		if (IS_ERR(resp)) {
-			rc = PTR_ERR(resp);
-			resp = NULL;
-			goto error;
-		}
-
-		/* If resp is NULL then we're still chaining so return and
-		 * wait for the next part of the PDU.  Else, the PDU is
-		 * complete so pass it up.
-		 */
-		if (!resp)
-			return;
-
 		rc = 0;
 		break;
 
 	case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
-		if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
-			PROTOCOL_ERR("14.12.3.3");
-			rc = -EIO;
-			goto exit;
-		}
-
-		ddev->curr_nfc_dep_pni =
-			DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
-
-		if (ddev->chaining_skb && !DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) {
-			kfree_skb(ddev->saved_skb);
-			ddev->saved_skb = NULL;
-
-			rc = digital_in_send_dep_req(ddev, NULL,
-						     ddev->chaining_skb,
-						     ddev->data_exch);
-			if (rc)
-				goto error;
-
-			return;
-		}
-
 		pr_err("Received a ACK/NACK PDU\n");
-		rc = -EINVAL;
-		goto exit;
+		rc = -EIO;
+		goto error;
 
 	case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
-		if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { /* ATN */
-			rc = digital_in_send_saved_skb(ddev, data_exch);
-			if (rc) {
-				kfree_skb(ddev->saved_skb);
-				goto error;
-			}
-
-			return;
+		if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
+			rc = -EINVAL;
+			goto error;
 		}
 
-		kfree_skb(ddev->saved_skb);
-		ddev->saved_skb = NULL;
-
-		rc = digital_in_send_rtox(ddev, data_exch, resp->data[0]);
+		rc = digital_in_send_rtox(ddev, data_exch, resp->data[3]);
 		if (rc)
 			goto error;
 
@@ -831,18 +431,30 @@
 		return;
 	}
 
+	if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
+		pr_err("MI bit set. Chained PDU not supported\n");
+		rc = -EIO;
+		goto error;
+	}
+
+	size = sizeof(struct digital_dep_req_res);
+
+	if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb))
+		size++;
+
+	if (size > resp->len) {
+		rc = -EIO;
+		goto error;
+	}
+
+	skb_pull(resp, size);
+
 exit:
 	data_exch->cb(data_exch->cb_context, resp, rc);
 
 error:
 	kfree(data_exch);
 
-	kfree_skb(ddev->chaining_skb);
-	ddev->chaining_skb = NULL;
-
-	kfree_skb(ddev->saved_skb);
-	ddev->saved_skb = NULL;
-
 	if (rc)
 		kfree_skb(resp);
 }
@@ -852,47 +464,20 @@
 			    struct digital_data_exch *data_exch)
 {
 	struct digital_dep_req_res *dep_req;
-	struct sk_buff *chaining_skb, *tmp_skb;
-	int rc;
 
 	skb_push(skb, sizeof(struct digital_dep_req_res));
 
 	dep_req = (struct digital_dep_req_res *)skb->data;
-
 	dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
 	dep_req->cmd = DIGITAL_CMD_DEP_REQ;
 	dep_req->pfb = ddev->curr_nfc_dep_pni;
 
-	ddev->atn_count = 0;
-	ddev->nack_count = 0;
+	digital_skb_push_dep_sod(ddev, skb);
 
-	chaining_skb = ddev->chaining_skb;
+	ddev->skb_add_crc(skb);
 
-	tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_req, data_exch);
-	if (IS_ERR(tmp_skb))
-		return PTR_ERR(tmp_skb);
-
-	digital_skb_push_dep_sod(ddev, tmp_skb);
-
-	ddev->skb_add_crc(tmp_skb);
-
-	ddev->saved_skb = skb_get(tmp_skb);
-	ddev->saved_skb_len = tmp_skb->len;
-
-	rc = digital_in_send_cmd(ddev, tmp_skb, 1500, digital_in_recv_dep_res,
-				 data_exch);
-	if (rc) {
-		if (tmp_skb != skb)
-			kfree_skb(tmp_skb);
-
-		kfree_skb(chaining_skb);
-		ddev->chaining_skb = NULL;
-
-		kfree_skb(ddev->saved_skb);
-		ddev->saved_skb = NULL;
-	}
-
-	return rc;
+	return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
+				   data_exch);
 }
 
 static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
@@ -922,106 +507,11 @@
 	}
 }
 
-static int digital_tg_send_ack(struct nfc_digital_dev *ddev,
-			       struct digital_data_exch *data_exch)
-{
-	struct digital_dep_req_res *dep_res;
-	struct sk_buff *skb;
-	int rc;
-
-	skb = digital_skb_alloc(ddev, 1);
-	if (!skb)
-		return -ENOMEM;
-
-	skb_push(skb, sizeof(struct digital_dep_req_res));
-
-	dep_res = (struct digital_dep_req_res *)skb->data;
-
-	dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
-	dep_res->cmd = DIGITAL_CMD_DEP_RES;
-	dep_res->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
-		       ddev->curr_nfc_dep_pni;
-
-	if (ddev->did) {
-		dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
-
-		memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
-		       sizeof(ddev->did));
-	}
-
-	ddev->curr_nfc_dep_pni =
-		DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
-
-	digital_skb_push_dep_sod(ddev, skb);
-
-	ddev->skb_add_crc(skb);
-
-	ddev->saved_skb = skb_get(skb);
-	ddev->saved_skb_len = skb->len;
-
-	rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
-				 data_exch);
-	if (rc) {
-		kfree_skb(skb);
-		kfree_skb(ddev->saved_skb);
-		ddev->saved_skb = NULL;
-	}
-
-	return rc;
-}
-
-static int digital_tg_send_atn(struct nfc_digital_dev *ddev)
-{
-	struct digital_dep_req_res *dep_res;
-	struct sk_buff *skb;
-	int rc;
-
-	skb = digital_skb_alloc(ddev, 1);
-	if (!skb)
-		return -ENOMEM;
-
-	skb_push(skb, sizeof(struct digital_dep_req_res));
-
-	dep_res = (struct digital_dep_req_res *)skb->data;
-
-	dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
-	dep_res->cmd = DIGITAL_CMD_DEP_RES;
-	dep_res->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
-
-	if (ddev->did) {
-		dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
-
-		memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
-		       sizeof(ddev->did));
-	}
-
-	digital_skb_push_dep_sod(ddev, skb);
-
-	ddev->skb_add_crc(skb);
-
-	rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
-				 NULL);
-	if (rc)
-		kfree_skb(skb);
-
-	return rc;
-}
-
-static int digital_tg_send_saved_skb(struct nfc_digital_dev *ddev)
-{
-	skb_get(ddev->saved_skb);
-	skb_push(ddev->saved_skb, ddev->saved_skb_len);
-
-	return digital_tg_send_cmd(ddev, ddev->saved_skb, 1500,
-				   digital_tg_recv_dep_req, NULL);
-}
-
 static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
 				    struct sk_buff *resp)
 {
 	int rc;
 	struct digital_dep_req_res *dep_req;
-	u8 pfb;
 	size_t size;
 
 	if (IS_ERR(resp)) {
@@ -1042,11 +532,6 @@
 		goto exit;
 	}
 
-	if (resp->len > ddev->local_payload_max) {
-		rc = -EMSGSIZE;
-		goto exit;
-	}
-
 	size = sizeof(struct digital_dep_req_res);
 	dep_req = (struct digital_dep_req_res *)resp->data;
 
@@ -1056,147 +541,34 @@
 		goto exit;
 	}
 
-	pfb = dep_req->pfb;
+	if (DIGITAL_NFC_DEP_DID_BIT_SET(dep_req->pfb))
+		size++;
 
-	if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
-		if (ddev->did && (ddev->did == resp->data[3])) {
-			size++;
-		} else {
-			rc = -EIO;
-			goto exit;
-		}
-	} else if (ddev->did) {
+	if (resp->len < size) {
 		rc = -EIO;
 		goto exit;
 	}
 
-	if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
-		rc = -EIO;
+	switch (DIGITAL_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
+	case DIGITAL_NFC_DEP_PFB_I_PDU:
+		pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
+		ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(dep_req->pfb);
+		break;
+	case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
+		pr_err("Received a ACK/NACK PDU\n");
+		rc = -EINVAL;
 		goto exit;
-	}
-
-	if (size > resp->len) {
-		rc = -EIO;
+	case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
+		pr_err("Received a SUPERVISOR PDU\n");
+		rc = -EINVAL;
 		goto exit;
 	}
 
 	skb_pull(resp, size);
 
-	switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
-	case DIGITAL_NFC_DEP_PFB_I_PDU:
-		pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
-
-		if ((ddev->atn_count && (DIGITAL_NFC_DEP_PFB_PNI(pfb - 1) !=
-						ddev->curr_nfc_dep_pni)) ||
-		    (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni)) {
-			PROTOCOL_ERR("14.12.3.4");
-			rc = -EIO;
-			goto exit;
-		}
-
-		if (ddev->atn_count) {
-			ddev->atn_count = 0;
-
-			rc = digital_tg_send_saved_skb(ddev);
-			if (rc)
-				goto exit;
-
-			return;
-		}
-
-		kfree_skb(ddev->saved_skb);
-		ddev->saved_skb = NULL;
-
-		resp = digital_recv_dep_data_gather(ddev, pfb, resp,
-						    digital_tg_send_ack, NULL);
-		if (IS_ERR(resp)) {
-			rc = PTR_ERR(resp);
-			resp = NULL;
-			goto exit;
-		}
-
-		/* If resp is NULL then we're still chaining so return and
-		 * wait for the next part of the PDU.  Else, the PDU is
-		 * complete so pass it up.
-		 */
-		if (!resp)
-			return;
-
-		rc = 0;
-		break;
-	case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
-		if (!DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { /* ACK */
-			if ((ddev->atn_count &&
-			     (DIGITAL_NFC_DEP_PFB_PNI(pfb - 1) !=
-						ddev->curr_nfc_dep_pni)) ||
-			    (DIGITAL_NFC_DEP_PFB_PNI(pfb) !=
-						ddev->curr_nfc_dep_pni) ||
-			    !ddev->chaining_skb || !ddev->saved_skb) {
-				rc = -EIO;
-				goto exit;
-			}
-
-			if (ddev->atn_count) {
-				ddev->atn_count = 0;
-
-				rc = digital_tg_send_saved_skb(ddev);
-				if (rc)
-					goto exit;
-
-				return;
-			}
-
-			kfree_skb(ddev->saved_skb);
-			ddev->saved_skb = NULL;
-
-			rc = digital_tg_send_dep_res(ddev, ddev->chaining_skb);
-			if (rc)
-				goto exit;
-		} else { /* NACK */
-			if ((DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) !=
-						ddev->curr_nfc_dep_pni) ||
-			    !ddev->saved_skb) {
-				rc = -EIO;
-				goto exit;
-			}
-
-			ddev->atn_count = 0;
-
-			rc = digital_tg_send_saved_skb(ddev);
-			if (rc) {
-				kfree_skb(ddev->saved_skb);
-				goto exit;
-			}
-		}
-
-		return;
-	case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
-		if (DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
-			rc = -EINVAL;
-			goto exit;
-		}
-
-		rc = digital_tg_send_atn(ddev);
-		if (rc)
-			goto exit;
-
-		ddev->atn_count++;
-
-		kfree_skb(resp);
-		return;
-	}
-
 	rc = nfc_tm_data_received(ddev->nfc_dev, resp);
 
 exit:
-	kfree_skb(ddev->chaining_skb);
-	ddev->chaining_skb = NULL;
-
-	ddev->atn_count = 0;
-
-	kfree_skb(ddev->saved_skb);
-	ddev->saved_skb = NULL;
-
 	if (rc)
 		kfree_skb(resp);
 }
@@ -1204,54 +576,20 @@
 int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
 {
 	struct digital_dep_req_res *dep_res;
-	struct sk_buff *chaining_skb, *tmp_skb;
-	int rc;
 
 	skb_push(skb, sizeof(struct digital_dep_req_res));
-
 	dep_res = (struct digital_dep_req_res *)skb->data;
 
 	dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
 	dep_res->cmd = DIGITAL_CMD_DEP_RES;
 	dep_res->pfb = ddev->curr_nfc_dep_pni;
 
-	if (ddev->did) {
-		dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
+	digital_skb_push_dep_sod(ddev, skb);
 
-		memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
-		       sizeof(ddev->did));
-	}
+	ddev->skb_add_crc(skb);
 
-	ddev->curr_nfc_dep_pni =
-		DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
-
-	chaining_skb = ddev->chaining_skb;
-
-	tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_res, NULL);
-	if (IS_ERR(tmp_skb))
-		return PTR_ERR(tmp_skb);
-
-	digital_skb_push_dep_sod(ddev, tmp_skb);
-
-	ddev->skb_add_crc(tmp_skb);
-
-	ddev->saved_skb = skb_get(tmp_skb);
-	ddev->saved_skb_len = tmp_skb->len;
-
-	rc = digital_tg_send_cmd(ddev, tmp_skb, 1500, digital_tg_recv_dep_req,
-				 NULL);
-	if (rc) {
-		if (tmp_skb != skb)
-			kfree_skb(tmp_skb);
-
-		kfree_skb(chaining_skb);
-		ddev->chaining_skb = NULL;
-
-		kfree_skb(ddev->saved_skb);
-		ddev->saved_skb = NULL;
-	}
-
-	return rc;
+	return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
+				   NULL);
 }
 
 static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
@@ -1294,10 +632,9 @@
 
 	ddev->skb_add_crc(skb);
 
-	ddev->curr_nfc_dep_pni = 0;
-
 	rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
 				 (void *)(unsigned long)rf_tech);
+
 	if (rc)
 		kfree_skb(skb);
 
@@ -1310,7 +647,7 @@
 	int rc;
 	struct digital_psl_req *psl_req;
 	u8 rf_tech;
-	u8 dsi, payload_size, payload_bits;
+	u8 dsi;
 
 	if (IS_ERR(resp)) {
 		rc = PTR_ERR(resp);
@@ -1355,18 +692,6 @@
 		goto exit;
 	}
 
-	payload_bits = DIGITAL_PAYLOAD_FSL_TO_BITS(psl_req->fsl);
-	payload_size = digital_payload_bits_to_size(payload_bits);
-
-	if (!payload_size || (payload_size > min(ddev->local_payload_max,
-						 ddev->remote_payload_max))) {
-		rc = -EINVAL;
-		goto exit;
-	}
-
-	ddev->local_payload_max = payload_size;
-	ddev->remote_payload_max = payload_size;
-
 	rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
 
 exit:
@@ -1387,8 +712,6 @@
 	if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
 		offset++;
 
-	ddev->atn_count = 0;
-
 	if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
 		digital_tg_recv_psl_req(ddev, arg, resp);
 	else
@@ -1400,7 +723,7 @@
 {
 	struct digital_atr_res *atr_res;
 	struct sk_buff *skb;
-	u8 *gb, payload_bits;
+	u8 *gb;
 	size_t gb_len;
 	int rc;
 
@@ -1421,11 +744,7 @@
 	atr_res->cmd = DIGITAL_CMD_ATR_RES;
 	memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
 	atr_res->to = 8;
-
-	ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
-	payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
-	atr_res->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
-
+	atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
 	if (gb_len) {
 		skb_put(skb, gb_len);
 
@@ -1437,12 +756,12 @@
 
 	ddev->skb_add_crc(skb);
 
-	ddev->curr_nfc_dep_pni = 0;
-
 	rc = digital_tg_send_cmd(ddev, skb, 999,
 				 digital_tg_send_atr_res_complete, NULL);
-	if (rc)
+	if (rc) {
 		kfree_skb(skb);
+		return rc;
+	}
 
 	return rc;
 }
@@ -1453,7 +772,7 @@
 	int rc;
 	struct digital_atr_req *atr_req;
 	size_t gb_len, min_size;
-	u8 poll_tech_count, payload_bits;
+	u8 poll_tech_count;
 
 	if (IS_ERR(resp)) {
 		rc = PTR_ERR(resp);
@@ -1496,22 +815,11 @@
 	atr_req = (struct digital_atr_req *)resp->data;
 
 	if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
-	    atr_req->cmd != DIGITAL_CMD_ATR_REQ ||
-	    atr_req->did > DIGITAL_DID_MAX) {
+	    atr_req->cmd != DIGITAL_CMD_ATR_REQ) {
 		rc = -EINVAL;
 		goto exit;
 	}
 
-	payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_req->pp);
-	ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
-
-	if (!ddev->remote_payload_max) {
-		rc = -EINVAL;
-		goto exit;
-	}
-
-	ddev->did = atr_req->did;
-
 	rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
 				     NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
 	if (rc)
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index 91df487..677d24b 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -345,9 +345,6 @@
 
 	pr_debug("\n");
 
-	if (hdev->gate2pipe[dest_gate] == NFC_HCI_DO_NOT_CREATE_PIPE)
-		return 0;
-
 	if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE)
 		return -EADDRINUSE;
 
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index ef50e77..1177082 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -167,48 +167,6 @@
 void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
 			  struct sk_buff *skb)
 {
-	int r = 0;
-	u8 gate = nfc_hci_pipe2gate(hdev, pipe);
-	u8 local_gate, new_pipe;
-	u8 gate_opened = 0x00;
-
-	pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
-
-	switch (cmd) {
-	case NFC_HCI_ADM_NOTIFY_PIPE_CREATED:
-		if (skb->len != 5) {
-			r = -EPROTO;
-			break;
-		}
-
-		local_gate = skb->data[3];
-		new_pipe = skb->data[4];
-		nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0);
-
-		/* save the new created pipe and bind with local gate,
-		 * the description for skb->data[3] is destination gate id
-		 * but since we received this cmd from host controller, we
-		 * are the destination and it is our local gate
-		 */
-		hdev->gate2pipe[local_gate] = new_pipe;
-		break;
-	case NFC_HCI_ANY_OPEN_PIPE:
-		/* if the pipe is already created, we allow remote host to
-		 * open it
-		 */
-		if (gate != 0xff)
-			nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK,
-					      &gate_opened, 1);
-		break;
-	case NFC_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
-		nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0);
-		break;
-	default:
-		pr_info("Discarded unknown cmd %x to gate %x\n", cmd, gate);
-		r = -EINVAL;
-		break;
-	}
-
 	kfree_skb(skb);
 }
 
@@ -759,19 +717,6 @@
 	return 0;
 }
 
-static int hci_se_io(struct nfc_dev *nfc_dev, u32 se_idx,
-		     u8 *apdu, size_t apdu_length,
-		     se_io_cb_t cb, void *cb_context)
-{
-	struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
-
-	if (hdev->ops->se_io)
-		return hdev->ops->se_io(hdev, se_idx, apdu,
-					apdu_length, cb, cb_context);
-
-	return 0;
-}
-
 static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err)
 {
 	mutex_lock(&hdev->msg_tx_mutex);
@@ -885,7 +830,6 @@
 	.discover_se = hci_discover_se,
 	.enable_se = hci_enable_se,
 	.disable_se = hci_disable_se,
-	.se_io = hci_se_io,
 };
 
 struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops,
diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
index 3621a90..a3ad69a 100644
--- a/net/nfc/llcp_commands.c
+++ b/net/nfc/llcp_commands.c
@@ -401,8 +401,7 @@
 	u8 *miux_tlv = NULL, miux_tlv_length;
 	u8 *rw_tlv = NULL, rw_tlv_length, rw;
 	int err;
-	u16 size = 0;
-	__be16 miux;
+	u16 size = 0, miux;
 
 	pr_debug("Sending CONNECT\n");
 
@@ -466,8 +465,7 @@
 	u8 *miux_tlv = NULL, miux_tlv_length;
 	u8 *rw_tlv = NULL, rw_tlv_length, rw;
 	int err;
-	u16 size = 0;
-	__be16 miux;
+	u16 size = 0, miux;
 
 	pr_debug("Sending CC\n");
 
@@ -667,7 +665,7 @@
 	if (msg_data == NULL)
 		return -ENOMEM;
 
-	if (memcpy_from_msg(msg_data, msg, len)) {
+	if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
 		kfree(msg_data);
 		return -EFAULT;
 	}
@@ -733,7 +731,7 @@
 	if (msg_data == NULL)
 		return -ENOMEM;
 
-	if (memcpy_from_msg(msg_data, msg, len)) {
+	if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
 		kfree(msg_data);
 		return -EFAULT;
 	}
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index ecf84de..5d9a9d8 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -1,6 +1,5 @@
 /*
  * Copyright (C) 2011  Intel Corporation. All rights reserved.
- * Copyright (C) 2014 Marvell International Ltd.
  *
  * 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
@@ -1516,10 +1515,8 @@
 	struct nfc_llcp_local *local;
 
 	local = nfc_llcp_find_local(dev);
-	if (local == NULL) {
-		kfree_skb(skb);
+	if (local == NULL)
 		return -ENODEV;
-	}
 
 	__nfc_llcp_recv(local, skb);
 
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index e181e29..51f077a 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -524,13 +524,13 @@
 
 static inline unsigned int llcp_accept_poll(struct sock *parent)
 {
-	struct nfc_llcp_sock *llcp_sock, *parent_sock;
+	struct nfc_llcp_sock *llcp_sock, *n, *parent_sock;
 	struct sock *sk;
 
 	parent_sock = nfc_llcp_sock(parent);
 
-	list_for_each_entry(llcp_sock, &parent_sock->accept_queue,
-			    accept_queue) {
+	list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue,
+				 accept_queue) {
 		sk = &llcp_sock->sk;
 
 		if (sk->sk_state == LLCP_CONNECTED)
@@ -832,7 +832,7 @@
 	copied = min_t(unsigned int, rlen, len);
 
 	cskb = skb;
-	if (skb_copy_datagram_msg(cskb, 0, msg, copied)) {
+	if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) {
 		if (!(flags & MSG_PEEK))
 			skb_queue_head(&sk->sk_receive_queue, skb);
 		return -EFAULT;
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 51feb5e..90b16cb 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -3,7 +3,6 @@
  *  NFC Controller (NFCC) and a Device Host (DH).
  *
  *  Copyright (C) 2011 Texas Instruments, Inc.
- *  Copyright (C) 2014 Marvell International Ltd.
  *
  *  Written by Ilan Elias <ilane@ti.com>
  *
@@ -197,24 +196,18 @@
 	nci_send_cmd(ndev, NCI_OP_CORE_SET_CONFIG_CMD, (3 + param->len), &cmd);
 }
 
-struct nci_rf_discover_param {
-	__u32	im_protocols;
-	__u32	tm_protocols;
-};
-
 static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
 {
-	struct nci_rf_discover_param *param =
-		(struct nci_rf_discover_param *)opt;
 	struct nci_rf_disc_cmd cmd;
+	__u32 protocols = opt;
 
 	cmd.num_disc_configs = 0;
 
 	if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
-	    (param->im_protocols & NFC_PROTO_JEWEL_MASK ||
-	     param->im_protocols & NFC_PROTO_MIFARE_MASK ||
-	     param->im_protocols & NFC_PROTO_ISO14443_MASK ||
-	     param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) {
+	    (protocols & NFC_PROTO_JEWEL_MASK ||
+	     protocols & NFC_PROTO_MIFARE_MASK ||
+	     protocols & NFC_PROTO_ISO14443_MASK ||
+	     protocols & NFC_PROTO_NFC_DEP_MASK)) {
 		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
 			NCI_NFC_A_PASSIVE_POLL_MODE;
 		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -222,7 +215,7 @@
 	}
 
 	if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
-	    (param->im_protocols & NFC_PROTO_ISO14443_B_MASK)) {
+	    (protocols & NFC_PROTO_ISO14443_B_MASK)) {
 		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
 			NCI_NFC_B_PASSIVE_POLL_MODE;
 		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -230,8 +223,8 @@
 	}
 
 	if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
-	    (param->im_protocols & NFC_PROTO_FELICA_MASK ||
-	     param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) {
+	    (protocols & NFC_PROTO_FELICA_MASK ||
+	     protocols & NFC_PROTO_NFC_DEP_MASK)) {
 		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
 			NCI_NFC_F_PASSIVE_POLL_MODE;
 		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -239,25 +232,13 @@
 	}
 
 	if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
-	    (param->im_protocols & NFC_PROTO_ISO15693_MASK)) {
+	    (protocols & NFC_PROTO_ISO15693_MASK)) {
 		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
 			NCI_NFC_V_PASSIVE_POLL_MODE;
 		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
 		cmd.num_disc_configs++;
 	}
 
-	if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS - 1) &&
-	    (param->tm_protocols & NFC_PROTO_NFC_DEP_MASK)) {
-		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
-			NCI_NFC_A_PASSIVE_LISTEN_MODE;
-		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
-		cmd.num_disc_configs++;
-		cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
-			NCI_NFC_F_PASSIVE_LISTEN_MODE;
-		cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
-		cmd.num_disc_configs++;
-	}
-
 	nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD,
 		     (1 + (cmd.num_disc_configs * sizeof(struct disc_config))),
 		     &cmd);
@@ -299,7 +280,7 @@
 {
 	struct nci_rf_deactivate_cmd cmd;
 
-	cmd.type = opt;
+	cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE;
 
 	nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD,
 		     sizeof(struct nci_rf_deactivate_cmd), &cmd);
@@ -460,7 +441,6 @@
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
 	struct nci_set_config_param param;
-	int rc;
 
 	param.val = nfc_get_local_general_bytes(nfc_dev, &param.len);
 	if ((param.val == NULL) || (param.len == 0))
@@ -471,45 +451,14 @@
 
 	param.id = NCI_PN_ATR_REQ_GEN_BYTES;
 
-	rc = nci_request(ndev, nci_set_config_req, (unsigned long)&param,
-			 msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
-	if (rc)
-		return rc;
-
-	param.id = NCI_LN_ATR_RES_GEN_BYTES;
-
 	return nci_request(ndev, nci_set_config_req, (unsigned long)&param,
 			   msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
 }
 
-static int nci_set_listen_parameters(struct nfc_dev *nfc_dev)
-{
-	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-	int rc;
-	__u8 val;
-
-	val = NCI_LA_SEL_INFO_NFC_DEP_MASK;
-
-	rc = nci_set_config(ndev, NCI_LA_SEL_INFO, 1, &val);
-	if (rc)
-		return rc;
-
-	val = NCI_LF_PROTOCOL_TYPE_NFC_DEP_MASK;
-
-	rc = nci_set_config(ndev, NCI_LF_PROTOCOL_TYPE, 1, &val);
-	if (rc)
-		return rc;
-
-	val = NCI_LF_CON_BITR_F_212 | NCI_LF_CON_BITR_F_424;
-
-	return nci_set_config(ndev, NCI_LF_CON_BITR_F, 1, &val);
-}
-
 static int nci_start_poll(struct nfc_dev *nfc_dev,
 			  __u32 im_protocols, __u32 tm_protocols)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-	struct nci_rf_discover_param param;
 	int rc;
 
 	if ((atomic_read(&ndev->state) == NCI_DISCOVERY) ||
@@ -527,14 +476,13 @@
 	    (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) {
 		pr_debug("target active or w4 select, implicitly deactivate\n");
 
-		rc = nci_request(ndev, nci_rf_deactivate_req,
-				 NCI_DEACTIVATE_TYPE_IDLE_MODE,
+		rc = nci_request(ndev, nci_rf_deactivate_req, 0,
 				 msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
 		if (rc)
 			return -EBUSY;
 	}
 
-	if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) {
+	if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
 		rc = nci_set_local_general_bytes(nfc_dev);
 		if (rc) {
 			pr_err("failed to set local general bytes\n");
@@ -542,15 +490,7 @@
 		}
 	}
 
-	if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
-		rc = nci_set_listen_parameters(nfc_dev);
-		if (rc)
-			pr_err("failed to set listen parameters\n");
-	}
-
-	param.im_protocols = im_protocols;
-	param.tm_protocols = tm_protocols;
-	rc = nci_request(ndev, nci_rf_discover_req, (unsigned long)&param,
+	rc = nci_request(ndev, nci_rf_discover_req, im_protocols,
 			 msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
 
 	if (!rc)
@@ -569,7 +509,7 @@
 		return;
 	}
 
-	nci_request(ndev, nci_rf_deactivate_req, NCI_DEACTIVATE_TYPE_IDLE_MODE,
+	nci_request(ndev, nci_rf_deactivate_req, 0,
 		    msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
 }
 
@@ -654,8 +594,7 @@
 	ndev->target_active_prot = 0;
 
 	if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
-		nci_request(ndev, nci_rf_deactivate_req,
-			    NCI_DEACTIVATE_TYPE_SLEEP_MODE,
+		nci_request(ndev, nci_rf_deactivate_req, 0,
 			    msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
 	}
 }
@@ -683,24 +622,9 @@
 
 static int nci_dep_link_down(struct nfc_dev *nfc_dev)
 {
-	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-	int rc;
-
 	pr_debug("entry\n");
 
-	if (nfc_dev->rf_mode == NFC_RF_INITIATOR) {
-		nci_deactivate_target(nfc_dev, NULL);
-	} else {
-		if (atomic_read(&ndev->state) == NCI_LISTEN_ACTIVE ||
-		    atomic_read(&ndev->state) == NCI_DISCOVERY) {
-			nci_request(ndev, nci_rf_deactivate_req, 0,
-				msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
-		}
-
-		rc = nfc_tm_deactivated(nfc_dev);
-		if (rc)
-			pr_err("error when signaling tm deactivation\n");
-	}
+	nci_deactivate_target(nfc_dev, NULL);
 
 	return 0;
 }
@@ -734,58 +658,18 @@
 	return rc;
 }
 
-static int nci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
-{
-	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-	int rc;
-
-	rc = nci_send_data(ndev, NCI_STATIC_RF_CONN_ID, skb);
-	if (rc)
-		pr_err("unable to send data\n");
-
-	return rc;
-}
-
 static int nci_enable_se(struct nfc_dev *nfc_dev, u32 se_idx)
 {
-	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-
-	if (ndev->ops->enable_se)
-		return ndev->ops->enable_se(ndev, se_idx);
-
 	return 0;
 }
 
 static int nci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx)
 {
-	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-
-	if (ndev->ops->disable_se)
-		return ndev->ops->disable_se(ndev, se_idx);
-
 	return 0;
 }
 
 static int nci_discover_se(struct nfc_dev *nfc_dev)
 {
-	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-
-	if (ndev->ops->discover_se)
-		return ndev->ops->discover_se(ndev);
-
-	return 0;
-}
-
-static int nci_se_io(struct nfc_dev *nfc_dev, u32 se_idx,
-		     u8 *apdu, size_t apdu_length,
-		     se_io_cb_t cb, void *cb_context)
-{
-	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-
-	if (ndev->ops->se_io)
-		return ndev->ops->se_io(ndev, se_idx, apdu,
-				apdu_length, cb, cb_context);
-
 	return 0;
 }
 
@@ -799,11 +683,9 @@
 	.activate_target = nci_activate_target,
 	.deactivate_target = nci_deactivate_target,
 	.im_transceive = nci_transceive,
-	.tm_send = nci_tm_send,
 	.enable_se = nci_enable_se,
 	.disable_se = nci_disable_se,
 	.discover_se = nci_discover_se,
-	.se_io = nci_se_io,
 };
 
 /* ---- Interface to NCI drivers ---- */
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index a2de2a8..427ef2c 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -3,7 +3,6 @@
  *  NFC Controller (NFCC) and a Device Host (DH).
  *
  *  Copyright (C) 2011 Texas Instruments, Inc.
- *  Copyright (C) 2014 Marvell International Ltd.
  *
  *  Written by Ilan Elias <ilane@ti.com>
  *
@@ -185,16 +184,11 @@
 
 static void nci_add_rx_data_frag(struct nci_dev *ndev,
 				 struct sk_buff *skb,
-				 __u8 pbf, __u8 status)
+				 __u8 pbf)
 {
 	int reassembly_len;
 	int err = 0;
 
-	if (status) {
-		err = status;
-		goto exit;
-	}
-
 	if (ndev->rx_data_reassembly) {
 		reassembly_len = ndev->rx_data_reassembly->len;
 
@@ -229,24 +223,13 @@
 	}
 
 exit:
-	if (ndev->nfc_dev->rf_mode == NFC_RF_INITIATOR) {
-		nci_data_exchange_complete(ndev, skb, err);
-	} else if (ndev->nfc_dev->rf_mode == NFC_RF_TARGET) {
-		/* Data received in Target mode, forward to nfc core */
-		err = nfc_tm_data_received(ndev->nfc_dev, skb);
-		if (err)
-			pr_err("unable to handle received data\n");
-	} else {
-		pr_err("rf mode unknown\n");
-		kfree_skb(skb);
-	}
+	nci_data_exchange_complete(ndev, skb, err);
 }
 
 /* Rx Data packet */
 void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	__u8 pbf = nci_pbf(skb->data);
-	__u8 status = 0;
 
 	pr_debug("len %d\n", skb->len);
 
@@ -264,9 +247,8 @@
 	    ndev->target_active_prot == NFC_PROTO_ISO15693) {
 		/* frame I/F => remove the status byte */
 		pr_debug("frame I/F => remove the status byte\n");
-		status = skb->data[skb->len - 1];
 		skb_trim(skb, (skb->len - 1));
 	}
 
-	nci_add_rx_data_frag(ndev, skb, pbf, nci_to_errno(status));
+	nci_add_rx_data_frag(ndev, skb, pbf);
 }
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 22e453c..205b35f 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -103,7 +103,7 @@
 			struct rf_tech_specific_params_nfca_poll *nfca_poll,
 						     __u8 *data)
 {
-	nfca_poll->sens_res = __le16_to_cpu(*((__le16 *)data));
+	nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data));
 	data += 2;
 
 	nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE);
@@ -167,19 +167,7 @@
 	return data;
 }
 
-static __u8 *nci_extract_rf_params_nfcf_passive_listen(struct nci_dev *ndev,
-			struct rf_tech_specific_params_nfcf_listen *nfcf_listen,
-						     __u8 *data)
-{
-	nfcf_listen->local_nfcid2_len = min_t(__u8, *data++,
-					      NFC_NFCID2_MAXSIZE);
-	memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len);
-	data += nfcf_listen->local_nfcid2_len;
-
-	return data;
-}
-
-static __u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol)
+__u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol)
 {
 	if (ndev->ops->get_rfprotocol)
 		return ndev->ops->get_rfprotocol(ndev, rf_protocol);
@@ -413,29 +401,17 @@
 			struct nci_rf_intf_activated_ntf *ntf, __u8 *data)
 {
 	struct activation_params_poll_nfc_dep *poll;
-	struct activation_params_listen_nfc_dep *listen;
 
 	switch (ntf->activation_rf_tech_and_mode) {
 	case NCI_NFC_A_PASSIVE_POLL_MODE:
 	case NCI_NFC_F_PASSIVE_POLL_MODE:
 		poll = &ntf->activation_params.poll_nfc_dep;
-		poll->atr_res_len = min_t(__u8, *data++,
-					  NFC_ATR_RES_MAXSIZE - 2);
+		poll->atr_res_len = min_t(__u8, *data++, 63);
 		pr_debug("atr_res_len %d\n", poll->atr_res_len);
 		if (poll->atr_res_len > 0)
 			memcpy(poll->atr_res, data, poll->atr_res_len);
 		break;
 
-	case NCI_NFC_A_PASSIVE_LISTEN_MODE:
-	case NCI_NFC_F_PASSIVE_LISTEN_MODE:
-		listen = &ntf->activation_params.listen_nfc_dep;
-		listen->atr_req_len = min_t(__u8, *data++,
-					    NFC_ATR_REQ_MAXSIZE - 2);
-		pr_debug("atr_req_len %d\n", listen->atr_req_len);
-		if (listen->atr_req_len > 0)
-			memcpy(listen->atr_req, data, listen->atr_req_len);
-		break;
-
 	default:
 		pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
 		       ntf->activation_rf_tech_and_mode);
@@ -468,48 +444,6 @@
 	nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets);
 }
 
-static int nci_store_general_bytes_nfc_dep(struct nci_dev *ndev,
-		struct nci_rf_intf_activated_ntf *ntf)
-{
-	ndev->remote_gb_len = 0;
-
-	if (ntf->activation_params_len <= 0)
-		return NCI_STATUS_OK;
-
-	switch (ntf->activation_rf_tech_and_mode) {
-	case NCI_NFC_A_PASSIVE_POLL_MODE:
-	case NCI_NFC_F_PASSIVE_POLL_MODE:
-		ndev->remote_gb_len = min_t(__u8,
-			(ntf->activation_params.poll_nfc_dep.atr_res_len
-						- NFC_ATR_RES_GT_OFFSET),
-			NFC_ATR_RES_GB_MAXSIZE);
-		memcpy(ndev->remote_gb,
-		       (ntf->activation_params.poll_nfc_dep.atr_res
-						+ NFC_ATR_RES_GT_OFFSET),
-		       ndev->remote_gb_len);
-		break;
-
-	case NCI_NFC_A_PASSIVE_LISTEN_MODE:
-	case NCI_NFC_F_PASSIVE_LISTEN_MODE:
-		ndev->remote_gb_len = min_t(__u8,
-			(ntf->activation_params.listen_nfc_dep.atr_req_len
-						- NFC_ATR_REQ_GT_OFFSET),
-			NFC_ATR_REQ_GB_MAXSIZE);
-		memcpy(ndev->remote_gb,
-		       (ntf->activation_params.listen_nfc_dep.atr_req
-						+ NFC_ATR_REQ_GT_OFFSET),
-		       ndev->remote_gb_len);
-		break;
-
-	default:
-		pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
-		       ntf->activation_rf_tech_and_mode);
-		return NCI_STATUS_RF_PROTOCOL_ERROR;
-	}
-
-	return NCI_STATUS_OK;
-}
-
 static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
 					     struct sk_buff *skb)
 {
@@ -559,16 +493,6 @@
 				&(ntf.rf_tech_specific_params.nfcv_poll), data);
 			break;
 
-		case NCI_NFC_A_PASSIVE_LISTEN_MODE:
-			/* no RF technology specific parameters */
-			break;
-
-		case NCI_NFC_F_PASSIVE_LISTEN_MODE:
-			data = nci_extract_rf_params_nfcf_passive_listen(ndev,
-				&(ntf.rf_tech_specific_params.nfcf_listen),
-				data);
-			break;
-
 		default:
 			pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
 			       ntf.activation_rf_tech_and_mode);
@@ -622,39 +546,32 @@
 
 		/* store general bytes to be reported later in dep_link_up */
 		if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
-			err = nci_store_general_bytes_nfc_dep(ndev, &ntf);
-			if (err != NCI_STATUS_OK)
-				pr_err("unable to store general bytes\n");
+			ndev->remote_gb_len = 0;
+
+			if (ntf.activation_params_len > 0) {
+				/* ATR_RES general bytes at offset 15 */
+				ndev->remote_gb_len = min_t(__u8,
+					(ntf.activation_params
+					.poll_nfc_dep.atr_res_len
+					- NFC_ATR_RES_GT_OFFSET),
+					NFC_MAX_GT_LEN);
+				memcpy(ndev->remote_gb,
+				       (ntf.activation_params.poll_nfc_dep
+				       .atr_res + NFC_ATR_RES_GT_OFFSET),
+				       ndev->remote_gb_len);
+			}
 		}
 	}
 
-	if (!(ntf.activation_rf_tech_and_mode & NCI_RF_TECH_MODE_LISTEN_MASK)) {
-		/* Poll mode */
-		if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
-			/* A single target was found and activated
-			 * automatically */
-			atomic_set(&ndev->state, NCI_POLL_ACTIVE);
-			if (err == NCI_STATUS_OK)
-				nci_target_auto_activated(ndev, &ntf);
-		} else {	/* ndev->state == NCI_W4_HOST_SELECT */
-			/* A selected target was activated, so complete the
-			 * request */
-			atomic_set(&ndev->state, NCI_POLL_ACTIVE);
-			nci_req_complete(ndev, err);
-		}
-	} else {
-		/* Listen mode */
-		atomic_set(&ndev->state, NCI_LISTEN_ACTIVE);
-		if (err == NCI_STATUS_OK &&
-		    ntf.rf_protocol == NCI_RF_PROTOCOL_NFC_DEP) {
-			err = nfc_tm_activated(ndev->nfc_dev,
-					       NFC_PROTO_NFC_DEP_MASK,
-					       NFC_COMM_PASSIVE,
-					       ndev->remote_gb,
-					       ndev->remote_gb_len);
-			if (err != NCI_STATUS_OK)
-				pr_err("error when signaling tm activation\n");
-		}
+	if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
+		/* A single target was found and activated automatically */
+		atomic_set(&ndev->state, NCI_POLL_ACTIVE);
+		if (err == NCI_STATUS_OK)
+			nci_target_auto_activated(ndev, &ntf);
+	} else {	/* ndev->state == NCI_W4_HOST_SELECT */
+		/* A selected target was activated, so complete the request */
+		atomic_set(&ndev->state, NCI_POLL_ACTIVE);
+		nci_req_complete(ndev, err);
 	}
 }
 
@@ -678,21 +595,8 @@
 	if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
 		nci_data_exchange_complete(ndev, NULL, -EIO);
 
-	switch (ntf->type) {
-	case NCI_DEACTIVATE_TYPE_IDLE_MODE:
-		nci_clear_target_list(ndev);
-		atomic_set(&ndev->state, NCI_IDLE);
-		break;
-	case NCI_DEACTIVATE_TYPE_SLEEP_MODE:
-	case NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE:
-		atomic_set(&ndev->state, NCI_W4_HOST_SELECT);
-		break;
-	case NCI_DEACTIVATE_TYPE_DISCOVERY:
-		nci_clear_target_list(ndev);
-		atomic_set(&ndev->state, NCI_DISCOVERY);
-		break;
-	}
-
+	nci_clear_target_list(ndev);
+	atomic_set(&ndev->state, NCI_IDLE);
 	nci_req_complete(ndev, NCI_STATUS_OK);
 }
 
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 99c7065..f91cff1 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -813,31 +813,6 @@
 	return rc;
 }
 
-static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
-{
-	struct nfc_dev *dev;
-	u32 device_idx, target_idx, protocol;
-	int rc;
-
-	if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
-		return -EINVAL;
-
-	device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
-
-	dev = nfc_get_device(device_idx);
-	if (!dev)
-		return -ENODEV;
-
-	target_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
-	protocol = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
-
-	nfc_deactivate_target(dev, target_idx);
-	rc = nfc_activate_target(dev, target_idx, protocol);
-
-	nfc_put_device(dev);
-	return 0;
-}
-
 static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info)
 {
 	struct nfc_dev *dev;
@@ -1314,51 +1289,6 @@
 	return 0;
 }
 
-static int nfc_se_io(struct nfc_dev *dev, u32 se_idx,
-		     u8 *apdu, size_t apdu_length,
-		     se_io_cb_t cb, void *cb_context)
-{
-	struct nfc_se *se;
-	int rc;
-
-	pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx);
-
-	device_lock(&dev->dev);
-
-	if (!device_is_registered(&dev->dev)) {
-		rc = -ENODEV;
-		goto error;
-	}
-
-	if (!dev->dev_up) {
-		rc = -ENODEV;
-		goto error;
-	}
-
-	if (!dev->ops->se_io) {
-		rc = -EOPNOTSUPP;
-		goto error;
-	}
-
-	se = nfc_find_se(dev, se_idx);
-	if (!se) {
-		rc = -EINVAL;
-		goto error;
-	}
-
-	if (se->state != NFC_SE_ENABLED) {
-		rc = -ENODEV;
-		goto error;
-	}
-
-	rc = dev->ops->se_io(dev, se_idx, apdu,
-			apdu_length, cb, cb_context);
-
-error:
-	device_unlock(&dev->dev);
-	return rc;
-}
-
 struct se_io_ctx {
 	u32 dev_idx;
 	u32 se_idx;
@@ -1441,7 +1371,7 @@
 	ctx->dev_idx = dev_idx;
 	ctx->se_idx = se_idx;
 
-	return nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
+	return dev->ops->se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
 }
 
 static __genl_const struct genl_ops nfc_genl_ops[] = {
@@ -1529,11 +1459,6 @@
 		.doit = nfc_genl_se_io,
 		.policy = nfc_genl_policy,
 	},
-	{
-		.cmd = NFC_CMD_ACTIVATE_TARGET,
-		.doit = nfc_genl_activate_target,
-		.policy = nfc_genl_policy,
-	},
 };
 
 
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index 373e138..11c3544 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -231,7 +231,7 @@
 	if (skb == NULL)
 		return rc;
 
-	rc = memcpy_from_msg(skb_put(skb, len), msg, len);
+	rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
 	if (rc < 0) {
 		kfree_skb(skb);
 		return rc;
@@ -269,7 +269,7 @@
 		copied = len;
 	}
 
-	rc = skb_copy_datagram_msg(skb, 0, msg, copied);
+	rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
 	skb_free_datagram(sk, skb);
 
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index bc4e435..b292436 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -158,7 +158,7 @@
 	  Most distributions have a CRDA package.  So if unsure, say N.
 
 config CFG80211_WEXT
-	bool
+	bool "cfg80211 wireless extensions compatibility"
 	depends on CFG80211
 	depends on WEXT_CORE
 	help
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index bbc27ab..7730221 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,7 +10,7 @@
 obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
 
 cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
-cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
+cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o
 cfg80211-$(CPTCFG_CFG80211_DEBUGFS) += debugfs.o
 cfg80211-$(CPTCFG_CFG80211_WEXT) += wext-compat.o wext-sme.o
 cfg80211-$(CPTCFG_CFG80211_INTERNAL_REGDB) += regdb.o
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 7f9fa4d..8f21d4e 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -115,7 +115,7 @@
 EXPORT_SYMBOL(cfg80211_chandef_valid);
 
 static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
-				  u32 *pri40, u32 *pri80)
+				  int *pri40, int *pri80)
 {
 	int tmp;
 
@@ -366,7 +366,6 @@
 
 		break;
 	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_OCB:
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_AP_VLAN:
@@ -603,7 +602,7 @@
 {
 	struct ieee80211_sta_ht_cap *ht_cap;
 	struct ieee80211_sta_vht_cap *vht_cap;
-	u32 width, control_freq, cap;
+	u32 width, control_freq;
 
 	if (WARN_ON(!cfg80211_chandef_valid(chandef)))
 		return false;
@@ -643,8 +642,7 @@
 			return false;
 		break;
 	case NL80211_CHAN_WIDTH_80P80:
-		cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
-		if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+		if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
 			return false;
 	case NL80211_CHAN_WIDTH_80:
 		if (!vht_cap->vht_supported)
@@ -655,9 +653,7 @@
 	case NL80211_CHAN_WIDTH_160:
 		if (!vht_cap->vht_supported)
 			return false;
-		cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
-		if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
-		    cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+		if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
 			return false;
 		prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
 		width = 160;
@@ -896,13 +892,6 @@
 				*radar_detect |= BIT(wdev->chandef.width);
 		}
 		return;
-	case NL80211_IFTYPE_OCB:
-		if (wdev->chandef.chan) {
-			*chan = wdev->chandef.chan;
-			*chanmode = CHAN_MODE_SHARED;
-			return;
-		}
-		break;
 	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_AP_VLAN:
 	case NL80211_IFTYPE_WDS:
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 073bfe4..45d0435 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -86,11 +86,11 @@
 	return &rdev->wiphy;
 }
 
-static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev,
-				   const char *newname)
+int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
+			char *newname)
 {
 	struct cfg80211_registered_device *rdev2;
-	int wiphy_idx, taken = -1, digits;
+	int wiphy_idx, taken = -1, result, digits;
 
 	ASSERT_RTNL();
 
@@ -109,28 +109,15 @@
 			return -EINVAL;
 	}
 
-	/* Ensure another device does not already have this name. */
-	list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
-		if (strcmp(newname, wiphy_name(&rdev2->wiphy)) == 0)
-			return -EINVAL;
-
-	return 0;
-}
-
-int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
-			char *newname)
-{
-	int result;
-
-	ASSERT_RTNL();
 
 	/* Ignore nop renames */
-	if (strcmp(newname, wiphy_name(&rdev->wiphy)) == 0)
+	if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
 		return 0;
 
-	result = cfg80211_dev_check_name(rdev, newname);
-	if (result < 0)
-		return result;
+	/* Ensure another device does not already have this name. */
+	list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
+		if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0)
+			return -EINVAL;
 
 	result = device_rename(&rdev->wiphy.dev, newname);
 	if (result)
@@ -322,8 +309,7 @@
 
 /* exported functions */
 
-struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
-			   const char *requested_name)
+struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
 {
 	static atomic_t wiphy_counter = ATOMIC_INIT(0);
 
@@ -371,31 +357,7 @@
 	rdev->wiphy_idx--;
 
 	/* give it a proper name */
-	if (requested_name && requested_name[0]) {
-		int rv;
-
-		rtnl_lock();
-		rv = cfg80211_dev_check_name(rdev, requested_name);
-
-		if (rv < 0) {
-			rtnl_unlock();
-			goto use_default_name;
-		}
-
-		rv = dev_set_name(&rdev->wiphy.dev, "%s", requested_name);
-		rtnl_unlock();
-		if (rv)
-			goto use_default_name;
-	} else {
-use_default_name:
-		/* NOTE:  This is *probably* safe w/out holding rtnl because of
-		 * the restrictions on phy names.  Probably this call could
-		 * fail if some other part of the kernel (re)named a device
-		 * phyX.  But, might should add some locking and check return
-		 * value, and use a different name if this one exists?
-		 */
-		dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
-	}
+	dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
 
 	INIT_LIST_HEAD(&rdev->wdev_list);
 	INIT_LIST_HEAD(&rdev->beacon_registrations);
@@ -451,7 +413,7 @@
 
 	return &rdev->wiphy;
 }
-EXPORT_SYMBOL(wiphy_new_nm);
+EXPORT_SYMBOL(wiphy_new);
 
 static int wiphy_verify_combinations(struct wiphy *wiphy)
 {
@@ -548,24 +510,6 @@
 		    !wiphy->wowlan->tcp))
 		return -EINVAL;
 #endif
-	if (WARN_ON((wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
-		    (!rdev->ops->tdls_channel_switch ||
-		     !rdev->ops->tdls_cancel_channel_switch)))
-		return -EINVAL;
-
-	/*
-	 * if a wiphy has unsupported modes for regulatory channel enforcement,
-	 * opt-out of enforcement checking
-	 */
-	if (wiphy->interface_modes & ~(BIT(NL80211_IFTYPE_STATION) |
-				       BIT(NL80211_IFTYPE_P2P_CLIENT) |
-				       BIT(NL80211_IFTYPE_AP) |
-				       BIT(NL80211_IFTYPE_P2P_GO) |
-				       BIT(NL80211_IFTYPE_ADHOC) |
-				       BIT(NL80211_IFTYPE_P2P_DEVICE) |
-				       BIT(NL80211_IFTYPE_AP_VLAN) |
-				       BIT(NL80211_IFTYPE_MONITOR)))
-		wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
 
 	if (WARN_ON(wiphy->coalesce &&
 		    (!wiphy->coalesce->n_rules ||
@@ -894,22 +838,7 @@
 	case NL80211_IFTYPE_P2P_GO:
 		__cfg80211_stop_ap(rdev, dev, true);
 		break;
-	case NL80211_IFTYPE_OCB:
-		__cfg80211_leave_ocb(rdev, dev);
-		break;
-	case NL80211_IFTYPE_WDS:
-		/* must be handled by mac80211/driver, has no APIs */
-		break;
-	case NL80211_IFTYPE_P2P_DEVICE:
-		/* cannot happen, has no netdev */
-		break;
-	case NL80211_IFTYPE_AP_VLAN:
-	case NL80211_IFTYPE_MONITOR:
-		/* nothing to do */
-		break;
-	case NL80211_IFTYPE_UNSPECIFIED:
-	case NUM_NL80211_IFTYPES:
-		/* invalid */
+	default:
 		break;
 	}
 }
diff --git a/net/wireless/core.h b/net/wireless/core.h
index df247e3..b27f044 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -111,7 +111,6 @@
 	    rdev->wiphy.wowlan_config->tcp->sock)
 		sock_release(rdev->wiphy.wowlan_config->tcp->sock);
 	kfree(rdev->wiphy.wowlan_config->tcp);
-	kfree(rdev->wiphy.wowlan_config->nd_config);
 	kfree(rdev->wiphy.wowlan_config);
 #endif
 }
@@ -291,18 +290,6 @@
 			      struct wireless_dev *wdev,
 			      struct cfg80211_chan_def *chandef);
 
-/* OCB */
-int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
-			struct net_device *dev,
-			struct ocb_setup *setup);
-int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
-		      struct net_device *dev,
-		      struct ocb_setup *setup);
-int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
-			 struct net_device *dev);
-int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
-		       struct net_device *dev);
-
 /* AP */
 int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
 		       struct net_device *dev, bool notify);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b800567..f84c236 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -209,7 +209,7 @@
 }
 
 /* policy for the attributes */
-static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
+static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
 	[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
 				      .len = 20-1 },
@@ -388,14 +388,13 @@
 	[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
 	[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
 	[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
-	[NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
+	[NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
 	[NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
 	[NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
 	[NL80211_ATTR_TSID] = { .type = NLA_U8 },
 	[NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
 	[NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
 	[NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
-	[NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
 };
 
 /* policy for the key attributes */
@@ -429,7 +428,6 @@
 	[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
 	[NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
 	[NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
-	[NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
 };
 
 static const struct nla_policy
@@ -886,12 +884,7 @@
 		if (!wdev->current_bss)
 			return -ENOLINK;
 		break;
-	case NL80211_IFTYPE_UNSPECIFIED:
-	case NL80211_IFTYPE_OCB:
-	case NL80211_IFTYPE_MONITOR:
-	case NL80211_IFTYPE_P2P_DEVICE:
-	case NL80211_IFTYPE_WDS:
-	case NUM_NL80211_IFTYPES:
+	default:
 		return -EINVAL;
 	}
 
@@ -1090,8 +1083,6 @@
 	if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
 		return -ENOBUFS;
 
-	/* TODO: send wowlan net detect */
-
 	nla_nest_end(msg, nl_wowlan);
 
 	return 0;
@@ -1523,8 +1514,8 @@
 			if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
 				CMD(channel_switch, CHANNEL_SWITCH);
 			CMD(set_qos_map, SET_QOS_MAP);
-			if (rdev->wiphy.features &
-					NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
+			if (rdev->wiphy.flags &
+					WIPHY_FLAG_SUPPORTS_WMM_ADMISSION)
 				CMD(add_tx_ts, ADD_TX_TS);
 		}
 		/* add into the if now */
@@ -2319,8 +2310,7 @@
 static int nl80211_send_chandef(struct sk_buff *msg,
 				const struct cfg80211_chan_def *chandef)
 {
-	if (WARN_ON(!cfg80211_chandef_valid(chandef)))
-		return -EINVAL;
+	WARN_ON(!cfg80211_chandef_valid(chandef));
 
 	if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
 			chandef->chan->center_freq))
@@ -2348,16 +2338,12 @@
 
 static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
 			      struct cfg80211_registered_device *rdev,
-			      struct wireless_dev *wdev, bool removal)
+			      struct wireless_dev *wdev)
 {
 	struct net_device *dev = wdev->netdev;
-	u8 cmd = NL80211_CMD_NEW_INTERFACE;
 	void *hdr;
 
-	if (removal)
-		cmd = NL80211_CMD_DEL_INTERFACE;
-
-	hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
+	hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_INTERFACE);
 	if (!hdr)
 		return -1;
 
@@ -2424,7 +2410,7 @@
 			}
 			if (nl80211_send_iface(skb, NETLINK_CB_PORTID(cb->skb),
 					       cb->nlh->nlmsg_seq, NLM_F_MULTI,
-					       rdev, wdev, false) < 0) {
+					       rdev, wdev) < 0) {
 				goto out;
 			}
 			if_idx++;
@@ -2452,7 +2438,7 @@
 		return -ENOMEM;
 
 	if (nl80211_send_iface(msg, genl_info_snd_portid(info), info->snd_seq, 0,
-			       rdev, wdev, false) < 0) {
+			       rdev, wdev) < 0) {
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
@@ -2598,7 +2584,7 @@
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct vif_params params;
 	struct wireless_dev *wdev;
-	struct sk_buff *msg, *event;
+	struct sk_buff *msg;
 	int err;
 	enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
 	u32 flags;
@@ -2621,9 +2607,7 @@
 	    !(rdev->wiphy.interface_modes & (1 << type)))
 		return -EOPNOTSUPP;
 
-	if ((type == NL80211_IFTYPE_P2P_DEVICE ||
-	     rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
-	    info->attrs[NL80211_ATTR_MAC]) {
+	if (type == NL80211_IFTYPE_P2P_DEVICE && info->attrs[NL80211_ATTR_MAC]) {
 		nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
 			   ETH_ALEN);
 		if (!is_valid_ether_addr(params.macaddr))
@@ -2652,15 +2636,12 @@
 	wdev = rdev_add_virtual_intf(rdev,
 				nla_data(info->attrs[NL80211_ATTR_IFNAME]),
 				type, err ? NULL : &flags, &params);
-	if (WARN_ON(!wdev)) {
-		nlmsg_free(msg);
-		return -EPROTO;
-	} else if (IS_ERR(wdev)) {
+	if (IS_ERR(wdev)) {
 		nlmsg_free(msg);
 		return PTR_ERR(wdev);
 	}
 
-	if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
+	if (info->attrs[NL80211_ATTR_IFACE_SOCKET_OWNER])
 		wdev->owner_nlportid = genl_info_snd_portid(info);
 
 	switch (type) {
@@ -2696,25 +2677,11 @@
 	}
 
 	if (nl80211_send_iface(msg, genl_info_snd_portid(info), info->snd_seq, 0,
-			       rdev, wdev, false) < 0) {
+			       rdev, wdev) < 0) {
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
 
-	event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (event) {
-		if (nl80211_send_iface(event, 0, 0, 0,
-				       rdev, wdev, false) < 0) {
-			nlmsg_free(event);
-			goto out;
-		}
-
-		genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
-					event, 0, NL80211_MCGRP_CONFIG,
-					GFP_KERNEL);
-	}
-
-out:
 	return genlmsg_reply(msg, info);
 }
 
@@ -2722,18 +2689,10 @@
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct wireless_dev *wdev = info->user_ptr[1];
-	struct sk_buff *msg;
-	int status;
 
 	if (!rdev->ops->del_virtual_intf)
 		return -EOPNOTSUPP;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (msg && nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, true) < 0) {
-		nlmsg_free(msg);
-		msg = NULL;
-	}
-
 	/*
 	 * If we remove a wireless device without a netdev then clear
 	 * user_ptr[1] so that nl80211_post_doit won't dereference it
@@ -2744,15 +2703,7 @@
 	if (!wdev->netdev)
 		info->user_ptr[1] = NULL;
 
-	status = rdev_del_virtual_intf(rdev, wdev);
-	if (status >= 0 && msg)
-		genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
-					msg, 0, NL80211_MCGRP_CONFIG,
-					GFP_KERNEL);
-	else
-		nlmsg_free(msg);
-
-	return status;
+	return rdev_del_virtual_intf(rdev, wdev);
 }
 
 static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
@@ -4450,12 +4401,10 @@
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct net_device *dev = info->user_ptr[1];
-	struct station_del_parameters params;
-
-	memset(&params, 0, sizeof(params));
+	u8 *mac_addr = NULL;
 
 	if (info->attrs[NL80211_ATTR_MAC])
-		params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
+		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
 	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
@@ -4466,28 +4415,7 @@
 	if (!rdev->ops->del_station)
 		return -EOPNOTSUPP;
 
-	if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
-		params.subtype =
-			nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
-		if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
-		    params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
-			return -EINVAL;
-	} else {
-		/* Default to Deauthentication frame */
-		params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
-	}
-
-	if (info->attrs[NL80211_ATTR_REASON_CODE]) {
-		params.reason_code =
-			nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
-		if (params.reason_code == 0)
-			return -EINVAL; /* 0 is reserved */
-	} else {
-		/* Default to reason code 2 */
-		params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
-	}
-
-	return rdev_del_station(rdev, dev, &params);
+	return rdev_del_station(rdev, dev, mac_addr);
 }
 
 static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
@@ -4498,7 +4426,7 @@
 	void *hdr;
 	struct nlattr *pinfoattr;
 
-	hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
+	hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
 		return -1;
 
@@ -4699,96 +4627,6 @@
 	return rdev_del_mpath(rdev, dev, dst);
 }
 
-static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg80211_registered_device *rdev = info->user_ptr[0];
-	int err;
-	struct net_device *dev = info->user_ptr[1];
-	struct mpath_info pinfo;
-	struct sk_buff *msg;
-	u8 *dst = NULL;
-	u8 mpp[ETH_ALEN];
-
-	memset(&pinfo, 0, sizeof(pinfo));
-
-	if (!info->attrs[NL80211_ATTR_MAC])
-		return -EINVAL;
-
-	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
-
-	if (!rdev->ops->get_mpp)
-		return -EOPNOTSUPP;
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
-		return -EOPNOTSUPP;
-
-	err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
-	if (err)
-		return err;
-
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg)
-		return -ENOMEM;
-
-	if (nl80211_send_mpath(msg, genl_info_snd_portid(info), info->snd_seq, 0,
-			       dev, dst, mpp, &pinfo) < 0) {
-		nlmsg_free(msg);
-		return -ENOBUFS;
-	}
-
-	return genlmsg_reply(msg, info);
-}
-
-static int nl80211_dump_mpp(struct sk_buff *skb,
-			    struct netlink_callback *cb)
-{
-	struct mpath_info pinfo;
-	struct cfg80211_registered_device *rdev;
-	struct wireless_dev *wdev;
-	u8 dst[ETH_ALEN];
-	u8 mpp[ETH_ALEN];
-	int path_idx = cb->args[2];
-	int err;
-
-	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
-	if (err)
-		return err;
-
-	if (!rdev->ops->dump_mpp) {
-		err = -EOPNOTSUPP;
-		goto out_err;
-	}
-
-	if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
-		err = -EOPNOTSUPP;
-		goto out_err;
-	}
-
-	while (1) {
-		err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
-				    mpp, &pinfo);
-		if (err == -ENOENT)
-			break;
-		if (err)
-			goto out_err;
-
-		if (nl80211_send_mpath(skb, NETLINK_CB_PORTID(cb->skb),
-				       cb->nlh->nlmsg_seq, NLM_F_MULTI,
-				       wdev->netdev, dst, mpp,
-				       &pinfo) < 0)
-			goto out;
-
-		path_idx++;
-	}
-
- out:
-	cb->args[2] = path_idx;
-	err = skb->len;
- out_err:
-	nl80211_finish_wdev_dump(rdev);
-	return err;
-}
-
 static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -5427,11 +5265,11 @@
 {
 	struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
 	struct nlattr *nl_reg_rule;
-	char *alpha2;
-	int rem_reg_rules, r;
+	char *alpha2 = NULL;
+	int rem_reg_rules = 0, r = 0;
 	u32 num_rules = 0, rule_idx = 0, size_of_regd;
 	enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
-	struct ieee80211_regdomain *rd;
+	struct ieee80211_regdomain *rd = NULL;
 
 	if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
 		return -EINVAL;
@@ -5525,43 +5363,6 @@
 	return n_channels;
 }
 
-static int nl80211_parse_random_mac(struct nlattr **attrs,
-				    u8 *mac_addr, u8 *mac_addr_mask)
-{
-	int i;
-
-	if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
-		memset(mac_addr, 0, ETH_ALEN);
-		memset(mac_addr_mask, 0, ETH_ALEN);
-		mac_addr[0] = 0x2;
-		mac_addr_mask[0] = 0x3;
-
-		return 0;
-	}
-
-	/* need both or none */
-	if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
-		return -EINVAL;
-
-	memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
-	memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
-
-	/* don't allow or configure an mcast address */
-	if (!is_multicast_ether_addr(mac_addr_mask) ||
-	    is_multicast_ether_addr(mac_addr))
-		return -EINVAL;
-
-	/*
-	 * allow users to pass a MAC address that has bits set outside
-	 * of the mask, but don't bother drivers with having to deal
-	 * with such bits
-	 */
-	for (i = 0; i < ETH_ALEN; i++)
-		mac_addr[i] &= mac_addr_mask[i];
-
-	return 0;
-}
-
 static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -5739,25 +5540,6 @@
 			err = -EOPNOTSUPP;
 			goto out_free;
 		}
-
-		if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
-			if (!(wiphy->features &
-					NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR)) {
-				err = -EOPNOTSUPP;
-				goto out_free;
-			}
-
-			if (wdev->current_bss) {
-				err = -EOPNOTSUPP;
-				goto out_free;
-			}
-
-			err = nl80211_parse_random_mac(info->attrs,
-						       request->mac_addr,
-						       request->mac_addr_mask);
-			if (err)
-				goto out_free;
-		}
 	}
 
 	request->no_cck =
@@ -5784,12 +5566,14 @@
 	return err;
 }
 
-static struct cfg80211_sched_scan_request *
-nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
-			 struct nlattr **attrs)
+static int nl80211_start_sched_scan(struct sk_buff *skb,
+				    struct genl_info *info)
 {
 	struct cfg80211_sched_scan_request *request;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct nlattr *attr;
+	struct wiphy *wiphy;
 	int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i;
 	u32 interval;
 	enum ieee80211_band band;
@@ -5797,32 +5581,38 @@
 	struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
 	s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
 
-	if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
-		return ERR_PTR(-EINVAL);
+	if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
+	    !rdev->ops->sched_scan_start)
+		return -EOPNOTSUPP;
 
-	if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
-		return ERR_PTR(-EINVAL);
+	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+		return -EINVAL;
 
-	interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
+	if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
+		return -EINVAL;
+
+	interval = nla_get_u32(info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
 	if (interval == 0)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
-	if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
+	wiphy = &rdev->wiphy;
+
+	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
 		n_channels = validate_scan_freqs(
-				attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
+				info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
 		if (!n_channels)
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 	} else {
 		n_channels = ieee80211_get_num_supported_channels(wiphy);
 	}
 
-	if (attrs[NL80211_ATTR_SCAN_SSIDS])
-		nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
+	if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
+		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
 				    tmp)
 			n_ssids++;
 
 	if (n_ssids > wiphy->max_sched_scan_ssids)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	/*
 	 * First, count the number of 'real' matchsets. Due to an issue with
@@ -5833,9 +5623,9 @@
 	 * older userspace that treated a matchset with only the RSSI as the
 	 * global RSSI for all other matchsets - if there are other matchsets.
 	 */
-	if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
+	if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
 		nla_for_each_nested(attr,
-				    attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
+				    info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
 				    tmp) {
 			struct nlattr *rssi;
 
@@ -5843,7 +5633,7 @@
 					nla_data(attr), nla_len(attr),
 					nl80211_match_policy);
 			if (err)
-				return ERR_PTR(err);
+				return err;
 			/* add other standalone attributes here */
 			if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
 				n_match_sets++;
@@ -5860,23 +5650,30 @@
 		n_match_sets = 1;
 
 	if (n_match_sets > wiphy->max_match_sets)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
-	if (attrs[NL80211_ATTR_IE])
-		ie_len = nla_len(attrs[NL80211_ATTR_IE]);
+	if (info->attrs[NL80211_ATTR_IE])
+		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
 	else
 		ie_len = 0;
 
 	if (ie_len > wiphy->max_sched_scan_ie_len)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
+
+	if (rdev->sched_scan_req) {
+		err = -EINPROGRESS;
+		goto out;
+	}
 
 	request = kzalloc(sizeof(*request)
 			+ sizeof(*request->ssids) * n_ssids
 			+ sizeof(*request->match_sets) * n_match_sets
 			+ sizeof(*request->channels) * n_channels
 			+ ie_len, GFP_KERNEL);
-	if (!request)
-		return ERR_PTR(-ENOMEM);
+	if (!request) {
+		err = -ENOMEM;
+		goto out;
+	}
 
 	if (n_ssids)
 		request->ssids = (void *)&request->channels[n_channels];
@@ -5901,10 +5698,10 @@
 	request->n_match_sets = n_match_sets;
 
 	i = 0;
-	if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
+	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
 		/* user specified, bail out if channel not found */
 		nla_for_each_nested(attr,
-				    attrs[NL80211_ATTR_SCAN_FREQUENCIES],
+				    info->attrs[NL80211_ATTR_SCAN_FREQUENCIES],
 				    tmp) {
 			struct ieee80211_channel *chan;
 
@@ -5950,8 +5747,8 @@
 	request->n_channels = i;
 
 	i = 0;
-	if (attrs[NL80211_ATTR_SCAN_SSIDS]) {
-		nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
+	if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
+		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
 				    tmp) {
 			if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
 				err = -EINVAL;
@@ -5965,9 +5762,9 @@
 	}
 
 	i = 0;
-	if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
+	if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
 		nla_for_each_nested(attr,
-				    attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
+				    info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
 				    tmp) {
 			struct nlattr *ssid, *rssi;
 
@@ -6007,7 +5804,7 @@
 		}
 
 		/* there was no other matchset, so the RSSI one is alone */
-		if (i == 0 && n_match_sets)
+		if (i == 0)
 			request->match_sets[0].rssi_thold = default_match_rssi;
 
 		request->min_rssi_thold = INT_MAX;
@@ -6022,88 +5819,36 @@
 	if (ie_len) {
 		request->ie_len = ie_len;
 		memcpy((void *)request->ie,
-		       nla_data(attrs[NL80211_ATTR_IE]),
+		       nla_data(info->attrs[NL80211_ATTR_IE]),
 		       request->ie_len);
 	}
 
-	if (attrs[NL80211_ATTR_SCAN_FLAGS]) {
+	if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
 		request->flags = nla_get_u32(
-			attrs[NL80211_ATTR_SCAN_FLAGS]);
+			info->attrs[NL80211_ATTR_SCAN_FLAGS]);
 		if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
 		    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
 			err = -EOPNOTSUPP;
 			goto out_free;
 		}
-
-		if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
-			u32 flg = NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
-
-			if (!wdev) /* must be net-detect */
-				flg = NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
-
-			if (!(wiphy->features & flg)) {
-				err = -EOPNOTSUPP;
-				goto out_free;
-			}
-
-			if (wdev && wdev->current_bss) {
-				err = -EOPNOTSUPP;
-				goto out_free;
-			}
-
-			err = nl80211_parse_random_mac(attrs, request->mac_addr,
-						       request->mac_addr_mask);
-			if (err)
-				goto out_free;
-		}
 	}
 
+	request->dev = dev;
+	request->wiphy = &rdev->wiphy;
 	request->interval = interval;
 	request->scan_start = jiffies;
 
-	return request;
+	err = rdev_sched_scan_start(rdev, dev, request);
+	if (!err) {
+		rdev->sched_scan_req = request;
+		nl80211_send_sched_scan(rdev, dev,
+					NL80211_CMD_START_SCHED_SCAN);
+		goto out;
+	}
 
 out_free:
 	kfree(request);
-	return ERR_PTR(err);
-}
-
-static int nl80211_start_sched_scan(struct sk_buff *skb,
-				    struct genl_info *info)
-{
-	struct cfg80211_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	int err;
-
-	if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
-	    !rdev->ops->sched_scan_start)
-		return -EOPNOTSUPP;
-
-	if (rdev->sched_scan_req)
-		return -EINPROGRESS;
-
-	rdev->sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
-							info->attrs);
-	err = PTR_ERR_OR_ZERO(rdev->sched_scan_req);
-	if (err)
-		goto out_err;
-
-	err = rdev_sched_scan_start(rdev, dev, rdev->sched_scan_req);
-	if (err)
-		goto out_free;
-
-	rdev->sched_scan_req->dev = dev;
-	rdev->sched_scan_req->wiphy = &rdev->wiphy;
-
-	nl80211_send_sched_scan(rdev, dev,
-				NL80211_CMD_START_SCHED_SCAN);
-	return 0;
-
-out_free:
-	kfree(rdev->sched_scan_req);
-out_err:
-	rdev->sched_scan_req = NULL;
+out:
 	return err;
 }
 
@@ -6183,10 +5928,10 @@
 	 * function is called under RTNL lock, so this should not be a problem.
 	 */
 	static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
+	u8 radar_detect_width = 0;
 	int err;
 	bool need_new_beacon = false;
 	int len, i;
-	u32 cs_count;
 
 	if (!rdev->ops->channel_switch ||
 	    !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
@@ -6223,14 +5968,7 @@
 	if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
 		return -EINVAL;
 
-	/* Even though the attribute is u32, the specification says
-	 * u8, so let's make sure we don't overflow.
-	 */
-	cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
-	if (cs_count > 255)
-		return -EINVAL;
-
-	params.count = cs_count;
+	params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
 
 	if (!need_new_beacon)
 		goto skip_beacons;
@@ -6318,8 +6056,10 @@
 	if (err < 0)
 		return err;
 
-	if (err > 0)
+	if (err > 0) {
+		radar_detect_width = BIT(params.chandef.width);
 		params.radar_required = true;
+	}
 
 	if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
 		params.block_tx = true;
@@ -6570,6 +6310,8 @@
 	}
 
 	while (1) {
+		struct ieee80211_channel *chan;
+
 		res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
 		if (res == -ENOENT)
 			break;
@@ -6582,7 +6324,9 @@
 			goto out;
 		}
 
-		if (survey.channel->flags & IEEE80211_CHAN_DISABLED) {
+		chan = ieee80211_get_channel(&rdev->wiphy,
+					     survey.channel->center_freq);
+		if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
 			survey_idx++;
 			continue;
 		}
@@ -8418,28 +8162,6 @@
 	return -EINVAL;
 }
 
-static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg80211_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct ocb_setup setup = {};
-	int err;
-
-	err = nl80211_parse_chandef(rdev, info, &setup.chandef);
-	if (err)
-		return err;
-
-	return cfg80211_join_ocb(rdev, dev, &setup);
-}
-
-static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
-{
-	struct cfg80211_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-
-	return cfg80211_leave_ocb(rdev, dev);
-}
-
 static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -8824,39 +8546,6 @@
 	return 0;
 }
 
-static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
-				   const struct wiphy_wowlan_support *wowlan,
-				   struct nlattr *attr,
-				   struct cfg80211_wowlan *trig)
-{
-	struct nlattr **tb;
-	int err;
-
-	tb = kzalloc(NUM_NL80211_ATTR * sizeof(*tb), GFP_KERNEL);
-	if (!tb)
-		return -ENOMEM;
-
-	if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	err = nla_parse(tb, NL80211_ATTR_MAX,
-			nla_data(attr), nla_len(attr),
-			nl80211_policy);
-	if (err)
-		goto out;
-
-	trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb);
-	err = PTR_ERR_OR_ZERO(trig->nd_config);
-	if (err)
-		trig->nd_config = NULL;
-
-out:
-	kfree(tb);
-	return err;
-}
-
 static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9002,14 +8691,6 @@
 			goto error;
 	}
 
-	if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
-		err = nl80211_parse_wowlan_nd(
-			rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
-			&new_triggers);
-		if (err)
-			goto error;
-	}
-
 	ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
 	if (!ntrig) {
 		err = -ENOMEM;
@@ -9770,7 +9451,7 @@
 	u16 admitted_time = 0;
 	int err;
 
-	if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
+	if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
 		return -EOPNOTSUPP;
 
 	if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
@@ -9786,10 +9467,12 @@
 		return -EINVAL;
 
 	/* WMM uses TIDs 0-7 even for TSPEC */
-	if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
+	if (tsid < IEEE80211_FIRST_TSPEC_TSID) {
+		if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
+			return -EINVAL;
+	} else {
 		/* TODO: handle 802.11 TSPEC/admission control
-		 * need more attributes for that (e.g. BA session requirement);
-		 * change the WMM adminssion test above to allow both then
+		 * need more attributes for that (e.g. BA session requirement)
 		 */
 		return -EINVAL;
 	}
@@ -9845,98 +9528,6 @@
 	return err;
 }
 
-static int nl80211_tdls_channel_switch(struct sk_buff *skb,
-				       struct genl_info *info)
-{
-	struct cfg80211_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct cfg80211_chan_def chandef = {};
-	const u8 *addr;
-	u8 oper_class;
-	int err;
-
-	if (!rdev->ops->tdls_channel_switch ||
-	    !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
-		return -EOPNOTSUPP;
-
-	switch (dev->ieee80211_ptr->iftype) {
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_P2P_CLIENT:
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	if (!info->attrs[NL80211_ATTR_MAC] ||
-	    !info->attrs[NL80211_ATTR_OPER_CLASS])
-		return -EINVAL;
-
-	err = nl80211_parse_chandef(rdev, info, &chandef);
-	if (err)
-		return err;
-
-	/*
-	 * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
-	 * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
-	 * specification is not defined for them.
-	 */
-	if (chandef.chan->band == IEEE80211_BAND_2GHZ &&
-	    chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
-	    chandef.width != NL80211_CHAN_WIDTH_20)
-		return -EINVAL;
-
-	/* we will be active on the TDLS link */
-	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, wdev->iftype))
-		return -EINVAL;
-
-	/* don't allow switching to DFS channels */
-	if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
-		return -EINVAL;
-
-	addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
-	oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
-
-	wdev_lock(wdev);
-	err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
-	wdev_unlock(wdev);
-
-	return err;
-}
-
-static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
-					      struct genl_info *info)
-{
-	struct cfg80211_registered_device *rdev = info->user_ptr[0];
-	struct net_device *dev = info->user_ptr[1];
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	const u8 *addr;
-
-	if (!rdev->ops->tdls_channel_switch ||
-	    !rdev->ops->tdls_cancel_channel_switch ||
-	    !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
-		return -EOPNOTSUPP;
-
-	switch (dev->ieee80211_ptr->iftype) {
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_P2P_CLIENT:
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	if (!info->attrs[NL80211_ATTR_MAC])
-		return -EINVAL;
-
-	addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
-
-	wdev_lock(wdev);
-	rdev_tdls_cancel_channel_switch(rdev, dev, addr);
-	wdev_unlock(wdev);
-
-	return 0;
-}
-
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -10198,15 +9789,6 @@
 				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
-		.cmd = NL80211_CMD_GET_MPP,
-		.doit = nl80211_get_mpp,
-		.dumpit = nl80211_dump_mpp,
-		.policy = nl80211_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-				  NL80211_FLAG_NEED_RTNL,
-	},
-	{
 		.cmd = NL80211_CMD_SET_MPATH,
 		.doit = nl80211_set_mpath,
 		.policy = nl80211_policy,
@@ -10520,22 +10102,6 @@
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
-	{
-		.cmd = NL80211_CMD_JOIN_OCB,
-		.doit = nl80211_join_ocb,
-		.policy = nl80211_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-				  NL80211_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL80211_CMD_LEAVE_OCB,
-		.doit = nl80211_leave_ocb,
-		.policy = nl80211_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-				  NL80211_FLAG_NEED_RTNL,
-	},
 #ifdef CONFIG_PM
 	{
 		.cmd = NL80211_CMD_GET_WOWLAN,
@@ -10735,22 +10301,6 @@
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
-	{
-		.cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
-		.doit = nl80211_tdls_channel_switch,
-		.policy = nl80211_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-				  NL80211_FLAG_NEED_RTNL,
-	},
-	{
-		.cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
-		.doit = nl80211_tdls_cancel_channel_switch,
-		.policy = nl80211_policy,
-		.flags = GENL_ADMIN_PERM,
-		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-				  NL80211_FLAG_NEED_RTNL,
-	},
 };
 
 /* notification functions */
@@ -11782,155 +11332,55 @@
 }
 EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
 
-static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
-					    const char *mac, gfp_t gfp)
+void cfg80211_cqm_rssi_notify(struct net_device *dev,
+			      enum nl80211_cqm_rssi_threshold_event rssi_event,
+			      gfp_t gfp)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
-	struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
-	void **cb;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+	struct sk_buff *msg;
+	struct nlattr *pinfoattr;
+	void *hdr;
 
+	trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
 	if (!msg)
-		return NULL;
+		return;
 
-	cb = (void **)msg->cb;
-
-	cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
-	if (!cb[0]) {
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
+	if (!hdr) {
 		nlmsg_free(msg);
-		return NULL;
+		return;
 	}
 
 	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
 	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
 		goto nla_put_failure;
 
-	if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
+	pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM);
+	if (!pinfoattr)
 		goto nla_put_failure;
 
-	cb[1] = nla_nest_start(msg, NL80211_ATTR_CQM);
-	if (!cb[1])
-		goto nla_put_failure;
-
-	cb[2] = rdev;
-
-	return msg;
- nla_put_failure:
-	nlmsg_free(msg);
-	return NULL;
-}
-
-static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
-{
-	void **cb = (void **)msg->cb;
-	struct cfg80211_registered_device *rdev = cb[2];
-
-	nla_nest_end(msg, cb[1]);
-	genlmsg_end(msg, cb[0]);
-
-	memset(msg->cb, 0, sizeof(msg->cb));
-
-	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
-				NL80211_MCGRP_MLME, gfp);
-}
-
-void cfg80211_cqm_rssi_notify(struct net_device *dev,
-			      enum nl80211_cqm_rssi_threshold_event rssi_event,
-			      gfp_t gfp)
-{
-	struct sk_buff *msg;
-
-	trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
-
-	if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
-		    rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
-		return;
-
-	msg = cfg80211_prepare_cqm(dev, NULL, gfp);
-	if (!msg)
-		return;
-
 	if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
 			rssi_event))
 		goto nla_put_failure;
 
-	cfg80211_send_cqm(msg, gfp);
+	nla_nest_end(msg, pinfoattr);
 
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+				NL80211_MCGRP_MLME, gfp);
 	return;
 
  nla_put_failure:
+	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
 EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 
-void cfg80211_cqm_txe_notify(struct net_device *dev,
-			     const u8 *peer, u32 num_packets,
-			     u32 rate, u32 intvl, gfp_t gfp)
-{
-	struct sk_buff *msg;
-
-	msg = cfg80211_prepare_cqm(dev, peer, gfp);
-	if (!msg)
-		return;
-
-	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
-		goto nla_put_failure;
-
-	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
-		goto nla_put_failure;
-
-	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
-		goto nla_put_failure;
-
-	cfg80211_send_cqm(msg, gfp);
-	return;
-
- nla_put_failure:
-	nlmsg_free(msg);
-}
-EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
-
-void cfg80211_cqm_pktloss_notify(struct net_device *dev,
-				 const u8 *peer, u32 num_packets, gfp_t gfp)
-{
-	struct sk_buff *msg;
-
-	trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
-
-	msg = cfg80211_prepare_cqm(dev, peer, gfp);
-	if (!msg)
-		return;
-
-	if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
-		goto nla_put_failure;
-
-	cfg80211_send_cqm(msg, gfp);
-	return;
-
- nla_put_failure:
-	nlmsg_free(msg);
-}
-EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
-
-void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
-{
-	struct sk_buff *msg;
-
-	msg = cfg80211_prepare_cqm(dev, NULL, gfp);
-	if (!msg)
-		return;
-
-	if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
-		goto nla_put_failure;
-
-	cfg80211_send_cqm(msg, gfp);
-	return;
-
- nla_put_failure:
-	nlmsg_free(msg);
-}
-EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
-
 static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
 				     struct net_device *netdev, const u8 *bssid,
 				     const u8 *replay_ctr, gfp_t gfp)
@@ -12048,9 +11498,7 @@
 static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
 				     struct net_device *netdev,
 				     struct cfg80211_chan_def *chandef,
-				     gfp_t gfp,
-				     enum nl80211_commands notif,
-				     u8 count)
+				     gfp_t gfp)
 {
 	struct sk_buff *msg;
 	void *hdr;
@@ -12059,7 +11507,7 @@
 	if (!msg)
 		return;
 
-	hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CH_SWITCH_NOTIFY);
 	if (!hdr) {
 		nlmsg_free(msg);
 		return;
@@ -12071,10 +11519,6 @@
 	if (nl80211_send_chandef(msg, chandef))
 		goto nla_put_failure;
 
-	if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) &&
-	    (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count)))
-			goto nla_put_failure;
-
 	genlmsg_end(msg, hdr);
 
 	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@@ -12097,27 +11541,70 @@
 
 	trace_cfg80211_ch_switch_notify(dev, chandef);
 
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
+		    wdev->iftype != NL80211_IFTYPE_ADHOC &&
+		    wdev->iftype != NL80211_IFTYPE_MESH_POINT))
+		return;
+
 	wdev->chandef = *chandef;
 	wdev->preset_chandef = *chandef;
-	nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
-				 NL80211_CMD_CH_SWITCH_NOTIFY, 0);
+	nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
 }
 EXPORT_SYMBOL(cfg80211_ch_switch_notify);
 
-void cfg80211_ch_switch_started_notify(struct net_device *dev,
-				       struct cfg80211_chan_def *chandef,
-				       u8 count)
+void cfg80211_cqm_txe_notify(struct net_device *dev,
+			     const u8 *peer, u32 num_packets,
+			     u32 rate, u32 intvl, gfp_t gfp)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct wiphy *wiphy = wdev->wiphy;
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+	struct sk_buff *msg;
+	struct nlattr *pinfoattr;
+	void *hdr;
 
-	trace_cfg80211_ch_switch_started_notify(dev, chandef);
+	msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+	if (!msg)
+		return;
 
-	nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
-				 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count);
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer))
+		goto nla_put_failure;
+
+	pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM);
+	if (!pinfoattr)
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
+		goto nla_put_failure;
+
+	nla_nest_end(msg, pinfoattr);
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+				NL80211_MCGRP_MLME, gfp);
+	return;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
 }
-EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
+EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
 
 void
 nl80211_radar_notify(struct cfg80211_registered_device *rdev,
@@ -12167,6 +11654,54 @@
 	nlmsg_free(msg);
 }
 
+void cfg80211_cqm_pktloss_notify(struct net_device *dev,
+				 const u8 *peer, u32 num_packets, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+	struct sk_buff *msg;
+	struct nlattr *pinfoattr;
+	void *hdr;
+
+	trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer))
+		goto nla_put_failure;
+
+	pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM);
+	if (!pinfoattr)
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
+		goto nla_put_failure;
+
+	nla_nest_end(msg, pinfoattr);
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+				NL80211_MCGRP_MLME, gfp);
+	return;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
+
 void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
 			   u64 cookie, bool acked, gfp_t gfp)
 {
@@ -12254,67 +11789,6 @@
 EXPORT_SYMBOL(cfg80211_report_obss_beacon);
 
 #ifdef CONFIG_PM
-static int cfg80211_net_detect_results(struct sk_buff *msg,
-				       struct cfg80211_wowlan_wakeup *wakeup)
-{
-	struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
-	struct nlattr *nl_results, *nl_match, *nl_freqs;
-	int i, j;
-
-	nl_results = nla_nest_start(
-		msg, NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
-	if (!nl_results)
-		return -EMSGSIZE;
-
-	for (i = 0; i < nd->n_matches; i++) {
-		struct cfg80211_wowlan_nd_match *match = nd->matches[i];
-
-		nl_match = nla_nest_start(msg, i);
-		if (!nl_match)
-			break;
-
-		/* The SSID attribute is optional in nl80211, but for
-		 * simplicity reasons it's always present in the
-		 * cfg80211 structure.  If a driver can't pass the
-		 * SSID, that needs to be changed.  A zero length SSID
-		 * is still a valid SSID (wildcard), so it cannot be
-		 * used for this purpose.
-		 */
-		if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
-			    match->ssid.ssid)) {
-			nla_nest_cancel(msg, nl_match);
-			goto out;
-		}
-
-		if (match->n_channels) {
-			nl_freqs = nla_nest_start(
-				msg, NL80211_ATTR_SCAN_FREQUENCIES);
-			if (!nl_freqs) {
-				nla_nest_cancel(msg, nl_match);
-				goto out;
-			}
-
-			for (j = 0; j < match->n_channels; j++) {
-				if (nla_put_u32(msg,
-						NL80211_ATTR_WIPHY_FREQ,
-						match->channels[j])) {
-					nla_nest_cancel(msg, nl_freqs);
-					nla_nest_cancel(msg, nl_match);
-					goto out;
-				}
-			}
-
-			nla_nest_end(msg, nl_freqs);
-		}
-
-		nla_nest_end(msg, nl_match);
-	}
-
-out:
-	nla_nest_end(msg, nl_results);
-	return 0;
-}
-
 void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
 				   struct cfg80211_wowlan_wakeup *wakeup,
 				   gfp_t gfp)
@@ -12409,10 +11883,6 @@
 				goto free_msg;
 		}
 
-		if (wakeup->net_detect &&
-		    cfg80211_net_detect_results(msg, wakeup))
-				goto free_msg;
-
 		nla_nest_end(msg, reasons);
 	}
 
diff --git a/net/wireless/ocb.c b/net/wireless/ocb.c
deleted file mode 100644
index c00d4a7..0000000
--- a/net/wireless/ocb.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * OCB mode implementation
- *
- * Copyright: (c) 2014 Czech Technical University in Prague
- *            (c) 2014 Volkswagen Group Research
- * Author:    Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
- * Funded by: Volkswagen Group Research
- *
- * 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/ieee80211.h>
-#include <net/cfg80211.h>
-#include "nl80211.h"
-#include "core.h"
-#include "rdev-ops.h"
-
-int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
-			struct net_device *dev,
-			struct ocb_setup *setup)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	int err;
-
-	ASSERT_WDEV_LOCK(wdev);
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
-		return -EOPNOTSUPP;
-
-	if (WARN_ON(!setup->chandef.chan))
-		return -EINVAL;
-
-	err = rdev_join_ocb(rdev, dev, setup);
-	if (!err)
-		wdev->chandef = setup->chandef;
-
-	return err;
-}
-
-int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
-		      struct net_device *dev,
-		      struct ocb_setup *setup)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	int err;
-
-	wdev_lock(wdev);
-	err = __cfg80211_join_ocb(rdev, dev, setup);
-	wdev_unlock(wdev);
-
-	return err;
-}
-
-int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
-			 struct net_device *dev)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	int err;
-
-	ASSERT_WDEV_LOCK(wdev);
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
-		return -EOPNOTSUPP;
-
-	if (!rdev->ops->leave_ocb)
-		return -EOPNOTSUPP;
-
-	err = rdev_leave_ocb(rdev, dev);
-	if (!err)
-		memset(&wdev->chandef, 0, sizeof(wdev->chandef));
-
-	return err;
-}
-
-int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
-		       struct net_device *dev)
-{
-	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	int err;
-
-	wdev_lock(wdev);
-	err = __cfg80211_leave_ocb(rdev, dev);
-	wdev_unlock(wdev);
-
-	return err;
-}
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 0336264..6a1867f 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -178,12 +178,11 @@
 }
 
 static inline int rdev_del_station(struct cfg80211_registered_device *rdev,
-				   struct net_device *dev,
-				   struct station_del_parameters *params)
+				   struct net_device *dev, u8 *mac)
 {
 	int ret;
-	trace_rdev_del_station(&rdev->wiphy, dev, params);
-	ret = rdev->ops->del_station(&rdev->wiphy, dev, params);
+	trace_rdev_del_station(&rdev->wiphy, dev, mac);
+	ret = rdev->ops->del_station(&rdev->wiphy, dev, mac);
 	trace_rdev_return_int(&rdev->wiphy, ret);
 	return ret;
 }
@@ -264,18 +263,6 @@
 
 }
 
-static inline int rdev_get_mpp(struct cfg80211_registered_device *rdev,
-			       struct net_device *dev, u8 *dst, u8 *mpp,
-			       struct mpath_info *pinfo)
-{
-	int ret;
-
-	trace_rdev_get_mpp(&rdev->wiphy, dev, dst, mpp);
-	ret = rdev->ops->get_mpp(&rdev->wiphy, dev, dst, mpp, pinfo);
-	trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
-	return ret;
-}
-
 static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev,
 				  struct net_device *dev, int idx, u8 *dst,
 				  u8 *next_hop, struct mpath_info *pinfo)
@@ -284,20 +271,7 @@
 	int ret;
 	trace_rdev_dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop);
 	ret = rdev->ops->dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop,
-				    pinfo);
-	trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
-	return ret;
-}
-
-static inline int rdev_dump_mpp(struct cfg80211_registered_device *rdev,
-				struct net_device *dev, int idx, u8 *dst,
-				u8 *mpp, struct mpath_info *pinfo)
-
-{
-	int ret;
-
-	trace_rdev_dump_mpp(&rdev->wiphy, dev, idx, dst, mpp);
-	ret = rdev->ops->dump_mpp(&rdev->wiphy, dev, idx, dst, mpp, pinfo);
+				     pinfo);
 	trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
 	return ret;
 }
@@ -348,27 +322,6 @@
 	return ret;
 }
 
-static inline int rdev_join_ocb(struct cfg80211_registered_device *rdev,
-				struct net_device *dev,
-				struct ocb_setup *setup)
-{
-	int ret;
-	trace_rdev_join_ocb(&rdev->wiphy, dev, setup);
-	ret = rdev->ops->join_ocb(&rdev->wiphy, dev, setup);
-	trace_rdev_return_int(&rdev->wiphy, ret);
-	return ret;
-}
-
-static inline int rdev_leave_ocb(struct cfg80211_registered_device *rdev,
-				 struct net_device *dev)
-{
-	int ret;
-	trace_rdev_leave_ocb(&rdev->wiphy, dev);
-	ret = rdev->ops->leave_ocb(&rdev->wiphy, dev);
-	trace_rdev_return_int(&rdev->wiphy, ret);
-	return ret;
-}
-
 static inline int rdev_change_bss(struct cfg80211_registered_device *rdev,
 				  struct net_device *dev,
 				  struct bss_parameters *params)
@@ -993,28 +946,4 @@
 	return ret;
 }
 
-static inline int
-rdev_tdls_channel_switch(struct cfg80211_registered_device *rdev,
-			 struct net_device *dev, const u8 *addr,
-			 u8 oper_class, struct cfg80211_chan_def *chandef)
-{
-	int ret;
-
-	trace_rdev_tdls_channel_switch(&rdev->wiphy, dev, addr, oper_class,
-				       chandef);
-	ret = rdev->ops->tdls_channel_switch(&rdev->wiphy, dev, addr,
-					     oper_class, chandef);
-	trace_rdev_return_int(&rdev->wiphy, ret);
-	return ret;
-}
-
-static inline void
-rdev_tdls_cancel_channel_switch(struct cfg80211_registered_device *rdev,
-				struct net_device *dev, const u8 *addr)
-{
-	trace_rdev_tdls_cancel_channel_switch(&rdev->wiphy, dev, addr);
-	rdev->ops->tdls_cancel_channel_switch(&rdev->wiphy, dev, addr);
-	trace_rdev_return_void(&rdev->wiphy);
-}
-
 #endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index ec2e3b5..78d0648 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -56,7 +56,6 @@
 #include <net/cfg80211.h>
 #include "core.h"
 #include "reg.h"
-#include "rdev-ops.h"
 #include "regdb.h"
 #include "nl80211.h"
 
@@ -67,12 +66,6 @@
 #define REG_DBG_PRINT(args...)
 #endif
 
-/*
- * Grace period we give before making sure all current interfaces reside on
- * channels allowed by the current regulatory domain.
- */
-#define REG_ENFORCE_GRACE_MS 60000
-
 /**
  * enum reg_request_treatment - regulatory request treatment
  *
@@ -217,9 +210,6 @@
 	struct ieee80211_channel chan;
 };
 
-static void reg_check_chans_work(struct work_struct *work);
-static DECLARE_DELAYED_WORK(reg_check_chans, reg_check_chans_work);
-
 static void reg_todo(struct work_struct *work);
 static DECLARE_WORK(reg_work, reg_todo);
 
@@ -583,9 +573,8 @@
 	return get_cfg80211_regdom();
 }
 
-static unsigned int
-reg_get_max_bandwidth_from_range(const struct ieee80211_regdomain *rd,
-				 const struct ieee80211_reg_rule *rule)
+unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
+				   const struct ieee80211_reg_rule *rule)
 {
 	const struct ieee80211_freq_range *freq_range = &rule->freq_range;
 	const struct ieee80211_freq_range *freq_range_tmp;
@@ -633,27 +622,6 @@
 	return end_freq - start_freq;
 }
 
-unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
-				   const struct ieee80211_reg_rule *rule)
-{
-	unsigned int bw = reg_get_max_bandwidth_from_range(rd, rule);
-
-	if (rule->flags & NL80211_RRF_NO_160MHZ)
-		bw = min_t(unsigned int, bw, MHZ_TO_KHZ(80));
-	if (rule->flags & NL80211_RRF_NO_80MHZ)
-		bw = min_t(unsigned int, bw, MHZ_TO_KHZ(40));
-
-	/*
-	 * HT40+/HT40- limits are handled per-channel. Only limit BW if both
-	 * are not allowed.
-	 */
-	if (rule->flags & NL80211_RRF_NO_HT40MINUS &&
-	    rule->flags & NL80211_RRF_NO_HT40PLUS)
-		bw = min_t(unsigned int, bw, MHZ_TO_KHZ(20));
-
-	return bw;
-}
-
 /* Sanity check on a regulatory rule */
 static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 {
@@ -978,16 +946,6 @@
 		channel_flags |= IEEE80211_CHAN_NO_OFDM;
 	if (rd_flags & NL80211_RRF_NO_OUTDOOR)
 		channel_flags |= IEEE80211_CHAN_INDOOR_ONLY;
-	if (rd_flags & NL80211_RRF_GO_CONCURRENT)
-		channel_flags |= IEEE80211_CHAN_GO_CONCURRENT;
-	if (rd_flags & NL80211_RRF_NO_HT40MINUS)
-		channel_flags |= IEEE80211_CHAN_NO_HT40MINUS;
-	if (rd_flags & NL80211_RRF_NO_HT40PLUS)
-		channel_flags |= IEEE80211_CHAN_NO_HT40PLUS;
-	if (rd_flags & NL80211_RRF_NO_80MHZ)
-		channel_flags |= IEEE80211_CHAN_NO_80MHZ;
-	if (rd_flags & NL80211_RRF_NO_160MHZ)
-		channel_flags |= IEEE80211_CHAN_NO_160MHZ;
 	return channel_flags;
 }
 
@@ -1528,102 +1486,6 @@
 		wiphy->reg_notifier(wiphy, request);
 }
 
-static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
-{
-	struct ieee80211_channel *ch;
-	struct cfg80211_chan_def chandef;
-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
-	bool ret = true;
-
-	wdev_lock(wdev);
-
-	if (!wdev->netdev || !netif_running(wdev->netdev))
-		goto out;
-
-	switch (wdev->iftype) {
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_P2P_GO:
-		if (!wdev->beacon_interval)
-			goto out;
-
-		ret = cfg80211_reg_can_beacon(wiphy,
-					      &wdev->chandef, wdev->iftype);
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		if (!wdev->ssid_len)
-			goto out;
-
-		ret = cfg80211_reg_can_beacon(wiphy,
-					      &wdev->chandef, wdev->iftype);
-		break;
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_P2P_CLIENT:
-		if (!wdev->current_bss ||
-		    !wdev->current_bss->pub.channel)
-			goto out;
-
-		ch = wdev->current_bss->pub.channel;
-		if (rdev->ops->get_channel &&
-		    !rdev_get_channel(rdev, wdev, &chandef))
-			ret = cfg80211_chandef_usable(wiphy, &chandef,
-						      IEEE80211_CHAN_DISABLED);
-		else
-			ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
-		break;
-	case NL80211_IFTYPE_MONITOR:
-	case NL80211_IFTYPE_AP_VLAN:
-	case NL80211_IFTYPE_P2P_DEVICE:
-		/* no enforcement required */
-		break;
-	default:
-		/* others not implemented for now */
-		WARN_ON(1);
-		break;
-	}
-
-out:
-	wdev_unlock(wdev);
-	return ret;
-}
-
-static void reg_leave_invalid_chans(struct wiphy *wiphy)
-{
-	struct wireless_dev *wdev;
-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
-
-	ASSERT_RTNL();
-
-	list_for_each_entry(wdev, &rdev->wdev_list, list)
-		if (!reg_wdev_chan_valid(wiphy, wdev))
-			cfg80211_leave(rdev, wdev);
-}
-
-static void reg_check_chans_work(struct work_struct *work)
-{
-	struct cfg80211_registered_device *rdev;
-
-	REG_DBG_PRINT("Verifying active interfaces after reg change\n");
-	rtnl_lock();
-
-	list_for_each_entry(rdev, &cfg80211_rdev_list, list)
-		if (!(rdev->wiphy.regulatory_flags &
-		      REGULATORY_IGNORE_STALE_KICKOFF))
-			reg_leave_invalid_chans(&rdev->wiphy);
-
-	rtnl_unlock();
-}
-
-static void reg_check_channels(void)
-{
-	/*
-	 * Give usermode a chance to do something nicer (move to another
-	 * channel, orderly disconnection), before forcing a disconnection.
-	 */
-	mod_delayed_work(system_power_efficient_wq,
-			 &reg_check_chans,
-			 msecs_to_jiffies(REG_ENFORCE_GRACE_MS));
-}
-
 static void wiphy_update_regulatory(struct wiphy *wiphy,
 				    enum nl80211_reg_initiator initiator)
 {
@@ -1663,8 +1525,6 @@
 		wiphy = &rdev->wiphy;
 		wiphy_update_regulatory(wiphy, initiator);
 	}
-
-	reg_check_channels();
 }
 
 static void handle_channel_custom(struct wiphy *wiphy,
@@ -1705,23 +1565,10 @@
 	if (max_bandwidth_khz < MHZ_TO_KHZ(160))
 		bw_flags |= IEEE80211_CHAN_NO_160MHZ;
 
-	chan->dfs_state_entered = jiffies;
-	chan->dfs_state = NL80211_DFS_USABLE;
-
-	chan->beacon_found = false;
 	chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
 	chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
 	chan->max_reg_power = chan->max_power =
 		(int) MBM_TO_DBM(power_rule->max_eirp);
-
-	if (chan->flags & IEEE80211_CHAN_RADAR) {
-		if (reg_rule->dfs_cac_ms)
-			chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
-		else
-			chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
-	}
-
-	chan->max_power = chan->max_reg_power;
 }
 
 static void handle_band_custom(struct wiphy *wiphy,
@@ -1913,7 +1760,7 @@
 reg_process_hint_driver(struct wiphy *wiphy,
 			struct regulatory_request *driver_request)
 {
-	const struct ieee80211_regdomain *regd, *tmp;
+	const struct ieee80211_regdomain *regd;
 	enum reg_request_treatment treatment;
 
 	treatment = __reg_process_hint_driver(driver_request);
@@ -1933,10 +1780,7 @@
 			reg_free_request(driver_request);
 			return REG_REQ_IGNORE;
 		}
-
-		tmp = get_wiphy_regdom(wiphy);
 		rcu_assign_pointer(wiphy->regd, regd);
-		rcu_free_regdom(tmp);
 	}
 
 
@@ -1995,8 +1839,11 @@
 			return REG_REQ_IGNORE;
 		return REG_REQ_ALREADY_SET;
 	}
-
-	if (regdom_changes(country_ie_request->alpha2))
+	/*
+	 * Two consecutive Country IE hints on the same wiphy.
+	 * This should be picked up early by the driver/stack
+	 */
+	if (WARN_ON(regdom_changes(country_ie_request->alpha2)))
 		return REG_REQ_OK;
 	return REG_REQ_ALREADY_SET;
 }
@@ -2084,10 +1931,8 @@
 
 	/* This is required so that the orig_* parameters are saved */
 	if (treatment == REG_REQ_ALREADY_SET && wiphy &&
-	    wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
+	    wiphy->regulatory_flags & REGULATORY_STRICT_REG)
 		wiphy_update_regulatory(wiphy, reg_request->initiator);
-		reg_check_channels();
-	}
 
 	return;
 
@@ -2968,7 +2813,6 @@
 
 	cancel_work_sync(&reg_work);
 	cancel_delayed_work_sync(&reg_timeout);
-	cancel_delayed_work_sync(&reg_check_chans);
 
 	/* Lock to suppress warnings */
 	rtnl_lock();
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 969c09f..f365a0c 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -80,18 +80,9 @@
 	if (!request)
 		return -ENOMEM;
 
-	if (wdev->conn->params.channel) {
-		enum ieee80211_band band = wdev->conn->params.channel->band;
-		struct ieee80211_supported_band *sband =
-			wdev->wiphy->bands[band];
-
-		if (!sband) {
-			kfree(request);
-			return -EINVAL;
-		}
+	if (wdev->conn->params.channel)
 		request->channels[0] = wdev->conn->params.channel;
-		request->rates[band] = (1 << sband->n_bitrates) - 1;
-	} else {
+	else {
 		int i = 0, j;
 		enum ieee80211_band band;
 		struct ieee80211_supported_band *bands;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index d9d146d..c9b6b8e 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -600,11 +600,6 @@
 	TP_ARGS(wiphy, netdev)
 );
 
-DEFINE_EVENT(wiphy_netdev_evt, rdev_leave_ocb,
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
-	TP_ARGS(wiphy, netdev)
-);
-
 DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
 	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
 	TP_ARGS(wiphy, netdev)
@@ -685,34 +680,9 @@
 		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac))
 );
 
-DECLARE_EVENT_CLASS(station_del,
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
-		 struct station_del_parameters *params),
-	TP_ARGS(wiphy, netdev, params),
-	TP_STRUCT__entry(
-		WIPHY_ENTRY
-		NETDEV_ENTRY
-		MAC_ENTRY(sta_mac)
-		__field(u8, subtype)
-		__field(u16, reason_code)
-	),
-	TP_fast_assign(
-		WIPHY_ASSIGN;
-		NETDEV_ASSIGN;
-		MAC_ASSIGN(sta_mac, params->mac);
-		__entry->subtype = params->subtype;
-		__entry->reason_code = params->reason_code;
-	),
-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
-		  ", subtype: %u, reason_code: %u",
-		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
-		  __entry->subtype, __entry->reason_code)
-);
-
-DEFINE_EVENT(station_del, rdev_del_station,
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
-		 struct station_del_parameters *params),
-	TP_ARGS(wiphy, netdev, params)
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_del_station,
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+	TP_ARGS(wiphy, netdev, mac)
 );
 
 DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_get_station,
@@ -831,51 +801,6 @@
 		  MAC_PR_ARG(next_hop))
 );
 
-TRACE_EVENT(rdev_get_mpp,
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
-		 u8 *dst, u8 *mpp),
-	TP_ARGS(wiphy, netdev, dst, mpp),
-	TP_STRUCT__entry(
-		WIPHY_ENTRY
-		NETDEV_ENTRY
-		MAC_ENTRY(dst)
-		MAC_ENTRY(mpp)
-	),
-	TP_fast_assign(
-		WIPHY_ASSIGN;
-		NETDEV_ASSIGN;
-		MAC_ASSIGN(dst, dst);
-		MAC_ASSIGN(mpp, mpp);
-	),
-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT
-		  ", mpp: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG,
-		  MAC_PR_ARG(dst), MAC_PR_ARG(mpp))
-);
-
-TRACE_EVENT(rdev_dump_mpp,
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx,
-		 u8 *dst, u8 *mpp),
-	TP_ARGS(wiphy, netdev, idx, mpp, dst),
-	TP_STRUCT__entry(
-		WIPHY_ENTRY
-		NETDEV_ENTRY
-		MAC_ENTRY(dst)
-		MAC_ENTRY(mpp)
-		__field(int, idx)
-	),
-	TP_fast_assign(
-		WIPHY_ASSIGN;
-		NETDEV_ASSIGN;
-		MAC_ASSIGN(dst, dst);
-		MAC_ASSIGN(mpp, mpp);
-		__entry->idx = idx;
-	),
-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: "
-		  MAC_PR_FMT ", mpp: " MAC_PR_FMT,
-		  WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst),
-		  MAC_PR_ARG(mpp))
-);
-
 TRACE_EVENT(rdev_return_int_mpath_info,
 	TP_PROTO(struct wiphy *wiphy, int ret, struct mpath_info *pinfo),
 	TP_ARGS(wiphy, ret, pinfo),
@@ -1321,22 +1246,6 @@
 		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid)
 );
 
-TRACE_EVENT(rdev_join_ocb,
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
-		 const struct ocb_setup *setup),
-	TP_ARGS(wiphy, netdev, setup),
-	TP_STRUCT__entry(
-		WIPHY_ENTRY
-		NETDEV_ENTRY
-	),
-	TP_fast_assign(
-		WIPHY_ASSIGN;
-		NETDEV_ASSIGN;
-	),
-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
-		  WIPHY_PR_ARG, NETDEV_PR_ARG)
-);
-
 TRACE_EVENT(rdev_set_wiphy_params,
 	TP_PROTO(struct wiphy *wiphy, u32 changed),
 	TP_ARGS(wiphy, changed),
@@ -2032,48 +1941,6 @@
 		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tsid)
 );
 
-TRACE_EVENT(rdev_tdls_channel_switch,
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
-		 const u8 *addr, u8 oper_class,
-		 struct cfg80211_chan_def *chandef),
-	TP_ARGS(wiphy, netdev, addr, oper_class, chandef),
-	TP_STRUCT__entry(
-		WIPHY_ENTRY
-		NETDEV_ENTRY
-		MAC_ENTRY(addr)
-		__field(u8, oper_class)
-		CHAN_DEF_ENTRY
-	),
-	TP_fast_assign(
-		WIPHY_ASSIGN;
-		NETDEV_ASSIGN;
-		MAC_ASSIGN(addr, addr);
-		CHAN_DEF_ASSIGN(chandef);
-	),
-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT
-		  " oper class %d, " CHAN_DEF_PR_FMT,
-		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr),
-		  __entry->oper_class, CHAN_DEF_PR_ARG)
-);
-
-TRACE_EVENT(rdev_tdls_cancel_channel_switch,
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
-		 const u8 *addr),
-	TP_ARGS(wiphy, netdev, addr),
-	TP_STRUCT__entry(
-		WIPHY_ENTRY
-		NETDEV_ENTRY
-		MAC_ENTRY(addr)
-	),
-	TP_fast_assign(
-		WIPHY_ASSIGN;
-		NETDEV_ASSIGN;
-		MAC_ASSIGN(addr, addr);
-	),
-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
-		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr))
-);
-
 /*************************************************************
  *	     cfg80211 exported functions traces		     *
  *************************************************************/
@@ -2397,22 +2264,6 @@
 		  NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
 );
 
-TRACE_EVENT(cfg80211_ch_switch_started_notify,
-	TP_PROTO(struct net_device *netdev,
-		 struct cfg80211_chan_def *chandef),
-	TP_ARGS(netdev, chandef),
-	TP_STRUCT__entry(
-		NETDEV_ENTRY
-		CHAN_DEF_ENTRY
-	),
-	TP_fast_assign(
-		NETDEV_ASSIGN;
-		CHAN_DEF_ASSIGN(chandef);
-	),
-	TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT,
-		  NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
-);
-
 TRACE_EVENT(cfg80211_radar_event,
 	TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
 	TP_ARGS(wiphy, chandef),
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 0b5bd58..2a1733a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -442,8 +442,7 @@
 		break;
 	case cpu_to_le16(0):
 		if (iftype != NL80211_IFTYPE_ADHOC &&
-		    iftype != NL80211_IFTYPE_STATION &&
-		    iftype != NL80211_IFTYPE_OCB)
+		    iftype != NL80211_IFTYPE_STATION)
 				return -1;
 		break;
 	}
@@ -520,7 +519,6 @@
 		memcpy(hdr.addr3, skb->data, ETH_ALEN);
 		hdrlen = 24;
 		break;
-	case NL80211_IFTYPE_OCB:
 	case NL80211_IFTYPE_ADHOC:
 		/* DA SA BSSID */
 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -940,7 +938,6 @@
 			if (dev->ieee80211_ptr->use_4addr)
 				break;
 			/* fall through */
-		case NL80211_IFTYPE_OCB:
 		case NL80211_IFTYPE_P2P_CLIENT:
 		case NL80211_IFTYPE_ADHOC:
 			dev->priv_flags |= IFF_DONT_BRIDGE;
diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh
index b46d3fe..1eb42b0 100755
--- a/scripts/uninstall.sh
+++ b/scripts/uninstall.sh
@@ -10,8 +10,8 @@
 	compr=""
 fi
 
-for driver in $(find ${BACKPORT_DIR} -type f -name *.ko); do
-	mod_name=${driver/${BACKPORT_DIR}/${KLIB}${KMODDIR}}${compr}
+for driver in $(find ${BACKPORT_PWD} -type f -name *.ko); do
+	mod_name=${driver/${BACKPORT_PWD}/${KLIB}${KMODDIR}}${compr}
 	echo "  uninstall" $mod_name
 	rm -f $mod_name
 done
diff --git a/versions b/versions
index 012034c..1be7d6d 100644
--- a/versions
+++ b/versions
@@ -1,3 +1,3 @@
-BACKPORTS_VERSION="v3.19-rc1-1-0-g74aaf28"
-BACKPORTED_KERNEL_VERSION="v3.19-rc1-0-g97bf6af"
+BACKPORTS_VERSION="v3.18-rc1-1-0-g1f4af51"
+BACKPORTED_KERNEL_VERSION="v3.18-rc1-0-gf114040"
 BACKPORTED_KERNEL_NAME="Linux"