[linux-next] LinuxNextTracking branch, master, updated. next-20160112

batman at open-mesh.org batman at open-mesh.org
Wed Jan 13 00:15:47 CET 2016


The following commit has been merged in the master branch:
commit 0657c8b31c98792751f9cf2c760b0900952280de
Merge: ebb6757fb4af31609a03ded2924e19331efdd3b8 23c09c2640c1cb9cba919cf4f181ae99a46d53bc
Author: Stephen Rothwell <sfr at canb.auug.org.au>
Date:   Tue Jan 12 13:06:41 2016 +1100

    Merge remote-tracking branch 'net-next/master'

diff --combined MAINTAINERS
index c0bd912,74b84d4..d2b21c6
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@@ -206,7 -206,7 +206,7 @@@ F:	include/trace/events/9p.
  A8293 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -371,6 -371,15 +371,15 @@@ ADDRESS SPACE LAYOUT RANDOMIZATION (ASL
  M:	Jiri Kosina <jikos at kernel.org>
  S:	Maintained
  
+ ADF7242 IEEE 802.15.4 RADIO DRIVER
+ M:	Michael Hennerich <michael.hennerich at analog.com>
+ W:	https://wiki.analog.com/ADF7242
+ W:	http://ez.analog.com/community/linux-device-drivers
+ L:	linux-wpan at vger.kernel.org
+ S:	Supported
+ F:	drivers/net/ieee802154/adf7242.c
+ F:	Documentation/devicetree/bindings/net/ieee802154/adf7242.txt
+ 
  ADM1025 HARDWARE MONITOR DRIVER
  M:	Jean Delvare <jdelvare at suse.com>
  L:	lm-sensors at lm-sensors.org
@@@ -388,14 -397,14 +397,14 @@@ ADM8211 WIRELESS DRIVE
  L:	linux-wireless at vger.kernel.org
  W:	http://wireless.kernel.org/
  S:	Orphan
- F:	drivers/net/wireless/adm8211.*
+ F:	drivers/net/wireless/admtek/adm8211.*
  
  ADP1653 FLASH CONTROLLER DRIVER
  M:	Sakari Ailus <sakari.ailus at iki.fi>
  L:	linux-media at vger.kernel.org
  S:	Maintained
  F:	drivers/media/i2c/adp1653.c
 -F:	include/media/adp1653.h
 +F:	include/media/i2c/adp1653.h
  
  ADP5520 BACKLIGHT DRIVER WITH IO EXPANDER (ADP5520/ADP5501)
  M:	Michael Hennerich <michael.hennerich at analog.com>
@@@ -466,7 -475,7 +475,7 @@@ F:	sound/oss/aedsp16.
  AF9013 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -476,7 -485,7 +485,7 @@@ F:	drivers/media/dvb-frontends/af9013
  AF9033 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -522,7 -531,7 +531,7 @@@ AIMSLAB FM RADIO RECEIVER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/radio-aimslab*
  
@@@ -536,7 -545,7 +545,7 @@@ F:	include/linux/*aio*.
  AIRSPY MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -614,9 -623,9 +623,9 @@@ F:	drivers/crypto/ccp
  F:	include/linux/ccp.h
  
  AMD FAM15H PROCESSOR POWER MONITORING DRIVER
 -M:	Andreas Herrmann <herrmann.der.user at googlemail.com>
 +M:	Huang Rui <ray.huang at amd.com>
  L:	lm-sensors at lm-sensors.org
 -S:	Maintained
 +S:	Supported
  F:	Documentation/hwmon/fam15h_power
  F:	drivers/hwmon/fam15h_power.c
  
@@@ -1400,13 -1409,12 +1409,13 @@@ W:	http://www.arm.linux.org.uk
  S:	Maintained
  
  ARM/QUALCOMM SUPPORT
 -M:	Kumar Gala <galak at codeaurora.org>
 -M:	Andy Gross <agross at codeaurora.org>
 -M:	David Brown <davidb at codeaurora.org>
 +M:	Andy Gross <andy.gross at linaro.org>
 +M:	David Brown <david.brown at linaro.org>
  L:	linux-arm-msm at vger.kernel.org
  L:	linux-soc at vger.kernel.org
  S:	Maintained
 +F:	arch/arm/boot/dts/qcom-*.dts
 +F:	arch/arm/boot/dts/qcom-*.dtsi
  F:	arch/arm/mach-qcom/
  F:	drivers/soc/qcom/
  F:	drivers/tty/serial/msm_serial.h
@@@ -1414,22 -1422,13 +1423,22 @@@ F:	drivers/tty/serial/msm_serial.
  F:	drivers/*/pm8???-*
  F:	drivers/mfd/ssbi.c
  F:	drivers/firmware/qcom_scm.c
 -T:	git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
 +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git
  
  ARM/RADISYS ENP2611 MACHINE SUPPORT
  M:	Lennert Buytenhek <kernel at wantstofly.org>
  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
  S:	Maintained
  
 +ARM/RENESAS ARM64 ARCHITECTURE
 +M:	Simon Horman <horms at verge.net.au>
 +M:	Magnus Damm <magnus.damm at gmail.com>
 +L:	linux-sh at vger.kernel.org
 +Q:	http://patchwork.kernel.org/project/linux-sh/list/
 +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
 +S:	Supported
 +F:	arch/arm64/boot/dts/renesas/
 +
  ARM/RISCPC ARCHITECTURE
  M:	Russell King <linux at arm.linux.org.uk>
  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
@@@ -1527,6 -1526,7 +1536,6 @@@ ARM/SHMOBILE ARM ARCHITECTUR
  M:	Simon Horman <horms at verge.net.au>
  M:	Magnus Damm <magnus.damm at gmail.com>
  L:	linux-sh at vger.kernel.org
 -W:	http://oss.renesas.com
  Q:	http://patchwork.kernel.org/project/linux-sh/list/
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
  S:	Supported
@@@ -1597,13 -1597,6 +1606,13 @@@ T:	git git://git.kernel.org/pub/scm/lin
  N:	stm32
  F:	drivers/clocksource/armv7m_systick.c
  
 +ARM/TANGO ARCHITECTURE
 +M:	Marc Gonzalez <marc_gonzalez at sigmadesigns.com>
 +L:	linux-arm-kernel at lists.infradead.org
 +S:	Maintained
 +F:	arch/arm/mach-tango/
 +F:	arch/arm/boot/dts/tango*
 +
  ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
  M:	Lennert Buytenhek <kernel at wantstofly.org>
  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
@@@ -1658,8 -1651,6 +1667,8 @@@ F:	arch/arm/boot/dts/uniphier
  F:	arch/arm/include/asm/hardware/cache-uniphier.h
  F:	arch/arm/mach-uniphier/
  F:	arch/arm/mm/cache-uniphier.c
 +F:	arch/arm64/boot/dts/socionext/
 +F:	drivers/bus/uniphier-system-bus.c
  F:	drivers/i2c/busses/i2c-uniphier*
  F:	drivers/pinctrl/uniphier/
  F:	drivers/tty/serial/8250/8250_uniphier.c
@@@ -1791,7 -1782,7 +1800,7 @@@ L:	linux-media at vger.kernel.or
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
  F:	drivers/media/i2c/as3645a.c
 -F:	include/media/as3645a.h
 +F:	include/media/i2c/as3645a.h
  
  ASC7621 HARDWARE MONITOR DRIVER
  M:	George Joseph <george.joseph at fairview5.com>
@@@ -2011,7 -2002,7 +2020,7 @@@ L:	linux-wireless at vger.kernel.or
  W:	http://www.thekelleys.org.uk/atmel
  W:	http://atmelwlandriver.sourceforge.net/
  S:	Maintained
- F:	drivers/net/wireless/atmel*
+ F:	drivers/net/wireless/atmel/atmel*
  
  ATMEL MAXTOUCH DRIVER
  M:	Nick Dyer <nick.dyer at itdev.co.uk>
@@@ -2082,7 -2073,7 +2091,7 @@@ F:	net/ax25
  AZ6007 DVB DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
  F:	drivers/media/usb/dvb-usb-v2/az6007.c
@@@ -2091,7 -2082,7 +2100,7 @@@ AZTECH FM RADIO RECEIVER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/radio-aztech*
  
@@@ -2100,7 -2091,7 +2109,7 @@@ L:	linux-wireless at vger.kernel.or
  L:	b43-dev at lists.infradead.org
  W:	http://wireless.kernel.org/en/users/Drivers/b43
  S:	Odd Fixes
- F:	drivers/net/wireless/b43/
+ F:	drivers/net/wireless/broadcom/b43/
  
  B43LEGACY WIRELESS DRIVER
  M:	Larry Finger <Larry.Finger at lwfinger.net>
@@@ -2108,7 -2099,7 +2117,7 @@@ L:	linux-wireless at vger.kernel.or
  L:	b43-dev at lists.infradead.org
  W:	http://wireless.kernel.org/en/users/Drivers/b43
  S:	Maintained
- F:	drivers/net/wireless/b43legacy/
+ F:	drivers/net/wireless/broadcom/b43legacy/
  
  BACKLIGHT CLASS/SUBSYSTEM
  M:	Jingoo Han <jingoohan1 at gmail.com>
@@@ -2120,7 -2111,7 +2129,7 @@@ F:	include/linux/backlight.
  BATMAN ADVANCED
  M:	Marek Lindner <mareklindner at neomailbox.ch>
  M:	Simon Wunderlich <sw at simonwunderlich.de>
- M:	Antonio Quartulli <antonio at meshcoding.com>
+ M:	Antonio Quartulli <a at unstable.cc>
  L:	b.a.t.m.a.n at lists.open-mesh.org
  W:	http://www.open-mesh.org/
  S:	Maintained
@@@ -2144,7 -2135,7 +2153,7 @@@ BDISP ST MEDIA DRIVE
  M:	Fabien Dessenne <fabien.dessenne at st.com>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Supported
  F:	drivers/media/platform/sti/bdisp
  
@@@ -2375,7 -2366,6 +2384,7 @@@ M:	Brian Norris <computersforpeace at gmai
  M:	Gregory Fong <gregory.0xf0 at gmail.com>
  M:	Florian Fainelli <f.fainelli at gmail.com>
  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 +L:	bcm-kernel-feedback-list at broadcom.com
  T:	git git://github.com/broadcom/stblinux.git
  S:	Maintained
  F:	arch/arm/mach-bcm/*brcmstb*
@@@ -2411,7 -2401,7 +2420,7 @@@ M:	Hante Meuleman <meuleman at broadcom.co
  L:	linux-wireless at vger.kernel.org
  L:	brcm80211-dev-list at broadcom.com
  S:	Supported
- F:	drivers/net/wireless/brcm80211/
+ F:	drivers/net/wireless/broadcom/brcm80211/
  
  BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
  M:	QLogic-Storage-Upstream at qlogic.com
@@@ -2449,7 -2439,7 +2458,7 @@@ N:	bcm8831
  
  BROADCOM BRCMSTB GPIO DRIVER
  M:	Gregory Fong <gregory.0xf0 at gmail.com>
 -L:	bcm-kernel-feedback-list at broadcom.com>
 +L:	bcm-kernel-feedback-list at broadcom.com
  S:	Supported
  F:	drivers/gpio/gpio-brcmstb.c
  F:	Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
@@@ -2538,7 -2528,7 +2547,7 @@@ F:	fs/btrfs
  BTTV VIDEO4LINUX DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Odd fixes
  F:	Documentation/video4linux/bttv/
@@@ -2577,7 -2567,7 +2586,7 @@@ CADET FM/AM RADIO RECEIVER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/radio-cadet*
  
@@@ -2870,7 -2860,7 +2879,7 @@@ COBALT MEDIA DRIVE
  M:	Hans Verkuil <hans.verkuil at cisco.com>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Supported
  F:	drivers/media/pci/cobalt/
  
@@@ -2958,8 -2948,7 +2967,8 @@@ F:	drivers/usb/atm/cxacru.
  
  CONFIGFS
  M:	Joel Becker <jlbec at evilplan.org>
 -T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/configfs.git
 +M:	Christoph Hellwig <hch at lst.de>
 +T:	git git://git.infradead.org/users/hch/configfs.git
  S:	Supported
  F:	fs/configfs/
  F:	include/linux/configfs.h
@@@ -3116,15 -3105,6 +3125,15 @@@ S:	Maintaine
  F:	crypto/ansi_cprng.c
  F:	crypto/rng.c
  
 +CS3308 MEDIA DRIVER
 +M:	Hans Verkuil <hverkuil at xs4all.nl>
 +L:	linux-media at vger.kernel.org
 +T:	git git://linuxtv.org/media_tree.git
 +W:	http://linuxtv.org
 +S:	Odd Fixes
 +F:	drivers/media/i2c/cs3308.c
 +F:	drivers/media/i2c/cs3308.h
 +
  CS5535 Audio ALSA driver
  M:	Jaya Kumar <jayakumar.alsa at gmail.com>
  S:	Maintained
@@@ -3133,14 -3113,14 +3142,14 @@@ F:	sound/pci/cs5535audio
  CW1200 WLAN driver
  M:	Solomon Peachy <pizza at shaftnet.org>
  S:	Maintained
- F:	drivers/net/wireless/cw1200/
+ F:	drivers/net/wireless/st/cw1200/
  
  CX18 VIDEO4LINUX DRIVER
  M:	Andy Walls <awalls at md.metrocast.net>
  L:	ivtv-devel at ivtvdriver.org (subscribers-only)
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  W:	http://www.ivtvdriver.org/index.php/Cx18
  S:	Maintained
  F:	Documentation/video4linux/cx18.txt
@@@ -3151,7 -3131,7 +3160,7 @@@ CX2341X MPEG ENCODER HELPER MODUL
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/common/cx2341x*
  F:	include/media/cx2341x*
@@@ -3160,7 -3140,7 +3169,7 @@@ CX24120 MEDIA DRIVE
  M:	Jemma Denson <jdenson at gmail.com>
  M:	Patrick Boettcher <patrick.boettcher at posteo.de>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  S:	Maintained
  F:	drivers/media/dvb-frontends/cx24120*
@@@ -3168,7 -3148,7 +3177,7 @@@
  CX88 VIDEO4LINUX DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Odd fixes
  F:	Documentation/video4linux/cx88/
@@@ -3177,7 -3157,7 +3186,7 @@@ F:	drivers/media/pci/cx88
  CXD2820R MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3283,7 -3263,7 +3292,7 @@@ F:	drivers/net/wan/pc300
  CYPRESS_FIRMWARE MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3790,14 -3770,14 +3799,14 @@@ DT3155 MEDIA DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/pci/dt3155/
  
  DVB_USB_AF9015 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3807,7 -3787,7 +3816,7 @@@ F:	drivers/media/usb/dvb-usb-v2/af9015
  DVB_USB_AF9035 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3817,7 -3797,7 +3826,7 @@@ F:	drivers/media/usb/dvb-usb-v2/af9035
  DVB_USB_ANYSEE MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3827,7 -3807,7 +3836,7 @@@ F:	drivers/media/usb/dvb-usb-v2/anysee
  DVB_USB_AU6610 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3837,7 -3817,7 +3846,7 @@@ F:	drivers/media/usb/dvb-usb-v2/au6610
  DVB_USB_CE6230 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3847,7 -3827,7 +3856,7 @@@ F:	drivers/media/usb/dvb-usb-v2/ce6230
  DVB_USB_CXUSB MEDIA DRIVER
  M:	Michael Krufky <mkrufky at linuxtv.org>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://github.com/mkrufky
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/media_tree.git
@@@ -3857,7 -3837,7 +3866,7 @@@ F:	drivers/media/usb/dvb-usb/cxusb
  DVB_USB_EC168 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3867,7 -3847,7 +3876,7 @@@ F:	drivers/media/usb/dvb-usb-v2/ec168
  DVB_USB_GL861 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/anttip/media_tree.git
  S:	Maintained
@@@ -3876,7 -3856,7 +3885,7 @@@ F:	drivers/media/usb/dvb-usb-v2/gl861
  DVB_USB_MXL111SF MEDIA DRIVER
  M:	Michael Krufky <mkrufky at linuxtv.org>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://github.com/mkrufky
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mkrufky/mxl111sf.git
@@@ -3886,7 -3866,7 +3895,7 @@@ F:	drivers/media/usb/dvb-usb-v2/mxl111s
  DVB_USB_RTL28XXU MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3896,7 -3876,7 +3905,7 @@@ F:	drivers/media/usb/dvb-usb-v2/rtl28xx
  DVB_USB_V2 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3926,7 -3906,7 +3935,7 @@@ F:	Documentation/devicetree/bindings/in
  E4000 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -3942,7 -3922,7 +3951,7 @@@ F:	drivers/scsi/eata.
  EC100 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -4166,7 -4146,7 +4175,7 @@@ F:	drivers/net/ethernet/ibm/ehea
  EM28XX VIDEO4LINUX DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
  F:	drivers/media/usb/em28xx/
@@@ -4306,7 -4286,7 +4315,7 @@@ F:	drivers/media/tuners/fc0011.
  FC2580 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -4520,9 -4500,8 +4529,9 @@@ F:	include/linux/fs_enet_pd.
  FREESCALE QUICC ENGINE LIBRARY
  L:	linuxppc-dev at lists.ozlabs.org
  S:	Orphan
 -F:	arch/powerpc/sysdev/qe_lib/
 -F:	arch/powerpc/include/asm/*qe.h
 +F:	drivers/soc/fsl/qe/
 +F:	include/soc/fsl/*qe*.h
 +F:	include/soc/fsl/*ucc*.h
  
  FREESCALE USB PERIPHERAL DRIVERS
  M:	Li Yang <leoli at freescale.com>
@@@ -4630,7 -4609,7 +4639,7 @@@ M:	Heungjun Kim <riverful.kim at samsung.c
  L:	linux-media at vger.kernel.org
  S:	Maintained
  F:	drivers/media/i2c/m5mols/
 -F:	include/media/m5mols.h
 +F:	include/media/i2c/m5mols.h
  
  FUJITSU TABLET EXTRAS
  M:	Robert Gerlach <khnz at gmx.de>
@@@ -4676,7 -4655,7 +4685,7 @@@ GEMTEK FM RADIO RECEIVER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/radio-gemtek*
  
@@@ -4884,7 -4863,7 +4893,7 @@@ HDPVR USB VIDEO ENCODER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/usb/hdpvr/
  
@@@ -4903,7 -4882,7 +4912,7 @@@ F:	drivers/tty/hvc
  HACKRF MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -4946,7 -4925,7 +4955,7 @@@ F:	sound/parisc/harmony.
  HD29L2 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -5015,7 -4994,6 +5024,7 @@@ F:	arch/*/include/asm/suspend*.
  
  HID CORE LAYER
  M:	Jiri Kosina <jikos at kernel.org>
 +R:	Benjamin Tissoires <benjamin.tissoires at redhat.com>
  L:	linux-input at vger.kernel.org
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
  S:	Maintained
@@@ -5076,7 -5054,7 +5085,7 @@@ L:	hostap at shmoo.com (subscribers-only
  L:	linux-wireless at vger.kernel.org
  W:	http://hostap.epitest.fi/
  S:	Maintained
- F:	drivers/net/wireless/hostap/
+ F:	drivers/net/wireless/intersil/hostap/
  
  HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
  L:	platform-driver-x86 at vger.kernel.org
@@@ -5314,6 -5292,13 +5323,13 @@@ L:	netdev at vger.kernel.or
  S:	Supported
  F:	drivers/net/ethernet/ibm/ibmveth.*
  
+ IBM Power SRIOV Virtual NIC Device Driver
+ M:	Thomas Falcon <tlfalcon at linux.vnet.ibm.com>
+ M:	John Allen <jallen at linux.vnet.ibm.com>
+ L:	netdev at vger.kernel.org
+ S:	Supported
+ F:	drivers/net/ethernet/ibm/ibmvnic.*
+ 
  IBM Power Virtual SCSI Device Drivers
  M:	Tyrel Datwyler <tyreld at linux.vnet.ibm.com>
  L:	linux-scsi at vger.kernel.org
@@@ -5644,7 -5629,7 +5660,7 @@@ L:	linux-wireless at vger.kernel.or
  S:	Maintained
  F:	Documentation/networking/README.ipw2100
  F:	Documentation/networking/README.ipw2200
- F:	drivers/net/wireless/ipw2x00/
+ F:	drivers/net/wireless/intel/ipw2x00/
  
  INTEL(R) TRACE HUB
  M:	Alexander Shishkin <alexander.shishkin at linux.intel.com>
@@@ -5678,7 -5663,7 +5694,7 @@@ INTEL WIRELESS 3945ABG/BG, 4965AGN (iwl
  M:	Stanislaw Gruszka <sgruszka at redhat.com>
  L:	linux-wireless at vger.kernel.org
  S:	Supported
- F:	drivers/net/wireless/iwlegacy/
+ F:	drivers/net/wireless/intel/iwlegacy/
  
  INTEL WIRELESS WIFI LINK (iwlwifi)
  M:	Johannes Berg <johannes.berg at intel.com>
@@@ -5688,7 -5673,7 +5704,7 @@@ L:	linux-wireless at vger.kernel.or
  W:	http://intellinuxwireless.org
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
  S:	Supported
- F:	drivers/net/wireless/iwlwifi/
+ F:	drivers/net/wireless/intel/iwlwifi/
  
  INTEL MANAGEMENT ENGINE (mei)
  M:	Tomas Winkler <tomas.winkler at intel.com>
@@@ -5853,7 -5838,7 +5869,7 @@@ ISA RADIO MODUL
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/radio-isa*
  
@@@ -5923,7 -5908,7 +5939,7 @@@ F:	drivers/hwmon/it87.
  IT913X MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -5944,7 -5929,7 +5960,7 @@@ F:	include/uapi/linux/ivtv
  IX2505V MEDIA DRIVER
  M:	Malcolm Priestley <tvboxspy at gmail.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  S:	Maintained
  F:	drivers/media/dvb-frontends/ix2505v*
@@@ -6033,7 -6018,7 +6049,7 @@@ KEENE FM RADIO TRANSMITTER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/radio-keene*
  
@@@ -6246,12 -6231,6 +6262,12 @@@ S:	Maintaine
  F:	net/l3mdev
  F:	include/net/l3mdev.h
  
 +LANTIQ MIPS ARCHITECTURE
 +M:	John Crispin <blogic at openwrt.org>
 +L:	linux-mips at linux-mips.org
 +S:	Maintained
 +F:	arch/mips/lantiq
 +
  LAPB module
  L:	linux-x25 at vger.kernel.org
  S:	Orphan
@@@ -6291,7 -6270,7 +6307,7 @@@ F:	drivers/usb/misc/legousbtower.
  LG2160 MEDIA DRIVER
  M:	Michael Krufky <mkrufky at linuxtv.org>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://github.com/mkrufky
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mkrufky/tuners.git
@@@ -6301,7 -6280,7 +6317,7 @@@ F:	drivers/media/dvb-frontends/lg2160.
  LGDT3305 MEDIA DRIVER
  M:	Michael Krufky <mkrufky at linuxtv.org>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://github.com/mkrufky
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mkrufky/tuners.git
@@@ -6468,7 -6447,7 +6484,7 @@@ S:	Maintaine
  F:	arch/powerpc/platforms/8xx/
  
  LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
 -M:	Scott Wood <scottwood at freescale.com>
 +M:	Scott Wood <oss at buserror.net>
  M:	Kumar Gala <galak at kernel.crashing.org>
  W:	http://www.penguinppc.org/
  L:	linuxppc-dev at lists.ozlabs.org
@@@ -6558,7 -6537,7 +6574,7 @@@ F:	drivers/hwmon/lm95234.
  LME2510 MEDIA DRIVER
  M:	Malcolm Priestley <tvboxspy at gmail.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  S:	Maintained
  F:	drivers/media/usb/dvb-usb-v2/lmedm04*
@@@ -6664,7 -6643,7 +6680,7 @@@ F:	arch/m68k/hp300
  M88DS3103 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -6674,7 -6653,7 +6690,7 @@@ F:	drivers/media/dvb-frontends/m88ds310
  M88RS2000 MEDIA DRIVER
  M:	Malcolm Priestley <tvboxspy at gmail.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  S:	Maintained
  F:	drivers/media/dvb-frontends/m88rs2000*
@@@ -6745,7 -6724,7 +6761,7 @@@ F:	drivers/net/ethernet/marvell/sk
  MARVELL LIBERTAS WIRELESS DRIVER
  L:	libertas-dev at lists.infradead.org
  S:	Orphan
- F:	drivers/net/wireless/libertas/
+ F:	drivers/net/wireless/marvell/libertas/
  
  MARVELL MV643XX ETHERNET DRIVER
  M:	Sebastian Hesselbarth <sebastian.hesselbarth at gmail.com>
@@@ -6765,13 -6744,13 +6781,13 @@@ M:	Amitkumar Karwar <akarwar at marvell.co
  M:	Nishant Sarmukadam <nishants at marvell.com>
  L:	linux-wireless at vger.kernel.org
  S:	Maintained
- F:	drivers/net/wireless/mwifiex/
+ F:	drivers/net/wireless/marvell/mwifiex/
  
  MARVELL MWL8K WIRELESS DRIVER
  M:	Lennert Buytenhek <buytenh at wantstofly.org>
  L:	linux-wireless at vger.kernel.org
  S:	Odd Fixes
- F:	drivers/net/wireless/mwl8k.c
+ F:	drivers/net/wireless/marvell/mwl8k.c
  
  MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
  M:	Nicolas Pitre <nico at fluxnic.net>
@@@ -6853,7 -6832,7 +6869,7 @@@ MAXIRADIO FM RADIO RECEIVER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/radio-maxiradio*
  
@@@ -6875,7 -6854,7 +6891,7 @@@ F:	drivers/media/platform/vsp1
  MEDIA DRIVERS FOR ASCOT2E
  M:	Sergey Kozlov <serjk at netup.ru>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  W:	http://netup.tv/
  T:	git git://linuxtv.org/media_tree.git
  S:	Supported
@@@ -6884,7 -6863,7 +6900,7 @@@ F:	drivers/media/dvb-frontends/ascot2e
  MEDIA DRIVERS FOR CXD2841ER
  M:	Sergey Kozlov <serjk at netup.ru>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://netup.tv/
  T:	git git://linuxtv.org/media_tree.git
  S:	Supported
@@@ -6893,7 -6872,7 +6909,7 @@@ F:	drivers/media/dvb-frontends/cxd2841e
  MEDIA DRIVERS FOR HORUS3A
  M:	Sergey Kozlov <serjk at netup.ru>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://netup.tv/
  T:	git git://linuxtv.org/media_tree.git
  S:	Supported
@@@ -6902,7 -6881,7 +6918,7 @@@ F:	drivers/media/dvb-frontends/horus3a
  MEDIA DRIVERS FOR LNBH25
  M:	Sergey Kozlov <serjk at netup.ru>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://netup.tv/
  T:	git git://linuxtv.org/media_tree.git
  S:	Supported
@@@ -6911,7 -6890,7 +6927,7 @@@ F:	drivers/media/dvb-frontends/lnbh25
  MEDIA DRIVERS FOR NETUP PCI UNIVERSAL DVB devices
  M:	Sergey Kozlov <serjk at netup.ru>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://netup.tv/
  T:	git git://linuxtv.org/media_tree.git
  S:	Supported
@@@ -6921,7 -6900,7 +6937,7 @@@ MEDIA INPUT INFRASTRUCTURE (V4L/DVB
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  P:	LinuxTV.org Project
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  Q:	http://patchwork.kernel.org/project/linux-media/list/
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
@@@ -6930,7 -6909,6 +6946,7 @@@ F:	Documentation/video4linux
  F:	Documentation/DocBook/media/
  F:	drivers/media/
  F:	drivers/staging/media/
 +F:	include/linux/platform_data/media/
  F:	include/media/
  F:	include/uapi/linux/dvb/
  F:	include/uapi/linux/videodev2.h
@@@ -7082,7 -7060,7 +7098,7 @@@ MIROSOUND PCM20 FM RADIO RECEIVER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/radio/radio-miropcm20*
  
@@@ -7118,7 -7096,7 +7134,7 @@@ F:	drivers/iio/temperature/mlx90614.
  MN88472 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -7129,7 -7107,7 +7145,7 @@@ F:	drivers/media/dvb-frontends/mn88472.
  MN88473 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -7184,7 -7162,7 +7200,7 @@@ F:	drivers/platform/x86/msi-wmi.
  MSI001 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -7194,7 -7172,7 +7210,7 @@@ F:	drivers/media/tuners/msi001
  MSI2500 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -7213,7 -7191,7 +7229,7 @@@ L:	linux-media at vger.kernel.or
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
  F:	drivers/media/i2c/mt9m032.c
 -F:	include/media/mt9m032.h
 +F:	include/media/i2c/mt9m032.h
  
  MT9P031 APTINA CAMERA SENSOR
  M:	Laurent Pinchart <laurent.pinchart at ideasonboard.com>
@@@ -7221,7 -7199,7 +7237,7 @@@ L:	linux-media at vger.kernel.or
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
  F:	drivers/media/i2c/mt9p031.c
 -F:	include/media/mt9p031.h
 +F:	include/media/i2c/mt9p031.h
  
  MT9T001 APTINA CAMERA SENSOR
  M:	Laurent Pinchart <laurent.pinchart at ideasonboard.com>
@@@ -7229,7 -7207,7 +7245,7 @@@ L:	linux-media at vger.kernel.or
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
  F:	drivers/media/i2c/mt9t001.c
 -F:	include/media/mt9t001.h
 +F:	include/media/i2c/mt9t001.h
  
  MT9V032 APTINA CAMERA SENSOR
  M:	Laurent Pinchart <laurent.pinchart at ideasonboard.com>
@@@ -7238,7 -7216,7 +7254,7 @@@ T:	git git://linuxtv.org/media_tree.gi
  S:	Maintained
  F:	Documentation/devicetree/bindings/media/i2c/mt9v032.txt
  F:	drivers/media/i2c/mt9v032.c
 -F:	include/media/mt9v032.h
 +F:	include/media/i2c/mt9v032.h
  
  MULTIFUNCTION DEVICES (MFD)
  M:	Lee Jones <lee.jones at linaro.org>
@@@ -7282,7 -7260,7 +7298,7 @@@ F:	drivers/usb/musb
  MXL5007T MEDIA DRIVER
  M:	Michael Krufky <mkrufky at linuxtv.org>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://github.com/mkrufky
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mkrufky/tuners.git
@@@ -7407,6 -7385,13 +7423,13 @@@ F:	include/net/netrom.
  F:	include/uapi/linux/netrom.h
  F:	net/netrom/
  
+ NETRONOME ETHERNET DRIVERS
+ M:	Jakub Kicinski <jakub.kicinski at netronome.com>
+ M:	Rolf Neugebauer <rolf.neugebauer at netronome.com>
+ L:	oss-drivers at netronome.com
+ S:	Maintained
+ F:	drivers/net/ethernet/netronome/
+ 
  NETWORK BLOCK DEVICE (NBD)
  M:	Markus Pargmann <mpa at pengutronix.de>
  S:	Maintained
@@@ -7538,7 -7523,12 +7561,12 @@@ F:	net/nfc
  F:	include/net/nfc/
  F:	include/uapi/linux/nfc.h
  F:	drivers/nfc/
+ F:	include/linux/platform_data/microread.h
+ F:	include/linux/platform_data/nfcmrvl.h
+ F:	include/linux/platform_data/nxp-nci.h
  F:	include/linux/platform_data/pn544.h
+ F:	include/linux/platform_data/st21nfca.h
+ F:	include/linux/platform_data/st-nci.h
  F:	Documentation/devicetree/bindings/net/nfc/
  
  NFS, SUNRPC, AND LOCKD CLIENTS
@@@ -7988,7 -7978,7 +8016,7 @@@ L:	linux-wireless at vger.kernel.or
  W:	http://wireless.kernel.org/en/users/Drivers/orinoco
  W:	http://www.nongnu.org/orinoco/
  S:	Orphan
- F:	drivers/net/wireless/orinoco/
+ F:	drivers/net/wireless/intersil/orinoco/
  
  OSD LIBRARY and FILESYSTEM
  M:	Boaz Harrosh <ooo at electrozaur.com>
@@@ -8014,7 -8004,7 +8042,7 @@@ M:	Christian Lamparter <chunkeey at google
  L:	linux-wireless at vger.kernel.org
  W:	http://wireless.kernel.org/en/users/Drivers/p54
  S:	Maintained
- F:	drivers/net/wireless/p54/
+ F:	drivers/net/wireless/intersil/p54/
  
  PA SEMI ETHERNET DRIVER
  M:	Olof Johansson <olof at lixom.net>
@@@ -8281,19 -8271,11 +8309,19 @@@ F:	drivers/pci/host/pci-xgene-msi.
  
  PCIE DRIVER FOR HISILICON
  M:	Zhou Wang <wangzhou1 at hisilicon.com>
 +M:	Gabriele Paoloni <gabriele.paoloni at huawei.com>
  L:	linux-pci at vger.kernel.org
  S:	Maintained
  F:	Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
  F:	drivers/pci/host/pcie-hisi.c
  
 +PCIE DRIVER FOR QUALCOMM MSM
 +M:     Stanimir Varbanov <svarbanov at mm-sol.com>
 +L:     linux-pci at vger.kernel.org
 +L:     linux-arm-msm at vger.kernel.org
 +S:     Maintained
 +F:     drivers/pci/host/*qcom*
 +
  PCMCIA SUBSYSTEM
  P:	Linux PCMCIA Team
  L:	linux-pcmcia at lists.infradead.org
@@@ -8493,17 -8475,6 +8521,17 @@@ F:	fs/timerfd.
  F:	include/linux/timer*
  F:	kernel/time/*timer*
  
 +POWER MANAGEMENT CORE
 +M:	"Rafael J. Wysocki" <rjw at rjwysocki.net>
 +L:	linux-pm at vger.kernel.org
 +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 +S:	Supported
 +F:	drivers/base/power/
 +F:	include/linux/pm.h
 +F:	include/linux/pm_*
 +F:	include/linux/powercap.h
 +F:	drivers/powercap/
 +
  POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
  M:	Sebastian Reichel <sre at kernel.org>
  M:	Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
@@@ -8583,7 -8554,7 +8611,7 @@@ M:	"Luis R. Rodriguez" <mcgrof at gmail.co
  L:	linux-wireless at vger.kernel.org
  W:	http://wireless.kernel.org/en/users/Drivers/p54
  S:	Obsolete
- F:	drivers/net/wireless/prism54/
+ F:	drivers/net/wireless/intersil/prism54/
  
  PS3 NETWORK SUPPORT
  M:	Geoff Levand <geoff at infradead.org>
@@@ -8802,7 -8773,7 +8830,7 @@@ F:	include/uapi/linux/qnxtypes.
  QT1010 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -8880,19 -8851,13 +8908,19 @@@ L:	linux-fbdev at vger.kernel.or
  S:	Maintained
  F:	drivers/video/fbdev/aty/aty128fb.c
  
 +RALINK MIPS ARCHITECTURE
 +M:	John Crispin <blogic at openwrt.org>
 +L:	linux-mips at linux-mips.org
 +S:	Maintained
 +F:	arch/mips/ralink
 +
  RALINK RT2X00 WIRELESS LAN DRIVER
  P:	rt2x00 project
  M:	Stanislaw Gruszka <sgruszka at redhat.com>
  M:	Helmut Schaa <helmut.schaa at googlemail.com>
  L:	linux-wireless at vger.kernel.org
  S:	Maintained
- F:	drivers/net/wireless/rt2x00/
+ F:	drivers/net/wireless/ralink/rt2x00/
  
  RAMDISK RAM BLOCK DEVICE DRIVER
  M:	Jens Axboe <axboe at kernel.dk>
@@@ -9101,7 -9066,7 +9129,7 @@@ F:	net/rose
  RTL2830 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -9111,7 -9076,7 +9139,7 @@@ F:	drivers/media/dvb-frontends/rtl2830
  RTL2832 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -9121,7 -9086,7 +9149,7 @@@ F:	drivers/media/dvb-frontends/rtl2832
  RTL2832_SDR MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -9133,7 -9098,7 +9161,7 @@@ L:	linux-wireless at vger.kernel.or
  W:	http://wireless.kernel.org/
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:	Orphan
- F:	drivers/net/wireless/rtl818x/rtl8180/
+ F:	drivers/net/wireless/realtek/rtl818x/rtl8180/
  
  RTL8187 WIRELESS DRIVER
  M:	Herton Ronaldo Krzesinski <herton at canonical.com>
@@@ -9143,7 -9108,7 +9171,7 @@@ L:	linux-wireless at vger.kernel.or
  W:	http://wireless.kernel.org/
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:	Maintained
- F:	drivers/net/wireless/rtl818x/rtl8187/
+ F:	drivers/net/wireless/realtek/rtl818x/rtl8187/
  
  RTL8192CE WIRELESS DRIVER
  M:	Larry Finger <Larry.Finger at lwfinger.net>
@@@ -9152,8 -9117,8 +9180,8 @@@ L:	linux-wireless at vger.kernel.or
  W:	http://wireless.kernel.org/
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:	Maintained
- F:	drivers/net/wireless/rtlwifi/
- F:	drivers/net/wireless/rtlwifi/rtl8192ce/
+ F:	drivers/net/wireless/realtek/rtlwifi/
+ F:	drivers/net/wireless/realtek/rtlwifi/rtl8192ce/
  
  RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
  M:	Jes Sorensen <Jes.Sorensen at redhat.com>
@@@ -9197,7 -9162,7 +9225,7 @@@ F:	drivers/s390/block/dasd
  F:	block/partitions/ibm.c
  
  S390 NETWORK DRIVERS
- M:	Ursula Braun <ursula.braun at de.ibm.com>
+ M:	Ursula Braun <ubraun at linux.vnet.ibm.com>
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
@@@ -9227,7 -9192,7 +9255,7 @@@ S:	Supporte
  F:	drivers/s390/scsi/zfcp_*
  
  S390 IUCV NETWORK LAYER
- M:	Ursula Braun <ursula.braun at de.ibm.com>
+ M:	Ursula Braun <ubraun at linux.vnet.ibm.com>
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
@@@ -9252,14 -9217,14 +9280,14 @@@ SAA6588 RDS RECEIVER DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/i2c/saa6588*
  
  SAA7134 VIDEO4LINUX DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Odd fixes
  F:	Documentation/video4linux/*.saa7134
@@@ -9321,7 -9286,7 +9349,7 @@@ L:	linux-media at vger.kernel.or
  L:	linux-samsung-soc at vger.kernel.org (moderated for non-subscribers)
  S:	Maintained
  F:	drivers/media/platform/s3c-camif/
 -F:	include/media/s3c_camif.h
 +F:	include/media/drv-intf/s3c_camif.h
  
  SAMSUNG S5C73M3 CAMERA DRIVER
  M:	Kyungmin Park <kyungmin.park at samsung.com>
@@@ -9696,7 -9661,7 +9724,7 @@@ F:	drivers/misc/sgi-xp
  SI2157 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -9706,7 -9671,7 +9734,7 @@@ F:	drivers/media/tuners/si2157
  SI2168 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -9717,7 -9682,7 +9745,7 @@@ SI470X FM RADIO RECEIVER I2C DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/radio/si470x/radio-si470x-i2c.c
  
@@@ -9725,7 -9690,7 +9753,7 @@@ SI470X FM RADIO RECEIVER USB DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/si470x/radio-si470x-common.c
  F:	drivers/media/radio/si470x/radio-si470x.h
@@@ -9735,7 -9700,7 +9763,7 @@@ SI4713 FM RADIO TRANSMITTER I2C DRIVE
  M:	Eduardo Valentin <edubezval at gmail.com>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/radio/si4713/si4713.?
  
@@@ -9743,7 -9708,7 +9771,7 @@@ SI4713 FM RADIO TRANSMITTER PLATFORM DR
  M:	Eduardo Valentin <edubezval at gmail.com>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/radio/si4713/radio-platform-si4713.c
  
@@@ -9751,14 -9716,14 +9779,14 @@@ SI4713 FM RADIO TRANSMITTER USB DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/si4713/radio-usb-si4713.c
  
  SIANO DVB DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Odd fixes
  F:	drivers/media/common/siano/
@@@ -9783,7 -9748,7 +9811,7 @@@ SH_VOU V4L2 OUTPUT DRIVE
  L:	linux-media at vger.kernel.org
  S:	Orphan
  F:	drivers/media/platform/sh_vou.c
 -F:	include/media/sh_vou.h
 +F:	include/media/drv-intf/sh_vou.h
  
  SIMPLE FIRMWARE INTERFACE (SFI)
  M:	Len Brown <lenb at kernel.org>
@@@ -9824,7 -9789,7 +9852,7 @@@ F:	drivers/i2c/busses/i2c-davinci.
  TI DAVINCI SERIES MEDIA DRIVER
  M:	"Lad, Prabhakar" <prabhakar.csengg at gmail.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
  S:	Maintained
@@@ -9834,7 -9799,7 +9862,7 @@@ F:	include/media/davinci
  TI AM437X VPFE DRIVER
  M:	"Lad, Prabhakar" <prabhakar.csengg at gmail.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
  S:	Maintained
@@@ -9843,12 -9808,12 +9871,12 @@@ F:	drivers/media/platform/am437x
  OV2659 OMNIVISION SENSOR DRIVER
  M:	"Lad, Prabhakar" <prabhakar.csengg at gmail.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
  S:	Maintained
  F:	drivers/media/i2c/ov2659.c
 -F:	include/media/ov2659.h
 +F:	include/media/i2c/ov2659.h
  
  SILICON MOTION SM712 FRAME BUFFER DRIVER
  M:	Sudip Mukherjee <sudipm.mukherjee at gmail.com>
@@@ -9937,7 -9902,7 +9965,7 @@@ M:	Sakari Ailus <sakari.ailus at iki.fi
  L:	linux-media at vger.kernel.org
  S:	Maintained
  F:	drivers/media/i2c/smiapp/
 -F:	include/media/smiapp.h
 +F:	include/media/i2c/smiapp.h
  F:	drivers/media/i2c/smiapp-pll.c
  F:	drivers/media/i2c/smiapp-pll.h
  F:	include/uapi/linux/smiapp.h
@@@ -10101,7 -10066,7 +10129,7 @@@ F:	sound/soc/soc-generic-dmaengine-pcm.
  SP2 MEDIA DRIVER
  M:	Olli Salonen <olli.salonen at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  S:	Maintained
  F:	drivers/media/dvb-frontends/sp2*
@@@ -10463,7 -10428,7 +10491,7 @@@ F:	net/ipv4/tcp_lp.
  TDA10071 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -10473,7 -10438,7 +10501,7 @@@ F:	drivers/media/dvb-frontends/tda10071
  TDA18212 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -10483,7 -10448,7 +10511,7 @@@ F:	drivers/media/tuners/tda18212
  TDA18218 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -10493,7 -10458,7 +10521,7 @@@ F:	drivers/media/tuners/tda18218
  TDA18271 MEDIA DRIVER
  M:	Michael Krufky <mkrufky at linuxtv.org>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://github.com/mkrufky
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mkrufky/tuners.git
@@@ -10503,7 -10468,7 +10531,7 @@@ F:	drivers/media/tuners/tda18271
  TDA827x MEDIA DRIVER
  M:	Michael Krufky <mkrufky at linuxtv.org>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://github.com/mkrufky
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mkrufky/tuners.git
@@@ -10513,7 -10478,7 +10541,7 @@@ F:	drivers/media/tuners/tda8290.
  TDA8290 MEDIA DRIVER
  M:	Michael Krufky <mkrufky at linuxtv.org>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://linuxtv.org
  W:	http://github.com/mkrufky
  Q:	http://patchwork.linuxtv.org/project/linux-media/list/
  T:	git git://linuxtv.org/mkrufky/tuners.git
@@@ -10524,14 -10489,14 +10552,14 @@@ TDA9840 MEDIA DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/i2c/tda9840*
  
  TEA5761 TUNER DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Odd fixes
  F:	drivers/media/tuners/tea5761.*
@@@ -10539,7 -10504,7 +10567,7 @@@
  TEA5767 TUNER DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
  F:	drivers/media/tuners/tea5767.*
@@@ -10548,7 -10513,7 +10576,7 @@@ TEA6415C MEDIA DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/i2c/tea6415c*
  
@@@ -10556,7 -10521,7 +10584,7 @@@ TEA6420 MEDIA DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/i2c/tea6420*
  
@@@ -10654,7 -10619,7 +10682,7 @@@ THANKO'S RAREMONO AM/FM/SW RADIO RECEIV
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/radio/radio-raremono.c
  
@@@ -10804,7 -10769,6 +10832,7 @@@ F:	net/tipc
  TILE ARCHITECTURE
  M:	Chris Metcalf <cmetcalf at ezchip.com>
  W:	http://www.ezchip.com/scm/
 +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git
  S:	Supported
  F:	arch/tile/
  F:	drivers/char/tile-srom.c
@@@ -10879,7 -10843,7 +10907,7 @@@ M:	Mats Randgaard <matrandg at cisco.com
  L:	linux-media at vger.kernel.org
  S:	Maintained
  F:	drivers/media/i2c/tc358743*
 -F:	include/media/tc358743.h
 +F:	include/media/i2c/tc358743.h
  
  TMIO MMC DRIVER
  M:	Ian Molton <ian at mnementh.co.uk>
@@@ -10907,7 -10871,7 +10935,7 @@@ F:	mm/shmem.
  TM6000 VIDEO4LINUX DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Odd fixes
  F:	drivers/media/usb/tm6000/
@@@ -10916,7 -10880,7 +10944,7 @@@ TW68 VIDEO4LINUX DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/pci/tw68/
  
@@@ -10977,7 -10941,7 +11005,7 @@@ F:	include/uapi/linux/tty.
  TUA9001 MEDIA DRIVER
  M:	Antti Palosaari <crope at iki.fi>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org/
 +W:	https://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
@@@ -11179,7 -11143,6 +11207,7 @@@ F:	include/linux/usb/gadget
  
  USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
  M:	Jiri Kosina <jikos at kernel.org>
 +R:	Benjamin Tissoires <benjamin.tissoires at redhat.com>
  L:	linux-usb at vger.kernel.org
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
  S:	Maintained
@@@ -11257,6 -11220,13 +11285,13 @@@ L:	linux-usb at vger.kernel.or
  S:	Supported
  F:	drivers/usb/class/usblp.c
  
+ USB QMI WWAN NETWORK DRIVER
+ M:	Bjørn Mork <bjorn at mork.no>
+ L:	netdev at vger.kernel.org
+ S:	Maintained
+ F:	Documentation/ABI/testing/sysfs-class-net-qmi
+ F:	drivers/net/usb/qmi_wwan.c
+ 
  USB RTL8150 DRIVER
  M:	Petko Manolov <petkan at nucleusys.com>
  L:	linux-usb at vger.kernel.org
@@@ -11325,7 -11295,7 +11360,7 @@@ USB VISION DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Odd Fixes
  F:	drivers/media/usb/usbvision/
  
@@@ -11353,7 -11323,7 +11388,7 @@@ USB ZD1201 DRIVE
  L:	linux-wireless at vger.kernel.org
  W:	http://linux-lc100020.sourceforge.net
  S:	Orphan
- F:	drivers/net/wireless/zd1201.*
+ F:	drivers/net/wireless/zydas/zd1201.*
  
  USB ZR364XX DRIVER
  M:	Antoine Jacquet <royale at zerezo.com>
@@@ -11539,7 -11509,7 +11574,7 @@@ VIVID VIRTUAL VIDEO DRIVE
  M:	Hans Verkuil <hverkuil at xs4all.nl>
  L:	linux-media at vger.kernel.org
  T:	git git://linuxtv.org/media_tree.git
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  S:	Maintained
  F:	drivers/media/platform/vivid/*
  
@@@ -11828,7 -11798,7 +11863,7 @@@ F:	arch/x86/entry/vdso
  XC2028/3028 TUNER DRIVER
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  L:	linux-media at vger.kernel.org
 -W:	http://linuxtv.org
 +W:	https://linuxtv.org
  T:	git git://linuxtv.org/media_tree.git
  S:	Maintained
  F:	drivers/media/tuners/tuner-xc2028.*
@@@ -11984,7 -11954,7 +12019,7 @@@ W:	http://zd1211.ath.cx/wiki/DriverRewr
  L:	linux-wireless at vger.kernel.org
  L:	zd1211-devs at lists.sourceforge.net (subscribers-only)
  S:	Maintained
- F:	drivers/net/wireless/zd1211rw/
+ F:	drivers/net/wireless/zydas/zd1211rw/
  
  ZPOOL COMPRESSED PAGE STORAGE API
  M:	Dan Streetman <ddstreet at ieee.org>
@@@ -11997,7 -11967,7 +12032,7 @@@ ZR36067 VIDEO FOR LINUX DRIVE
  L:	mjpeg-users at lists.sourceforge.net
  L:	linux-media at vger.kernel.org
  W:	http://mjpeg.sourceforge.net/driver-zoran/
 -T:	hg http://linuxtv.org/hg/v4l-dvb
 +T:	hg https://linuxtv.org/hg/v4l-dvb
  S:	Odd Fixes
  F:	drivers/media/pci/zoran/
  
diff --combined crypto/algif_skcipher.c
index df483f9,5e20ca1..882de31
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@@ -31,11 -31,6 +31,11 @@@ struct skcipher_sg_list 
  	struct scatterlist sg[0];
  };
  
 +struct skcipher_tfm {
 +	struct crypto_skcipher *skcipher;
 +	bool has_key;
 +};
 +
  struct skcipher_ctx {
  	struct list_head tsgl;
  	struct af_alg_sgl rsgl;
@@@ -243,7 -238,7 +243,7 @@@ static void skcipher_wmem_wakeup(struc
  
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
- 	if (wq_has_sleeper(wq))
+ 	if (skwq_has_sleeper(wq))
  		wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
  							   POLLRDNORM |
  							   POLLRDBAND);
@@@ -293,7 -288,7 +293,7 @@@ static void skcipher_data_wakeup(struc
  
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
- 	if (wq_has_sleeper(wq))
+ 	if (skwq_has_sleeper(wq))
  		wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
  							   POLLRDNORM |
  							   POLLRDBAND);
@@@ -755,41 -750,17 +755,41 @@@ static struct proto_ops algif_skcipher_
  
  static void *skcipher_bind(const char *name, u32 type, u32 mask)
  {
 -	return crypto_alloc_skcipher(name, type, mask);
 +	struct skcipher_tfm *tfm;
 +	struct crypto_skcipher *skcipher;
 +
 +	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
 +	if (!tfm)
 +		return ERR_PTR(-ENOMEM);
 +
 +	skcipher = crypto_alloc_skcipher(name, type, mask);
 +	if (IS_ERR(skcipher)) {
 +		kfree(tfm);
 +		return ERR_CAST(skcipher);
 +	}
 +
 +	tfm->skcipher = skcipher;
 +
 +	return tfm;
  }
  
  static void skcipher_release(void *private)
  {
 -	crypto_free_skcipher(private);
 +	struct skcipher_tfm *tfm = private;
 +
 +	crypto_free_skcipher(tfm->skcipher);
 +	kfree(tfm);
  }
  
  static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
  {
 -	return crypto_skcipher_setkey(private, key, keylen);
 +	struct skcipher_tfm *tfm = private;
 +	int err;
 +
 +	err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
 +	tfm->has_key = !err;
 +
 +	return err;
  }
  
  static void skcipher_wait(struct sock *sk)
@@@ -821,25 -792,20 +821,25 @@@ static int skcipher_accept_parent(void 
  {
  	struct skcipher_ctx *ctx;
  	struct alg_sock *ask = alg_sk(sk);
 -	unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private);
 +	struct skcipher_tfm *tfm = private;
 +	struct crypto_skcipher *skcipher = tfm->skcipher;
 +	unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
 +
 +	if (!tfm->has_key)
 +		return -ENOKEY;
  
  	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
  	if (!ctx)
  		return -ENOMEM;
  
 -	ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private),
 +	ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
  			       GFP_KERNEL);
  	if (!ctx->iv) {
  		sock_kfree_s(sk, ctx, len);
  		return -ENOMEM;
  	}
  
 -	memset(ctx->iv, 0, crypto_skcipher_ivsize(private));
 +	memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
  
  	INIT_LIST_HEAD(&ctx->tsgl);
  	ctx->len = len;
@@@ -852,7 -818,7 +852,7 @@@
  
  	ask->private = ctx;
  
 -	skcipher_request_set_tfm(&ctx->req, private);
 +	skcipher_request_set_tfm(&ctx->req, skcipher);
  	skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
  				      af_alg_complete, &ctx->completion);
  
diff --combined drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 8344bba,622005a..f3c63dc
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@@ -29,7 -29,7 +29,7 @@@
  
  #include <asm/io.h>
  #if IS_ENABLED(CONFIG_UCC_GETH)
 -#include <asm/ucc.h>	/* for ucc_set_qe_mux_mii_mng() */
 +#include <soc/fsl/qe/ucc.h>
  #endif
  
  #include "gianfar.h"
@@@ -69,7 -69,6 +69,6 @@@ struct fsl_pq_mdio 
  struct fsl_pq_mdio_priv {
  	void __iomem *map;
  	struct fsl_pq_mii __iomem *regs;
- 	int irqs[PHY_MAX_ADDR];
  };
  
  /*
@@@ -401,7 -400,6 +400,6 @@@ static int fsl_pq_mdio_probe(struct pla
  	new_bus->read = &fsl_pq_mdio_read;
  	new_bus->write = &fsl_pq_mdio_write;
  	new_bus->reset = &fsl_pq_mdio_reset;
- 	new_bus->irq = priv->irqs;
  
  	err = of_address_to_resource(np, 0, &res);
  	if (err < 0) {
diff --combined drivers/net/ethernet/freescale/ucc_geth.c
index c30b72e,0e7f24e..bc0b1cb
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@@ -40,10 -40,10 +40,10 @@@
  #include <asm/uaccess.h>
  #include <asm/irq.h>
  #include <asm/io.h>
 -#include <asm/immap_qe.h>
 -#include <asm/qe.h>
 -#include <asm/ucc.h>
 -#include <asm/ucc_fast.h>
 +#include <soc/fsl/qe/immap_qe.h>
 +#include <soc/fsl/qe/qe.h>
 +#include <soc/fsl/qe/ucc.h>
 +#include <soc/fsl/qe/ucc_fast.h>
  #include <asm/machdep.h>
  
  #include "ucc_geth.h"
@@@ -1385,7 -1385,7 +1385,7 @@@ static int adjust_enet_interface(struc
  		value &= ~0x1000;	/* Turn off autonegotiation */
  		phy_write(tbiphy, ENET_TBI_MII_CR, value);
  
- 		put_device(&tbiphy->dev);
+ 		put_device(&tbiphy->mdio.dev);
  	}
  
  	init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
@@@ -1705,7 -1705,7 +1705,7 @@@ static void uec_configure_serdes(struc
  	 * several seconds for it to come back.
  	 */
  	if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) {
- 		put_device(&tbiphy->dev);
+ 		put_device(&tbiphy->mdio.dev);
  		return;
  	}
  
diff --combined drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 69281ca,199f91a..a23dc61
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@@ -41,16 -41,73 +41,73 @@@
  #include <linux/netdevice.h>
  #include <linux/bitops.h>
  #include <linux/if_vlan.h>
+ #include <linux/list.h>
  #include <net/switchdev.h>
  
+ #include "port.h"
  #include "core.h"
  
  #define MLXSW_SP_VFID_BASE VLAN_N_VID
+ #define MLXSW_SP_VFID_PORT_MAX 512	/* Non-bridged VLAN interfaces */
+ #define MLXSW_SP_VFID_BR_MAX 8192	/* Bridged VLAN interfaces */
+ #define MLXSW_SP_VFID_MAX (MLXSW_SP_VFID_PORT_MAX + MLXSW_SP_VFID_BR_MAX)
+ 
+ #define MLXSW_SP_LAG_MAX 64
+ #define MLXSW_SP_PORT_PER_LAG_MAX 16
+ 
+ #define MLXSW_SP_MID_MAX 7000
  
  struct mlxsw_sp_port;
  
+ struct mlxsw_sp_upper {
+ 	struct net_device *dev;
+ 	unsigned int ref_count;
+ };
+ 
+ struct mlxsw_sp_vfid {
+ 	struct list_head list;
+ 	u16 nr_vports;
+ 	u16 vfid;	/* Starting at 0 */
+ 	struct net_device *br_dev;
+ 	u16 vid;
+ };
+ 
+ struct mlxsw_sp_mid {
+ 	struct list_head list;
+ 	unsigned char addr[ETH_ALEN];
+ 	u16 vid;
+ 	u16 mid;
+ 	unsigned int ref_count;
+ };
+ 
+ static inline u16 mlxsw_sp_vfid_to_fid(u16 vfid)
+ {
+ 	return MLXSW_SP_VFID_BASE + vfid;
+ }
+ 
+ static inline u16 mlxsw_sp_fid_to_vfid(u16 fid)
+ {
+ 	return fid - MLXSW_SP_VFID_BASE;
+ }
+ 
+ static inline bool mlxsw_sp_fid_is_vfid(u16 fid)
+ {
+ 	return fid >= MLXSW_SP_VFID_BASE;
+ }
+ 
  struct mlxsw_sp {
- 	unsigned long active_vfids[BITS_TO_LONGS(VLAN_N_VID)];
+ 	struct {
+ 		struct list_head list;
+ 		unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_VFID_PORT_MAX)];
+ 	} port_vfids;
+ 	struct {
+ 		struct list_head list;
+ 		unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_VFID_BR_MAX)];
+ 	} br_vfids;
+ 	struct {
+ 		struct list_head list;
+ 		unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_MID_MAX)];
+ 	} br_mids;
  	unsigned long active_fids[BITS_TO_LONGS(VLAN_N_VID)];
  	struct mlxsw_sp_port **ports;
  	struct mlxsw_core *core;
@@@ -63,13 -120,16 +120,17 @@@
  	} fdb_notify;
  #define MLXSW_SP_DEFAULT_AGEING_TIME 300
  	u32 ageing_time;
 +	struct mutex fdb_lock;	/* Make sure FDB sessions are atomic. */
- 	struct {
- 		struct net_device *dev;
- 		unsigned int ref_count;
- 	} master_bridge;
+ 	struct mlxsw_sp_upper master_bridge;
+ 	struct mlxsw_sp_upper lags[MLXSW_SP_LAG_MAX];
  };
  
+ static inline struct mlxsw_sp_upper *
+ mlxsw_sp_lag_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
+ {
+ 	return &mlxsw_sp->lags[lag_id];
+ }
+ 
  struct mlxsw_sp_port_pcpu_stats {
  	u64			rx_packets;
  	u64			rx_bytes;
@@@ -88,15 -148,87 +149,87 @@@ struct mlxsw_sp_port 
  	u8 learning:1,
  	   learning_sync:1,
  	   uc_flood:1,
- 	   bridged:1;
+ 	   bridged:1,
+ 	   lagged:1;
  	u16 pvid;
+ 	u16 lag_id;
+ 	struct {
+ 		struct list_head list;
+ 		struct mlxsw_sp_vfid *vfid;
+ 		u16 vid;
+ 	} vport;
  	/* 802.1Q bridge VLANs */
- 	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+ 	unsigned long *active_vlans;
+ 	unsigned long *untagged_vlans;
  	/* VLAN interfaces */
- 	unsigned long active_vfids[BITS_TO_LONGS(VLAN_N_VID)];
- 	u16 nr_vfids;
+ 	struct list_head vports_list;
  };
  
+ static inline struct mlxsw_sp_port *
+ mlxsw_sp_port_lagged_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id, u8 port_index)
+ {
+ 	struct mlxsw_sp_port *mlxsw_sp_port;
+ 	u8 local_port;
+ 
+ 	local_port = mlxsw_core_lag_mapping_get(mlxsw_sp->core,
+ 						lag_id, port_index);
+ 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
+ 	return mlxsw_sp_port && mlxsw_sp_port->lagged ? mlxsw_sp_port : NULL;
+ }
+ 
+ static inline bool
+ mlxsw_sp_port_is_vport(const struct mlxsw_sp_port *mlxsw_sp_port)
+ {
+ 	return mlxsw_sp_port->vport.vfid;
+ }
+ 
+ static inline struct net_device *
+ mlxsw_sp_vport_br_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
+ {
+ 	return mlxsw_sp_vport->vport.vfid->br_dev;
+ }
+ 
+ static inline u16
+ mlxsw_sp_vport_vid_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
+ {
+ 	return mlxsw_sp_vport->vport.vid;
+ }
+ 
+ static inline u16
+ mlxsw_sp_vport_vfid_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
+ {
+ 	return mlxsw_sp_vport->vport.vfid->vfid;
+ }
+ 
+ static inline struct mlxsw_sp_port *
+ mlxsw_sp_port_vport_find(const struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
+ {
+ 	struct mlxsw_sp_port *mlxsw_sp_vport;
+ 
+ 	list_for_each_entry(mlxsw_sp_vport, &mlxsw_sp_port->vports_list,
+ 			    vport.list) {
+ 		if (mlxsw_sp_vport_vid_get(mlxsw_sp_vport) == vid)
+ 			return mlxsw_sp_vport;
+ 	}
+ 
+ 	return NULL;
+ }
+ 
+ static inline struct mlxsw_sp_port *
+ mlxsw_sp_port_vport_find_by_vfid(const struct mlxsw_sp_port *mlxsw_sp_port,
+ 				 u16 vfid)
+ {
+ 	struct mlxsw_sp_port *mlxsw_sp_vport;
+ 
+ 	list_for_each_entry(mlxsw_sp_vport, &mlxsw_sp_port->vports_list,
+ 			    vport.list) {
+ 		if (mlxsw_sp_vport_vfid_get(mlxsw_sp_vport) == vfid)
+ 			return mlxsw_sp_vport;
+ 	}
+ 
+ 	return NULL;
+ }
+ 
  enum mlxsw_sp_flood_table {
  	MLXSW_SP_FLOOD_TABLE_UC,
  	MLXSW_SP_FLOOD_TABLE_BM,
@@@ -119,5 -251,7 +252,7 @@@ int mlxsw_sp_port_add_vid(struct net_de
  			  u16 vid);
  int mlxsw_sp_port_kill_vid(struct net_device *dev,
  			   __be16 __always_unused proto, u16 vid);
+ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
+ 			     bool set, bool only_uc);
  
  #endif
diff --combined drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 80e2660,4cdc18e..ffe894e
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@@ -51,12 -51,50 +51,50 @@@
  #include "core.h"
  #include "reg.h"
  
+ static u16 mlxsw_sp_port_vid_to_fid_get(struct mlxsw_sp_port *mlxsw_sp_port,
+ 					u16 vid)
+ {
+ 	u16 fid = vid;
+ 
+ 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+ 		u16 vfid = mlxsw_sp_vport_vfid_get(mlxsw_sp_port);
+ 
+ 		fid = mlxsw_sp_vfid_to_fid(vfid);
+ 	}
+ 
+ 	if (!fid)
+ 		fid = mlxsw_sp_port->pvid;
+ 
+ 	return fid;
+ }
+ 
+ static struct mlxsw_sp_port *
+ mlxsw_sp_port_orig_get(struct net_device *dev,
+ 		       struct mlxsw_sp_port *mlxsw_sp_port)
+ {
+ 	struct mlxsw_sp_port *mlxsw_sp_vport;
+ 	u16 vid;
+ 
+ 	if (!is_vlan_dev(dev))
+ 		return mlxsw_sp_port;
+ 
+ 	vid = vlan_dev_vlan_id(dev);
+ 	mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
+ 	WARN_ON(!mlxsw_sp_vport);
+ 
+ 	return mlxsw_sp_vport;
+ }
+ 
  static int mlxsw_sp_port_attr_get(struct net_device *dev,
  				  struct switchdev_attr *attr)
  {
  	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
  	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
  
+ 	mlxsw_sp_port = mlxsw_sp_port_orig_get(attr->orig_dev, mlxsw_sp_port);
+ 	if (!mlxsw_sp_port)
+ 		return -EINVAL;
+ 
  	switch (attr->id) {
  	case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
  		attr->u.ppid.id_len = sizeof(mlxsw_sp->base_mac);
@@@ -105,8 -143,14 +143,14 @@@ static int mlxsw_sp_port_stp_state_set(
  	if (!spms_pl)
  		return -ENOMEM;
  	mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port);
- 	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
+ 
+ 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+ 		vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
  		mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state);
+ 	} else {
+ 		for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
+ 			mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state);
+ 	}
  
  	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl);
  	kfree(spms_pl);
@@@ -124,22 -168,38 +168,38 @@@ static int mlxsw_sp_port_attr_stp_state
  	return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state);
  }
  
+ static bool mlxsw_sp_vfid_is_vport_br(u16 vfid)
+ {
+ 	return vfid >= MLXSW_SP_VFID_PORT_MAX;
+ }
+ 
  static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
- 				     u16 fid_begin, u16 fid_end, bool set,
+ 				     u16 idx_begin, u16 idx_end, bool set,
  				     bool only_uc)
  {
  	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- 	u16 range = fid_end - fid_begin + 1;
+ 	u16 local_port = mlxsw_sp_port->local_port;
+ 	enum mlxsw_flood_table_type table_type;
+ 	u16 range = idx_end - idx_begin + 1;
  	char *sftr_pl;
  	int err;
  
+ 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+ 		table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID;
+ 		if (mlxsw_sp_vfid_is_vport_br(idx_begin))
+ 			local_port = mlxsw_sp_port->local_port;
+ 		else
+ 			local_port = MLXSW_PORT_CPU_PORT;
+ 	} else {
+ 		table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST;
+ 	}
+ 
  	sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
  	if (!sftr_pl)
  		return -ENOMEM;
  
- 	mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid_begin,
- 			    MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range,
- 			    mlxsw_sp_port->local_port, set);
+ 	mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, idx_begin,
+ 			    table_type, range, local_port, set);
  	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
  	if (err)
  		goto buffer_out;
@@@ -150,9 -210,8 +210,8 @@@
  	if (only_uc)
  		goto buffer_out;
  
- 	mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid_begin,
- 			    MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range,
- 			    mlxsw_sp_port->local_port, set);
+ 	mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, idx_begin,
+ 			    table_type, range, local_port, set);
  	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
  
  buffer_out:
@@@ -167,6 -226,13 +226,13 @@@ static int mlxsw_sp_port_uc_flood_set(s
  	u16 vid, last_visited_vid;
  	int err;
  
+ 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+ 		u16 vfid = mlxsw_sp_vport_vfid_get(mlxsw_sp_port);
+ 
+ 		return  __mlxsw_sp_port_flood_set(mlxsw_sp_port, vfid, vfid,
+ 						  set, true);
+ 	}
+ 
  	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
  		err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, set,
  						true);
@@@ -185,6 -251,16 +251,16 @@@ err_port_flood_set
  	return err;
  }
  
+ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
+ 			     bool set, bool only_uc)
+ {
+ 	/* In case of vFIDs, index into the flooding table is relative to
+ 	 * the start of the vFIDs range.
+ 	 */
+ 	return __mlxsw_sp_port_flood_set(mlxsw_sp_vport, vfid, vfid, set,
+ 					 only_uc);
+ }
+ 
  static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
  					   struct switchdev_trans *trans,
  					   unsigned long brport_flags)
@@@ -193,6 -269,9 +269,9 @@@
  	bool set;
  	int err;
  
+ 	if (!mlxsw_sp_port->bridged)
+ 		return -EINVAL;
+ 
  	if (switchdev_trans_ph_prepare(trans))
  		return 0;
  
@@@ -237,6 -316,22 +316,22 @@@ static int mlxsw_sp_port_attr_br_ageing
  	return mlxsw_sp_ageing_set(mlxsw_sp, ageing_time);
  }
  
+ static int mlxsw_sp_port_attr_br_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ 					  struct switchdev_trans *trans,
+ 					  struct net_device *orig_dev,
+ 					  bool vlan_enabled)
+ {
+ 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ 
+ 	/* SWITCHDEV_TRANS_PREPARE phase */
+ 	if ((!vlan_enabled) && (mlxsw_sp->master_bridge.dev == orig_dev)) {
+ 		netdev_err(mlxsw_sp_port->dev, "Bridge must be vlan-aware\n");
+ 		return -EINVAL;
+ 	}
+ 
+ 	return 0;
+ }
+ 
  static int mlxsw_sp_port_attr_set(struct net_device *dev,
  				  const struct switchdev_attr *attr,
  				  struct switchdev_trans *trans)
@@@ -244,6 -339,10 +339,10 @@@
  	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
  	int err = 0;
  
+ 	mlxsw_sp_port = mlxsw_sp_port_orig_get(attr->orig_dev, mlxsw_sp_port);
+ 	if (!mlxsw_sp_port)
+ 		return -EINVAL;
+ 
  	switch (attr->id) {
  	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
  		err = mlxsw_sp_port_attr_stp_state_set(mlxsw_sp_port, trans,
@@@ -257,6 -356,11 +356,11 @@@
  		err = mlxsw_sp_port_attr_br_ageing_set(mlxsw_sp_port, trans,
  						       attr->u.ageing_time);
  		break;
+ 	case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
+ 		err = mlxsw_sp_port_attr_br_vlan_set(mlxsw_sp_port, trans,
+ 						     attr->orig_dev,
+ 						     attr->u.vlan_filtering);
+ 		break;
  	default:
  		err = -EOPNOTSUPP;
  		break;
@@@ -304,7 -408,7 +408,7 @@@ static int mlxsw_sp_port_fid_map(struc
  {
  	enum mlxsw_reg_svfa_mt mt;
  
- 	if (mlxsw_sp_port->nr_vfids)
+ 	if (!list_empty(&mlxsw_sp_port->vports_list))
  		mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
  	else
  		mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
@@@ -316,7 -420,7 +420,7 @@@ static int mlxsw_sp_port_fid_unmap(stru
  {
  	enum mlxsw_reg_svfa_mt mt;
  
- 	if (!mlxsw_sp_port->nr_vfids)
+ 	if (list_empty(&mlxsw_sp_port->vports_list))
  		return 0;
  
  	mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
@@@ -342,14 -446,35 +446,35 @@@ err_port_add_vid
  	return err;
  }
  
+ static int __mlxsw_sp_port_vlans_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ 				     u16 vid_begin, u16 vid_end, bool is_member,
+ 				     bool untagged)
+ {
+ 	u16 vid, vid_e;
+ 	int err;
+ 
+ 	for (vid = vid_begin; vid <= vid_end;
+ 	     vid += MLXSW_REG_SPVM_REC_MAX_COUNT) {
+ 		vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1),
+ 			    vid_end);
+ 
+ 		err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e,
+ 					     is_member, untagged);
+ 		if (err)
+ 			return err;
+ 	}
+ 
+ 	return 0;
+ }
+ 
  static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
  				     u16 vid_begin, u16 vid_end,
  				     bool flag_untagged, bool flag_pvid)
  {
  	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
  	struct net_device *dev = mlxsw_sp_port->dev;
+ 	u16 vid, last_visited_vid, old_pvid;
  	enum mlxsw_reg_svfa_mt mt;
- 	u16 vid, vid_e;
  	int err;
  
  	/* In case this is invoked with BRIDGE_FLAGS_SELF and port is
@@@ -377,15 -502,18 +502,18 @@@
  			if (err) {
  				netdev_err(dev, "Failed to create FID=VID=%d mapping\n",
  					   vid);
- 				return err;
+ 				goto err_port_vid_to_fid_set;
  			}
  		}
+ 	}
  
- 		/* Set FID mapping according to port's mode */
+ 	/* Set FID mapping according to port's mode */
+ 	for (vid = vid_begin; vid <= vid_end; vid++) {
  		err = mlxsw_sp_port_fid_map(mlxsw_sp_port, vid);
  		if (err) {
  			netdev_err(dev, "Failed to map FID=%d", vid);
- 			return err;
+ 			last_visited_vid = --vid;
+ 			goto err_port_fid_map;
  		}
  	}
  
@@@ -393,83 -521,133 +521,133 @@@
  					true, false);
  	if (err) {
  		netdev_err(dev, "Failed to configure flooding\n");
- 		return err;
+ 		goto err_port_flood_set;
  	}
  
- 	for (vid = vid_begin; vid <= vid_end;
- 	     vid += MLXSW_REG_SPVM_REC_MAX_COUNT) {
- 		vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1),
- 			    vid_end);
- 
- 		err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e, true,
- 					     flag_untagged);
- 		if (err) {
- 			netdev_err(mlxsw_sp_port->dev, "Unable to add VIDs %d-%d\n",
- 				   vid, vid_e);
- 			return err;
- 		}
+ 	err = __mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end,
+ 					true, flag_untagged);
+ 	if (err) {
+ 		netdev_err(dev, "Unable to add VIDs %d-%d\n", vid_begin,
+ 			   vid_end);
+ 		goto err_port_vlans_set;
  	}
  
- 	vid = vid_begin;
- 	if (flag_pvid && mlxsw_sp_port->pvid != vid) {
- 		err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid);
+ 	old_pvid = mlxsw_sp_port->pvid;
+ 	if (flag_pvid && old_pvid != vid_begin) {
+ 		err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid_begin);
  		if (err) {
- 			netdev_err(mlxsw_sp_port->dev, "Unable to add PVID %d\n",
- 				   vid);
- 			return err;
+ 			netdev_err(dev, "Unable to add PVID %d\n", vid_begin);
+ 			goto err_port_pvid_set;
  		}
- 		mlxsw_sp_port->pvid = vid;
+ 		mlxsw_sp_port->pvid = vid_begin;
  	}
  
  	/* Changing activity bits only if HW operation succeded */
- 	for (vid = vid_begin; vid <= vid_end; vid++)
+ 	for (vid = vid_begin; vid <= vid_end; vid++) {
  		set_bit(vid, mlxsw_sp_port->active_vlans);
+ 		if (flag_untagged)
+ 			set_bit(vid, mlxsw_sp_port->untagged_vlans);
+ 		else
+ 			clear_bit(vid, mlxsw_sp_port->untagged_vlans);
+ 	}
  
- 	return mlxsw_sp_port_stp_state_set(mlxsw_sp_port,
- 					   mlxsw_sp_port->stp_state);
+ 	/* STP state change must be done after we set active VLANs */
+ 	err = mlxsw_sp_port_stp_state_set(mlxsw_sp_port,
+ 					  mlxsw_sp_port->stp_state);
+ 	if (err) {
+ 		netdev_err(dev, "Failed to set STP state\n");
+ 		goto err_port_stp_state_set;
+ 	}
+ 
+ 	return 0;
+ 
+ err_port_vid_to_fid_set:
+ 	mlxsw_sp_fid_destroy(mlxsw_sp, vid);
+ 	return err;
+ 
+ err_port_stp_state_set:
+ 	for (vid = vid_begin; vid <= vid_end; vid++)
+ 		clear_bit(vid, mlxsw_sp_port->active_vlans);
+ 	if (old_pvid != mlxsw_sp_port->pvid)
+ 		mlxsw_sp_port_pvid_set(mlxsw_sp_port, old_pvid);
+ err_port_pvid_set:
+ 	__mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end, false,
+ 				  false);
+ err_port_vlans_set:
+ 	__mlxsw_sp_port_flood_set(mlxsw_sp_port, vid_begin, vid_end, false,
+ 				  false);
+ err_port_flood_set:
+ 	last_visited_vid = vid_end;
+ err_port_fid_map:
+ 	for (vid = last_visited_vid; vid >= vid_begin; vid--)
+ 		mlxsw_sp_port_fid_unmap(mlxsw_sp_port, vid);
+ 	return err;
  }
  
  static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
  				   const struct switchdev_obj_port_vlan *vlan,
  				   struct switchdev_trans *trans)
  {
- 	bool untagged_flag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
- 	bool pvid_flag = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+ 	bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+ 	bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
  
  	if (switchdev_trans_ph_prepare(trans))
  		return 0;
  
  	return __mlxsw_sp_port_vlans_add(mlxsw_sp_port,
  					 vlan->vid_begin, vlan->vid_end,
- 					 untagged_flag, pvid_flag);
+ 					 flag_untagged, flag_pvid);
+ }
+ 
+ static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic)
+ {
+ 	return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
+ 			 MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
+ }
+ 
+ static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
+ {
+ 	return adding ? MLXSW_REG_SFD_OP_WRITE_EDIT :
+ 			MLXSW_REG_SFD_OP_WRITE_REMOVE;
  }
  
- static int mlxsw_sp_port_fdb_op(struct mlxsw_sp_port *mlxsw_sp_port,
- 				const char *mac, u16 vid, bool adding,
- 				bool dynamic)
+ static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+ 				   const char *mac, u16 fid, bool adding,
+ 				   bool dynamic)
  {
- 	enum mlxsw_reg_sfd_rec_policy policy;
- 	enum mlxsw_reg_sfd_op op;
  	char *sfd_pl;
  	int err;
  
- 	if (!vid)
- 		vid = mlxsw_sp_port->pvid;
+ 	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
+ 	if (!sfd_pl)
+ 		return -ENOMEM;
+ 
+ 	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
+ 	mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
+ 			      mac, fid, MLXSW_REG_SFD_REC_ACTION_NOP,
+ 			      local_port);
+ 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
+ 	kfree(sfd_pl);
+ 
+ 	return err;
+ }
+ 
+ static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
+ 				       const char *mac, u16 fid, u16 lag_vid,
+ 				       bool adding, bool dynamic)
+ {
+ 	char *sfd_pl;
+ 	int err;
  
  	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
  	if (!sfd_pl)
  		return -ENOMEM;
  
- 	policy = dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
- 			   MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
- 	op = adding ? MLXSW_REG_SFD_OP_WRITE_EDIT :
- 		      MLXSW_REG_SFD_OP_WRITE_REMOVE;
- 	mlxsw_reg_sfd_pack(sfd_pl, op, 0);
- 	mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy,
- 			      mac, vid, MLXSW_REG_SFD_REC_ACTION_NOP,
- 			      mlxsw_sp_port->local_port);
- 	err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(sfd),
- 			      sfd_pl);
+ 	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
+ 	mlxsw_reg_sfd_uc_lag_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
+ 				  mac, fid, MLXSW_REG_SFD_REC_ACTION_NOP,
+ 				  lag_vid, lag_id);
+ 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
  	kfree(sfd_pl);
  
  	return err;
@@@ -480,11 -658,162 +658,162 @@@ mlxsw_sp_port_fdb_static_add(struct mlx
  			     const struct switchdev_obj_port_fdb *fdb,
  			     struct switchdev_trans *trans)
  {
+ 	u16 fid = mlxsw_sp_port_vid_to_fid_get(mlxsw_sp_port, fdb->vid);
+ 	u16 lag_vid = 0;
+ 
+ 	if (switchdev_trans_ph_prepare(trans))
+ 		return 0;
+ 
+ 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+ 		lag_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
+ 	}
+ 
+ 	if (!mlxsw_sp_port->lagged)
+ 		return mlxsw_sp_port_fdb_uc_op(mlxsw_sp_port->mlxsw_sp,
+ 					       mlxsw_sp_port->local_port,
+ 					       fdb->addr, fid, true, false);
+ 	else
+ 		return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp_port->mlxsw_sp,
+ 						   mlxsw_sp_port->lag_id,
+ 						   fdb->addr, fid, lag_vid,
+ 						   true, false);
+ }
+ 
+ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
+ 				u16 fid, u16 mid, bool adding)
+ {
+ 	char *sfd_pl;
+ 	int err;
+ 
+ 	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
+ 	if (!sfd_pl)
+ 		return -ENOMEM;
+ 
+ 	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
+ 	mlxsw_reg_sfd_mc_pack(sfd_pl, 0, addr, fid,
+ 			      MLXSW_REG_SFD_REC_ACTION_NOP, mid);
+ 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
+ 	kfree(sfd_pl);
+ 	return err;
+ }
+ 
+ static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mid,
+ 				  bool add, bool clear_all_ports)
+ {
+ 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ 	char *smid_pl;
+ 	int err, i;
+ 
+ 	smid_pl = kmalloc(MLXSW_REG_SMID_LEN, GFP_KERNEL);
+ 	if (!smid_pl)
+ 		return -ENOMEM;
+ 
+ 	mlxsw_reg_smid_pack(smid_pl, mid, mlxsw_sp_port->local_port, add);
+ 	if (clear_all_ports) {
+ 		for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
+ 			if (mlxsw_sp->ports[i])
+ 				mlxsw_reg_smid_port_mask_set(smid_pl, i, 1);
+ 	}
+ 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid), smid_pl);
+ 	kfree(smid_pl);
+ 	return err;
+ }
+ 
+ static struct mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp *mlxsw_sp,
+ 					      const unsigned char *addr,
+ 					      u16 vid)
+ {
+ 	struct mlxsw_sp_mid *mid;
+ 
+ 	list_for_each_entry(mid, &mlxsw_sp->br_mids.list, list) {
+ 		if (ether_addr_equal(mid->addr, addr) && mid->vid == vid)
+ 			return mid;
+ 	}
+ 	return NULL;
+ }
+ 
+ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
+ 						const unsigned char *addr,
+ 						u16 vid)
+ {
+ 	struct mlxsw_sp_mid *mid;
+ 	u16 mid_idx;
+ 
+ 	mid_idx = find_first_zero_bit(mlxsw_sp->br_mids.mapped,
+ 				      MLXSW_SP_MID_MAX);
+ 	if (mid_idx == MLXSW_SP_MID_MAX)
+ 		return NULL;
+ 
+ 	mid = kzalloc(sizeof(*mid), GFP_KERNEL);
+ 	if (!mid)
+ 		return NULL;
+ 
+ 	set_bit(mid_idx, mlxsw_sp->br_mids.mapped);
+ 	ether_addr_copy(mid->addr, addr);
+ 	mid->vid = vid;
+ 	mid->mid = mid_idx;
+ 	mid->ref_count = 0;
+ 	list_add_tail(&mid->list, &mlxsw_sp->br_mids.list);
+ 
+ 	return mid;
+ }
+ 
+ static int __mlxsw_sp_mc_dec_ref(struct mlxsw_sp *mlxsw_sp,
+ 				 struct mlxsw_sp_mid *mid)
+ {
+ 	if (--mid->ref_count == 0) {
+ 		list_del(&mid->list);
+ 		clear_bit(mid->mid, mlxsw_sp->br_mids.mapped);
+ 		kfree(mid);
+ 		return 1;
+ 	}
+ 	return 0;
+ }
+ 
+ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
+ 				 const struct switchdev_obj_port_mdb *mdb,
+ 				 struct switchdev_trans *trans)
+ {
+ 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ 	struct net_device *dev = mlxsw_sp_port->dev;
+ 	struct mlxsw_sp_mid *mid;
+ 	u16 fid = mlxsw_sp_port_vid_to_fid_get(mlxsw_sp_port, mdb->vid);
+ 	int err = 0;
+ 
  	if (switchdev_trans_ph_prepare(trans))
  		return 0;
  
- 	return mlxsw_sp_port_fdb_op(mlxsw_sp_port, fdb->addr, fdb->vid,
- 				    true, false);
+ 	mid = __mlxsw_sp_mc_get(mlxsw_sp, mdb->addr, mdb->vid);
+ 	if (!mid) {
+ 		mid = __mlxsw_sp_mc_alloc(mlxsw_sp, mdb->addr, mdb->vid);
+ 		if (!mid) {
+ 			netdev_err(dev, "Unable to allocate MC group\n");
+ 			return -ENOMEM;
+ 		}
+ 	}
+ 	mid->ref_count++;
+ 
+ 	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true,
+ 				     mid->ref_count == 1);
+ 	if (err) {
+ 		netdev_err(dev, "Unable to set SMID\n");
+ 		goto err_out;
+ 	}
+ 
+ 	if (mid->ref_count == 1) {
+ 		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid, mid->mid,
+ 					   true);
+ 		if (err) {
+ 			netdev_err(dev, "Unable to set MC SFD\n");
+ 			goto err_out;
+ 		}
+ 	}
+ 
+ 	return 0;
+ 
+ err_out:
+ 	__mlxsw_sp_mc_dec_ref(mlxsw_sp, mid);
+ 	return err;
  }
  
  static int mlxsw_sp_port_obj_add(struct net_device *dev,
@@@ -494,8 -823,15 +823,15 @@@
  	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
  	int err = 0;
  
+ 	mlxsw_sp_port = mlxsw_sp_port_orig_get(obj->orig_dev, mlxsw_sp_port);
+ 	if (!mlxsw_sp_port)
+ 		return -EINVAL;
+ 
  	switch (obj->id) {
  	case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ 		if (mlxsw_sp_port_is_vport(mlxsw_sp_port))
+ 			return 0;
+ 
  		err = mlxsw_sp_port_vlans_add(mlxsw_sp_port,
  					      SWITCHDEV_OBJ_PORT_VLAN(obj),
  					      trans);
@@@ -505,6 -841,11 +841,11 @@@
  						   SWITCHDEV_OBJ_PORT_FDB(obj),
  						   trans);
  		break;
+ 	case SWITCHDEV_OBJ_ID_PORT_MDB:
+ 		err = mlxsw_sp_port_mdb_add(mlxsw_sp_port,
+ 					    SWITCHDEV_OBJ_PORT_MDB(obj),
+ 					    trans);
+ 		break;
  	default:
  		err = -EOPNOTSUPP;
  		break;
@@@ -532,7 -873,7 +873,7 @@@ static int __mlxsw_sp_port_vlans_del(st
  				     u16 vid_begin, u16 vid_end, bool init)
  {
  	struct net_device *dev = mlxsw_sp_port->dev;
- 	u16 vid, vid_e;
+ 	u16 vid, pvid;
  	int err;
  
  	/* In case this is invoked with BRIDGE_FLAGS_SELF and port is
@@@ -542,30 -883,23 +883,23 @@@
  	if (!init && !mlxsw_sp_port->bridged)
  		return mlxsw_sp_port_kill_vids(dev, vid_begin, vid_end);
  
- 	for (vid = vid_begin; vid <= vid_end;
- 	     vid += MLXSW_REG_SPVM_REC_MAX_COUNT) {
- 		vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1),
- 			    vid_end);
- 		err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e, false,
- 					     false);
- 		if (err) {
- 			netdev_err(mlxsw_sp_port->dev, "Unable to del VIDs %d-%d\n",
- 				   vid, vid_e);
- 			return err;
- 		}
+ 	err = __mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end,
+ 					false, false);
+ 	if (err) {
+ 		netdev_err(dev, "Unable to del VIDs %d-%d\n", vid_begin,
+ 			   vid_end);
+ 		return err;
  	}
  
- 	if ((mlxsw_sp_port->pvid >= vid_begin) &&
- 	    (mlxsw_sp_port->pvid <= vid_end)) {
+ 	pvid = mlxsw_sp_port->pvid;
+ 	if (pvid >= vid_begin && pvid <= vid_end && pvid != 1) {
  		/* Default VLAN is always 1 */
- 		mlxsw_sp_port->pvid = 1;
- 		err = mlxsw_sp_port_pvid_set(mlxsw_sp_port,
- 					     mlxsw_sp_port->pvid);
+ 		err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
  		if (err) {
- 			netdev_err(mlxsw_sp_port->dev, "Unable to del PVID %d\n",
- 				   vid);
+ 			netdev_err(dev, "Unable to del PVID %d\n", pvid);
  			return err;
  		}
+ 		mlxsw_sp_port->pvid = 1;
  	}
  
  	if (init)
@@@ -606,8 -940,54 +940,54 @@@ static in
  mlxsw_sp_port_fdb_static_del(struct mlxsw_sp_port *mlxsw_sp_port,
  			     const struct switchdev_obj_port_fdb *fdb)
  {
- 	return mlxsw_sp_port_fdb_op(mlxsw_sp_port, fdb->addr, fdb->vid,
- 				    false, false);
+ 	u16 fid = mlxsw_sp_port_vid_to_fid_get(mlxsw_sp_port, fdb->vid);
+ 	u16 lag_vid = 0;
+ 
+ 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+ 		lag_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
+ 	}
+ 
+ 	if (!mlxsw_sp_port->lagged)
+ 		return mlxsw_sp_port_fdb_uc_op(mlxsw_sp_port->mlxsw_sp,
+ 					       mlxsw_sp_port->local_port,
+ 					       fdb->addr, fid,
+ 					       false, false);
+ 	else
+ 		return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp_port->mlxsw_sp,
+ 						   mlxsw_sp_port->lag_id,
+ 						   fdb->addr, fid, lag_vid,
+ 						   false, false);
+ }
+ 
+ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
+ 				 const struct switchdev_obj_port_mdb *mdb)
+ {
+ 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ 	struct net_device *dev = mlxsw_sp_port->dev;
+ 	struct mlxsw_sp_mid *mid;
+ 	u16 fid = mlxsw_sp_port_vid_to_fid_get(mlxsw_sp_port, mdb->vid);
+ 	u16 mid_idx;
+ 	int err = 0;
+ 
+ 	mid = __mlxsw_sp_mc_get(mlxsw_sp, mdb->addr, mdb->vid);
+ 	if (!mid) {
+ 		netdev_err(dev, "Unable to remove port from MC DB\n");
+ 		return -EINVAL;
+ 	}
+ 
+ 	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false, false);
+ 	if (err)
+ 		netdev_err(dev, "Unable to remove port from SMID\n");
+ 
+ 	mid_idx = mid->mid;
+ 	if (__mlxsw_sp_mc_dec_ref(mlxsw_sp, mid)) {
+ 		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid, mid_idx,
+ 					   false);
+ 		if (err)
+ 			netdev_err(dev, "Unable to remove MC SFD\n");
+ 	}
+ 
+ 	return err;
  }
  
  static int mlxsw_sp_port_obj_del(struct net_device *dev,
@@@ -616,8 -996,15 +996,15 @@@
  	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
  	int err = 0;
  
+ 	mlxsw_sp_port = mlxsw_sp_port_orig_get(obj->orig_dev, mlxsw_sp_port);
+ 	if (!mlxsw_sp_port)
+ 		return -EINVAL;
+ 
  	switch (obj->id) {
  	case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ 		if (mlxsw_sp_port_is_vport(mlxsw_sp_port))
+ 			return 0;
+ 
  		err = mlxsw_sp_port_vlans_del(mlxsw_sp_port,
  					      SWITCHDEV_OBJ_PORT_VLAN(obj));
  		break;
@@@ -625,6 -1012,9 +1012,9 @@@
  		err = mlxsw_sp_port_fdb_static_del(mlxsw_sp_port,
  						   SWITCHDEV_OBJ_PORT_FDB(obj));
  		break;
+ 	case SWITCHDEV_OBJ_ID_PORT_MDB:
+ 		err = mlxsw_sp_port_mdb_del(mlxsw_sp_port,
+ 					    SWITCHDEV_OBJ_PORT_MDB(obj));
  	default:
  		err = -EOPNOTSUPP;
  		break;
@@@ -633,14 -1023,31 +1023,31 @@@
  	return err;
  }
  
+ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
+ 						   u16 lag_id)
+ {
+ 	struct mlxsw_sp_port *mlxsw_sp_port;
+ 	int i;
+ 
+ 	for (i = 0; i < MLXSW_SP_PORT_PER_LAG_MAX; i++) {
+ 		mlxsw_sp_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
+ 		if (mlxsw_sp_port)
+ 			return mlxsw_sp_port;
+ 	}
+ 	return NULL;
+ }
+ 
  static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
  				  struct switchdev_obj_port_fdb *fdb,
  				  switchdev_obj_dump_cb_t *cb)
  {
+ 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ 	u16 vport_vid = 0, vport_fid = 0;
  	char *sfd_pl;
  	char mac[ETH_ALEN];
- 	u16 vid;
+ 	u16 fid;
  	u8 local_port;
+ 	u16 lag_id;
  	u8 num_rec;
  	int stored_err = 0;
  	int i;
@@@ -650,12 -1057,18 +1057,19 @@@
  	if (!sfd_pl)
  		return -ENOMEM;
  
 +	mutex_lock(&mlxsw_sp_port->mlxsw_sp->fdb_lock);
+ 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+ 		u16 tmp;
+ 
+ 		tmp = mlxsw_sp_vport_vfid_get(mlxsw_sp_port);
+ 		vport_fid = mlxsw_sp_vfid_to_fid(tmp);
+ 		vport_vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
+ 	}
+ 
  	mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0);
  	do {
  		mlxsw_reg_sfd_num_rec_set(sfd_pl, MLXSW_REG_SFD_REC_MAX_COUNT);
- 		err = mlxsw_reg_query(mlxsw_sp_port->mlxsw_sp->core,
- 				      MLXSW_REG(sfd), sfd_pl);
+ 		err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
  		if (err)
  			goto out;
  
@@@ -670,22 -1083,45 +1084,46 @@@
  		for (i = 0; i < num_rec; i++) {
  			switch (mlxsw_reg_sfd_rec_type_get(sfd_pl, i)) {
  			case MLXSW_REG_SFD_REC_TYPE_UNICAST:
- 				mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac, &vid,
+ 				mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac, &fid,
  							&local_port);
  				if (local_port == mlxsw_sp_port->local_port) {
+ 					if (vport_fid && vport_fid != fid)
+ 						continue;
+ 					else if (vport_fid)
+ 						fdb->vid = vport_vid;
+ 					else
+ 						fdb->vid = fid;
+ 					ether_addr_copy(fdb->addr, mac);
+ 					fdb->ndm_state = NUD_REACHABLE;
+ 					err = cb(&fdb->obj);
+ 					if (err)
+ 						stored_err = err;
+ 				}
+ 				break;
+ 			case MLXSW_REG_SFD_REC_TYPE_UNICAST_LAG:
+ 				mlxsw_reg_sfd_uc_lag_unpack(sfd_pl, i,
+ 							    mac, &fid, &lag_id);
+ 				if (mlxsw_sp_port ==
+ 				    mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id)) {
+ 					if (vport_fid && vport_fid != fid)
+ 						continue;
+ 					else if (vport_fid)
+ 						fdb->vid = vport_vid;
+ 					else
+ 						fdb->vid = fid;
  					ether_addr_copy(fdb->addr, mac);
  					fdb->ndm_state = NUD_REACHABLE;
- 					fdb->vid = vid;
  					err = cb(&fdb->obj);
  					if (err)
  						stored_err = err;
  				}
+ 				break;
  			}
  		}
  	} while (num_rec == MLXSW_REG_SFD_REC_MAX_COUNT);
  
  out:
 +	mutex_unlock(&mlxsw_sp_port->mlxsw_sp->fdb_lock);
  	kfree(sfd_pl);
  	return stored_err ? stored_err : err;
  }
@@@ -697,10 -1133,19 +1135,19 @@@ static int mlxsw_sp_port_vlan_dump(stru
  	u16 vid;
  	int err = 0;
  
+ 	if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+ 		vlan->flags = 0;
+ 		vlan->vid_begin = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
+ 		vlan->vid_end = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
+ 		return cb(&vlan->obj);
+ 	}
+ 
  	for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
  		vlan->flags = 0;
  		if (vid == mlxsw_sp_port->pvid)
  			vlan->flags |= BRIDGE_VLAN_INFO_PVID;
+ 		if (test_bit(vid, mlxsw_sp_port->untagged_vlans))
+ 			vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
  		vlan->vid_begin = vid;
  		vlan->vid_end = vid;
  		err = cb(&vlan->obj);
@@@ -717,6 -1162,10 +1164,10 @@@ static int mlxsw_sp_port_obj_dump(struc
  	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
  	int err = 0;
  
+ 	mlxsw_sp_port = mlxsw_sp_port_orig_get(obj->orig_dev, mlxsw_sp_port);
+ 	if (!mlxsw_sp_port)
+ 		return -EINVAL;
+ 
  	switch (obj->id) {
  	case SWITCHDEV_OBJ_ID_PORT_VLAN:
  		err = mlxsw_sp_port_vlan_dump(mlxsw_sp_port,
@@@ -742,6 -1191,21 +1193,21 @@@ static const struct switchdev_ops mlxsw
  	.switchdev_port_obj_dump	= mlxsw_sp_port_obj_dump,
  };
  
+ static void mlxsw_sp_fdb_call_notifiers(bool learning, bool learning_sync,
+ 					bool adding, char *mac, u16 vid,
+ 					struct net_device *dev)
+ {
+ 	struct switchdev_notifier_fdb_info info;
+ 	unsigned long notifier_type;
+ 
+ 	if (learning && learning_sync) {
+ 		info.addr = mac;
+ 		info.vid = vid;
+ 		notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
+ 		call_switchdev_notifiers(notifier_type, dev, &info.info);
+ 	}
+ }
+ 
  static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
  					    char *sfn_pl, int rec_index,
  					    bool adding)
@@@ -749,34 -1213,119 +1215,119 @@@
  	struct mlxsw_sp_port *mlxsw_sp_port;
  	char mac[ETH_ALEN];
  	u8 local_port;
- 	u16 vid;
+ 	u16 vid, fid;
+ 	bool do_notification = true;
  	int err;
  
- 	mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &vid, &local_port);
+ 	mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &fid, &local_port);
  	mlxsw_sp_port = mlxsw_sp->ports[local_port];
  	if (!mlxsw_sp_port) {
  		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect local port in FDB notification\n");
- 		return;
+ 		goto just_remove;
+ 	}
+ 
+ 	if (mlxsw_sp_fid_is_vfid(fid)) {
+ 		u16 vfid = mlxsw_sp_fid_to_vfid(fid);
+ 		struct mlxsw_sp_port *mlxsw_sp_vport;
+ 
+ 		mlxsw_sp_vport = mlxsw_sp_port_vport_find_by_vfid(mlxsw_sp_port,
+ 								  vfid);
+ 		if (!mlxsw_sp_vport) {
+ 			netdev_err(mlxsw_sp_port->dev, "Failed to find a matching vPort following FDB notification\n");
+ 			goto just_remove;
+ 		}
+ 		vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
+ 		/* Override the physical port with the vPort. */
+ 		mlxsw_sp_port = mlxsw_sp_vport;
+ 	} else {
+ 		vid = fid;
  	}
  
- 	err = mlxsw_sp_port_fdb_op(mlxsw_sp_port, mac, vid,
- 				   adding && mlxsw_sp_port->learning, true);
+ 	adding = adding && mlxsw_sp_port->learning;
+ 
+ do_fdb_op:
+ 	err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid,
+ 				      adding, true);
  	if (err) {
  		if (net_ratelimit())
  			netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
  		return;
  	}
  
- 	if (mlxsw_sp_port->learning && mlxsw_sp_port->learning_sync) {
- 		struct switchdev_notifier_fdb_info info;
- 		unsigned long notifier_type;
+ 	if (!do_notification)
+ 		return;
+ 	mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning,
+ 				    mlxsw_sp_port->learning_sync,
+ 				    adding, mac, vid, mlxsw_sp_port->dev);
+ 	return;
+ 
+ just_remove:
+ 	adding = false;
+ 	do_notification = false;
+ 	goto do_fdb_op;
+ }
  
- 		info.addr = mac;
- 		info.vid = vid;
- 		notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
- 		call_switchdev_notifiers(notifier_type, mlxsw_sp_port->dev,
- 					 &info.info);
+ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
+ 						char *sfn_pl, int rec_index,
+ 						bool adding)
+ {
+ 	struct mlxsw_sp_port *mlxsw_sp_port;
+ 	char mac[ETH_ALEN];
+ 	u16 lag_vid = 0;
+ 	u16 lag_id;
+ 	u16 vid, fid;
+ 	bool do_notification = true;
+ 	int err;
+ 
+ 	mlxsw_reg_sfn_mac_lag_unpack(sfn_pl, rec_index, mac, &fid, &lag_id);
+ 	mlxsw_sp_port = mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id);
+ 	if (!mlxsw_sp_port) {
+ 		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Cannot find port representor for LAG\n");
+ 		goto just_remove;
  	}
+ 
+ 	if (mlxsw_sp_fid_is_vfid(fid)) {
+ 		u16 vfid = mlxsw_sp_fid_to_vfid(fid);
+ 		struct mlxsw_sp_port *mlxsw_sp_vport;
+ 
+ 		mlxsw_sp_vport = mlxsw_sp_port_vport_find_by_vfid(mlxsw_sp_port,
+ 								  vfid);
+ 		if (!mlxsw_sp_vport) {
+ 			netdev_err(mlxsw_sp_port->dev, "Failed to find a matching vPort following FDB notification\n");
+ 			goto just_remove;
+ 		}
+ 
+ 		vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
+ 		lag_vid = vid;
+ 		/* Override the physical port with the vPort. */
+ 		mlxsw_sp_port = mlxsw_sp_vport;
+ 	} else {
+ 		vid = fid;
+ 	}
+ 
+ 	adding = adding && mlxsw_sp_port->learning;
+ 
+ do_fdb_op:
+ 	err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
+ 					  adding, true);
+ 	if (err) {
+ 		if (net_ratelimit())
+ 			netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
+ 		return;
+ 	}
+ 
+ 	if (!do_notification)
+ 		return;
+ 	mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning,
+ 				    mlxsw_sp_port->learning_sync,
+ 				    adding, mac, vid,
+ 				    mlxsw_sp_lag_get(mlxsw_sp, lag_id)->dev);
+ 	return;
+ 
+ just_remove:
+ 	adding = false;
+ 	do_notification = false;
+ 	goto do_fdb_op;
  }
  
  static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp,
@@@ -791,6 -1340,14 +1342,14 @@@
  		mlxsw_sp_fdb_notify_mac_process(mlxsw_sp, sfn_pl,
  						rec_index, false);
  		break;
+ 	case MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC_LAG:
+ 		mlxsw_sp_fdb_notify_mac_lag_process(mlxsw_sp, sfn_pl,
+ 						    rec_index, true);
+ 		break;
+ 	case MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC_LAG:
+ 		mlxsw_sp_fdb_notify_mac_lag_process(mlxsw_sp, sfn_pl,
+ 						    rec_index, false);
+ 		break;
  	}
  }
  
@@@ -814,7 -1371,6 +1373,7 @@@ static void mlxsw_sp_fdb_notify_work(st
  
  	mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work);
  
 +	mutex_lock(&mlxsw_sp->fdb_lock);
  	do {
  		mlxsw_reg_sfn_pack(sfn_pl);
  		err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
@@@ -827,7 -1383,6 +1386,7 @@@
  			mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
  
  	} while (num_rec);
 +	mutex_unlock(&mlxsw_sp->fdb_lock);
  
  	kfree(sfn_pl);
  	mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
@@@ -842,7 -1397,6 +1401,7 @@@ static int mlxsw_sp_fdb_init(struct mlx
  		dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n");
  		return err;
  	}
 +	mutex_init(&mlxsw_sp->fdb_lock);
  	INIT_DELAYED_WORK(&mlxsw_sp->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
  	mlxsw_sp->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
  	mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
@@@ -882,7 -1436,8 +1441,8 @@@ int mlxsw_sp_port_vlan_init(struct mlxs
  	 * with VID 1.
  	 */
  	mlxsw_sp_port->pvid = 1;
- 	err = __mlxsw_sp_port_vlans_del(mlxsw_sp_port, 0, VLAN_N_VID, true);
+ 	err = __mlxsw_sp_port_vlans_del(mlxsw_sp_port, 0, VLAN_N_VID - 1,
+ 					true);
  	if (err) {
  		netdev_err(dev, "Unable to init VLANs\n");
  		return err;
diff --combined drivers/net/ethernet/renesas/ravb_main.c
index fef4fa12,9e20f37..ac43ed9
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@@ -32,6 -32,8 +32,8 @@@
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  
+ #include <asm/div64.h>
+ 
  #include "ravb.h"
  
  #define RAVB_DEF_MSG_ENABLE \
@@@ -113,12 -115,15 +115,15 @@@ static void ravb_read_mac_address(struc
  	if (mac) {
  		ether_addr_copy(ndev->dev_addr, mac);
  	} else {
- 		ndev->dev_addr[0] = (ravb_read(ndev, MAHR) >> 24);
- 		ndev->dev_addr[1] = (ravb_read(ndev, MAHR) >> 16) & 0xFF;
- 		ndev->dev_addr[2] = (ravb_read(ndev, MAHR) >> 8) & 0xFF;
- 		ndev->dev_addr[3] = (ravb_read(ndev, MAHR) >> 0) & 0xFF;
- 		ndev->dev_addr[4] = (ravb_read(ndev, MALR) >> 8) & 0xFF;
- 		ndev->dev_addr[5] = (ravb_read(ndev, MALR) >> 0) & 0xFF;
+ 		u32 mahr = ravb_read(ndev, MAHR);
+ 		u32 malr = ravb_read(ndev, MALR);
+ 
+ 		ndev->dev_addr[0] = (mahr >> 24) & 0xFF;
+ 		ndev->dev_addr[1] = (mahr >> 16) & 0xFF;
+ 		ndev->dev_addr[2] = (mahr >>  8) & 0xFF;
+ 		ndev->dev_addr[3] = (mahr >>  0) & 0xFF;
+ 		ndev->dev_addr[4] = (malr >>  8) & 0xFF;
+ 		ndev->dev_addr[5] = (malr >>  0) & 0xFF;
  	}
  }
  
@@@ -338,13 -343,16 +343,13 @@@ error
  static void ravb_emac_init(struct net_device *ndev)
  {
  	struct ravb_private *priv = netdev_priv(ndev);
 -	u32 ecmr;
  
  	/* Receive frame limit set register */
  	ravb_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, RFLR);
  
  	/* PAUSE prohibition */
 -	ecmr =  ravb_read(ndev, ECMR);
 -	ecmr &= ECMR_DM;
 -	ecmr |= ECMR_ZPF | (priv->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
 -	ravb_write(ndev, ecmr, ECMR);
 +	ravb_write(ndev, ECMR_ZPF | (priv->duplex ? ECMR_DM : 0) |
 +		   ECMR_TE | ECMR_RE, ECMR);
  
  	ravb_set_rate(ndev);
  
@@@ -402,9 -410,11 +407,11 @@@ static int ravb_dmac_init(struct net_de
  	/* Timestamp enable */
  	ravb_write(ndev, TCCR_TFEN, TCCR);
  
- 	/* Interrupt enable: */
+ 	/* Interrupt init: */
  	/* Frame receive */
  	ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0);
+ 	/* Disable FIFO full warning */
+ 	ravb_write(ndev, 0, RIC1);
  	/* Receive FIFO full error, descriptor empty */
  	ravb_write(ndev, RIC2_QFE0 | RIC2_QFE1 | RIC2_RFFE, RIC2);
  	/* Frame transmitted, timestamp FIFO updated */
@@@ -872,6 -882,7 +879,7 @@@ static int ravb_phy_init(struct net_dev
  	struct ravb_private *priv = netdev_priv(ndev);
  	struct phy_device *phydev;
  	struct device_node *pn;
+ 	int err;
  
  	priv->link = 0;
  	priv->speed = 0;
@@@ -879,6 -890,17 +887,17 @@@
  
  	/* Try connecting to PHY */
  	pn = of_parse_phandle(np, "phy-handle", 0);
+ 	if (!pn) {
+ 		/* In the case of a fixed PHY, the DT node associated
+ 		 * to the PHY is the Ethernet MAC DT node.
+ 		 */
+ 		if (of_phy_is_fixed_link(np)) {
+ 			err = of_phy_register_fixed_link(np);
+ 			if (err)
+ 				return err;
+ 		}
+ 		pn = of_node_get(np);
+ 	}
  	phydev = of_phy_connect(ndev, pn, ravb_adjust_link, 0,
  				priv->phy_interface);
  	if (!phydev) {
@@@ -905,8 -927,7 +924,7 @@@
  	/* 10BASE is not supported */
  	phydev->supported &= ~PHY_10BT_FEATURES;
  
- 	netdev_info(ndev, "attached PHY %d (IRQ %d) to driver %s\n",
- 		    phydev->addr, phydev->irq, phydev->drv->name);
+ 	phy_attached_info(phydev);
  
  	priv->phydev = phydev;
  
@@@ -1229,7 -1250,8 +1247,8 @@@ static int ravb_open(struct net_device 
  	ravb_emac_init(ndev);
  
  	/* Initialise PTP Clock driver */
- 	ravb_ptp_init(ndev, priv->pdev);
+ 	if (priv->chip_id == RCAR_GEN2)
+ 		ravb_ptp_init(ndev, priv->pdev);
  
  	netif_tx_start_all_queues(ndev);
  
@@@ -1242,7 -1264,8 +1261,8 @@@
  
  out_ptp_stop:
  	/* Stop PTP Clock driver */
- 	ravb_ptp_stop(ndev);
+ 	if (priv->chip_id == RCAR_GEN2)
+ 		ravb_ptp_stop(ndev);
  out_free_irq2:
  	if (priv->chip_id == RCAR_GEN3)
  		free_irq(priv->emac_irq, ndev);
@@@ -1471,12 -1494,12 +1491,12 @@@ static int ravb_close(struct net_devic
  
  	/* Disable interrupts by clearing the interrupt masks. */
  	ravb_write(ndev, 0, RIC0);
- 	ravb_write(ndev, 0, RIC1);
  	ravb_write(ndev, 0, RIC2);
  	ravb_write(ndev, 0, TIC);
  
  	/* Stop PTP Clock driver */
- 	ravb_ptp_stop(ndev);
+ 	if (priv->chip_id == RCAR_GEN2)
+ 		ravb_ptp_stop(ndev);
  
  	/* Set the config mode to stop the AVB-DMAC's processes */
  	if (ravb_stop_dma(ndev) < 0)
@@@ -1656,11 -1679,45 +1676,45 @@@ static int ravb_mdio_release(struct rav
  static const struct of_device_id ravb_match_table[] = {
  	{ .compatible = "renesas,etheravb-r8a7790", .data = (void *)RCAR_GEN2 },
  	{ .compatible = "renesas,etheravb-r8a7794", .data = (void *)RCAR_GEN2 },
+ 	{ .compatible = "renesas,etheravb-rcar-gen2", .data = (void *)RCAR_GEN2 },
  	{ .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 },
+ 	{ .compatible = "renesas,etheravb-rcar-gen3", .data = (void *)RCAR_GEN3 },
  	{ }
  };
  MODULE_DEVICE_TABLE(of, ravb_match_table);
  
+ static int ravb_set_gti(struct net_device *ndev)
+ {
+ 
+ 	struct device *dev = ndev->dev.parent;
+ 	struct device_node *np = dev->of_node;
+ 	unsigned long rate;
+ 	struct clk *clk;
+ 	uint64_t inc;
+ 
+ 	clk = of_clk_get(np, 0);
+ 	if (IS_ERR(clk)) {
+ 		dev_err(dev, "could not get clock\n");
+ 		return PTR_ERR(clk);
+ 	}
+ 
+ 	rate = clk_get_rate(clk);
+ 	clk_put(clk);
+ 
+ 	inc = 1000000000ULL << 20;
+ 	do_div(inc, rate);
+ 
+ 	if (inc < GTI_TIV_MIN || inc > GTI_TIV_MAX) {
+ 		dev_err(dev, "gti.tiv increment 0x%llx is outside the range 0x%x - 0x%x\n",
+ 			inc, GTI_TIV_MIN, GTI_TIV_MAX);
+ 		return -EINVAL;
+ 	}
+ 
+ 	ravb_write(ndev, inc, GTI);
+ 
+ 	return 0;
+ }
+ 
  static int ravb_probe(struct platform_device *pdev)
  {
  	struct device_node *np = pdev->dev.of_node;
@@@ -1749,15 -1806,25 +1803,25 @@@
  	ndev->ethtool_ops = &ravb_ethtool_ops;
  
  	/* Set AVB config mode */
- 	ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_OPC) | CCC_OPC_CONFIG,
- 		   CCC);
+ 	if (chip_id == RCAR_GEN2) {
+ 		ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_OPC) |
+ 			   CCC_OPC_CONFIG, CCC);
+ 		/* Set CSEL value */
+ 		ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_CSEL) |
+ 			   CCC_CSEL_HPB, CCC);
+ 	} else {
+ 		ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_OPC) |
+ 			   CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB, CCC);
+ 	}
  
  	/* Set CSEL value */
  	ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_CSEL) | CCC_CSEL_HPB,
  		   CCC);
  
  	/* Set GTI value */
- 	ravb_write(ndev, ((1000 << 20) / 130) & GTI_TIV, GTI);
+ 	error = ravb_set_gti(ndev);
+ 	if (error)
+ 		goto out_release;
  
  	/* Request GTI loading */
  	ravb_write(ndev, ravb_read(ndev, GCCR) | GCCR_LTI, GCCR);
@@@ -1780,6 -1847,10 +1844,10 @@@
  	/* Initialise HW timestamp list */
  	INIT_LIST_HEAD(&priv->ts_skb_list);
  
+ 	/* Initialise PTP Clock driver */
+ 	if (chip_id != RCAR_GEN2)
+ 		ravb_ptp_init(ndev, pdev);
+ 
  	/* Debug message level */
  	priv->msg_enable = RAVB_DEF_MSG_ENABLE;
  
@@@ -1821,6 -1892,10 +1889,10 @@@ out_napi_del
  out_dma_free:
  	dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
  			  priv->desc_bat_dma);
+ 
+ 	/* Stop PTP Clock driver */
+ 	if (chip_id != RCAR_GEN2)
+ 		ravb_ptp_stop(ndev);
  out_release:
  	if (ndev)
  		free_netdev(ndev);
@@@ -1835,6 -1910,10 +1907,10 @@@ static int ravb_remove(struct platform_
  	struct net_device *ndev = platform_get_drvdata(pdev);
  	struct ravb_private *priv = netdev_priv(ndev);
  
+ 	/* Stop PTP Clock driver */
+ 	if (priv->chip_id != RCAR_GEN2)
+ 		ravb_ptp_stop(ndev);
+ 
  	dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
  			  priv->desc_bat_dma);
  	/* Set reset mode */
diff --combined drivers/net/ethernet/renesas/sh_eth.c
index 9c1e290,c5ec57ce..dfa9e59
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@@ -473,6 -473,109 +473,109 @@@ static void sh_eth_set_duplex(struct ne
  		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
  }
  
+ static void sh_eth_chip_reset(struct net_device *ndev)
+ {
+ 	struct sh_eth_private *mdp = netdev_priv(ndev);
+ 
+ 	/* reset device */
+ 	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
+ 	mdelay(1);
+ }
+ 
+ static void sh_eth_set_rate_gether(struct net_device *ndev)
+ {
+ 	struct sh_eth_private *mdp = netdev_priv(ndev);
+ 
+ 	switch (mdp->speed) {
+ 	case 10: /* 10BASE */
+ 		sh_eth_write(ndev, GECMR_10, GECMR);
+ 		break;
+ 	case 100:/* 100BASE */
+ 		sh_eth_write(ndev, GECMR_100, GECMR);
+ 		break;
+ 	case 1000: /* 1000BASE */
+ 		sh_eth_write(ndev, GECMR_1000, GECMR);
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ }
+ 
+ #ifdef CONFIG_OF
+ /* R7S72100 */
+ static struct sh_eth_cpu_data r7s72100_data = {
+ 	.chip_reset	= sh_eth_chip_reset,
+ 	.set_duplex	= sh_eth_set_duplex,
+ 
+ 	.register_type	= SH_ETH_REG_FAST_RZ,
+ 
+ 	.ecsr_value	= ECSR_ICD,
+ 	.ecsipr_value	= ECSIPR_ICDIP,
+ 	.eesipr_value	= 0xff7f009f,
+ 
+ 	.tx_check	= EESR_TC1 | EESR_FTC,
+ 	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
+ 			  EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
+ 			  EESR_TDE | EESR_ECI,
+ 	.fdr_value	= 0x0000070f,
+ 
+ 	.no_psr		= 1,
+ 	.apr		= 1,
+ 	.mpr		= 1,
+ 	.tpauser	= 1,
+ 	.hw_swap	= 1,
+ 	.rpadir		= 1,
+ 	.rpadir_value   = 2 << 16,
+ 	.no_trimd	= 1,
+ 	.no_ade		= 1,
+ 	.hw_crc		= 1,
+ 	.tsu		= 1,
+ 	.shift_rd0	= 1,
+ };
+ 
+ static void sh_eth_chip_reset_r8a7740(struct net_device *ndev)
+ {
+ 	struct sh_eth_private *mdp = netdev_priv(ndev);
+ 
+ 	/* reset device */
+ 	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
+ 	mdelay(1);
+ 
+ 	sh_eth_select_mii(ndev);
+ }
+ 
+ /* R8A7740 */
+ static struct sh_eth_cpu_data r8a7740_data = {
+ 	.chip_reset	= sh_eth_chip_reset_r8a7740,
+ 	.set_duplex	= sh_eth_set_duplex,
+ 	.set_rate	= sh_eth_set_rate_gether,
+ 
+ 	.register_type	= SH_ETH_REG_GIGABIT,
+ 
+ 	.ecsr_value	= ECSR_ICD | ECSR_MPD,
+ 	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
+ 	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+ 
+ 	.tx_check	= EESR_TC1 | EESR_FTC,
+ 	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
+ 			  EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
+ 			  EESR_TDE | EESR_ECI,
+ 	.fdr_value	= 0x0000070f,
+ 
+ 	.apr		= 1,
+ 	.mpr		= 1,
+ 	.tpauser	= 1,
+ 	.bculr		= 1,
+ 	.hw_swap	= 1,
+ 	.rpadir		= 1,
+ 	.rpadir_value   = 2 << 16,
+ 	.no_trimd	= 1,
+ 	.no_ade		= 1,
+ 	.tsu		= 1,
+ 	.select_mii	= 1,
+ 	.shift_rd0	= 1,
+ };
+ 
  /* There is CPU dependent code */
  static void sh_eth_set_rate_r8a777x(struct net_device *ndev)
  {
@@@ -538,6 -641,7 +641,7 @@@ static struct sh_eth_cpu_data r8a779x_d
  	.hw_swap	= 1,
  	.rmiimode	= 1,
  };
+ #endif /* CONFIG_OF */
  
  static void sh_eth_set_rate_sh7724(struct net_device *ndev)
  {
@@@ -695,34 -799,6 +799,6 @@@ static struct sh_eth_cpu_data sh7757_da
  	.tsu		= 1,
  };
  
- static void sh_eth_chip_reset(struct net_device *ndev)
- {
- 	struct sh_eth_private *mdp = netdev_priv(ndev);
- 
- 	/* reset device */
- 	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
- 	mdelay(1);
- }
- 
- static void sh_eth_set_rate_gether(struct net_device *ndev)
- {
- 	struct sh_eth_private *mdp = netdev_priv(ndev);
- 
- 	switch (mdp->speed) {
- 	case 10: /* 10BASE */
- 		sh_eth_write(ndev, GECMR_10, GECMR);
- 		break;
- 	case 100:/* 100BASE */
- 		sh_eth_write(ndev, GECMR_100, GECMR);
- 		break;
- 	case 1000: /* 1000BASE */
- 		sh_eth_write(ndev, GECMR_1000, GECMR);
- 		break;
- 	default:
- 		break;
- 	}
- }
- 
  /* SH7734 */
  static struct sh_eth_cpu_data sh7734_data = {
  	.chip_reset	= sh_eth_chip_reset,
@@@ -780,80 -856,6 +856,6 @@@ static struct sh_eth_cpu_data sh7763_da
  	.irq_flags	= IRQF_SHARED,
  };
  
- static void sh_eth_chip_reset_r8a7740(struct net_device *ndev)
- {
- 	struct sh_eth_private *mdp = netdev_priv(ndev);
- 
- 	/* reset device */
- 	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
- 	mdelay(1);
- 
- 	sh_eth_select_mii(ndev);
- }
- 
- /* R8A7740 */
- static struct sh_eth_cpu_data r8a7740_data = {
- 	.chip_reset	= sh_eth_chip_reset_r8a7740,
- 	.set_duplex	= sh_eth_set_duplex,
- 	.set_rate	= sh_eth_set_rate_gether,
- 
- 	.register_type	= SH_ETH_REG_GIGABIT,
- 
- 	.ecsr_value	= ECSR_ICD | ECSR_MPD,
- 	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
- 	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
- 
- 	.tx_check	= EESR_TC1 | EESR_FTC,
- 	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
- 			  EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
- 			  EESR_TDE | EESR_ECI,
- 	.fdr_value	= 0x0000070f,
- 
- 	.apr		= 1,
- 	.mpr		= 1,
- 	.tpauser	= 1,
- 	.bculr		= 1,
- 	.hw_swap	= 1,
- 	.rpadir		= 1,
- 	.rpadir_value   = 2 << 16,
- 	.no_trimd	= 1,
- 	.no_ade		= 1,
- 	.tsu		= 1,
- 	.select_mii	= 1,
- 	.shift_rd0	= 1,
- };
- 
- /* R7S72100 */
- static struct sh_eth_cpu_data r7s72100_data = {
- 	.chip_reset	= sh_eth_chip_reset,
- 	.set_duplex	= sh_eth_set_duplex,
- 
- 	.register_type	= SH_ETH_REG_FAST_RZ,
- 
- 	.ecsr_value	= ECSR_ICD,
- 	.ecsipr_value	= ECSIPR_ICDIP,
- 	.eesipr_value	= 0xff7f009f,
- 
- 	.tx_check	= EESR_TC1 | EESR_FTC,
- 	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
- 			  EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
- 			  EESR_TDE | EESR_ECI,
- 	.fdr_value	= 0x0000070f,
- 
- 	.no_psr		= 1,
- 	.apr		= 1,
- 	.mpr		= 1,
- 	.tpauser	= 1,
- 	.hw_swap	= 1,
- 	.rpadir		= 1,
- 	.rpadir_value   = 2 << 16,
- 	.no_trimd	= 1,
- 	.no_ade		= 1,
- 	.hw_crc		= 1,
- 	.tsu		= 1,
- 	.shift_rd0	= 1,
- };
- 
  static struct sh_eth_cpu_data sh7619_data = {
  	.register_type	= SH_ETH_REG_FAST_SH3_SH2,
  
@@@ -965,30 -967,6 +967,6 @@@ static void sh_eth_set_receive_align(st
  		skb_reserve(skb, SH_ETH_RX_ALIGN - reserve);
  }
  
- 
- /* CPU <-> EDMAC endian convert */
- static inline __u32 cpu_to_edmac(struct sh_eth_private *mdp, u32 x)
- {
- 	switch (mdp->edmac_endian) {
- 	case EDMAC_LITTLE_ENDIAN:
- 		return cpu_to_le32(x);
- 	case EDMAC_BIG_ENDIAN:
- 		return cpu_to_be32(x);
- 	}
- 	return x;
- }
- 
- static inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
- {
- 	switch (mdp->edmac_endian) {
- 	case EDMAC_LITTLE_ENDIAN:
- 		return le32_to_cpu(x);
- 	case EDMAC_BIG_ENDIAN:
- 		return be32_to_cpu(x);
- 	}
- 	return x;
- }
- 
  /* Program the hardware MAC address from dev->dev_addr. */
  static void update_mac_address(struct net_device *ndev)
  {
@@@ -1011,12 -989,15 +989,15 @@@ static void read_mac_address(struct net
  	if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) {
  		memcpy(ndev->dev_addr, mac, ETH_ALEN);
  	} else {
- 		ndev->dev_addr[0] = (sh_eth_read(ndev, MAHR) >> 24);
- 		ndev->dev_addr[1] = (sh_eth_read(ndev, MAHR) >> 16) & 0xFF;
- 		ndev->dev_addr[2] = (sh_eth_read(ndev, MAHR) >> 8) & 0xFF;
- 		ndev->dev_addr[3] = (sh_eth_read(ndev, MAHR) & 0xFF);
- 		ndev->dev_addr[4] = (sh_eth_read(ndev, MALR) >> 8) & 0xFF;
- 		ndev->dev_addr[5] = (sh_eth_read(ndev, MALR) & 0xFF);
+ 		u32 mahr = sh_eth_read(ndev, MAHR);
+ 		u32 malr = sh_eth_read(ndev, MALR);
+ 
+ 		ndev->dev_addr[0] = (mahr >> 24) & 0xFF;
+ 		ndev->dev_addr[1] = (mahr >> 16) & 0xFF;
+ 		ndev->dev_addr[2] = (mahr >>  8) & 0xFF;
+ 		ndev->dev_addr[3] = (mahr >>  0) & 0xFF;
+ 		ndev->dev_addr[4] = (malr >>  8) & 0xFF;
+ 		ndev->dev_addr[5] = (malr >>  0) & 0xFF;
  	}
  }
  
@@@ -1032,56 -1013,34 +1013,34 @@@ struct bb_info 
  	void (*set_gate)(void *addr);
  	struct mdiobb_ctrl ctrl;
  	void *addr;
- 	u32 mmd_msk;/* MMD */
- 	u32 mdo_msk;
- 	u32 mdi_msk;
- 	u32 mdc_msk;
  };
  
- /* PHY bit set */
- static void bb_set(void *addr, u32 msk)
+ static void sh_mdio_ctrl(struct mdiobb_ctrl *ctrl, u32 mask, int set)
  {
- 	iowrite32(ioread32(addr) | msk, addr);
- }
+ 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+ 	u32 pir;
  
- /* PHY bit clear */
- static void bb_clr(void *addr, u32 msk)
- {
- 	iowrite32((ioread32(addr) & ~msk), addr);
- }
+ 	if (bitbang->set_gate)
+ 		bitbang->set_gate(bitbang->addr);
  
- /* PHY bit read */
- static int bb_read(void *addr, u32 msk)
- {
- 	return (ioread32(addr) & msk) != 0;
+ 	pir = ioread32(bitbang->addr);
+ 	if (set)
+ 		pir |=  mask;
+ 	else
+ 		pir &= ~mask;
+ 	iowrite32(pir, bitbang->addr);
  }
  
  /* Data I/O pin control */
  static void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
  {
- 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
- 
- 	if (bitbang->set_gate)
- 		bitbang->set_gate(bitbang->addr);
- 
- 	if (bit)
- 		bb_set(bitbang->addr, bitbang->mmd_msk);
- 	else
- 		bb_clr(bitbang->addr, bitbang->mmd_msk);
+ 	sh_mdio_ctrl(ctrl, PIR_MMD, bit);
  }
  
  /* Set bit data*/
  static void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
  {
- 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
- 
- 	if (bitbang->set_gate)
- 		bitbang->set_gate(bitbang->addr);
- 
- 	if (bit)
- 		bb_set(bitbang->addr, bitbang->mdo_msk);
- 	else
- 		bb_clr(bitbang->addr, bitbang->mdo_msk);
+ 	sh_mdio_ctrl(ctrl, PIR_MDO, bit);
  }
  
  /* Get bit data*/
@@@ -1092,21 -1051,13 +1051,13 @@@ static int sh_get_mdio(struct mdiobb_ct
  	if (bitbang->set_gate)
  		bitbang->set_gate(bitbang->addr);
  
- 	return bb_read(bitbang->addr, bitbang->mdi_msk);
+ 	return (ioread32(bitbang->addr) & PIR_MDI) != 0;
  }
  
  /* MDC pin control */
  static void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
  {
- 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
- 
- 	if (bitbang->set_gate)
- 		bitbang->set_gate(bitbang->addr);
- 
- 	if (bit)
- 		bb_set(bitbang->addr, bitbang->mdc_msk);
- 	else
- 		bb_clr(bitbang->addr, bitbang->mdc_msk);
+ 	sh_mdio_ctrl(ctrl, PIR_MDC, bit);
  }
  
  /* mdio bus control struct */
@@@ -1189,7 -1140,7 +1140,7 @@@ static void sh_eth_ring_format(struct n
  		rxdesc = &mdp->rx_ring[i];
  		/* The size of the buffer is a multiple of 32 bytes. */
  		buf_len = ALIGN(mdp->rx_buf_sz, 32);
- 		rxdesc->len = cpu_to_edmac(mdp, buf_len << 16);
+ 		rxdesc->len = cpu_to_le32(buf_len << 16);
  		dma_addr = dma_map_single(&ndev->dev, skb->data, buf_len,
  					  DMA_FROM_DEVICE);
  		if (dma_mapping_error(&ndev->dev, dma_addr)) {
@@@ -1197,8 -1148,8 +1148,8 @@@
  			break;
  		}
  		mdp->rx_skbuff[i] = skb;
- 		rxdesc->addr = cpu_to_edmac(mdp, dma_addr);
- 		rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
+ 		rxdesc->addr = cpu_to_le32(dma_addr);
+ 		rxdesc->status = cpu_to_le32(RD_RACT | RD_RFP);
  
  		/* Rx descriptor address set */
  		if (i == 0) {
@@@ -1212,7 -1163,7 +1163,7 @@@
  	mdp->dirty_rx = (u32) (i - mdp->num_rx_ring);
  
  	/* Mark the last entry as wrapping the ring. */
- 	rxdesc->status |= cpu_to_edmac(mdp, RD_RDLE);
+ 	rxdesc->status |= cpu_to_le32(RD_RDLE);
  
  	memset(mdp->tx_ring, 0, tx_ringsize);
  
@@@ -1220,8 -1171,8 +1171,8 @@@
  	for (i = 0; i < mdp->num_tx_ring; i++) {
  		mdp->tx_skbuff[i] = NULL;
  		txdesc = &mdp->tx_ring[i];
- 		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
- 		txdesc->len = cpu_to_edmac(mdp, 0);
+ 		txdesc->status = cpu_to_le32(TD_TFP);
+ 		txdesc->len = cpu_to_le32(0);
  		if (i == 0) {
  			/* Tx descriptor address set */
  			sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
@@@ -1231,7 -1182,7 +1182,7 @@@
  		}
  	}
  
- 	txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
+ 	txdesc->status |= cpu_to_le32(TD_TDLE);
  }
  
  /* Get skb and descriptor buffer */
@@@ -1289,6 -1240,7 +1240,6 @@@ static int sh_eth_dev_init(struct net_d
  {
  	int ret = 0;
  	struct sh_eth_private *mdp = netdev_priv(ndev);
 -	u32 val;
  
  	/* Soft Reset */
  	ret = sh_eth_reset(ndev);
@@@ -1341,8 -1293,10 +1292,8 @@@
  	}
  
  	/* PAUSE Prohibition */
 -	val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
 -		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
 -
 -	sh_eth_write(ndev, val, ECMR);
 +	sh_eth_write(ndev, ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) |
 +		     ECMR_TE | ECMR_RE, ECMR);
  
  	if (mdp->cd->set_rate)
  		mdp->cd->set_rate(ndev);
@@@ -1384,7 -1338,7 +1335,7 @@@ static void sh_eth_dev_exit(struct net_
  	 * packet boundary if it's currently running
  	 */
  	for (i = 0; i < mdp->num_tx_ring; i++)
- 		mdp->tx_ring[i].status &= ~cpu_to_edmac(mdp, TD_TACT);
+ 		mdp->tx_ring[i].status &= ~cpu_to_le32(TD_TACT);
  
  	/* Disable TX FIFO egress to MAC */
  	sh_eth_rcv_snd_disable(ndev);
@@@ -1416,29 -1370,28 +1367,28 @@@ static int sh_eth_txfree(struct net_dev
  	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
  		entry = mdp->dirty_tx % mdp->num_tx_ring;
  		txdesc = &mdp->tx_ring[entry];
- 		if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
+ 		if (txdesc->status & cpu_to_le32(TD_TACT))
  			break;
  		/* TACT bit must be checked before all the following reads */
  		dma_rmb();
  		netif_info(mdp, tx_done, ndev,
  			   "tx entry %d status 0x%08x\n",
- 			   entry, edmac_to_cpu(mdp, txdesc->status));
+ 			   entry, le32_to_cpu(txdesc->status));
  		/* Free the original skb. */
  		if (mdp->tx_skbuff[entry]) {
- 			dma_unmap_single(&ndev->dev,
- 					 edmac_to_cpu(mdp, txdesc->addr),
- 					 edmac_to_cpu(mdp, txdesc->len) >> 16,
+ 			dma_unmap_single(&ndev->dev, le32_to_cpu(txdesc->addr),
+ 					 le32_to_cpu(txdesc->len) >> 16,
  					 DMA_TO_DEVICE);
  			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
  			mdp->tx_skbuff[entry] = NULL;
  			free_num++;
  		}
- 		txdesc->status = cpu_to_edmac(mdp, TD_TFP);
+ 		txdesc->status = cpu_to_le32(TD_TFP);
  		if (entry >= mdp->num_tx_ring - 1)
- 			txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
+ 			txdesc->status |= cpu_to_le32(TD_TDLE);
  
  		ndev->stats.tx_packets++;
- 		ndev->stats.tx_bytes += edmac_to_cpu(mdp, txdesc->len) >> 16;
+ 		ndev->stats.tx_bytes += le32_to_cpu(txdesc->len) >> 16;
  	}
  	return free_num;
  }
@@@ -1462,11 -1415,11 +1412,11 @@@ static int sh_eth_rx(struct net_device 
  	boguscnt = min(boguscnt, *quota);
  	limit = boguscnt;
  	rxdesc = &mdp->rx_ring[entry];
- 	while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
+ 	while (!(rxdesc->status & cpu_to_le32(RD_RACT))) {
  		/* RACT bit must be checked before all the following reads */
  		dma_rmb();
- 		desc_status = edmac_to_cpu(mdp, rxdesc->status);
- 		pkt_len = edmac_to_cpu(mdp, rxdesc->len) & RD_RFL;
+ 		desc_status = le32_to_cpu(rxdesc->status);
+ 		pkt_len = le32_to_cpu(rxdesc->len) & RD_RFL;
  
  		if (--boguscnt < 0)
  			break;
@@@ -1504,7 -1457,7 +1454,7 @@@
  			if (desc_status & RD_RFS10)
  				ndev->stats.rx_over_errors++;
  		} else	if (skb) {
- 			dma_addr = edmac_to_cpu(mdp, rxdesc->addr);
+ 			dma_addr = le32_to_cpu(rxdesc->addr);
  			if (!mdp->cd->hw_swap)
  				sh_eth_soft_swap(
  					phys_to_virt(ALIGN(dma_addr, 4)),
@@@ -1533,7 -1486,7 +1483,7 @@@
  		rxdesc = &mdp->rx_ring[entry];
  		/* The size of the buffer is 32 byte boundary. */
  		buf_len = ALIGN(mdp->rx_buf_sz, 32);
- 		rxdesc->len = cpu_to_edmac(mdp, buf_len << 16);
+ 		rxdesc->len = cpu_to_le32(buf_len << 16);
  
  		if (mdp->rx_skbuff[entry] == NULL) {
  			skb = netdev_alloc_skb(ndev, skbuff_size);
@@@ -1549,15 -1502,14 +1499,14 @@@
  			mdp->rx_skbuff[entry] = skb;
  
  			skb_checksum_none_assert(skb);
- 			rxdesc->addr = cpu_to_edmac(mdp, dma_addr);
+ 			rxdesc->addr = cpu_to_le32(dma_addr);
  		}
  		dma_wmb(); /* RACT bit must be set after all the above writes */
  		if (entry >= mdp->num_rx_ring - 1)
  			rxdesc->status |=
- 				cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDLE);
+ 				cpu_to_le32(RD_RACT | RD_RFP | RD_RDLE);
  		else
- 			rxdesc->status |=
- 				cpu_to_edmac(mdp, RD_RACT | RD_RFP);
+ 			rxdesc->status |= cpu_to_le32(RD_RACT | RD_RFP);
  	}
  
  	/* Restart Rx engine if stopped. */
@@@ -1874,8 -1826,7 +1823,7 @@@ static int sh_eth_phy_init(struct net_d
  		return PTR_ERR(phydev);
  	}
  
- 	netdev_info(ndev, "attached PHY %d (IRQ %d) to driver %s\n",
- 		    phydev->addr, phydev->irq, phydev->drv->name);
+ 	phy_attached_info(phydev);
  
  	mdp->phydev = phydev;
  
@@@ -2357,8 -2308,8 +2305,8 @@@ static void sh_eth_tx_timeout(struct ne
  	/* Free all the skbuffs in the Rx queue. */
  	for (i = 0; i < mdp->num_rx_ring; i++) {
  		rxdesc = &mdp->rx_ring[i];
- 		rxdesc->status = cpu_to_edmac(mdp, 0);
- 		rxdesc->addr = cpu_to_edmac(mdp, 0xBADF00D0);
+ 		rxdesc->status = cpu_to_le32(0);
+ 		rxdesc->addr = cpu_to_le32(0xBADF00D0);
  		dev_kfree_skb(mdp->rx_skbuff[i]);
  		mdp->rx_skbuff[i] = NULL;
  	}
@@@ -2406,14 -2357,14 +2354,14 @@@ static int sh_eth_start_xmit(struct sk_
  		kfree_skb(skb);
  		return NETDEV_TX_OK;
  	}
- 	txdesc->addr = cpu_to_edmac(mdp, dma_addr);
- 	txdesc->len  = cpu_to_edmac(mdp, skb->len << 16);
+ 	txdesc->addr = cpu_to_le32(dma_addr);
+ 	txdesc->len  = cpu_to_le32(skb->len << 16);
  
  	dma_wmb(); /* TACT bit must be set after all the above writes */
  	if (entry >= mdp->num_tx_ring - 1)
- 		txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
+ 		txdesc->status |= cpu_to_le32(TD_TACT | TD_TDLE);
  	else
- 		txdesc->status |= cpu_to_edmac(mdp, TD_TACT);
+ 		txdesc->status |= cpu_to_le32(TD_TACT);
  
  	mdp->cur_tx++;
  
@@@ -2908,7 -2859,7 +2856,7 @@@ static int sh_mdio_release(struct sh_et
  static int sh_mdio_init(struct sh_eth_private *mdp,
  			struct sh_eth_plat_data *pd)
  {
- 	int ret, i;
+ 	int ret;
  	struct bb_info *bitbang;
  	struct platform_device *pdev = mdp->pdev;
  	struct device *dev = &mdp->pdev->dev;
@@@ -2921,10 -2872,6 +2869,6 @@@
  	/* bitbang init */
  	bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
  	bitbang->set_gate = pd->set_mdio_gate;
- 	bitbang->mdi_msk = PIR_MDI;
- 	bitbang->mdo_msk = PIR_MDO;
- 	bitbang->mmd_msk = PIR_MMD;
- 	bitbang->mdc_msk = PIR_MDC;
  	bitbang->ctrl.ops = &bb_ops;
  
  	/* MII controller setting */
@@@ -2938,20 -2885,10 +2882,10 @@@
  	snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
  		 pdev->name, pdev->id);
  
- 	/* PHY IRQ */
- 	mdp->mii_bus->irq = devm_kmalloc_array(dev, PHY_MAX_ADDR, sizeof(int),
- 					       GFP_KERNEL);
- 	if (!mdp->mii_bus->irq) {
- 		ret = -ENOMEM;
- 		goto out_free_bus;
- 	}
- 
  	/* register MDIO bus */
  	if (dev->of_node) {
  		ret = of_mdiobus_register(mdp->mii_bus, dev->of_node);
  	} else {
- 		for (i = 0; i < PHY_MAX_ADDR; i++)
- 			mdp->mii_bus->irq[i] = PHY_POLL;
  		if (pd->phy_irq > 0)
  			mdp->mii_bus->irq[pd->phy] = pd->phy_irq;
  
@@@ -3123,8 -3060,6 +3057,6 @@@ static int sh_eth_drv_probe(struct plat
  	/* get PHY ID */
  	mdp->phy_id = pd->phy;
  	mdp->phy_interface = pd->phy_interface;
- 	/* EDMAC endian */
- 	mdp->edmac_endian = pd->edmac_endian;
  	mdp->no_ether_link = pd->no_ether_link;
  	mdp->ether_link_active_low = pd->ether_link_active_low;
  
@@@ -3304,13 -3239,6 +3236,6 @@@ static struct platform_device_id sh_eth
  	{ "sh7757-ether", (kernel_ulong_t)&sh7757_data },
  	{ "sh7757-gether", (kernel_ulong_t)&sh7757_data_giga },
  	{ "sh7763-gether", (kernel_ulong_t)&sh7763_data },
- 	{ "r7s72100-ether", (kernel_ulong_t)&r7s72100_data },
- 	{ "r8a7740-gether", (kernel_ulong_t)&r8a7740_data },
- 	{ "r8a777x-ether", (kernel_ulong_t)&r8a777x_data },
- 	{ "r8a7790-ether", (kernel_ulong_t)&r8a779x_data },
- 	{ "r8a7791-ether", (kernel_ulong_t)&r8a779x_data },
- 	{ "r8a7793-ether", (kernel_ulong_t)&r8a779x_data },
- 	{ "r8a7794-ether", (kernel_ulong_t)&r8a779x_data },
  	{ }
  };
  MODULE_DEVICE_TABLE(platform, sh_eth_id_table);
diff --combined drivers/net/geneve.c
index db96b0c,24b077a..7456569
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@@ -71,8 -71,14 +71,14 @@@ struct geneve_dev 
  	__be16		   dst_port;
  	bool		   collect_md;
  	struct gro_cells   gro_cells;
+ 	u32		   flags;
  };
  
+ /* Geneve device flags */
+ #define GENEVE_F_UDP_CSUM		BIT(0)
+ #define GENEVE_F_UDP_ZERO_CSUM6_TX	BIT(1)
+ #define GENEVE_F_UDP_ZERO_CSUM6_RX	BIT(2)
+ 
  struct geneve_sock {
  	bool			collect_md;
  	struct list_head	list;
@@@ -81,6 -87,7 +87,7 @@@
  	int			refcnt;
  	struct udp_offload	udp_offloads;
  	struct hlist_head	vni_list[VNI_HASH_SIZE];
+ 	u32			flags;
  };
  
  static inline __u32 geneve_net_vni_hash(u8 vni[3])
@@@ -343,7 -350,7 +350,7 @@@ error
  }
  
  static struct socket *geneve_create_sock(struct net *net, bool ipv6,
- 					 __be16 port)
+ 					 __be16 port, u32 flags)
  {
  	struct socket *sock;
  	struct udp_port_cfg udp_conf;
@@@ -354,6 -361,8 +361,8 @@@
  	if (ipv6) {
  		udp_conf.family = AF_INET6;
  		udp_conf.ipv6_v6only = 1;
+ 		udp_conf.use_udp6_rx_checksums =
+ 		    !(flags & GENEVE_F_UDP_ZERO_CSUM6_RX);
  	} else {
  		udp_conf.family = AF_INET;
  		udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
@@@ -371,16 -380,27 +380,27 @@@
  
  static void geneve_notify_add_rx_port(struct geneve_sock *gs)
  {
+ 	struct net_device *dev;
  	struct sock *sk = gs->sock->sk;
+ 	struct net *net = sock_net(sk);
  	sa_family_t sa_family = sk->sk_family;
+ 	__be16 port = inet_sk(sk)->inet_sport;
  	int err;
  
  	if (sa_family == AF_INET) {
 -		err = udp_add_offload(&gs->udp_offloads);
 +		err = udp_add_offload(sock_net(sk), &gs->udp_offloads);
  		if (err)
  			pr_warn("geneve: udp_add_offload failed with status %d\n",
  				err);
  	}
+ 
+ 	rcu_read_lock();
+ 	for_each_netdev_rcu(net, dev) {
+ 		if (dev->netdev_ops->ndo_add_geneve_port)
+ 			dev->netdev_ops->ndo_add_geneve_port(dev, sa_family,
+ 							     port);
+ 	}
+ 	rcu_read_unlock();
  }
  
  static int geneve_hlen(struct genevehdr *gh)
@@@ -480,7 -500,7 +500,7 @@@ static int geneve_gro_complete(struct s
  
  /* Create new listen socket if needed */
  static struct geneve_sock *geneve_socket_create(struct net *net, __be16 port,
- 						bool ipv6)
+ 						bool ipv6, u32 flags)
  {
  	struct geneve_net *gn = net_generic(net, geneve_net_id);
  	struct geneve_sock *gs;
@@@ -492,7 -512,7 +512,7 @@@
  	if (!gs)
  		return ERR_PTR(-ENOMEM);
  
- 	sock = geneve_create_sock(net, ipv6, port);
+ 	sock = geneve_create_sock(net, ipv6, port, flags);
  	if (IS_ERR(sock)) {
  		kfree(gs);
  		return ERR_CAST(sock);
@@@ -521,8 -541,20 +541,20 @@@
  
  static void geneve_notify_del_rx_port(struct geneve_sock *gs)
  {
+ 	struct net_device *dev;
  	struct sock *sk = gs->sock->sk;
+ 	struct net *net = sock_net(sk);
  	sa_family_t sa_family = sk->sk_family;
+ 	__be16 port = inet_sk(sk)->inet_sport;
+ 
+ 	rcu_read_lock();
+ 	for_each_netdev_rcu(net, dev) {
+ 		if (dev->netdev_ops->ndo_del_geneve_port)
+ 			dev->netdev_ops->ndo_del_geneve_port(dev, sa_family,
+ 							     port);
+ 	}
+ 
+ 	rcu_read_unlock();
  
  	if (sa_family == AF_INET)
  		udp_del_offload(&gs->udp_offloads);
@@@ -575,12 -607,13 +607,13 @@@ static int geneve_sock_add(struct genev
  		goto out;
  	}
  
- 	gs = geneve_socket_create(net, geneve->dst_port, ipv6);
+ 	gs = geneve_socket_create(net, geneve->dst_port, ipv6, geneve->flags);
  	if (IS_ERR(gs))
  		return PTR_ERR(gs);
  
  out:
  	gs->collect_md = geneve->collect_md;
+ 	gs->flags = geneve->flags;
  #if IS_ENABLED(CONFIG_IPV6)
  	if (ipv6)
  		geneve->sock6 = gs;
@@@ -642,11 -675,12 +675,12 @@@ static void geneve_build_header(struct 
  
  static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
  			    __be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
- 			    bool csum, bool xnet)
+ 			    u32 flags, bool xnet)
  {
  	struct genevehdr *gnvh;
  	int min_headroom;
  	int err;
+ 	bool udp_sum = !!(flags & GENEVE_F_UDP_CSUM);
  
  	skb_scrub_packet(skb, xnet);
  
@@@ -658,7 -692,7 +692,7 @@@
  		goto free_rt;
  	}
  
- 	skb = udp_tunnel_handle_offloads(skb, csum);
+ 	skb = udp_tunnel_handle_offloads(skb, udp_sum);
  	if (IS_ERR(skb)) {
  		err = PTR_ERR(skb);
  		goto free_rt;
@@@ -678,11 -712,12 +712,12 @@@ free_rt
  #if IS_ENABLED(CONFIG_IPV6)
  static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb,
  			     __be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
- 			     bool csum, bool xnet)
+ 			     u32 flags, bool xnet)
  {
  	struct genevehdr *gnvh;
  	int min_headroom;
  	int err;
+ 	bool udp_sum = !(flags & GENEVE_F_UDP_ZERO_CSUM6_TX);
  
  	skb_scrub_packet(skb, xnet);
  
@@@ -694,7 -729,7 +729,7 @@@
  		goto free_dst;
  	}
  
- 	skb = udp_tunnel_handle_offloads(skb, csum);
+ 	skb = udp_tunnel_handle_offloads(skb, udp_sum);
  	if (IS_ERR(skb)) {
  		err = PTR_ERR(skb);
  		goto free_dst;
@@@ -824,9 -859,9 +859,9 @@@ static netdev_tx_t geneve_xmit_skb(stru
  	struct flowi4 fl4;
  	__u8 tos, ttl;
  	__be16 sport;
- 	bool udp_csum;
  	__be16 df;
  	bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
+ 	u32 flags = geneve->flags;
  
  	if (geneve->collect_md) {
  		if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
@@@ -857,9 -892,13 +892,13 @@@
  		if (key->tun_flags & TUNNEL_GENEVE_OPT)
  			opts = ip_tunnel_info_opts(info);
  
- 		udp_csum = !!(key->tun_flags & TUNNEL_CSUM);
+ 		if (key->tun_flags & TUNNEL_CSUM)
+ 			flags |= GENEVE_F_UDP_CSUM;
+ 		else
+ 			flags &= ~GENEVE_F_UDP_CSUM;
+ 
  		err = geneve_build_skb(rt, skb, key->tun_flags, vni,
- 				       info->options_len, opts, udp_csum, xnet);
+ 				       info->options_len, opts, flags, xnet);
  		if (unlikely(err))
  			goto err;
  
@@@ -867,9 -906,8 +906,8 @@@
  		ttl = key->ttl;
  		df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
  	} else {
- 		udp_csum = false;
  		err = geneve_build_skb(rt, skb, 0, geneve->vni,
- 				       0, NULL, udp_csum, xnet);
+ 				       0, NULL, flags, xnet);
  		if (unlikely(err))
  			goto err;
  
@@@ -880,12 -918,11 +918,11 @@@
  		ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
  		df = 0;
  	}
- 	err = udp_tunnel_xmit_skb(rt, gs4->sock->sk, skb, fl4.saddr, fl4.daddr,
- 				  tos, ttl, df, sport, geneve->dst_port,
- 				  !net_eq(geneve->net, dev_net(geneve->dev)),
- 				  !udp_csum);
+ 	udp_tunnel_xmit_skb(rt, gs4->sock->sk, skb, fl4.saddr, fl4.daddr,
+ 			    tos, ttl, df, sport, geneve->dst_port,
+ 			    !net_eq(geneve->net, dev_net(geneve->dev)),
+ 			    !(flags & GENEVE_F_UDP_CSUM));
  
- 	iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
  	return NETDEV_TX_OK;
  
  tx_error:
@@@ -912,8 -949,8 +949,8 @@@ static netdev_tx_t geneve6_xmit_skb(str
  	struct flowi6 fl6;
  	__u8 prio, ttl;
  	__be16 sport;
- 	bool udp_csum;
  	bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
+ 	u32 flags = geneve->flags;
  
  	if (geneve->collect_md) {
  		if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
@@@ -942,19 -979,22 +979,22 @@@
  		if (key->tun_flags & TUNNEL_GENEVE_OPT)
  			opts = ip_tunnel_info_opts(info);
  
- 		udp_csum = !!(key->tun_flags & TUNNEL_CSUM);
+ 		if (key->tun_flags & TUNNEL_CSUM)
+ 			flags |= GENEVE_F_UDP_CSUM;
+ 		else
+ 			flags &= ~GENEVE_F_UDP_CSUM;
+ 
  		err = geneve6_build_skb(dst, skb, key->tun_flags, vni,
  					info->options_len, opts,
- 					udp_csum, xnet);
+ 					flags, xnet);
  		if (unlikely(err))
  			goto err;
  
  		prio = ip_tunnel_ecn_encap(key->tos, iip, skb);
  		ttl = key->ttl;
  	} else {
- 		udp_csum = false;
  		err = geneve6_build_skb(dst, skb, 0, geneve->vni,
- 					0, NULL, udp_csum, xnet);
+ 					0, NULL, flags, xnet);
  		if (unlikely(err))
  			goto err;
  
@@@ -964,9 -1004,10 +1004,10 @@@
  			ttl = 1;
  		ttl = ttl ? : ip6_dst_hoplimit(dst);
  	}
- 	err = udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev,
- 				   &fl6.saddr, &fl6.daddr, prio, ttl,
- 				   sport, geneve->dst_port, !udp_csum);
+ 	udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev,
+ 			     &fl6.saddr, &fl6.daddr, prio, ttl,
+ 			     sport, geneve->dst_port,
+ 			     !!(flags & GENEVE_F_UDP_ZERO_CSUM6_TX));
  	return NETDEV_TX_OK;
  
  tx_error:
@@@ -1065,6 -1106,30 +1106,30 @@@ static struct device_type geneve_type 
  	.name = "geneve",
  };
  
+ /* Calls the ndo_add_geneve_port of the caller in order to
+  * supply the listening GENEVE udp ports. Callers are expected
+  * to implement the ndo_add_geneve_port.
+  */
+ void geneve_get_rx_port(struct net_device *dev)
+ {
+ 	struct net *net = dev_net(dev);
+ 	struct geneve_net *gn = net_generic(net, geneve_net_id);
+ 	struct geneve_sock *gs;
+ 	sa_family_t sa_family;
+ 	struct sock *sk;
+ 	__be16 port;
+ 
+ 	rcu_read_lock();
+ 	list_for_each_entry_rcu(gs, &gn->sock_list, list) {
+ 		sk = gs->sock->sk;
+ 		sa_family = sk->sk_family;
+ 		port = inet_sk(sk)->inet_sport;
+ 		dev->netdev_ops->ndo_add_geneve_port(dev, sa_family, port);
+ 	}
+ 	rcu_read_unlock();
+ }
+ EXPORT_SYMBOL_GPL(geneve_get_rx_port);
+ 
  /* Initialize the device structure. */
  static void geneve_setup(struct net_device *dev)
  {
@@@ -1097,6 -1162,9 +1162,9 @@@ static const struct nla_policy geneve_p
  	[IFLA_GENEVE_TOS]		= { .type = NLA_U8 },
  	[IFLA_GENEVE_PORT]		= { .type = NLA_U16 },
  	[IFLA_GENEVE_COLLECT_METADATA]	= { .type = NLA_FLAG },
+ 	[IFLA_GENEVE_UDP_CSUM]		= { .type = NLA_U8 },
+ 	[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]	= { .type = NLA_U8 },
+ 	[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]	= { .type = NLA_U8 },
  };
  
  static int geneve_validate(struct nlattr *tb[], struct nlattr *data[])
@@@ -1150,7 -1218,7 +1218,7 @@@ static struct geneve_dev *geneve_find_d
  static int geneve_configure(struct net *net, struct net_device *dev,
  			    union geneve_addr *remote,
  			    __u32 vni, __u8 ttl, __u8 tos, __be16 dst_port,
- 			    bool metadata)
+ 			    bool metadata, u32 flags)
  {
  	struct geneve_net *gn = net_generic(net, geneve_net_id);
  	struct geneve_dev *t, *geneve = netdev_priv(dev);
@@@ -1181,6 -1249,7 +1249,7 @@@
  	geneve->tos = tos;
  	geneve->dst_port = dst_port;
  	geneve->collect_md = metadata;
+ 	geneve->flags = flags;
  
  	t = geneve_find_dev(gn, dst_port, remote, geneve->vni,
  			    &tun_on_same_port, &tun_collect_md);
@@@ -1219,6 -1288,7 +1288,7 @@@ static int geneve_newlink(struct net *n
  	bool metadata = false;
  	union geneve_addr remote = geneve_remote_unspec;
  	__u32 vni = 0;
+ 	u32 flags = 0;
  
  	if (data[IFLA_GENEVE_REMOTE] && data[IFLA_GENEVE_REMOTE6])
  		return -EINVAL;
@@@ -1259,8 -1329,20 +1329,20 @@@
  	if (data[IFLA_GENEVE_COLLECT_METADATA])
  		metadata = true;
  
+ 	if (data[IFLA_GENEVE_UDP_CSUM] &&
+ 	    nla_get_u8(data[IFLA_GENEVE_UDP_CSUM]))
+ 		flags |= GENEVE_F_UDP_CSUM;
+ 
+ 	if (data[IFLA_GENEVE_UDP_ZERO_CSUM6_TX] &&
+ 	    nla_get_u8(data[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]))
+ 		flags |= GENEVE_F_UDP_ZERO_CSUM6_TX;
+ 
+ 	if (data[IFLA_GENEVE_UDP_ZERO_CSUM6_RX] &&
+ 	    nla_get_u8(data[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]))
+ 		flags |= GENEVE_F_UDP_ZERO_CSUM6_RX;
+ 
  	return geneve_configure(net, dev, &remote, vni, ttl, tos, dst_port,
- 				metadata);
+ 				metadata, flags);
  }
  
  static void geneve_dellink(struct net_device *dev, struct list_head *head)
@@@ -1279,6 -1361,9 +1361,9 @@@ static size_t geneve_get_size(const str
  		nla_total_size(sizeof(__u8)) +  /* IFLA_GENEVE_TOS */
  		nla_total_size(sizeof(__be16)) +  /* IFLA_GENEVE_PORT */
  		nla_total_size(0) +	 /* IFLA_GENEVE_COLLECT_METADATA */
+ 		nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_CSUM */
+ 		nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_ZERO_CSUM6_TX */
+ 		nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_ZERO_CSUM6_RX */
  		0;
  }
  
@@@ -1315,6 -1400,14 +1400,14 @@@ static int geneve_fill_info(struct sk_b
  			goto nla_put_failure;
  	}
  
+ 	if (nla_put_u8(skb, IFLA_GENEVE_UDP_CSUM,
+ 		       !!(geneve->flags & GENEVE_F_UDP_CSUM)) ||
+ 	    nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
+ 		       !!(geneve->flags & GENEVE_F_UDP_ZERO_CSUM6_TX)) ||
+ 	    nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
+ 		       !!(geneve->flags & GENEVE_F_UDP_ZERO_CSUM6_RX)))
+ 		goto nla_put_failure;
+ 
  	return 0;
  
  nla_put_failure:
@@@ -1348,7 -1441,7 +1441,7 @@@ struct net_device *geneve_dev_create_fb
  		return dev;
  
  	err = geneve_configure(net, dev, &geneve_remote_unspec,
- 			       0, 0, 0, htons(dst_port), true);
+ 			       0, 0, 0, htons(dst_port), true, 0);
  	if (err) {
  		free_netdev(dev);
  		return ERR_PTR(err);
diff --combined drivers/net/phy/micrel.c
index 7a56799,0dbc649..03833db
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@@ -73,6 -73,17 +73,17 @@@
  
  #define PS_TO_REG				200
  
+ struct kszphy_hw_stat {
+ 	const char *string;
+ 	u8 reg;
+ 	u8 bits;
+ };
+ 
+ static struct kszphy_hw_stat kszphy_hw_stats[] = {
+ 	{ "phy_receive_errors", 21, 16},
+ 	{ "phy_idle_errors", 10, 8 },
+ };
+ 
  struct kszphy_type {
  	u32 led_mode_reg;
  	u16 interrupt_level_mask;
@@@ -86,6 -97,7 +97,7 @@@ struct kszphy_priv 
  	int led_mode;
  	bool rmii_ref_clk_sel;
  	bool rmii_ref_clk_sel_val;
+ 	u64 stats[ARRAY_SIZE(kszphy_hw_stats)];
  };
  
  static const struct kszphy_type ksz8021_type = {
@@@ -212,7 -224,7 +224,7 @@@ static int kszphy_setup_led(struct phy_
  	rc = phy_write(phydev, reg, temp);
  out:
  	if (rc < 0)
- 		dev_err(&phydev->dev, "failed to set led mode\n");
+ 		phydev_err(phydev, "failed to set led mode\n");
  
  	return rc;
  }
@@@ -231,7 -243,7 +243,7 @@@ static int kszphy_broadcast_disable(str
  	ret = phy_write(phydev, MII_KSZPHY_OMSO, ret | KSZPHY_OMSO_B_CAST_OFF);
  out:
  	if (ret)
- 		dev_err(&phydev->dev, "failed to disable broadcast address\n");
+ 		phydev_err(phydev, "failed to disable broadcast address\n");
  
  	return ret;
  }
@@@ -251,7 -263,7 +263,7 @@@ static int kszphy_nand_tree_disable(str
  			ret & ~KSZPHY_OMSO_NAND_TREE_ON);
  out:
  	if (ret)
- 		dev_err(&phydev->dev, "failed to disable NAND tree mode\n");
+ 		phydev_err(phydev, "failed to disable NAND tree mode\n");
  
  	return ret;
  }
@@@ -276,7 -288,8 +288,8 @@@ static int kszphy_config_init(struct ph
  	if (priv->rmii_ref_clk_sel) {
  		ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val);
  		if (ret) {
- 			dev_err(&phydev->dev, "failed to set rmii reference clock\n");
+ 			phydev_err(phydev,
+ 				   "failed to set rmii reference clock\n");
  			return ret;
  		}
  	}
@@@ -337,7 -350,7 +350,7 @@@ static int ksz9021_load_values_from_of(
  
  static int ksz9021_config_init(struct phy_device *phydev)
  {
- 	const struct device *dev = &phydev->dev;
+ 	const struct device *dev = &phydev->mdio.dev;
  	const struct device_node *of_node = dev->of_node;
  	const struct device *dev_walker;
  
@@@ -345,7 -358,7 +358,7 @@@
  	 * properties in the MAC node. Walk up the tree of devices to
  	 * find a device with an OF node.
  	 */
- 	dev_walker = &phydev->dev;
+ 	dev_walker = &phydev->mdio.dev;
  	do {
  		of_node = dev_walker->of_node;
  		dev_walker = dev_walker->parent;
@@@ -458,7 -471,7 +471,7 @@@ static int ksz9031_center_flp_timing(st
  
  static int ksz9031_config_init(struct phy_device *phydev)
  {
- 	const struct device *dev = &phydev->dev;
+ 	const struct device *dev = &phydev->mdio.dev;
  	const struct device_node *of_node = dev->of_node;
  	static const char *clk_skews[2] = {"rxc-skew-ps", "txc-skew-ps"};
  	static const char *rx_data_skews[4] = {
@@@ -470,17 -483,9 +483,17 @@@
  		"txd2-skew-ps", "txd3-skew-ps"
  	};
  	static const char *control_skews[2] = {"txen-skew-ps", "rxdv-skew-ps"};
 +	const struct device *dev_walker;
  
 -	if (!of_node && dev->parent->of_node)
 -		of_node = dev->parent->of_node;
 +	/* The Micrel driver has a deprecated option to place phy OF
 +	 * properties in the MAC node. Walk up the tree of devices to
 +	 * find a device with an OF node.
 +	 */
- 	dev_walker = &phydev->dev;
++	dev_walker = &phydev->mdio.dev;
 +	do {
 +		of_node = dev_walker->of_node;
 +		dev_walker = dev_walker->parent;
 +	} while (!of_node && dev_walker);
  
  	if (of_node) {
  		ksz9031_of_load_skew_values(phydev, of_node,
@@@ -577,15 -582,60 +590,60 @@@ ksz9021_wr_mmd_phyreg(struct phy_devic
  {
  }
  
+ static int kszphy_get_sset_count(struct phy_device *phydev)
+ {
+ 	return ARRAY_SIZE(kszphy_hw_stats);
+ }
+ 
+ static void kszphy_get_strings(struct phy_device *phydev, u8 *data)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++) {
+ 		memcpy(data + i * ETH_GSTRING_LEN,
+ 		       kszphy_hw_stats[i].string, ETH_GSTRING_LEN);
+ 	}
+ }
+ 
+ #ifndef UINT64_MAX
+ #define UINT64_MAX              (u64)(~((u64)0))
+ #endif
+ static u64 kszphy_get_stat(struct phy_device *phydev, int i)
+ {
+ 	struct kszphy_hw_stat stat = kszphy_hw_stats[i];
+ 	struct kszphy_priv *priv = phydev->priv;
+ 	u64 val;
+ 
+ 	val = phy_read(phydev, stat.reg);
+ 	if (val < 0) {
+ 		val = UINT64_MAX;
+ 	} else {
+ 		val = val & ((1 << stat.bits) - 1);
+ 		priv->stats[i] += val;
+ 		val = priv->stats[i];
+ 	}
+ 
+ 	return val;
+ }
+ 
+ static void kszphy_get_stats(struct phy_device *phydev,
+ 			     struct ethtool_stats *stats, u64 *data)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++)
+ 		data[i] = kszphy_get_stat(phydev, i);
+ }
+ 
  static int kszphy_probe(struct phy_device *phydev)
  {
  	const struct kszphy_type *type = phydev->drv->driver_data;
- 	const struct device_node *np = phydev->dev.of_node;
+ 	const struct device_node *np = phydev->mdio.dev.of_node;
  	struct kszphy_priv *priv;
  	struct clk *clk;
  	int ret;
  
- 	priv = devm_kzalloc(&phydev->dev, sizeof(*priv), GFP_KERNEL);
+ 	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
  	if (!priv)
  		return -ENOMEM;
  
@@@ -600,15 -650,15 +658,15 @@@
  			priv->led_mode = -1;
  
  		if (priv->led_mode > 3) {
- 			dev_err(&phydev->dev, "invalid led mode: 0x%02x\n",
- 					priv->led_mode);
+ 			phydev_err(phydev, "invalid led mode: 0x%02x\n",
+ 				   priv->led_mode);
  			priv->led_mode = -1;
  		}
  	} else {
  		priv->led_mode = -1;
  	}
  
- 	clk = devm_clk_get(&phydev->dev, "rmii-ref");
+ 	clk = devm_clk_get(&phydev->mdio.dev, "rmii-ref");
  	/* NOTE: clk may be NULL if building without CONFIG_HAVE_CLK */
  	if (!IS_ERR_OR_NULL(clk)) {
  		unsigned long rate = clk_get_rate(clk);
@@@ -623,7 -673,8 +681,8 @@@
  		} else if (rate > 49500000 && rate < 50500000) {
  			priv->rmii_ref_clk_sel_val = !rmii_ref_clk_sel_25_mhz;
  		} else {
- 			dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate);
+ 			phydev_err(phydev, "Clock rate out of range: %ld\n",
+ 				   rate);
  			return -EINVAL;
  		}
  	}
@@@ -650,9 -701,11 +709,11 @@@ static struct phy_driver ksphy_driver[
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ8021,
  	.phy_id_mask	= 0x00ffffff,
@@@ -667,9 -720,11 +728,11 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ8031,
  	.phy_id_mask	= 0x00ffffff,
@@@ -684,9 -739,11 +747,11 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ8041,
  	.phy_id_mask	= 0x00fffff0,
@@@ -701,9 -758,11 +766,11 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ8041RNLI,
  	.phy_id_mask	= 0x00fffff0,
@@@ -718,9 -777,11 +785,11 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ8051,
  	.phy_id_mask	= 0x00fffff0,
@@@ -735,9 -796,11 +804,11 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ8001,
  	.name		= "Micrel KSZ8001 or KS8721",
@@@ -751,9 -814,11 +822,11 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ8081,
  	.name		= "Micrel KSZ8081 or KSZ8091",
@@@ -767,9 -832,11 +840,11 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ8061,
  	.name		= "Micrel KSZ8061",
@@@ -781,9 -848,11 +856,11 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE,},
  }, {
  	.phy_id		= PHY_ID_KSZ9021,
  	.phy_id_mask	= 0x000ffffe,
@@@ -796,11 -865,13 +873,13 @@@
  	.read_status	= genphy_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
  	.read_mmd_indirect = ksz9021_rd_mmd_phyreg,
  	.write_mmd_indirect = ksz9021_wr_mmd_phyreg,
- 	.driver		= { .owner = THIS_MODULE, },
  }, {
  	.phy_id		= PHY_ID_KSZ9031,
  	.phy_id_mask	= 0x00fffff0,
@@@ -813,9 -884,11 +892,11 @@@
  	.read_status	= ksz9031_read_status,
  	.ack_interrupt	= kszphy_ack_interrupt,
  	.config_intr	= kszphy_config_intr,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE, },
  }, {
  	.phy_id		= PHY_ID_KSZ8873MLL,
  	.phy_id_mask	= 0x00fffff0,
@@@ -825,9 -898,11 +906,11 @@@
  	.config_init	= kszphy_config_init,
  	.config_aneg	= ksz8873mll_config_aneg,
  	.read_status	= ksz8873mll_read_status,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE, },
  }, {
  	.phy_id		= PHY_ID_KSZ886X,
  	.phy_id_mask	= 0x00fffff0,
@@@ -837,9 -912,11 +920,11 @@@
  	.config_init	= kszphy_config_init,
  	.config_aneg	= genphy_config_aneg,
  	.read_status	= genphy_read_status,
+ 	.get_sset_count = kszphy_get_sset_count,
+ 	.get_strings	= kszphy_get_strings,
+ 	.get_stats	= kszphy_get_stats,
  	.suspend	= genphy_suspend,
  	.resume		= genphy_resume,
- 	.driver		= { .owner = THIS_MODULE, },
  } };
  
  module_phy_driver(ksphy_driver);
diff --combined drivers/net/usb/lan78xx.c
index d54f536,1662b7b..2ed5333
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@@ -603,59 -603,6 +603,59 @@@ static int lan78xx_read_raw_otp(struct 
  	return 0;
  }
  
 +static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset,
 +				 u32 length, u8 *data)
 +{
 +	int i;
 +	int ret;
 +	u32 buf;
 +	unsigned long timeout;
 +
 +	ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
 +
 +	if (buf & OTP_PWR_DN_PWRDN_N_) {
 +		/* clear it and wait to be cleared */
 +		ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0);
 +
 +		timeout = jiffies + HZ;
 +		do {
 +			udelay(1);
 +			ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
 +			if (time_after(jiffies, timeout)) {
 +				netdev_warn(dev->net,
 +					    "timeout on OTP_PWR_DN completion");
 +				return -EIO;
 +			}
 +		} while (buf & OTP_PWR_DN_PWRDN_N_);
 +	}
 +
 +	/* set to BYTE program mode */
 +	ret = lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
 +
 +	for (i = 0; i < length; i++) {
 +		ret = lan78xx_write_reg(dev, OTP_ADDR1,
 +					((offset + i) >> 8) & OTP_ADDR1_15_11);
 +		ret = lan78xx_write_reg(dev, OTP_ADDR2,
 +					((offset + i) & OTP_ADDR2_10_3));
 +		ret = lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]);
 +		ret = lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
 +		ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
 +
 +		timeout = jiffies + HZ;
 +		do {
 +			udelay(1);
 +			ret = lan78xx_read_reg(dev, OTP_STATUS, &buf);
 +			if (time_after(jiffies, timeout)) {
 +				netdev_warn(dev->net,
 +					    "Timeout on OTP_STATUS completion");
 +				return -EIO;
 +			}
 +		} while (buf & OTP_STATUS_BUSY_);
 +	}
 +
 +	return 0;
 +}
 +
  static int lan78xx_read_otp(struct lan78xx_net *dev, u32 offset,
  			    u32 length, u8 *data)
  {
@@@ -1022,7 -969,7 +1022,7 @@@ static int lan78xx_ethtool_set_eeprom(s
  		 (ee->offset == 0) &&
  		 (ee->len == 512) &&
  		 (data[0] == OTP_INDICATOR_1))
 -		return lan78xx_write_raw_eeprom(dev, ee->offset, ee->len, data);
 +		return lan78xx_write_raw_otp(dev, ee->offset, ee->len, data);
  
  	return -EINVAL;
  }
@@@ -1511,12 -1458,6 +1511,6 @@@ static int lan78xx_mdio_init(struct lan
  	snprintf(dev->mdiobus->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
  		 dev->udev->bus->busnum, dev->udev->devnum);
  
- 	dev->mdiobus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
- 	if (!dev->mdiobus->irq) {
- 		ret = -ENOMEM;
- 		goto exit1;
- 	}
- 
  	/* handle our own interrupt */
  	for (i = 0; i < PHY_MAX_ADDR; i++)
  		dev->mdiobus->irq[i] = PHY_IGNORE_INTERRUPT;
@@@ -1532,13 -1473,11 +1526,11 @@@
  	ret = mdiobus_register(dev->mdiobus);
  	if (ret) {
  		netdev_err(dev->net, "can't register MDIO bus\n");
- 		goto exit2;
+ 		goto exit1;
  	}
  
  	netdev_dbg(dev->net, "registered mdiobus bus %s\n", dev->mdiobus->id);
  	return 0;
- exit2:
- 	kfree(dev->mdiobus->irq);
  exit1:
  	mdiobus_free(dev->mdiobus);
  	return ret;
@@@ -1547,7 -1486,6 +1539,6 @@@
  static void lan78xx_remove_mdio(struct lan78xx_net *dev)
  {
  	mdiobus_unregister(dev->mdiobus);
- 	kfree(dev->mdiobus->irq);
  	mdiobus_free(dev->mdiobus);
  }
  
diff --combined drivers/net/usb/qmi_wwan.c
index 772b9d0,3341d8a..23e9880
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@@ -14,7 -14,9 +14,9 @@@
  #include <linux/netdevice.h>
  #include <linux/ethtool.h>
  #include <linux/etherdevice.h>
+ #include <linux/if_arp.h>
  #include <linux/mii.h>
+ #include <linux/rtnetlink.h>
  #include <linux/usb.h>
  #include <linux/usb/cdc.h>
  #include <linux/usb/usbnet.h>
@@@ -48,11 -50,100 +50,100 @@@
  struct qmi_wwan_state {
  	struct usb_driver *subdriver;
  	atomic_t pmcount;
- 	unsigned long unused;
+ 	unsigned long flags;
  	struct usb_interface *control;
  	struct usb_interface *data;
  };
  
+ enum qmi_wwan_flags {
+ 	QMI_WWAN_FLAG_RAWIP = 1 << 0,
+ };
+ 
+ static void qmi_wwan_netdev_setup(struct net_device *net)
+ {
+ 	struct usbnet *dev = netdev_priv(net);
+ 	struct qmi_wwan_state *info = (void *)&dev->data;
+ 
+ 	if (info->flags & QMI_WWAN_FLAG_RAWIP) {
+ 		net->header_ops      = NULL;  /* No header */
+ 		net->type            = ARPHRD_NONE;
+ 		net->hard_header_len = 0;
+ 		net->addr_len        = 0;
+ 		net->flags           = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
+ 		netdev_dbg(net, "mode: raw IP\n");
+ 	} else if (!net->header_ops) { /* don't bother if already set */
+ 		ether_setup(net);
+ 		netdev_dbg(net, "mode: Ethernet\n");
+ 	}
+ 
+ 	/* recalculate buffers after changing hard_header_len */
+ 	usbnet_change_mtu(net, net->mtu);
+ }
+ 
+ static ssize_t raw_ip_show(struct device *d, struct device_attribute *attr, char *buf)
+ {
+ 	struct usbnet *dev = netdev_priv(to_net_dev(d));
+ 	struct qmi_wwan_state *info = (void *)&dev->data;
+ 
+ 	return sprintf(buf, "%c\n", info->flags & QMI_WWAN_FLAG_RAWIP ? 'Y' : 'N');
+ }
+ 
+ static ssize_t raw_ip_store(struct device *d,  struct device_attribute *attr, const char *buf, size_t len)
+ {
+ 	struct usbnet *dev = netdev_priv(to_net_dev(d));
+ 	struct qmi_wwan_state *info = (void *)&dev->data;
+ 	bool enable;
+ 	int ret;
+ 
+ 	if (strtobool(buf, &enable))
+ 		return -EINVAL;
+ 
+ 	/* no change? */
+ 	if (enable == (info->flags & QMI_WWAN_FLAG_RAWIP))
+ 		return len;
+ 
+ 	if (!rtnl_trylock())
+ 		return restart_syscall();
+ 
+ 	/* we don't want to modify a running netdev */
+ 	if (netif_running(dev->net)) {
+ 		netdev_err(dev->net, "Cannot change a running device\n");
+ 		ret = -EBUSY;
+ 		goto err;
+ 	}
+ 
+ 	/* let other drivers deny the change */
+ 	ret = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev->net);
+ 	ret = notifier_to_errno(ret);
+ 	if (ret) {
+ 		netdev_err(dev->net, "Type change was refused\n");
+ 		goto err;
+ 	}
+ 
+ 	if (enable)
+ 		info->flags |= QMI_WWAN_FLAG_RAWIP;
+ 	else
+ 		info->flags &= ~QMI_WWAN_FLAG_RAWIP;
+ 	qmi_wwan_netdev_setup(dev->net);
+ 	call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev->net);
+ 	ret = len;
+ err:
+ 	rtnl_unlock();
+ 	return ret;
+ }
+ 
+ static DEVICE_ATTR_RW(raw_ip);
+ 
+ static struct attribute *qmi_wwan_sysfs_attrs[] = {
+ 	&dev_attr_raw_ip.attr,
+ 	NULL,
+ };
+ 
+ static struct attribute_group qmi_wwan_sysfs_attr_group = {
+ 	.name = "qmi",
+ 	.attrs = qmi_wwan_sysfs_attrs,
+ };
+ 
  /* default ethernet address used by the modem */
  static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
  
@@@ -80,6 -171,8 +171,8 @@@ static const u8 buggy_fw_addr[ETH_ALEN
   */
  static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
  {
+ 	struct qmi_wwan_state *info = (void *)&dev->data;
+ 	bool rawip = info->flags & QMI_WWAN_FLAG_RAWIP;
  	__be16 proto;
  
  	/* This check is no longer done by usbnet */
@@@ -94,15 -187,25 +187,25 @@@
  		proto = htons(ETH_P_IPV6);
  		break;
  	case 0x00:
+ 		if (rawip)
+ 			return 0;
  		if (is_multicast_ether_addr(skb->data))
  			return 1;
  		/* possibly bogus destination - rewrite just in case */
  		skb_reset_mac_header(skb);
  		goto fix_dest;
  	default:
+ 		if (rawip)
+ 			return 0;
  		/* pass along other packets without modifications */
  		return 1;
  	}
+ 	if (rawip) {
+ 		skb->dev = dev->net; /* normally set by eth_type_trans */
+ 		skb->protocol = proto;
+ 		return 1;
+ 	}
+ 
  	if (skb_headroom(skb) < ETH_HLEN)
  		return 0;
  	skb_push(skb, ETH_HLEN);
@@@ -223,6 -326,20 +326,20 @@@ err
  	return rv;
  }
  
+ /* Send CDC SetControlLineState request, setting or clearing the DTR.
+  * "Required for Autoconnect and 9x30 to wake up" according to the
+  * GobiNet driver. The requirement has been verified on an MDM9230
+  * based Sierra Wireless MC7455
+  */
+ static int qmi_wwan_change_dtr(struct usbnet *dev, bool on)
+ {
+ 	u8 intf = dev->intf->cur_altsetting->desc.bInterfaceNumber;
+ 
+ 	return usbnet_write_cmd(dev, USB_CDC_REQ_SET_CONTROL_LINE_STATE,
+ 				USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 				on ? 0x01 : 0x00, intf, NULL, 0);
+ }
+ 
  static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
  {
  	int status = -1;
@@@ -257,7 -374,10 +374,10 @@@
  				"bogus CDC Union: master=%u, slave=%u\n",
  				cdc_union->bMasterInterface0,
  				cdc_union->bSlaveInterface0);
- 			goto err;
+ 
+ 			/* ignore and continue... */
+ 			cdc_union = NULL;
+ 			info->data = intf;
  		}
  	}
  
@@@ -280,6 -400,24 +400,24 @@@
  		usb_driver_release_interface(driver, info->data);
  	}
  
+ 	/* disabling remote wakeup on MDM9x30 devices has the same
+ 	 * effect as clearing DTR. The device will not respond to QMI
+ 	 * requests until we set DTR again.  This is similar to a
+ 	 * QMI_CTL SYNC request, clearing a lot of firmware state
+ 	 * including the client ID allocations.
+ 	 *
+ 	 * Our usage model allows a session to span multiple
+ 	 * open/close events, so we must prevent the firmware from
+ 	 * clearing out state the clients might need.
+ 	 *
+ 	 * MDM9x30 is the first QMI chipset with USB3 support. Abuse
+ 	 * this fact to enable the quirk.
+ 	 */
+ 	if (le16_to_cpu(dev->udev->descriptor.bcdUSB) >= 0x0201) {
+ 		qmi_wwan_manage_power(dev, 1);
+ 		qmi_wwan_change_dtr(dev, true);
+ 	}
+ 
  	/* Never use the same address on both ends of the link, even if the
  	 * buggy firmware told us to. Or, if device is assigned the well-known
  	 * buggy firmware MAC address, replace it with a random address,
@@@ -294,6 -432,7 +432,7 @@@
  		dev->net->dev_addr[0] &= 0xbf;	/* clear "IP" bit */
  	}
  	dev->net->netdev_ops = &qmi_wwan_netdev_ops;
+ 	dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group;
  err:
  	return status;
  }
@@@ -307,6 -446,12 +446,12 @@@ static void qmi_wwan_unbind(struct usbn
  	if (info->subdriver && info->subdriver->disconnect)
  		info->subdriver->disconnect(info->control);
  
+ 	/* disable MDM9x30 quirk */
+ 	if (le16_to_cpu(dev->udev->descriptor.bcdUSB) >= 0x0201) {
+ 		qmi_wwan_change_dtr(dev, false);
+ 		qmi_wwan_manage_power(dev, 0);
+ 	}
+ 
  	/* allow user to unbind using either control or data */
  	if (intf == info->control)
  		other = info->data;
@@@ -715,8 -860,6 +860,6 @@@ static const struct usb_device_id produ
  	{QMI_FIXED_INTF(0x1199, 0x9056, 8)},	/* Sierra Wireless Modem */
  	{QMI_FIXED_INTF(0x1199, 0x9057, 8)},
  	{QMI_FIXED_INTF(0x1199, 0x9061, 8)},	/* Sierra Wireless Modem */
- 	{QMI_FIXED_INTF(0x1199, 0x9070, 8)},	/* Sierra Wireless MC74xx/EM74xx */
- 	{QMI_FIXED_INTF(0x1199, 0x9070, 10)},	/* Sierra Wireless MC74xx/EM74xx */
  	{QMI_FIXED_INTF(0x1199, 0x9071, 8)},	/* Sierra Wireless MC74xx/EM74xx */
  	{QMI_FIXED_INTF(0x1199, 0x9071, 10)},	/* Sierra Wireless MC74xx/EM74xx */
  	{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},	/* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
@@@ -743,7 -886,6 +886,7 @@@
  	{QMI_FIXED_INTF(0x413c, 0x81b1, 8)},	/* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
  	{QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},	/* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
  	{QMI_FIXED_INTF(0x22de, 0x9061, 3)},	/* WeTelecom WPD-600N */
 +	{QMI_FIXED_INTF(0x1e0e, 0x9001, 5)},	/* SIMCom 7230E */
  
  	/* 4. Gobi 1000 devices */
  	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
diff --combined drivers/net/usb/r8152.c
index ef9aab6,230c73c..d1f78c2
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@@ -25,13 -25,12 +25,13 @@@
  #include <uapi/linux/mdio.h>
  #include <linux/mdio.h>
  #include <linux/usb/cdc.h>
 +#include <linux/suspend.h>
  
  /* Information for net-next */
  #define NETNEXT_VERSION		"08"
  
  /* Information for net */
 -#define NET_VERSION		"2"
 +#define NET_VERSION		"3"
  
  #define DRIVER_VERSION		"v1." NETNEXT_VERSION "." NET_VERSION
  #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd at realtek.com>"
@@@ -605,9 -604,6 +605,9 @@@ struct r8152 
  	struct delayed_work schedule;
  	struct mii_if_info mii;
  	struct mutex control;	/* use for hw setting */
 +#ifdef CONFIG_PM_SLEEP
 +	struct notifier_block pm_notifier;
 +#endif
  
  	struct rtl_ops {
  		void (*init)(struct r8152 *);
@@@ -1942,7 -1938,6 +1942,6 @@@ static void _rtl8152_set_rx_mode(struc
  	__le32 tmp[2];
  	u32 ocp_data;
  
- 	clear_bit(RTL8152_SET_RX_MODE, &tp->flags);
  	netif_stop_queue(netdev);
  	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
  	ocp_data &= ~RCR_ACPT_ALL;
@@@ -1990,7 -1985,7 +1989,7 @@@ rtl8152_features_check(struct sk_buff *
  	int offset = skb_transport_offset(skb);
  
  	if ((mss || skb->ip_summed == CHECKSUM_PARTIAL) && offset > max_offset)
- 		features &= ~(NETIF_F_ALL_CSUM | NETIF_F_GSO_MASK);
+ 		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
  	else if ((skb->len + sizeof(struct tx_desc)) > agg_buf_sz)
  		features &= ~NETIF_F_GSO_MASK;
  
@@@ -2428,8 -2423,6 +2427,6 @@@ static void rtl_phy_reset(struct r8152 
  	u16 data;
  	int i;
  
- 	clear_bit(PHY_RESET, &tp->flags);
- 
  	data = r8152_mdio_read(tp, MII_BMCR);
  
  	/* don't reset again before the previous one complete */
@@@ -2459,23 -2452,23 +2456,23 @@@ static void r8153_teredo_off(struct r81
  	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0);
  }
  
- static void r8152b_disable_aldps(struct r8152 *tp)
- {
- 	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
- 	msleep(20);
- }
- 
- static inline void r8152b_enable_aldps(struct r8152 *tp)
+ static void r8152_aldps_en(struct r8152 *tp, bool enable)
  {
- 	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
- 					    LINKENA | DIS_SDSAVE);
+ 	if (enable) {
+ 		ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
+ 						    LINKENA | DIS_SDSAVE);
+ 	} else {
+ 		ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA |
+ 						    DIS_SDSAVE);
+ 		msleep(20);
+ 	}
  }
  
  static void rtl8152_disable(struct r8152 *tp)
  {
- 	r8152b_disable_aldps(tp);
+ 	r8152_aldps_en(tp, false);
  	rtl_disable(tp);
- 	r8152b_enable_aldps(tp);
+ 	r8152_aldps_en(tp, true);
  }
  
  static void r8152b_hw_phy_cfg(struct r8152 *tp)
@@@ -2787,30 -2780,26 +2784,26 @@@ static void r8153_enter_oob(struct r815
  	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
  }
  
- static void r8153_disable_aldps(struct r8152 *tp)
+ static void r8153_aldps_en(struct r8152 *tp, bool enable)
  {
  	u16 data;
  
  	data = ocp_reg_read(tp, OCP_POWER_CFG);
- 	data &= ~EN_ALDPS;
- 	ocp_reg_write(tp, OCP_POWER_CFG, data);
- 	msleep(20);
- }
- 
- static void r8153_enable_aldps(struct r8152 *tp)
- {
- 	u16 data;
- 
- 	data = ocp_reg_read(tp, OCP_POWER_CFG);
- 	data |= EN_ALDPS;
- 	ocp_reg_write(tp, OCP_POWER_CFG, data);
+ 	if (enable) {
+ 		data |= EN_ALDPS;
+ 		ocp_reg_write(tp, OCP_POWER_CFG, data);
+ 	} else {
+ 		data &= ~EN_ALDPS;
+ 		ocp_reg_write(tp, OCP_POWER_CFG, data);
+ 		msleep(20);
+ 	}
  }
  
  static void rtl8153_disable(struct r8152 *tp)
  {
- 	r8153_disable_aldps(tp);
+ 	r8153_aldps_en(tp, false);
  	rtl_disable(tp);
- 	r8153_enable_aldps(tp);
+ 	r8153_aldps_en(tp, true);
  	usb_enable_lpm(tp->udev);
  }
  
@@@ -2888,10 -2877,9 +2881,9 @@@ static int rtl8152_set_speed(struct r81
  	r8152_mdio_write(tp, MII_ADVERTISE, anar);
  	r8152_mdio_write(tp, MII_BMCR, bmcr);
  
- 	if (test_bit(PHY_RESET, &tp->flags)) {
+ 	if (test_and_clear_bit(PHY_RESET, &tp->flags)) {
  		int i;
  
- 		clear_bit(PHY_RESET, &tp->flags);
  		for (i = 0; i < 50; i++) {
  			msleep(20);
  			if ((r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET) == 0)
@@@ -2900,7 -2888,6 +2892,6 @@@
  	}
  
  out:
- 
  	return ret;
  }
  
@@@ -2909,9 -2896,9 +2900,9 @@@ static void rtl8152_up(struct r8152 *tp
  	if (test_bit(RTL8152_UNPLUG, &tp->flags))
  		return;
  
- 	r8152b_disable_aldps(tp);
+ 	r8152_aldps_en(tp, false);
  	r8152b_exit_oob(tp);
- 	r8152b_enable_aldps(tp);
+ 	r8152_aldps_en(tp, true);
  }
  
  static void rtl8152_down(struct r8152 *tp)
@@@ -2922,9 -2909,9 +2913,9 @@@
  	}
  
  	r8152_power_cut_en(tp, false);
- 	r8152b_disable_aldps(tp);
+ 	r8152_aldps_en(tp, false);
  	r8152b_enter_oob(tp);
- 	r8152b_enable_aldps(tp);
+ 	r8152_aldps_en(tp, true);
  }
  
  static void rtl8153_up(struct r8152 *tp)
@@@ -2933,9 -2920,9 +2924,9 @@@
  		return;
  
  	r8153_u1u2en(tp, false);
- 	r8153_disable_aldps(tp);
+ 	r8153_aldps_en(tp, false);
  	r8153_first_init(tp);
- 	r8153_enable_aldps(tp);
+ 	r8153_aldps_en(tp, true);
  	r8153_u2p3en(tp, true);
  	r8153_u1u2en(tp, true);
  	usb_enable_lpm(tp->udev);
@@@ -2951,9 -2938,9 +2942,9 @@@ static void rtl8153_down(struct r8152 *
  	r8153_u1u2en(tp, false);
  	r8153_u2p3en(tp, false);
  	r8153_power_cut_en(tp, false);
- 	r8153_disable_aldps(tp);
+ 	r8153_aldps_en(tp, false);
  	r8153_enter_oob(tp);
- 	r8153_enable_aldps(tp);
+ 	r8153_aldps_en(tp, true);
  }
  
  static bool rtl8152_in_nway(struct r8152 *tp)
@@@ -2987,7 -2974,6 +2978,6 @@@ static void set_carrier(struct r8152 *t
  	struct net_device *netdev = tp->netdev;
  	u8 speed;
  
- 	clear_bit(RTL8152_LINK_CHG, &tp->flags);
  	speed = rtl8152_get_speed(tp);
  
  	if (speed & LINK_STATUS) {
@@@ -3030,20 -3016,18 +3020,18 @@@ static void rtl_work_func_t(struct work
  		goto out1;
  	}
  
- 	if (test_bit(RTL8152_LINK_CHG, &tp->flags))
+ 	if (test_and_clear_bit(RTL8152_LINK_CHG, &tp->flags))
  		set_carrier(tp);
  
- 	if (test_bit(RTL8152_SET_RX_MODE, &tp->flags))
+ 	if (test_and_clear_bit(RTL8152_SET_RX_MODE, &tp->flags))
  		_rtl8152_set_rx_mode(tp->netdev);
  
  	/* don't schedule napi before linking */
- 	if (test_bit(SCHEDULE_NAPI, &tp->flags) &&
- 	    netif_carrier_ok(tp->netdev)) {
- 		clear_bit(SCHEDULE_NAPI, &tp->flags);
+ 	if (test_and_clear_bit(SCHEDULE_NAPI, &tp->flags) &&
+ 	    netif_carrier_ok(tp->netdev))
  		napi_schedule(&tp->napi);
- 	}
  
- 	if (test_bit(PHY_RESET, &tp->flags))
+ 	if (test_and_clear_bit(PHY_RESET, &tp->flags))
  		rtl_phy_reset(tp);
  
  	mutex_unlock(&tp->control);
@@@ -3052,33 -3036,6 +3040,33 @@@ out1
  	usb_autopm_put_interface(tp->intf);
  }
  
 +#ifdef CONFIG_PM_SLEEP
 +static int rtl_notifier(struct notifier_block *nb, unsigned long action,
 +			void *data)
 +{
 +	struct r8152 *tp = container_of(nb, struct r8152, pm_notifier);
 +
 +	switch (action) {
 +	case PM_HIBERNATION_PREPARE:
 +	case PM_SUSPEND_PREPARE:
 +		usb_autopm_get_interface(tp->intf);
 +		break;
 +
 +	case PM_POST_HIBERNATION:
 +	case PM_POST_SUSPEND:
 +		usb_autopm_put_interface(tp->intf);
 +		break;
 +
 +	case PM_POST_RESTORE:
 +	case PM_RESTORE_PREPARE:
 +	default:
 +		break;
 +	}
 +
 +	return NOTIFY_DONE;
 +}
 +#endif
 +
  static int rtl8152_open(struct net_device *netdev)
  {
  	struct r8152 *tp = netdev_priv(netdev);
@@@ -3121,10 -3078,6 +3109,10 @@@
  	mutex_unlock(&tp->control);
  
  	usb_autopm_put_interface(tp->intf);
 +#ifdef CONFIG_PM_SLEEP
 +	tp->pm_notifier.notifier_call = rtl_notifier;
 +	register_pm_notifier(&tp->pm_notifier);
 +#endif
  
  out:
  	return res;
@@@ -3135,9 -3088,6 +3123,9 @@@ static int rtl8152_close(struct net_dev
  	struct r8152 *tp = netdev_priv(netdev);
  	int res = 0;
  
 +#ifdef CONFIG_PM_SLEEP
 +	unregister_pm_notifier(&tp->pm_notifier);
 +#endif
  	napi_disable(&tp->napi);
  	clear_bit(WORK_ENABLE, &tp->flags);
  	usb_kill_urb(tp->intr_urb);
@@@ -3276,7 -3226,7 +3264,7 @@@ static void r8152b_init(struct r8152 *t
  	if (test_bit(RTL8152_UNPLUG, &tp->flags))
  		return;
  
- 	r8152b_disable_aldps(tp);
+ 	r8152_aldps_en(tp, false);
  
  	if (tp->version == RTL_VER_01) {
  		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
@@@ -3298,7 -3248,7 +3286,7 @@@
  	ocp_write_word(tp, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data);
  
  	r8152b_enable_eee(tp);
- 	r8152b_enable_aldps(tp);
+ 	r8152_aldps_en(tp, true);
  	r8152b_enable_fc(tp);
  	rtl_tally_reset(tp);
  
@@@ -3316,7 -3266,7 +3304,7 @@@ static void r8153_init(struct r8152 *tp
  	if (test_bit(RTL8152_UNPLUG, &tp->flags))
  		return;
  
- 	r8153_disable_aldps(tp);
+ 	r8153_aldps_en(tp, false);
  	r8153_u1u2en(tp, false);
  
  	for (i = 0; i < 500; i++) {
@@@ -3405,7 -3355,7 +3393,7 @@@
  		       EEE_SPDWN_EN);
  
  	r8153_enable_eee(tp);
- 	r8153_enable_aldps(tp);
+ 	r8153_aldps_en(tp, true);
  	r8152b_enable_fc(tp);
  	rtl_tally_reset(tp);
  	r8153_u2p3en(tp, true);
diff --combined drivers/net/vxlan.c
index e1e147f,fecf7b6..2d88c79
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@@ -621,7 -621,7 +621,7 @@@ static void vxlan_notify_add_rx_port(st
  	int err;
  
  	if (sa_family == AF_INET) {
 -		err = udp_add_offload(&vs->udp_offloads);
 +		err = udp_add_offload(net, &vs->udp_offloads);
  		if (err)
  			pr_warn("vxlan: udp_add_offload failed with status %d\n", err);
  	}
@@@ -1841,9 -1841,10 +1841,10 @@@ static int vxlan_xmit_skb(struct rtabl
  
  	skb_set_inner_protocol(skb, htons(ETH_P_TEB));
  
- 	return udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos,
- 				   ttl, df, src_port, dst_port, xnet,
- 				   !(vxflags & VXLAN_F_UDP_CSUM));
+ 	udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos, ttl, df,
+ 			    src_port, dst_port, xnet,
+ 			    !(vxflags & VXLAN_F_UDP_CSUM));
+ 	return 0;
  }
  
  #if IS_ENABLED(CONFIG_IPV6)
@@@ -2056,8 -2057,6 +2057,6 @@@ static void vxlan_xmit_one(struct sk_bu
  			skb = NULL;
  			goto rt_tx_error;
  		}
- 
- 		iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
  #if IS_ENABLED(CONFIG_IPV6)
  	} else {
  		struct dst_entry *ndst;
@@@ -2751,7 -2750,7 +2750,7 @@@ static int vxlan_dev_configure(struct n
  			       struct vxlan_config *conf)
  {
  	struct vxlan_net *vn = net_generic(src_net, vxlan_net_id);
 -	struct vxlan_dev *vxlan = netdev_priv(dev);
 +	struct vxlan_dev *vxlan = netdev_priv(dev), *tmp;
  	struct vxlan_rdst *dst = &vxlan->default_dst;
  	unsigned short needed_headroom = ETH_HLEN;
  	int err;
@@@ -2817,15 -2816,9 +2816,15 @@@
  	if (!vxlan->cfg.age_interval)
  		vxlan->cfg.age_interval = FDB_AGE_DEFAULT;
  
 -	if (vxlan_find_vni(src_net, conf->vni, use_ipv6 ? AF_INET6 : AF_INET,
 -			   vxlan->cfg.dst_port, vxlan->flags))
 +	list_for_each_entry(tmp, &vn->vxlan_list, next) {
 +		if (tmp->cfg.vni == conf->vni &&
 +		    (tmp->default_dst.remote_ip.sa.sa_family == AF_INET6 ||
 +		     tmp->cfg.saddr.sa.sa_family == AF_INET6) == use_ipv6 &&
 +		    tmp->cfg.dst_port == vxlan->cfg.dst_port &&
 +		    (tmp->flags & VXLAN_F_RCV_FLAGS) ==
 +		    (vxlan->flags & VXLAN_F_RCV_FLAGS))
  		return -EEXIST;
 +	}
  
  	dev->ethtool_ops = &vxlan_ethtool_ops;
  
diff --combined drivers/net/wireless/marvell/libertas/debugfs.c
index faed182,26cbf1d..faed182
--- a/drivers/net/wireless/marvell/libertas/debugfs.c
+++ b/drivers/net/wireless/marvell/libertas/debugfs.c
@@@ -56,15 -56,19 +56,15 @@@ static ssize_t lbs_sleepparams_write(st
  				loff_t *ppos)
  {
  	struct lbs_private *priv = file->private_data;
 -	ssize_t buf_size, ret;
 +	ssize_t ret;
  	struct sleep_params sp;
  	int p1, p2, p3, p4, p5, p6;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	if (!buf)
 -		return -ENOMEM;
 +	char *buf;
 +
 +	buf = memdup_user_nul(user_buf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, user_buf, buf_size)) {
 -		ret = -EFAULT;
 -		goto out_unlock;
 -	}
  	ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
  	if (ret != 6) {
  		ret = -EINVAL;
@@@ -84,7 -88,7 +84,7 @@@
  		ret = -EINVAL;
  
  out_unlock:
 -	free_page(addr);
 +	kfree(buf);
  	return ret;
  }
  
@@@ -121,14 -125,18 +121,14 @@@ static ssize_t lbs_host_sleep_write(str
  				loff_t *ppos)
  {
  	struct lbs_private *priv = file->private_data;
 -	ssize_t buf_size, ret;
 +	ssize_t ret;
  	int host_sleep;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	if (!buf)
 -		return -ENOMEM;
 +	char *buf;
 +
 +	buf = memdup_user_nul(user_buf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, user_buf, buf_size)) {
 -		ret = -EFAULT;
 -		goto out_unlock;
 -	}
  	ret = sscanf(buf, "%d", &host_sleep);
  	if (ret != 1) {
  		ret = -EINVAL;
@@@ -154,7 -162,7 +154,7 @@@
  		ret = count;
  
  out_unlock:
 -	free_page(addr);
 +	kfree(buf);
  	return ret;
  }
  
@@@ -273,15 -281,21 +273,15 @@@ static ssize_t lbs_threshold_write(uint
  	struct cmd_ds_802_11_subscribe_event *events;
  	struct mrvl_ie_thresholds *tlv;
  	struct lbs_private *priv = file->private_data;
 -	ssize_t buf_size;
  	int value, freq, new_mask;
  	uint16_t curr_mask;
  	char *buf;
  	int ret;
  
 -	buf = (char *)get_zeroed_page(GFP_KERNEL);
 -	if (!buf)
 -		return -ENOMEM;
 +	buf = memdup_user_nul(userbuf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, userbuf, buf_size)) {
 -		ret = -EFAULT;
 -		goto out_page;
 -	}
  	ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
  	if (ret != 3) {
  		ret = -EINVAL;
@@@ -329,7 -343,7 +329,7 @@@
   out_events:
  	kfree(events);
   out_page:
 -	free_page((unsigned long)buf);
 +	kfree(buf);
  	return ret;
  }
  
@@@ -458,15 -472,22 +458,15 @@@ static ssize_t lbs_rdmac_write(struct f
  				    size_t count, loff_t *ppos)
  {
  	struct lbs_private *priv = file->private_data;
 -	ssize_t res, buf_size;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	if (!buf)
 -		return -ENOMEM;
 +	char *buf;
 +
 +	buf = memdup_user_nul(userbuf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, userbuf, buf_size)) {
 -		res = -EFAULT;
 -		goto out_unlock;
 -	}
  	priv->mac_offset = simple_strtoul(buf, NULL, 16);
 -	res = count;
 -out_unlock:
 -	free_page(addr);
 -	return res;
 +	kfree(buf);
 +	return count;
  }
  
  static ssize_t lbs_wrmac_write(struct file *file,
@@@ -475,14 -496,18 +475,14 @@@
  {
  
  	struct lbs_private *priv = file->private_data;
 -	ssize_t res, buf_size;
 +	ssize_t res;
  	u32 offset, value;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	if (!buf)
 -		return -ENOMEM;
 +	char *buf;
 +
 +	buf = memdup_user_nul(userbuf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, userbuf, buf_size)) {
 -		res = -EFAULT;
 -		goto out_unlock;
 -	}
  	res = sscanf(buf, "%x %x", &offset, &value);
  	if (res != 2) {
  		res = -EFAULT;
@@@ -495,7 -520,7 +495,7 @@@
  	if (!res)
  		res = count;
  out_unlock:
 -	free_page(addr);
 +	kfree(buf);
  	return res;
  }
  
@@@ -529,16 -554,22 +529,16 @@@ static ssize_t lbs_rdbbp_write(struct f
  				    size_t count, loff_t *ppos)
  {
  	struct lbs_private *priv = file->private_data;
 -	ssize_t res, buf_size;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	if (!buf)
 -		return -ENOMEM;
 +	char *buf;
 +
 +	buf = memdup_user_nul(userbuf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, userbuf, buf_size)) {
 -		res = -EFAULT;
 -		goto out_unlock;
 -	}
  	priv->bbp_offset = simple_strtoul(buf, NULL, 16);
 -	res = count;
 -out_unlock:
 -	free_page(addr);
 -	return res;
 +	kfree(buf);
 +
 +	return count;
  }
  
  static ssize_t lbs_wrbbp_write(struct file *file,
@@@ -547,14 -578,18 +547,14 @@@
  {
  
  	struct lbs_private *priv = file->private_data;
 -	ssize_t res, buf_size;
 +	ssize_t res;
  	u32 offset, value;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	if (!buf)
 -		return -ENOMEM;
 +	char *buf;
 +
 +	buf = memdup_user_nul(userbuf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, userbuf, buf_size)) {
 -		res = -EFAULT;
 -		goto out_unlock;
 -	}
  	res = sscanf(buf, "%x %x", &offset, &value);
  	if (res != 2) {
  		res = -EFAULT;
@@@ -567,7 -602,7 +567,7 @@@
  	if (!res)
  		res = count;
  out_unlock:
 -	free_page(addr);
 +	kfree(buf);
  	return res;
  }
  
@@@ -601,15 -636,22 +601,15 @@@ static ssize_t lbs_rdrf_write(struct fi
  				    size_t count, loff_t *ppos)
  {
  	struct lbs_private *priv = file->private_data;
 -	ssize_t res, buf_size;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	if (!buf)
 -		return -ENOMEM;
 +	char *buf;
 +
 +	buf = memdup_user_nul(userbuf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, userbuf, buf_size)) {
 -		res = -EFAULT;
 -		goto out_unlock;
 -	}
  	priv->rf_offset = simple_strtoul(buf, NULL, 16);
 -	res = count;
 -out_unlock:
 -	free_page(addr);
 -	return res;
 +	kfree(buf);
 +	return count;
  }
  
  static ssize_t lbs_wrrf_write(struct file *file,
@@@ -618,14 -660,18 +618,14 @@@
  {
  
  	struct lbs_private *priv = file->private_data;
 -	ssize_t res, buf_size;
 +	ssize_t res;
  	u32 offset, value;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	if (!buf)
 -		return -ENOMEM;
 +	char *buf;
 +
 +	buf = memdup_user_nul(userbuf, min(count, len - 1));
 +	if (IS_ERR(buf))
 +		return PTR_ERR(buf);
  
 -	buf_size = min(count, len - 1);
 -	if (copy_from_user(buf, userbuf, buf_size)) {
 -		res = -EFAULT;
 -		goto out_unlock;
 -	}
  	res = sscanf(buf, "%x %x", &offset, &value);
  	if (res != 2) {
  		res = -EFAULT;
@@@ -638,7 -684,7 +638,7 @@@
  	if (!res)
  		res = count;
  out_unlock:
 -	free_page(addr);
 +	kfree(buf);
  	return res;
  }
  
@@@ -869,9 -915,16 +869,9 @@@ static ssize_t lbs_debugfs_write(struc
  	if (cnt == 0)
  		return 0;
  
 -	pdata = kmalloc(cnt + 1, GFP_KERNEL);
 -	if (pdata == NULL)
 -		return 0;
 -
 -	if (copy_from_user(pdata, buf, cnt)) {
 -		lbs_deb_debugfs("Copy from user failed\n");
 -		kfree(pdata);
 -		return 0;
 -	}
 -	pdata[cnt] = '\0';
 +	pdata = memdup_user_nul(buf, cnt);
 +	if (IS_ERR(pdata))
 +		return PTR_ERR(pdata);
  
  	p0 = pdata;
  	for (i = 0; i < num_of_items; i++) {
diff --combined drivers/net/wireless/marvell/mwifiex/debugfs.c
index 0000000,5e55629..0b9c580
mode 000000,100644..100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@@ -1,0 -1,1035 +1,1003 @@@
+ /*
+  * Marvell Wireless LAN device driver: debugfs
+  *
+  * Copyright (C) 2011-2014, Marvell International Ltd.
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available by writing to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  */
+ 
+ #include <linux/debugfs.h>
+ 
+ #include "main.h"
+ #include "11n.h"
+ 
+ 
+ static struct dentry *mwifiex_dfs_dir;
+ 
+ static char *bss_modes[] = {
+ 	"UNSPECIFIED",
+ 	"ADHOC",
+ 	"STATION",
+ 	"AP",
+ 	"AP_VLAN",
+ 	"WDS",
+ 	"MONITOR",
+ 	"MESH_POINT",
+ 	"P2P_CLIENT",
+ 	"P2P_GO",
+ 	"P2P_DEVICE",
+ };
+ 
+ /*
+  * Proc info file read handler.
+  *
+  * This function is called when the 'info' file is opened for reading.
+  * It prints the following driver related information -
+  *      - Driver name
+  *      - Driver version
+  *      - Driver extended version
+  *      - Interface name
+  *      - BSS mode
+  *      - Media state (connected or disconnected)
+  *      - MAC address
+  *      - Total number of Tx bytes
+  *      - Total number of Rx bytes
+  *      - Total number of Tx packets
+  *      - Total number of Rx packets
+  *      - Total number of dropped Tx packets
+  *      - Total number of dropped Rx packets
+  *      - Total number of corrupted Tx packets
+  *      - Total number of corrupted Rx packets
+  *      - Carrier status (on or off)
+  *      - Tx queue status (started or stopped)
+  *
+  * For STA mode drivers, it also prints the following extra -
+  *      - ESSID
+  *      - BSSID
+  *      - Channel
+  *      - Region code
+  *      - Multicast count
+  *      - Multicast addresses
+  */
+ static ssize_t
+ mwifiex_info_read(struct file *file, char __user *ubuf,
+ 		  size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv =
+ 		(struct mwifiex_private *) file->private_data;
+ 	struct net_device *netdev = priv->netdev;
+ 	struct netdev_hw_addr *ha;
+ 	struct netdev_queue *txq;
+ 	unsigned long page = get_zeroed_page(GFP_KERNEL);
+ 	char *p = (char *) page, fmt[64];
+ 	struct mwifiex_bss_info info;
+ 	ssize_t ret;
+ 	int i = 0;
+ 
+ 	if (!p)
+ 		return -ENOMEM;
+ 
+ 	memset(&info, 0, sizeof(info));
+ 	ret = mwifiex_get_bss_info(priv, &info);
+ 	if (ret)
+ 		goto free_and_exit;
+ 
+ 	mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1);
+ 
+ 	if (!priv->version_str[0])
+ 		mwifiex_get_ver_ext(priv);
+ 
+ 	p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
+ 	p += sprintf(p, "driver_version = %s", fmt);
+ 	p += sprintf(p, "\nverext = %s", priv->version_str);
+ 	p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);
+ 
+ 	if (info.bss_mode >= ARRAY_SIZE(bss_modes))
+ 		p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
+ 	else
+ 		p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
+ 
+ 	p += sprintf(p, "media_state=\"%s\"\n",
+ 		     (!priv->media_connected ? "Disconnected" : "Connected"));
+ 	p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
+ 
+ 	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
+ 		p += sprintf(p, "multicast_count=\"%d\"\n",
+ 			     netdev_mc_count(netdev));
+ 		p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
+ 		p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
+ 		p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
+ 		p += sprintf(p, "country_code = \"%s\"\n", info.country_code);
+ 
+ 		netdev_for_each_mc_addr(ha, netdev)
+ 			p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
+ 					i++, ha->addr);
+ 	}
+ 
+ 	p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
+ 	p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
+ 	p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
+ 	p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
+ 	p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
+ 	p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
+ 	p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
+ 	p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
+ 	p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
+ 					 ? "on" : "off"));
+ 	p += sprintf(p, "tx queue");
+ 	for (i = 0; i < netdev->num_tx_queues; i++) {
+ 		txq = netdev_get_tx_queue(netdev, i);
+ 		p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
+ 			     "stopped" : "started");
+ 	}
+ 	p += sprintf(p, "\n");
+ 
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
+ 				      (unsigned long) p - page);
+ 
+ free_and_exit:
+ 	free_page(page);
+ 	return ret;
+ }
+ 
+ /*
+  * Proc device dump read handler.
+  *
+  * This function is called when the 'device_dump' file is opened for
+  * reading.
+  * This function dumps driver information and firmware memory segments
+  * (ex. DTCM, ITCM, SQRAM etc.) for
+  * debugging.
+  */
+ static ssize_t
+ mwifiex_device_dump_read(struct file *file, char __user *ubuf,
+ 			 size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv = file->private_data;
+ 
+ 	if (!priv->adapter->if_ops.device_dump)
+ 		return -EIO;
+ 
+ 	priv->adapter->if_ops.device_dump(priv->adapter);
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * Proc getlog file read handler.
+  *
+  * This function is called when the 'getlog' file is opened for reading
+  * It prints the following log information -
+  *      - Number of multicast Tx frames
+  *      - Number of failed packets
+  *      - Number of Tx retries
+  *      - Number of multicast Tx retries
+  *      - Number of duplicate frames
+  *      - Number of RTS successes
+  *      - Number of RTS failures
+  *      - Number of ACK failures
+  *      - Number of fragmented Rx frames
+  *      - Number of multicast Rx frames
+  *      - Number of FCS errors
+  *      - Number of Tx frames
+  *      - WEP ICV error counts
+  *      - Number of received beacons
+  *      - Number of missed beacons
+  */
+ static ssize_t
+ mwifiex_getlog_read(struct file *file, char __user *ubuf,
+ 		    size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv =
+ 		(struct mwifiex_private *) file->private_data;
+ 	unsigned long page = get_zeroed_page(GFP_KERNEL);
+ 	char *p = (char *) page;
+ 	ssize_t ret;
+ 	struct mwifiex_ds_get_stats stats;
+ 
+ 	if (!p)
+ 		return -ENOMEM;
+ 
+ 	memset(&stats, 0, sizeof(stats));
+ 	ret = mwifiex_get_stats_info(priv, &stats);
+ 	if (ret)
+ 		goto free_and_exit;
+ 
+ 	p += sprintf(p, "\n"
+ 		     "mcasttxframe     %u\n"
+ 		     "failed           %u\n"
+ 		     "retry            %u\n"
+ 		     "multiretry       %u\n"
+ 		     "framedup         %u\n"
+ 		     "rtssuccess       %u\n"
+ 		     "rtsfailure       %u\n"
+ 		     "ackfailure       %u\n"
+ 		     "rxfrag           %u\n"
+ 		     "mcastrxframe     %u\n"
+ 		     "fcserror         %u\n"
+ 		     "txframe          %u\n"
+ 		     "wepicverrcnt-1   %u\n"
+ 		     "wepicverrcnt-2   %u\n"
+ 		     "wepicverrcnt-3   %u\n"
+ 		     "wepicverrcnt-4   %u\n"
+ 		     "bcn_rcv_cnt   %u\n"
+ 		     "bcn_miss_cnt   %u\n",
+ 		     stats.mcast_tx_frame,
+ 		     stats.failed,
+ 		     stats.retry,
+ 		     stats.multi_retry,
+ 		     stats.frame_dup,
+ 		     stats.rts_success,
+ 		     stats.rts_failure,
+ 		     stats.ack_failure,
+ 		     stats.rx_frag,
+ 		     stats.mcast_rx_frame,
+ 		     stats.fcs_error,
+ 		     stats.tx_frame,
+ 		     stats.wep_icv_error[0],
+ 		     stats.wep_icv_error[1],
+ 		     stats.wep_icv_error[2],
+ 		     stats.wep_icv_error[3],
+ 		     stats.bcn_rcv_cnt,
+ 		     stats.bcn_miss_cnt);
+ 
+ 
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
+ 				      (unsigned long) p - page);
+ 
+ free_and_exit:
+ 	free_page(page);
+ 	return ret;
+ }
+ 
+ /* Sysfs histogram file read handler.
+  *
+  * This function is called when the 'histogram' file is opened for reading
+  * It prints the following histogram information -
+  *      - Number of histogram samples
+  *      - Receive packet number of each rx_rate
+  *      - Receive packet number of each snr
+  *      - Receive packet number of each nosie_flr
+  *      - Receive packet number of each signal streath
+  */
+ static ssize_t
+ mwifiex_histogram_read(struct file *file, char __user *ubuf,
+ 		       size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv =
+ 		(struct mwifiex_private *)file->private_data;
+ 	ssize_t ret;
+ 	struct mwifiex_histogram_data *phist_data;
+ 	int i, value;
+ 	unsigned long page = get_zeroed_page(GFP_KERNEL);
+ 	char *p = (char *)page;
+ 
+ 	if (!p)
+ 		return -ENOMEM;
+ 
+ 	if (!priv || !priv->hist_data)
+ 		return -EFAULT;
+ 	phist_data = priv->hist_data;
+ 
+ 	p += sprintf(p, "\n"
+ 		     "total samples = %d\n",
+ 		     atomic_read(&phist_data->num_samples));
+ 
+ 	p += sprintf(p, "rx rates (in Mbps): 0=1M   1=2M");
+ 	p += sprintf(p, "2=5.5M  3=11M   4=6M   5=9M  6=12M\n");
+ 	p += sprintf(p, "7=18M  8=24M  9=36M  10=48M  11=54M");
+ 	p += sprintf(p, "12-27=MCS0-15(BW20) 28-43=MCS0-15(BW40)\n");
+ 
+ 	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
+ 		p += sprintf(p, "44-53=MCS0-9(VHT:BW20)");
+ 		p += sprintf(p, "54-63=MCS0-9(VHT:BW40)");
+ 		p += sprintf(p, "64-73=MCS0-9(VHT:BW80)\n\n");
+ 	} else {
+ 		p += sprintf(p, "\n");
+ 	}
+ 
+ 	for (i = 0; i < MWIFIEX_MAX_RX_RATES; i++) {
+ 		value = atomic_read(&phist_data->rx_rate[i]);
+ 		if (value)
+ 			p += sprintf(p, "rx_rate[%02d] = %d\n", i, value);
+ 	}
+ 
+ 	if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) {
+ 		for (i = MWIFIEX_MAX_RX_RATES; i < MWIFIEX_MAX_AC_RX_RATES;
+ 		     i++) {
+ 			value = atomic_read(&phist_data->rx_rate[i]);
+ 			if (value)
+ 				p += sprintf(p, "rx_rate[%02d] = %d\n",
+ 					   i, value);
+ 		}
+ 	}
+ 
+ 	for (i = 0; i < MWIFIEX_MAX_SNR; i++) {
+ 		value =  atomic_read(&phist_data->snr[i]);
+ 		if (value)
+ 			p += sprintf(p, "snr[%02ddB] = %d\n", i, value);
+ 	}
+ 	for (i = 0; i < MWIFIEX_MAX_NOISE_FLR; i++) {
+ 		value = atomic_read(&phist_data->noise_flr[i]);
+ 		if (value)
+ 			p += sprintf(p, "noise_flr[-%02ddBm] = %d\n",
+ 				(int)(i-128), value);
+ 	}
+ 	for (i = 0; i < MWIFIEX_MAX_SIG_STRENGTH; i++) {
+ 		value = atomic_read(&phist_data->sig_str[i]);
+ 		if (value)
+ 			p += sprintf(p, "sig_strength[-%02ddBm] = %d\n",
+ 				i, value);
+ 	}
+ 
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page,
+ 				      (unsigned long)p - page);
+ 
+ 	return ret;
+ }
+ 
+ static ssize_t
+ mwifiex_histogram_write(struct file *file, const char __user *ubuf,
+ 			size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv = (void *)file->private_data;
+ 
+ 	if (priv && priv->hist_data)
+ 		mwifiex_hist_data_reset(priv);
+ 	return 0;
+ }
+ 
+ static struct mwifiex_debug_info info;
+ 
+ /*
+  * Proc debug file read handler.
+  *
+  * This function is called when the 'debug' file is opened for reading
+  * It prints the following log information -
+  *      - Interrupt count
+  *      - WMM AC VO packets count
+  *      - WMM AC VI packets count
+  *      - WMM AC BE packets count
+  *      - WMM AC BK packets count
+  *      - Maximum Tx buffer size
+  *      - Tx buffer size
+  *      - Current Tx buffer size
+  *      - Power Save mode
+  *      - Power Save state
+  *      - Deep Sleep status
+  *      - Device wakeup required status
+  *      - Number of wakeup tries
+  *      - Host Sleep configured status
+  *      - Host Sleep activated status
+  *      - Number of Tx timeouts
+  *      - Number of command timeouts
+  *      - Last timed out command ID
+  *      - Last timed out command action
+  *      - Last command ID
+  *      - Last command action
+  *      - Last command index
+  *      - Last command response ID
+  *      - Last command response index
+  *      - Last event
+  *      - Last event index
+  *      - Number of host to card command failures
+  *      - Number of sleep confirm command failures
+  *      - Number of host to card data failure
+  *      - Number of deauthentication events
+  *      - Number of disassociation events
+  *      - Number of link lost events
+  *      - Number of deauthentication commands
+  *      - Number of association success commands
+  *      - Number of association failure commands
+  *      - Number of commands sent
+  *      - Number of data packets sent
+  *      - Number of command responses received
+  *      - Number of events received
+  *      - Tx BA stream table (TID, RA)
+  *      - Rx reorder table (TID, TA, Start window, Window size, Buffer)
+  */
+ static ssize_t
+ mwifiex_debug_read(struct file *file, char __user *ubuf,
+ 		   size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv =
+ 		(struct mwifiex_private *) file->private_data;
+ 	unsigned long page = get_zeroed_page(GFP_KERNEL);
+ 	char *p = (char *) page;
+ 	ssize_t ret;
+ 
+ 	if (!p)
+ 		return -ENOMEM;
+ 
+ 	ret = mwifiex_get_debug_info(priv, &info);
+ 	if (ret)
+ 		goto free_and_exit;
+ 
+ 	p += mwifiex_debug_info_to_buffer(priv, p, &info);
+ 
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
+ 				      (unsigned long) p - page);
+ 
+ free_and_exit:
+ 	free_page(page);
+ 	return ret;
+ }
+ 
+ static u32 saved_reg_type, saved_reg_offset, saved_reg_value;
+ 
+ /*
+  * Proc regrdwr file write handler.
+  *
+  * This function is called when the 'regrdwr' file is opened for writing
+  *
+  * This function can be used to write to a register.
+  */
+ static ssize_t
+ mwifiex_regrdwr_write(struct file *file,
+ 		      const char __user *ubuf, size_t count, loff_t *ppos)
+ {
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *) addr;
 -	size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
++	char *buf;
+ 	int ret;
+ 	u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX;
+ 
 -	if (!buf)
 -		return -ENOMEM;
 -
 -
 -	if (copy_from_user(buf, ubuf, buf_size)) {
 -		ret = -EFAULT;
 -		goto done;
 -	}
++	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
++	if (IS_ERR(buf))
++		return PTR_ERR(buf);
+ 
+ 	sscanf(buf, "%u %x %x", &reg_type, &reg_offset, &reg_value);
+ 
+ 	if (reg_type == 0 || reg_offset == 0) {
+ 		ret = -EINVAL;
+ 		goto done;
+ 	} else {
+ 		saved_reg_type = reg_type;
+ 		saved_reg_offset = reg_offset;
+ 		saved_reg_value = reg_value;
+ 		ret = count;
+ 	}
+ done:
 -	free_page(addr);
++	kfree(buf);
+ 	return ret;
+ }
+ 
+ /*
+  * Proc regrdwr file read handler.
+  *
+  * This function is called when the 'regrdwr' file is opened for reading
+  *
+  * This function can be used to read from a register.
+  */
+ static ssize_t
+ mwifiex_regrdwr_read(struct file *file, char __user *ubuf,
+ 		     size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv =
+ 		(struct mwifiex_private *) file->private_data;
+ 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ 	char *buf = (char *) addr;
+ 	int pos = 0, ret = 0;
+ 	u32 reg_value;
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+ 
+ 	if (!saved_reg_type) {
+ 		/* No command has been given */
+ 		pos += snprintf(buf, PAGE_SIZE, "0");
+ 		goto done;
+ 	}
+ 	/* Set command has been given */
+ 	if (saved_reg_value != UINT_MAX) {
+ 		ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset,
+ 					saved_reg_value);
+ 
+ 		pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n",
+ 				saved_reg_type, saved_reg_offset,
+ 				saved_reg_value);
+ 
+ 		ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+ 
+ 		goto done;
+ 	}
+ 	/* Get command has been given */
+ 	ret = mwifiex_reg_read(priv, saved_reg_type,
+ 			       saved_reg_offset, &reg_value);
+ 	if (ret) {
+ 		ret = -EINVAL;
+ 		goto done;
+ 	}
+ 
+ 	pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type,
+ 			saved_reg_offset, reg_value);
+ 
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+ 
+ done:
+ 	free_page(addr);
+ 	return ret;
+ }
+ 
+ /* Proc debug_mask file read handler.
+  * This function is called when the 'debug_mask' file is opened for reading
+  * This function can be used read driver debugging mask value.
+  */
+ static ssize_t
+ mwifiex_debug_mask_read(struct file *file, char __user *ubuf,
+ 			size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv =
+ 		(struct mwifiex_private *)file->private_data;
+ 	unsigned long page = get_zeroed_page(GFP_KERNEL);
+ 	char *buf = (char *)page;
+ 	size_t ret = 0;
+ 	int pos = 0;
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+ 
+ 	pos += snprintf(buf, PAGE_SIZE, "debug mask=0x%08x\n",
+ 			priv->adapter->debug_mask);
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+ 
+ 	free_page(page);
+ 	return ret;
+ }
+ 
+ /* Proc debug_mask file read handler.
+  * This function is called when the 'debug_mask' file is opened for reading
+  * This function can be used read driver debugging mask value.
+  */
+ static ssize_t
+ mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
+ 			 size_t count, loff_t *ppos)
+ {
+ 	int ret;
+ 	unsigned long debug_mask;
+ 	struct mwifiex_private *priv = (void *)file->private_data;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (void *)addr;
 -	size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
++	char *buf;
+ 
 -	if (!buf)
 -		return -ENOMEM;
 -
 -	if (copy_from_user(buf, ubuf, buf_size)) {
 -		ret = -EFAULT;
 -		goto done;
 -	}
++	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
++	if (IS_ERR(buf))
++		return PTR_ERR(buf);
+ 
+ 	if (kstrtoul(buf, 0, &debug_mask)) {
+ 		ret = -EINVAL;
+ 		goto done;
+ 	}
+ 
+ 	priv->adapter->debug_mask = debug_mask;
+ 	ret = count;
+ done:
 -	free_page(addr);
++	kfree(buf);
+ 	return ret;
+ }
+ 
+ /* Proc memrw file write handler.
+  * This function is called when the 'memrw' file is opened for writing
+  * This function can be used to write to a memory location.
+  */
+ static ssize_t
+ mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
+ 		    loff_t *ppos)
+ {
+ 	int ret;
+ 	char cmd;
+ 	struct mwifiex_ds_mem_rw mem_rw;
+ 	u16 cmd_action;
+ 	struct mwifiex_private *priv = (void *)file->private_data;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (void *)addr;
 -	size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
 -
 -	if (!buf)
 -		return -ENOMEM;
++	char *buf;
+ 
 -	if (copy_from_user(buf, ubuf, buf_size)) {
 -		ret = -EFAULT;
 -		goto done;
 -	}
++	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
++	if (IS_ERR(buf))
++		return PTR_ERR(buf);
+ 
+ 	ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value);
+ 	if (ret != 3) {
+ 		ret = -EINVAL;
+ 		goto done;
+ 	}
+ 
+ 	if ((cmd == 'r') || (cmd == 'R')) {
+ 		cmd_action = HostCmd_ACT_GEN_GET;
+ 		mem_rw.value = 0;
+ 	} else if ((cmd == 'w') || (cmd == 'W')) {
+ 		cmd_action = HostCmd_ACT_GEN_SET;
+ 	} else {
+ 		ret = -EINVAL;
+ 		goto done;
+ 	}
+ 
+ 	memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw));
+ 	if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
+ 			     &mem_rw, true))
+ 		ret = -1;
+ 	else
+ 		ret = count;
+ 
+ done:
 -	free_page(addr);
++	kfree(buf);
+ 	return ret;
+ }
+ 
+ /* Proc memrw file read handler.
+  * This function is called when the 'memrw' file is opened for reading
+  * This function can be used to read from a memory location.
+  */
+ static ssize_t
+ mwifiex_memrw_read(struct file *file, char __user *ubuf,
+ 		   size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv = (void *)file->private_data;
+ 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ 	char *buf = (char *)addr;
+ 	int ret, pos = 0;
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+ 
+ 	pos += snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr,
+ 			priv->mem_rw.value);
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+ 
+ 	free_page(addr);
+ 	return ret;
+ }
+ 
+ static u32 saved_offset = -1, saved_bytes = -1;
+ 
+ /*
+  * Proc rdeeprom file write handler.
+  *
+  * This function is called when the 'rdeeprom' file is opened for writing
+  *
+  * This function can be used to write to a RDEEPROM location.
+  */
+ static ssize_t
+ mwifiex_rdeeprom_write(struct file *file,
+ 		       const char __user *ubuf, size_t count, loff_t *ppos)
+ {
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *) addr;
 -	size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
++	char *buf;
+ 	int ret = 0;
+ 	int offset = -1, bytes = -1;
+ 
 -	if (!buf)
 -		return -ENOMEM;
 -
 -
 -	if (copy_from_user(buf, ubuf, buf_size)) {
 -		ret = -EFAULT;
 -		goto done;
 -	}
++	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
++	if (IS_ERR(buf))
++		return PTR_ERR(buf);
+ 
+ 	sscanf(buf, "%d %d", &offset, &bytes);
+ 
+ 	if (offset == -1 || bytes == -1) {
+ 		ret = -EINVAL;
+ 		goto done;
+ 	} else {
+ 		saved_offset = offset;
+ 		saved_bytes = bytes;
+ 		ret = count;
+ 	}
+ done:
 -	free_page(addr);
++	kfree(buf);
+ 	return ret;
+ }
+ 
+ /*
+  * Proc rdeeprom read write handler.
+  *
+  * This function is called when the 'rdeeprom' file is opened for reading
+  *
+  * This function can be used to read from a RDEEPROM location.
+  */
+ static ssize_t
+ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf,
+ 		      size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv =
+ 		(struct mwifiex_private *) file->private_data;
+ 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ 	char *buf = (char *) addr;
+ 	int pos, ret, i;
+ 	u8 value[MAX_EEPROM_DATA];
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+ 
+ 	if (saved_offset == -1) {
+ 		/* No command has been given */
+ 		pos = snprintf(buf, PAGE_SIZE, "0");
+ 		goto done;
+ 	}
+ 
+ 	/* Get command has been given */
+ 	ret = mwifiex_eeprom_read(priv, (u16) saved_offset,
+ 				  (u16) saved_bytes, value);
+ 	if (ret) {
+ 		ret = -EINVAL;
+ 		goto out_free;
+ 	}
+ 
+ 	pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
+ 
+ 	for (i = 0; i < saved_bytes; i++)
+ 		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]);
+ 
+ done:
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+ out_free:
+ 	free_page(addr);
+ 	return ret;
+ }
+ 
+ /* Proc hscfg file write handler
+  * This function can be used to configure the host sleep parameters.
+  */
+ static ssize_t
+ mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
+ 		    size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv = (void *)file->private_data;
 -	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 -	char *buf = (char *)addr;
 -	size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
++	char *buf;
+ 	int ret, arg_num;
+ 	struct mwifiex_ds_hs_cfg hscfg;
+ 	int conditions = HS_CFG_COND_DEF;
+ 	u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;
+ 
 -	if (!buf)
 -		return -ENOMEM;
 -
 -	if (copy_from_user(buf, ubuf, buf_size)) {
 -		ret = -EFAULT;
 -		goto done;
 -	}
++	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
++	if (IS_ERR(buf))
++		return PTR_ERR(buf);
+ 
+ 	arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);
+ 
+ 	memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
+ 
+ 	if (arg_num > 3) {
+ 		mwifiex_dbg(priv->adapter, ERROR,
+ 			    "Too many arguments\n");
+ 		ret = -EINVAL;
+ 		goto done;
+ 	}
+ 
+ 	if (arg_num >= 1 && arg_num < 3)
+ 		mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
+ 				      MWIFIEX_SYNC_CMD, &hscfg);
+ 
+ 	if (arg_num) {
+ 		if (conditions == HS_CFG_CANCEL) {
+ 			mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
+ 			ret = count;
+ 			goto done;
+ 		}
+ 		hscfg.conditions = conditions;
+ 	}
+ 	if (arg_num >= 2)
+ 		hscfg.gpio = gpio;
+ 	if (arg_num == 3)
+ 		hscfg.gap = gap;
+ 
+ 	hscfg.is_invoke_hostcmd = false;
+ 	mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
+ 			      MWIFIEX_SYNC_CMD, &hscfg);
+ 
+ 	mwifiex_enable_hs(priv->adapter);
+ 	priv->adapter->hs_enabling = false;
+ 	ret = count;
+ done:
 -	free_page(addr);
++	kfree(buf);
+ 	return ret;
+ }
+ 
+ /* Proc hscfg file read handler
+  * This function can be used to read host sleep configuration
+  * parameters from driver.
+  */
+ static ssize_t
+ mwifiex_hscfg_read(struct file *file, char __user *ubuf,
+ 		   size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv = (void *)file->private_data;
+ 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ 	char *buf = (char *)addr;
+ 	int pos, ret;
+ 	struct mwifiex_ds_hs_cfg hscfg;
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+ 
+ 	mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
+ 			      MWIFIEX_SYNC_CMD, &hscfg);
+ 
+ 	pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions,
+ 		       hscfg.gpio, hscfg.gap);
+ 
+ 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+ 
+ 	free_page(addr);
+ 	return ret;
+ }
+ 
+ static ssize_t
+ mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf,
+ 			    size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv = file->private_data;
+ 	char buf[3];
+ 	bool timeshare_coex;
+ 	int ret;
+ 	unsigned int len;
+ 
+ 	if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
+ 		return -EOPNOTSUPP;
+ 
+ 	ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
+ 			       HostCmd_ACT_GEN_GET, 0, &timeshare_coex, true);
+ 	if (ret)
+ 		return ret;
+ 
+ 	len = sprintf(buf, "%d\n", timeshare_coex);
+ 	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+ }
+ 
+ static ssize_t
+ mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf,
+ 			     size_t count, loff_t *ppos)
+ {
+ 	bool timeshare_coex;
+ 	struct mwifiex_private *priv = file->private_data;
+ 	char kbuf[16];
+ 	int ret;
+ 
+ 	if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15)
+ 		return -EOPNOTSUPP;
+ 
+ 	memset(kbuf, 0, sizeof(kbuf));
+ 
+ 	if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count)))
+ 		return -EFAULT;
+ 
+ 	if (strtobool(kbuf, &timeshare_coex))
+ 		return -EINVAL;
+ 
+ 	ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX,
+ 			       HostCmd_ACT_GEN_SET, 0, &timeshare_coex, true);
+ 	if (ret)
+ 		return ret;
+ 	else
+ 		return count;
+ }
+ 
+ static ssize_t
+ mwifiex_reset_write(struct file *file,
+ 		    const char __user *ubuf, size_t count, loff_t *ppos)
+ {
+ 	struct mwifiex_private *priv = file->private_data;
+ 	struct mwifiex_adapter *adapter = priv->adapter;
+ 	char cmd;
+ 	bool result;
+ 
+ 	if (copy_from_user(&cmd, ubuf, sizeof(cmd)))
+ 		return -EFAULT;
+ 
+ 	if (strtobool(&cmd, &result))
+ 		return -EINVAL;
+ 
+ 	if (!result)
+ 		return -EINVAL;
+ 
+ 	if (adapter->if_ops.card_reset) {
+ 		dev_info(adapter->dev, "Resetting per request\n");
+ 		adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
+ 		mwifiex_cancel_all_pending_cmd(adapter);
+ 		adapter->if_ops.card_reset(adapter);
+ 	}
+ 
+ 	return count;
+ }
+ 
+ #define MWIFIEX_DFS_ADD_FILE(name) do {                                 \
+ 	if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir,        \
+ 			priv, &mwifiex_dfs_##name##_fops))              \
+ 		return;                                                 \
+ } while (0);
+ 
+ #define MWIFIEX_DFS_FILE_OPS(name)                                      \
+ static const struct file_operations mwifiex_dfs_##name##_fops = {       \
+ 	.read = mwifiex_##name##_read,                                  \
+ 	.write = mwifiex_##name##_write,                                \
+ 	.open = simple_open,                                            \
+ };
+ 
+ #define MWIFIEX_DFS_FILE_READ_OPS(name)                                 \
+ static const struct file_operations mwifiex_dfs_##name##_fops = {       \
+ 	.read = mwifiex_##name##_read,                                  \
+ 	.open = simple_open,                                            \
+ };
+ 
+ #define MWIFIEX_DFS_FILE_WRITE_OPS(name)                                \
+ static const struct file_operations mwifiex_dfs_##name##_fops = {       \
+ 	.write = mwifiex_##name##_write,                                \
+ 	.open = simple_open,                                            \
+ };
+ 
+ 
+ MWIFIEX_DFS_FILE_READ_OPS(info);
+ MWIFIEX_DFS_FILE_READ_OPS(debug);
+ MWIFIEX_DFS_FILE_READ_OPS(getlog);
+ MWIFIEX_DFS_FILE_READ_OPS(device_dump);
+ MWIFIEX_DFS_FILE_OPS(regrdwr);
+ MWIFIEX_DFS_FILE_OPS(rdeeprom);
+ MWIFIEX_DFS_FILE_OPS(memrw);
+ MWIFIEX_DFS_FILE_OPS(hscfg);
+ MWIFIEX_DFS_FILE_OPS(histogram);
+ MWIFIEX_DFS_FILE_OPS(debug_mask);
+ MWIFIEX_DFS_FILE_OPS(timeshare_coex);
+ MWIFIEX_DFS_FILE_WRITE_OPS(reset);
+ 
+ /*
+  * This function creates the debug FS directory structure and the files.
+  */
+ void
+ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
+ {
+ 	if (!mwifiex_dfs_dir || !priv)
+ 		return;
+ 
+ 	priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name,
+ 					       mwifiex_dfs_dir);
+ 
+ 	if (!priv->dfs_dev_dir)
+ 		return;
+ 
+ 	MWIFIEX_DFS_ADD_FILE(info);
+ 	MWIFIEX_DFS_ADD_FILE(debug);
+ 	MWIFIEX_DFS_ADD_FILE(getlog);
+ 	MWIFIEX_DFS_ADD_FILE(regrdwr);
+ 	MWIFIEX_DFS_ADD_FILE(rdeeprom);
+ 	MWIFIEX_DFS_ADD_FILE(device_dump);
+ 	MWIFIEX_DFS_ADD_FILE(memrw);
+ 	MWIFIEX_DFS_ADD_FILE(hscfg);
+ 	MWIFIEX_DFS_ADD_FILE(histogram);
+ 	MWIFIEX_DFS_ADD_FILE(debug_mask);
+ 	MWIFIEX_DFS_ADD_FILE(timeshare_coex);
+ 	MWIFIEX_DFS_ADD_FILE(reset);
+ }
+ 
+ /*
+  * This function removes the debug FS directory structure and the files.
+  */
+ void
+ mwifiex_dev_debugfs_remove(struct mwifiex_private *priv)
+ {
+ 	if (!priv)
+ 		return;
+ 
+ 	debugfs_remove_recursive(priv->dfs_dev_dir);
+ }
+ 
+ /*
+  * This function creates the top level proc directory.
+  */
+ void
+ mwifiex_debugfs_init(void)
+ {
+ 	if (!mwifiex_dfs_dir)
+ 		mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL);
+ }
+ 
+ /*
+  * This function removes the top level proc directory.
+  */
+ void
+ mwifiex_debugfs_remove(void)
+ {
+ 	if (mwifiex_dfs_dir)
+ 		debugfs_remove(mwifiex_dfs_dir);
+ }
diff --combined drivers/net/wireless/ti/wlcore/debugfs.c
index be72306,8367f9e..7f672f6
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@@ -1205,11 -1205,26 +1205,11 @@@ err_out
  
  static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig)
  {
 -	loff_t ret;
 -
  	/* only requests of dword-aligned size and offset are supported */
  	if (offset % 4)
  		return -EINVAL;
  
 -	switch (orig) {
 -	case SEEK_SET:
 -		file->f_pos = offset;
 -		ret = file->f_pos;
 -		break;
 -	case SEEK_CUR:
 -		file->f_pos += offset;
 -		ret = file->f_pos;
 -		break;
 -	default:
 -		ret = -EINVAL;
 -	}
 -
 -	return ret;
 +	return no_seek_end_llseek(file, offset, orig);
  }
  
  static const struct file_operations dev_mem_ops = {
@@@ -1219,6 -1234,65 +1219,65 @@@
  	.llseek = dev_mem_seek,
  };
  
+ static ssize_t fw_logger_read(struct file *file, char __user *user_buf,
+ 			      size_t count, loff_t *ppos)
+ {
+ 	struct wl1271 *wl = file->private_data;
+ 
+ 	return wl1271_format_buffer(user_buf, count,
+ 					ppos, "%d\n",
+ 					wl->conf.fwlog.output);
+ }
+ 
+ static ssize_t fw_logger_write(struct file *file,
+ 			       const char __user *user_buf,
+ 			       size_t count, loff_t *ppos)
+ {
+ 	struct wl1271 *wl = file->private_data;
+ 	unsigned long value;
+ 	int ret;
+ 
+ 	ret = kstrtoul_from_user(user_buf, count, 0, &value);
+ 	if (ret < 0) {
+ 		wl1271_warning("illegal value in fw_logger");
+ 		return -EINVAL;
+ 	}
+ 
+ 	if ((value > 2) || (value == 0)) {
+ 		wl1271_warning("fw_logger value must be 1-UART 2-SDIO");
+ 		return -ERANGE;
+ 	}
+ 
+ 	if (wl->conf.fwlog.output == 0) {
+ 		wl1271_warning("iligal opperation - fw logger disabled by default, please change mode via wlconf");
+ 		return -EINVAL;
+ 	}
+ 
+ 	mutex_lock(&wl->mutex);
+ 	ret = wl1271_ps_elp_wakeup(wl);
+ 	if (ret < 0) {
+ 		count = ret;
+ 		goto out;
+ 	}
+ 
+ 	wl->conf.fwlog.output = value;
+ 
+ 	ret = wl12xx_cmd_config_fwlog(wl);
+ 
+ 	wl1271_ps_elp_sleep(wl);
+ 
+ out:
+ 	mutex_unlock(&wl->mutex);
+ 	return count;
+ }
+ 
+ static const struct file_operations fw_logger_ops = {
+ 	.open = simple_open,
+ 	.read = fw_logger_read,
+ 	.write = fw_logger_write,
+ 	.llseek = default_llseek,
+ };
+ 
  static int wl1271_debugfs_add_files(struct wl1271 *wl,
  				    struct dentry *rootdir)
  {
@@@ -1245,6 -1319,7 +1304,7 @@@
  	DEBUGFS_ADD(irq_timeout, rootdir);
  	DEBUGFS_ADD(fw_stats_raw, rootdir);
  	DEBUGFS_ADD(sleep_auth, rootdir);
+ 	DEBUGFS_ADD(fw_logger, rootdir);
  
  	streaming = debugfs_create_dir("rx_streaming", rootdir);
  	if (!streaming || IS_ERR(streaming))
diff --combined lib/Kconfig.debug
index 749e886,0d76ecc..fba805e
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@@ -216,7 -216,7 +216,7 @@@ config STRIP_ASM_SYM
  
  config READABLE_ASM
          bool "Generate readable assembler code"
 -        depends on DEBUG_KERNEL
 +        depends on DEBUG_KERNEL && !LTO
          help
            Disable some compiler optimizations that tend to generate human unreadable
            assembler output. This may make the kernel slightly slower, but it helps
@@@ -1484,6 -1484,29 +1484,29 @@@ config OF_RECONFIG_NOTIFIER_ERROR_INJEC
  
  	  If unsure, say N.
  
+ config NETDEV_NOTIFIER_ERROR_INJECT
+ 	tristate "Netdev notifier error injection module"
+ 	depends on NET && NOTIFIER_ERROR_INJECTION
+ 	help
+ 	  This option provides the ability to inject artificial errors to
+ 	  netdevice notifier chain callbacks.  It is controlled through debugfs
+ 	  interface /sys/kernel/debug/notifier-error-inject/netdev
+ 
+ 	  If the notifier call chain should be failed with some events
+ 	  notified, write the error code to "actions/<notifier event>/error".
+ 
+ 	  Example: Inject netdevice mtu change error (-22 = -EINVAL)
+ 
+ 	  # cd /sys/kernel/debug/notifier-error-inject/netdev
+ 	  # echo -22 > actions/NETDEV_CHANGEMTU/error
+ 	  # ip link set eth0 mtu 1024
+ 	  RTNETLINK answers: Invalid argument
+ 
+ 	  To compile this code as a module, choose M here: the module will
+ 	  be called netdev-notifier-error-inject.
+ 
+ 	  If unsure, say N.
+ 
  config FAULT_INJECTION
  	bool "Fault-injection framework"
  	depends on DEBUG_KERNEL
diff --combined net/batman-adv/bat_iv_ogm.c
index aa94b4e,2467024..df625de
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@@ -185,8 -185,7 +185,8 @@@ unlock
  static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node,
  				     int max_if_num, int del_if_num)
  {
 -	int chunk_size,  ret = -ENOMEM, if_offset;
 +	int ret = -ENOMEM;
 +	size_t chunk_size, if_offset;
  	void *data_ptr = NULL;
  
  	spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
@@@ -204,9 -203,8 +204,9 @@@
  	memcpy(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size);
  
  	/* copy second part */
 +	if_offset = (del_if_num + 1) * chunk_size;
  	memcpy((char *)data_ptr + del_if_num * chunk_size,
 -	       orig_node->bat_iv.bcast_own + ((del_if_num + 1) * chunk_size),
 +	       (uint8_t *)orig_node->bat_iv.bcast_own + if_offset,
  	       (max_if_num - del_if_num) * chunk_size);
  
  free_bcast_own:
@@@ -363,7 -361,6 +363,6 @@@ batadv_iv_ogm_primary_iface_set(struct 
  	unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
  
  	batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
- 	batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
  	batadv_ogm_packet->ttl = BATADV_TTL;
  }
  
@@@ -844,8 -841,6 +843,6 @@@ static void batadv_iv_ogm_forward(struc
  		   "Forwarding packet: tq: %i, ttl: %i\n",
  		   batadv_ogm_packet->tq, batadv_ogm_packet->ttl);
  
- 	/* switch of primaries first hop flag when forwarding */
- 	batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP;
  	if (is_single_hop_neigh)
  		batadv_ogm_packet->flags |= BATADV_DIRECTLINK;
  	else
@@@ -1381,6 -1376,7 +1378,7 @@@ batadv_iv_ogm_process_per_outif(const s
  				struct batadv_hard_iface *if_outgoing)
  {
  	struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
+ 	struct batadv_hardif_neigh_node *hardif_neigh = NULL;
  	struct batadv_neigh_node *router = NULL;
  	struct batadv_neigh_node *router_router = NULL;
  	struct batadv_orig_node *orig_neigh_node;
@@@ -1425,6 -1421,13 +1423,13 @@@
  		goto out;
  	}
  
+ 	if (is_single_hop_neigh) {
+ 		hardif_neigh = batadv_hardif_neigh_get(if_incoming,
+ 						       ethhdr->h_source);
+ 		if (hardif_neigh)
+ 			hardif_neigh->last_seen = jiffies;
+ 	}
+ 
  	router = batadv_orig_router_get(orig_node, if_outgoing);
  	if (router) {
  		router_router = batadv_orig_router_get(router->orig_node,
@@@ -1559,6 -1562,8 +1564,8 @@@ out
  		batadv_neigh_node_free_ref(router_router);
  	if (orig_neigh_router)
  		batadv_neigh_node_free_ref(orig_neigh_router);
+ 	if (hardif_neigh)
+ 		batadv_hardif_neigh_free_ref(hardif_neigh);
  
  	kfree_skb(skb_priv);
  }
@@@ -1864,6 -1869,58 +1871,58 @@@ next
  }
  
  /**
+  * batadv_iv_hardif_neigh_print - print a single hop neighbour node
+  * @seq: neighbour table seq_file struct
+  * @hardif_neigh: hardif neighbour information
+  */
+ static void
+ batadv_iv_hardif_neigh_print(struct seq_file *seq,
+ 			     struct batadv_hardif_neigh_node *hardif_neigh)
+ {
+ 	int last_secs, last_msecs;
+ 
+ 	last_secs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) / 1000;
+ 	last_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) % 1000;
+ 
+ 	seq_printf(seq, "   %10s   %pM %4i.%03is\n",
+ 		   hardif_neigh->if_incoming->net_dev->name,
+ 		   hardif_neigh->addr, last_secs, last_msecs);
+ }
+ 
+ /**
+  * batadv_iv_ogm_neigh_print - print the single hop neighbour list
+  * @bat_priv: the bat priv with all the soft interface information
+  * @seq: neighbour table seq_file struct
+  */
+ static void batadv_iv_neigh_print(struct batadv_priv *bat_priv,
+ 				  struct seq_file *seq)
+ {
+ 	struct net_device *net_dev = (struct net_device *)seq->private;
+ 	struct batadv_hardif_neigh_node *hardif_neigh;
+ 	struct batadv_hard_iface *hard_iface;
+ 	int batman_count = 0;
+ 
+ 	seq_printf(seq, "   %10s        %-13s %s\n",
+ 		   "IF", "Neighbor", "last-seen");
+ 
+ 	rcu_read_lock();
+ 	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+ 		if (hard_iface->soft_iface != net_dev)
+ 			continue;
+ 
+ 		hlist_for_each_entry_rcu(hardif_neigh,
+ 					 &hard_iface->neigh_list, list) {
+ 			batadv_iv_hardif_neigh_print(seq, hardif_neigh);
+ 			batman_count++;
+ 		}
+ 	}
+ 	rcu_read_unlock();
+ 
+ 	if (batman_count == 0)
+ 		seq_puts(seq, "No batman nodes in range ...\n");
+ }
+ 
+ /**
   * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors
   * @neigh1: the first neighbor object of the comparison
   * @if_outgoing1: outgoing interface for the first neighbor
@@@ -1904,8 -1961,8 +1963,8 @@@ out
  }
  
  /**
-  * batadv_iv_ogm_neigh_is_eob - check if neigh1 is equally good or better than
-  *  neigh2 from the metric prospective
+  * batadv_iv_ogm_neigh_is_sob - check if neigh1 is similarly good or better
+  *  than neigh2 from the metric prospective
   * @neigh1: the first neighbor object of the comparison
   * @if_outgoing1: outgoing interface for the first neighbor
   * @neigh2: the second neighbor object of the comparison
@@@ -1915,7 -1972,7 +1974,7 @@@
   * the metric via neigh2, false otherwise.
   */
  static bool
- batadv_iv_ogm_neigh_is_eob(struct batadv_neigh_node *neigh1,
+ batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1,
  			   struct batadv_hard_iface *if_outgoing1,
  			   struct batadv_neigh_node *neigh2,
  			   struct batadv_hard_iface *if_outgoing2)
@@@ -1955,7 -2012,8 +2014,8 @@@ static struct batadv_algo_ops batadv_ba
  	.bat_ogm_schedule = batadv_iv_ogm_schedule,
  	.bat_ogm_emit = batadv_iv_ogm_emit,
  	.bat_neigh_cmp = batadv_iv_ogm_neigh_cmp,
- 	.bat_neigh_is_equiv_or_better = batadv_iv_ogm_neigh_is_eob,
+ 	.bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob,
+ 	.bat_neigh_print = batadv_iv_neigh_print,
  	.bat_orig_print = batadv_iv_ogm_orig_print,
  	.bat_orig_free = batadv_iv_ogm_orig_free,
  	.bat_orig_add_if = batadv_iv_ogm_orig_add_if,
diff --combined net/core/pktgen.c
index 4da4d51,2be1444..1474cfd
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@@ -2787,9 -2787,7 +2787,9 @@@ static struct sk_buff *pktgen_alloc_skb
  	} else {
  		 skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT);
  	}
 -	skb_reserve(skb, LL_RESERVED_SPACE(dev));
 +
 +	if (likely(skb))
 +		skb_reserve(skb, LL_RESERVED_SPACE(dev));
  
  	return skb;
  }
@@@ -2900,7 -2898,7 +2900,7 @@@ static struct sk_buff *fill_packet_ipv4
  
  	if (!(pkt_dev->flags & F_UDPCSUM)) {
  		skb->ip_summed = CHECKSUM_NONE;
- 	} else if (odev->features & NETIF_F_V4_CSUM) {
+ 	} else if (odev->features & (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM)) {
  		skb->ip_summed = CHECKSUM_PARTIAL;
  		skb->csum = 0;
  		udp4_hwcsum(skb, iph->saddr, iph->daddr);
@@@ -3034,7 -3032,7 +3034,7 @@@ static struct sk_buff *fill_packet_ipv6
  
  	if (!(pkt_dev->flags & F_UDPCSUM)) {
  		skb->ip_summed = CHECKSUM_NONE;
- 	} else if (odev->features & NETIF_F_V6_CSUM) {
+ 	} else if (odev->features & (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM)) {
  		skb->ip_summed = CHECKSUM_PARTIAL;
  		skb->csum_start = skb_transport_header(skb) - skb->head;
  		skb->csum_offset = offsetof(struct udphdr, check);
diff --combined net/ipv4/ip_output.c
index 36ac9f3,568e2bc..512a447
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@@ -76,7 -76,6 +76,6 @@@
  #include <linux/igmp.h>
  #include <linux/netfilter_ipv4.h>
  #include <linux/netfilter_bridge.h>
- #include <linux/mroute.h>
  #include <linux/netlink.h>
  #include <linux/tcp.h>
  
@@@ -912,7 -911,7 +911,7 @@@ static int __ip_append_data(struct soc
  	 */
  	if (transhdrlen &&
  	    length + fragheaderlen <= mtu &&
- 	    rt->dst.dev->features & NETIF_F_V4_CSUM &&
+ 	    rt->dst.dev->features & (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM) &&
  	    !(flags & MSG_MORE) &&
  	    !exthdrlen)
  		csummode = CHECKSUM_PARTIAL;
@@@ -921,7 -920,7 +920,7 @@@
  	if (((length > mtu) || (skb && skb_is_gso(skb))) &&
  	    (sk->sk_protocol == IPPROTO_UDP) &&
  	    (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len &&
 -	    (sk->sk_type == SOCK_DGRAM)) {
 +	    (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) {
  		err = ip_ufo_append_data(sk, queue, getfrag, from, length,
  					 hh_len, fragheaderlen, transhdrlen,
  					 maxfraglen, flags);
diff --combined net/ipv4/udp_offload.c
index 5d396b9,1300426..4c519c1
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@@ -21,7 -21,6 +21,7 @@@ static struct udp_offload_priv __rcu *u
  
  struct udp_offload_priv {
  	struct udp_offload	*offload;
 +	possible_net_t	net;
  	struct rcu_head		rcu;
  	struct udp_offload_priv __rcu *next;
  };
@@@ -61,8 -60,9 +61,9 @@@ static struct sk_buff *__skb_udp_tunnel
  
  	/* Try to offload checksum if possible */
  	offload_csum = !!(need_csum &&
- 			  (skb->dev->features &
- 			   (is_ipv6 ? NETIF_F_V6_CSUM : NETIF_F_V4_CSUM)));
+ 			  ((skb->dev->features & NETIF_F_HW_CSUM) ||
+ 			   (skb->dev->features & (is_ipv6 ?
+ 			    NETIF_F_IPV6_CSUM : NETIF_F_IP_CSUM))));
  
  	/* segment inner packet. */
  	enc_features = skb->dev->hw_enc_features & features;
@@@ -242,14 -242,13 +243,14 @@@ out
  	return segs;
  }
  
 -int udp_add_offload(struct udp_offload *uo)
 +int udp_add_offload(struct net *net, struct udp_offload *uo)
  {
  	struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_ATOMIC);
  
  	if (!new_offload)
  		return -ENOMEM;
  
 +	write_pnet(&new_offload->net, net);
  	new_offload->offload = uo;
  
  	spin_lock(&udp_offload_lock);
@@@ -313,8 -312,7 +314,8 @@@ struct sk_buff **udp_gro_receive(struc
  	rcu_read_lock();
  	uo_priv = rcu_dereference(udp_offload_base);
  	for (; uo_priv != NULL; uo_priv = rcu_dereference(uo_priv->next)) {
 -		if (uo_priv->offload->port == uh->dest &&
 +		if (net_eq(read_pnet(&uo_priv->net), dev_net(skb->dev)) &&
 +		    uo_priv->offload->port == uh->dest &&
  		    uo_priv->offload->callbacks.gro_receive)
  			goto unflush;
  	}
@@@ -392,8 -390,7 +393,8 @@@ int udp_gro_complete(struct sk_buff *sk
  
  	uo_priv = rcu_dereference(udp_offload_base);
  	for (; uo_priv != NULL; uo_priv = rcu_dereference(uo_priv->next)) {
 -		if (uo_priv->offload->port == uh->dest &&
 +		if (net_eq(read_pnet(&uo_priv->net), dev_net(skb->dev)) &&
 +		    uo_priv->offload->port == uh->dest &&
  		    uo_priv->offload->callbacks.gro_complete)
  			break;
  	}
diff --combined net/ipv6/ip6_output.c
index 6473889,2f74845..23de98f
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@@ -1322,7 -1322,7 +1322,7 @@@ emsgsize
  	    headersize == sizeof(struct ipv6hdr) &&
  	    length < mtu - headersize &&
  	    !(flags & MSG_MORE) &&
- 	    rt->dst.dev->features & NETIF_F_V6_CSUM)
+ 	    rt->dst.dev->features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
  		csummode = CHECKSUM_PARTIAL;
  
  	if (sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) {
@@@ -1353,7 -1353,7 +1353,7 @@@
  	     (skb && skb_is_gso(skb))) &&
  	    (sk->sk_protocol == IPPROTO_UDP) &&
  	    (rt->dst.dev->features & NETIF_F_UFO) &&
 -	    (sk->sk_type == SOCK_DGRAM)) {
 +	    (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) {
  		err = ip6_ufo_append_data(sk, queue, getfrag, from, length,
  					  hh_len, fragheaderlen,
  					  transhdrlen, mtu, flags, fl6);
diff --combined net/ipv6/tcp_ipv6.c
index bd100b4,9ecb012..db9f1c3
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@@ -462,10 -462,8 +462,10 @@@ static int tcp_v6_send_synack(const str
  		if (np->repflow && ireq->pktopts)
  			fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
  
 +		rcu_read_lock();
  		err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
  			       np->tclass);
 +		rcu_read_unlock();
  		err = net_xmit_eval(err);
  	}
  
@@@ -856,7 -854,9 +856,9 @@@ static void tcp_v6_send_reset(const str
  
  #ifdef CONFIG_TCP_MD5SIG
  	hash_location = tcp_parse_md5sig_option(th);
- 	if (!sk && hash_location) {
+ 	if (sk && sk_fullsock(sk)) {
+ 		key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
+ 	} else if (hash_location) {
  		/*
  		 * active side is lost. Try to find listening socket through
  		 * source port, and then find md5 key through listening socket.
@@@ -879,8 -879,6 +881,6 @@@
  		genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb);
  		if (genhash || memcmp(hash_location, newhash, 16) != 0)
  			goto release_sk1;
- 	} else {
- 		key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL;
  	}
  #endif
  
@@@ -1137,7 -1135,7 +1137,7 @@@ static struct sock *tcp_v6_syn_recv_soc
  		 */
  		tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr,
  			       AF_INET6, key->key, key->keylen,
- 			       sk_gfp_atomic(sk, GFP_ATOMIC));
+ 			       sk_gfp_mask(sk, GFP_ATOMIC));
  	}
  #endif
  
@@@ -1153,7 -1151,7 +1153,7 @@@
  		/* Clone pktoptions received with SYN, if we own the req */
  		if (ireq->pktopts) {
  			newnp->pktoptions = skb_clone(ireq->pktopts,
- 						      sk_gfp_atomic(sk, GFP_ATOMIC));
+ 						      sk_gfp_mask(sk, GFP_ATOMIC));
  			consume_skb(ireq->pktopts);
  			ireq->pktopts = NULL;
  			if (newnp->pktoptions)
@@@ -1219,7 -1217,7 +1219,7 @@@ static int tcp_v6_do_rcv(struct sock *s
  					       --ANK (980728)
  	 */
  	if (np->rxopt.all)
- 		opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC));
+ 		opt_skb = skb_clone(skb, sk_gfp_mask(sk, GFP_ATOMIC));
  
  	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
  		struct dst_entry *dst = sk->sk_rx_dst;
@@@ -1518,7 -1516,9 +1518,9 @@@ do_time_wait
  		break;
  	case TCP_TW_RST:
  		tcp_v6_restore_cb(skb);
- 		goto no_tcp_socket;
+ 		tcp_v6_send_reset(sk, skb);
+ 		inet_twsk_deschedule_put(inet_twsk(sk));
+ 		goto discard_it;
  	case TCP_TW_SUCCESS:
  		;
  	}
@@@ -1891,6 -1891,7 +1893,7 @@@ struct proto tcpv6_prot = 
  	.proto_cgroup		= tcp_proto_cgroup,
  #endif
  	.clear_sk		= tcp_v6_clear_sk,
+ 	.diag_destroy		= tcp_abort,
  };
  
  static const struct inet6_protocol tcpv6_protocol = {
diff --combined net/sctp/sm_sideeffect.c
index be23d5c,4f170ad..2e21384
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@@ -63,7 -63,7 +63,7 @@@ static int sctp_cmd_interpreter(sctp_ev
  static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
  			     sctp_state_t state,
  			     struct sctp_endpoint *ep,
 -			     struct sctp_association *asoc,
 +			     struct sctp_association **asoc,
  			     void *event_arg,
  			     sctp_disposition_t status,
  			     sctp_cmd_seq_t *commands,
@@@ -477,6 -477,8 +477,8 @@@ static void sctp_do_8_2_transport_strik
  					 struct sctp_transport *transport,
  					 int is_hb)
  {
+ 	struct net *net = sock_net(asoc->base.sk);
+ 
  	/* The check for association's overall error counter exceeding the
  	 * threshold is done in the state function.
  	 */
@@@ -503,7 -505,8 +505,8 @@@
  	 * is SCTP_ACTIVE, then mark this transport as Partially Failed,
  	 * see SCTP Quick Failover Draft, section 5.1
  	 */
- 	if ((transport->state == SCTP_ACTIVE) &&
+ 	if (net->sctp.pf_enable &&
+ 	   (transport->state == SCTP_ACTIVE) &&
  	   (asoc->pf_retrans < transport->pathmaxrxt) &&
  	   (transport->error_count > asoc->pf_retrans)) {
  
@@@ -863,7 -866,6 +866,6 @@@ static void sctp_cmd_delete_tcb(sctp_cm
  	    (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK))
  		return;
  
- 	sctp_unhash_established(asoc);
  	sctp_association_free(asoc);
  }
  
@@@ -1123,7 -1125,7 +1125,7 @@@ int sctp_do_sm(struct net *net, sctp_ev
  	debug_post_sfn();
  
  	error = sctp_side_effects(event_type, subtype, state,
 -				  ep, asoc, event_arg, status,
 +				  ep, &asoc, event_arg, status,
  				  &commands, gfp);
  	debug_post_sfx();
  
@@@ -1136,7 -1138,7 +1138,7 @@@
  static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
  			     sctp_state_t state,
  			     struct sctp_endpoint *ep,
 -			     struct sctp_association *asoc,
 +			     struct sctp_association **asoc,
  			     void *event_arg,
  			     sctp_disposition_t status,
  			     sctp_cmd_seq_t *commands,
@@@ -1151,7 -1153,7 +1153,7 @@@
  	 * disposition SCTP_DISPOSITION_CONSUME.
  	 */
  	if (0 != (error = sctp_cmd_interpreter(event_type, subtype, state,
 -					       ep, asoc,
 +					       ep, *asoc,
  					       event_arg, status,
  					       commands, gfp)))
  		goto bail;
@@@ -1174,12 -1176,11 +1176,12 @@@
  		break;
  
  	case SCTP_DISPOSITION_DELETE_TCB:
 +	case SCTP_DISPOSITION_ABORT:
  		/* This should now be a command. */
 +		*asoc = NULL;
  		break;
  
  	case SCTP_DISPOSITION_CONSUME:
 -	case SCTP_DISPOSITION_ABORT:
  		/*
  		 * We should no longer have much work to do here as the
  		 * real work has been done as explicit commands above.
@@@ -1267,7 -1268,6 +1269,6 @@@ static int sctp_cmd_interpreter(sctp_ev
  			asoc = cmd->obj.asoc;
  			BUG_ON(asoc->peer.primary_path == NULL);
  			sctp_endpoint_add_asoc(ep, asoc);
- 			sctp_hash_established(asoc);
  			break;
  
  		case SCTP_CMD_UPDATE_ASSOC:
diff --combined net/sctp/sysctl.c
index 3e0fc51,ccbfc93..daf8554
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@@ -308,6 -308,13 +308,13 @@@ static struct ctl_table sctp_net_table[
  		.extra1		= &max_autoclose_min,
  		.extra2		= &max_autoclose_max,
  	},
+ 	{
+ 		.procname	= "pf_enable",
+ 		.data		= &init_net.sctp.pf_enable,
+ 		.maxlen		= sizeof(int),
+ 		.mode		= 0644,
+ 		.proc_handler	= proc_dointvec,
+ 	},
  
  	{ /* sentinel */ }
  };
@@@ -320,7 -327,7 +327,7 @@@ static int proc_sctp_do_hmac_alg(struc
  	struct ctl_table tbl;
  	bool changed = false;
  	char *none = "none";
 -	char tmp[8];
 +	char tmp[8] = {0};
  	int ret;
  
  	memset(&tbl, 0, sizeof(struct ctl_table));
diff --combined net/unix/af_unix.c
index e3f85bc,e6d3556..c5bf5ef
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@@ -451,7 -451,7 +451,7 @@@ static void unix_write_space(struct soc
  	rcu_read_lock();
  	if (unix_writable(sk)) {
  		wq = rcu_dereference(sk->sk_wq);
- 		if (wq_has_sleeper(wq))
+ 		if (skwq_has_sleeper(wq))
  			wake_up_interruptible_sync_poll(&wq->wait,
  				POLLOUT | POLLWRNORM | POLLWRBAND);
  		sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
@@@ -1513,21 -1513,6 +1513,21 @@@ static void unix_destruct_scm(struct sk
  	sock_wfree(skb);
  }
  
 +/*
 + * The "user->unix_inflight" variable is protected by the garbage
 + * collection lock, and we just read it locklessly here. If you go
 + * over the limit, there might be a tiny race in actually noticing
 + * it across threads. Tough.
 + */
 +static inline bool too_many_unix_fds(struct task_struct *p)
 +{
 +	struct user_struct *user = current_user();
 +
 +	if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)))
 +		return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
 +	return false;
 +}
 +
  #define MAX_RECURSION_LEVEL 4
  
  static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
@@@ -1536,9 -1521,6 +1536,9 @@@
  	unsigned char max_level = 0;
  	int unix_sock_count = 0;
  
 +	if (too_many_unix_fds(current))
 +		return -ETOOMANYREFS;
 +
  	for (i = scm->fp->count - 1; i >= 0; i--) {
  		struct sock *sk = unix_get_socket(scm->fp->fp[i]);
  
@@@ -1560,8 -1542,10 +1560,8 @@@
  	if (!UNIXCB(skb).fp)
  		return -ENOMEM;
  
 -	if (unix_sock_count) {
 -		for (i = scm->fp->count - 1; i >= 0; i--)
 -			unix_inflight(scm->fp->fp[i]);
 -	}
 +	for (i = scm->fp->count - 1; i >= 0; i--)
 +		unix_inflight(scm->fp->fp[i]);
  	return max_level;
  }
  
@@@ -2108,8 -2092,8 +2108,8 @@@ static int unix_dgram_recvmsg(struct so
  	struct scm_cookie scm;
  	struct sock *sk = sock->sk;
  	struct unix_sock *u = unix_sk(sk);
- 	int noblock = flags & MSG_DONTWAIT;
- 	struct sk_buff *skb;
+ 	struct sk_buff *skb, *last;
+ 	long timeo;
  	int err;
  	int peeked, skip;
  
@@@ -2117,30 -2101,38 +2117,38 @@@
  	if (flags&MSG_OOB)
  		goto out;
  
- 	err = mutex_lock_interruptible(&u->readlock);
- 	if (unlikely(err)) {
- 		/* recvmsg() in non blocking mode is supposed to return -EAGAIN
- 		 * sk_rcvtimeo is not honored by mutex_lock_interruptible()
- 		 */
- 		err = noblock ? -EAGAIN : -ERESTARTSYS;
- 		goto out;
- 	}
+ 	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
  
- 	skip = sk_peek_offset(sk, flags);
+ 	do {
+ 		mutex_lock(&u->readlock);
  
- 	skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
- 	if (!skb) {
+ 		skip = sk_peek_offset(sk, flags);
+ 		skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err,
+ 					      &last);
+ 		if (skb)
+ 			break;
+ 
+ 		mutex_unlock(&u->readlock);
+ 
+ 		if (err != -EAGAIN)
+ 			break;
+ 	} while (timeo &&
+ 		 !__skb_wait_for_more_packets(sk, &err, &timeo, last));
+ 
+ 	if (!skb) { /* implies readlock unlocked */
  		unix_state_lock(sk);
  		/* Signal EOF on disconnected non-blocking SEQPACKET socket. */
  		if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
  		    (sk->sk_shutdown & RCV_SHUTDOWN))
  			err = 0;
  		unix_state_unlock(sk);
- 		goto out_unlock;
+ 		goto out;
  	}
  
- 	wake_up_interruptible_sync_poll(&u->peer_wait,
- 					POLLOUT | POLLWRNORM | POLLWRBAND);
+ 	if (wq_has_sleeper(&u->peer_wait))
+ 		wake_up_interruptible_sync_poll(&u->peer_wait,
+ 						POLLOUT | POLLWRNORM |
+ 						POLLWRBAND);
  
  	if (msg->msg_name)
  		unix_copy_addr(msg, skb->sk);
@@@ -2192,7 -2184,6 +2200,6 @@@
  
  out_free:
  	skb_free_datagram(sk, skb);
- out_unlock:
  	mutex_unlock(&u->readlock);
  out:
  	return err;

-- 
LinuxNextTracking


More information about the linux-merge mailing list