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

batman at open-mesh.org batman at open-mesh.org
Fri Aug 21 00:15:43 CEST 2015


The following commit has been merged in the master branch:
commit 76f768f481ce19da2e23c1b5ccadb14213eb250a
Merge: f94b2fed0a5dabd329dac2a191cc6db63ec7223e def63be85fe774477fb66043003e5b2ee748c4fa
Author: Stephen Rothwell <sfr at canb.auug.org.au>
Date:   Thu Aug 20 12:37:51 2015 +1000

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

diff --combined MAINTAINERS
index e67ffa2,7b528b8..41b0296
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@@ -158,6 -158,7 +158,7 @@@ L:	linux-wpan at vger.kernel.or
  S:	Maintained
  F:	net/6lowpan/
  F:	include/net/6lowpan.h
+ F:	Documentation/networking/6lowpan.txt
  
  6PACK NETWORK DRIVER FOR AX.25
  M:	Andreas Koensgen <ajk at comnets.uni-bremen.de>
@@@ -799,13 -800,11 +800,13 @@@ F:	arch/arm/include/asm/floppy.
  ARM PMU PROFILING AND DEBUGGING
  M:	Will Deacon <will.deacon at arm.com>
  S:	Maintained
 -F:	arch/arm/kernel/perf_event*
 +F:	arch/arm/kernel/perf_*
  F:	arch/arm/oprofile/common.c
 -F:	arch/arm/include/asm/pmu.h
  F:	arch/arm/kernel/hw_breakpoint.c
  F:	arch/arm/include/asm/hw_breakpoint.h
 +F:	arch/arm/include/asm/perf_event.h
 +F:	drivers/perf/arm_pmu.c
 +F:	include/linux/perf/arm_pmu.h
  
  ARM PORT
  M:	Russell King <linux at arm.linux.org.uk>
@@@ -1467,7 -1466,9 +1468,7 @@@ F:	arch/arm/boot/dts/emev2
  F:	arch/arm/boot/dts/r7s*
  F:	arch/arm/boot/dts/r8a*
  F:	arch/arm/boot/dts/sh*
 -F:	arch/arm/configs/armadillo800eva_defconfig
  F:	arch/arm/configs/bockw_defconfig
 -F:	arch/arm/configs/kzm9g_defconfig
  F:	arch/arm/configs/marzen_defconfig
  F:	arch/arm/configs/shmobile_defconfig
  F:	arch/arm/include/debug/renesas-scif.S
@@@ -1506,7 -1507,6 +1507,7 @@@ F:	arch/arm/boot/dts/sti
  F:	drivers/clocksource/arm_global_timer.c
  F:	drivers/i2c/busses/i2c-st.c
  F:	drivers/media/rc/st_rc.c
 +F:	drivers/media/platform/sti/c8sectpfe/
  F:	drivers/mmc/host/sdhci-st.c
  F:	drivers/phy/phy-miphy28lp.c
  F:	drivers/phy/phy-miphy365x.c
@@@ -1580,10 -1580,7 +1581,10 @@@ ARM/UNIPHIER ARCHITECTUR
  M:	Masahiro Yamada <yamada.masahiro at socionext.com>
  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
  S:	Maintained
 +F:	arch/arm/boot/dts/uniphier*
  F:	arch/arm/mach-uniphier/
 +F:	drivers/pinctrl/uniphier/
 +F:	drivers/tty/serial/8250/8250_uniphier.c
  N:	uniphier
  
  ARM/Ux500 ARM ARCHITECTURE
@@@ -1678,7 -1675,7 +1679,7 @@@ M:	Michal Simek <michal.simek at xilinx.co
  R:	Sören Brinkmann <soren.brinkmann at xilinx.com>
  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
  W:	http://wiki.xilinx.com
 -T:	git git://git.xilinx.com/linux-xlnx.git
 +T:	git https://github.com/Xilinx/linux-xlnx.git
  S:	Supported
  F:	arch/arm/mach-zynq/
  F:	drivers/cpuidle/cpuidle-zynq.c
@@@ -2222,9 -2219,7 +2223,9 @@@ F:	drivers/clocksource/bcm_kona_timer.
  BROADCOM BCM2835 ARM ARCHITECTURE
  M:	Stephen Warren <swarren at wwwdotorg.org>
  M:	Lee Jones <lee at kernel.org>
 +M:	Eric Anholt <eric at anholt.net>
  L:	linux-rpi-kernel at lists.infradead.org (moderated for non-subscribers)
 +L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
  S:	Maintained
  N:	bcm2835
@@@ -3593,15 -3588,6 +3594,15 @@@ S:	Maintaine
  F:	drivers/gpu/drm/rockchip/
  F:	Documentation/devicetree/bindings/video/rockchip*
  
 +DRM DRIVERS FOR STI
 +M:	Benjamin Gaignard <benjamin.gaignard at linaro.org>
 +M:	Vincent Abriou <vincent.abriou at st.com>
 +L:	dri-devel at lists.freedesktop.org
 +T:	git http://git.linaro.org/people/benjamin.gaignard/kernel.git
 +S:	Maintained
 +F:	drivers/gpu/drm/sti
 +F:	Documentation/devicetree/bindings/gpu/st,stih4xx.txt
 +
  DSBR100 USB FM RADIO DRIVER
  M:	Alexey Klimov <klimov.linux at gmail.com>
  L:	linux-media at vger.kernel.org
@@@ -4074,6 -4060,15 +4075,6 @@@ F:	Documentation/filesystems/ext2.tx
  F:	fs/ext2/
  F:	include/linux/ext2*
  
 -EXT3 FILE SYSTEM
 -M:	Jan Kara <jack at suse.com>
 -M:	Andrew Morton <akpm at linux-foundation.org>
 -M:	Andreas Dilger <adilger.kernel at dilger.ca>
 -L:	linux-ext4 at vger.kernel.org
 -S:	Maintained
 -F:	Documentation/filesystems/ext3.txt
 -F:	fs/ext3/
 -
  EXT4 FILE SYSTEM
  M:	"Theodore Ts'o" <tytso at mit.edu>
  M:	Andreas Dilger <adilger.kernel at dilger.ca>
@@@ -4412,7 -4407,6 +4413,7 @@@ F:	include/linux/fscache*.
  F2FS FILE SYSTEM
  M:	Jaegeuk Kim <jaegeuk at kernel.org>
  M:	Changman Lee <cm224.lee at samsung.com>
 +R:	Chao Yu <chao2.yu at samsung.com>
  L:	linux-f2fs-devel at lists.sourceforge.net
  W:	http://en.wikipedia.org/wiki/F2FS
  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
@@@ -4421,7 -4415,6 +4422,7 @@@ F:	Documentation/filesystems/f2fs.tx
  F:	Documentation/ABI/testing/sysfs-fs-f2fs
  F:	fs/f2fs/
  F:	include/linux/f2fs_fs.h
 +F:	include/trace/events/f2fs.h
  
  FUJITSU FR-V (FRV) PORT
  M:	David Howells <dhowells at redhat.com>
@@@ -5763,20 -5756,21 +5764,20 @@@ S:	Maintaine
  F:	fs/jffs2/
  F:	include/uapi/linux/jffs2.h
  
 -JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
 -M:	Andrew Morton <akpm at linux-foundation.org>
 -M:	Jan Kara <jack at suse.com>
 -L:	linux-ext4 at vger.kernel.org
 -S:	Maintained
 -F:	fs/jbd/
 -F:	include/linux/jbd.h
 -
  JOURNALLING LAYER FOR BLOCK DEVICES (JBD2)
  M:	"Theodore Ts'o" <tytso at mit.edu>
 +M:	Jan Kara <jack at suse.com>
  L:	linux-ext4 at vger.kernel.org
  S:	Maintained
  F:	fs/jbd2/
  F:	include/linux/jbd2.h
  
 +JPU V4L2 MEM2MEM DRIVER FOR RENESAS
 +M:	Mikhail Ulyanov <mikhail.ulyanov at cogentembedded.com>
 +L:	linux-media at vger.kernel.org
 +S:	Maintained
 +F:	drivers/media/platform/rcar_jpu.c
 +
  JSM Neo PCI based serial card
  M:	Thadeu Lima de Souza Cascardo <cascardo at linux.vnet.ibm.com>
  L:	linux-serial at vger.kernel.org
@@@ -5903,6 -5897,7 +5904,6 @@@ F:	arch/powerpc/kvm
  KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
  M:	Christian Borntraeger <borntraeger at de.ibm.com>
  M:	Cornelia Huck <cornelia.huck at de.ibm.com>
 -M:	linux390 at de.ibm.com
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
@@@ -6516,7 -6511,7 +6517,7 @@@ F:	drivers/net/ethernet/marvell/mvneta.
  
  MARVELL MWIFIEX WIRELESS DRIVER
  M:	Amitkumar Karwar <akarwar at marvell.com>
- M:	Avinash Patil <patila at marvell.com>
+ M:	Nishant Sarmukadam <nishants at marvell.com>
  L:	linux-wireless at vger.kernel.org
  S:	Maintained
  F:	drivers/net/wireless/mwifiex/
@@@ -6545,13 -6540,6 +6546,13 @@@ S:	Maintaine
  F:	Documentation/hwmon/max16065
  F:	drivers/hwmon/max16065.c
  
 +MAX20751 HARDWARE MONITOR DRIVER
 +M:	Guenter Roeck <linux at roeck-us.net>
 +L:	lm-sensors at lm-sensors.org
 +S:	Maintained
 +F:	Documentation/hwmon/max20751
 +F:	drivers/hwmon/max20751.c
 +
  MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
  M:	"Hans J. Koch" <hjk at hansjkoch.de>
  L:	lm-sensors at lm-sensors.org
@@@ -6612,51 -6600,6 +6613,51 @@@ S:	Supporte
  F:	Documentation/devicetree/bindings/media/renesas,vsp1.txt
  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:	http://netup.tv/
 +T:	git git://linuxtv.org/media_tree.git
 +S:	Supported
 +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:	http://netup.tv/
 +T:	git git://linuxtv.org/media_tree.git
 +S:	Supported
 +F:	drivers/media/dvb-frontends/cxd2841er*
 +
 +MEDIA DRIVERS FOR HORUS3A
 +M:	Sergey Kozlov <serjk at netup.ru>
 +L:	linux-media at vger.kernel.org
 +W:	http://linuxtv.org/
 +W:	http://netup.tv/
 +T:	git git://linuxtv.org/media_tree.git
 +S:	Supported
 +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:	http://netup.tv/
 +T:	git git://linuxtv.org/media_tree.git
 +S:	Supported
 +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:	http://netup.tv/
 +T:	git git://linuxtv.org/media_tree.git
 +S:	Supported
 +F:	drivers/media/pci/netup_unidvb/*
 +
  MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
  M:	Mauro Carvalho Chehab <mchehab at osg.samsung.com>
  P:	LinuxTV.org Project
@@@ -6706,6 -6649,15 +6707,15 @@@ W:	http://www.mellanox.co
  Q:	http://patchwork.ozlabs.org/project/netdev/list/
  F:	drivers/net/ethernet/mellanox/mlx4/en_*
  
+ MELLANOX ETHERNET SWITCH DRIVERS
+ M:	Jiri Pirko <jiri at mellanox.com>
+ M:	Ido Schimmel <idosch at mellanox.com>
+ L:	netdev at vger.kernel.org
+ S:	Supported
+ W:	http://www.mellanox.com
+ Q:	http://patchwork.ozlabs.org/project/netdev/list/
+ F:	drivers/net/ethernet/mellanox/mlxsw/
+ 
  MEMORY MANAGEMENT
  L:	linux-mm at kvack.org
  W:	http://www.linux-mm.org
@@@ -8133,15 -8085,6 +8143,15 @@@ S:	Maintaine
  F:	include/linux/power_supply.h
  F:	drivers/power/
  
 +POWER STATE COORDINATION INTERFACE (PSCI)
 +M:	Mark Rutland <mark.rutland at arm.com>
 +M:	Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
 +L:	linux-arm-kernel at lists.infradead.org
 +S:	Maintained
 +F:	drivers/firmware/psci.c
 +F:	include/linux/psci.h
 +F:	include/uapi/linux/psci.h
 +
  PNP SUPPORT
  M:	"Rafael J. Wysocki" <rafael.j.wysocki at intel.com>
  S:	Maintained
@@@ -8765,6 -8708,7 +8775,6 @@@ F:	drivers/video/fbdev/savage
  S390
  M:	Martin Schwidefsky <schwidefsky at de.ibm.com>
  M:	Heiko Carstens <heiko.carstens at de.ibm.com>
 -M:	linux390 at de.ibm.com
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
@@@ -8792,6 -8736,7 +8802,6 @@@ F:	block/partitions/ibm.
  
  S390 NETWORK DRIVERS
  M:	Ursula Braun <ursula.braun at de.ibm.com>
 -M:	linux390 at de.ibm.com
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
@@@ -8808,6 -8753,7 +8818,6 @@@ F:	drivers/pci/hotplug/s390_pci_hpc.
  
  S390 ZCRYPT DRIVER
  M:	Ingo Tuchscherer <ingo.tuchscherer at de.ibm.com>
 -M:	linux390 at de.ibm.com
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
@@@ -8815,6 -8761,7 +8825,6 @@@ F:	drivers/s390/crypto
  
  S390 ZFCP DRIVER
  M:	Steffen Maier <maier at linux.vnet.ibm.com>
 -M:	linux390 at de.ibm.com
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
@@@ -8822,6 -8769,7 +8832,6 @@@ F:	drivers/s390/scsi/zfcp_
  
  S390 IUCV NETWORK LAYER
  M:	Ursula Braun <ursula.braun at de.ibm.com>
 -M:	linux390 at de.ibm.com
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
@@@ -8974,6 -8922,13 +8984,13 @@@ F:	include/linux/dma/dw.
  F:	include/linux/platform_data/dma-dw.h
  F:	drivers/dma/dw/
  
+ SYNOPSYS DESIGNWARE ETHERNET QOS 4.10a driver
+ M: Lars Persson <lars.persson at axis.com>
+ L: netdev at vger.kernel.org
+ S: Supported
+ F: Documentation/devicetree/bindings/net/snps,dwc-qos-ethernet.txt
+ F: drivers/net/ethernet/synopsys/dwc_eth_qos.c
+ 
  SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
  M:	Seungwon Jeon <tgih.jun at samsung.com>
  M:	Jaehoon Chung <jh80.chung at samsung.com>
@@@ -9938,7 -9893,6 +9955,7 @@@ S:	Supporte
  F:	arch/arc/
  F:	Documentation/devicetree/bindings/arc/
  F:	drivers/tty/serial/arc_uart.c
 +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git
  
  SYNOPSYS ARC SDP platform support
  M:	Alexey Brodkin <abrodkin at synopsys.com>
@@@ -10393,13 -10347,6 +10410,13 @@@ F:	drivers/char/toshiba.
  F:	include/linux/toshiba.h
  F:	include/uapi/linux/toshiba.h
  
 +TOSHIBA TC358743 DRIVER
 +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
 +
  TMIO MMC DRIVER
  M:	Ian Molton <ian at mnementh.co.uk>
  L:	linux-mmc at vger.kernel.org
diff --combined arch/arm/boot/dts/am33xx.dtsi
index 01a2d94,8b59c86..b222306
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@@ -103,15 -103,6 +103,15 @@@
  			#size-cells = <1>;
  			ranges = <0 0x44c00000 0x280000>;
  
 +			wkup_m3: wkup_m3 at 100000 {
 +				compatible = "ti,am3352-wkup-m3";
 +				reg = <0x100000 0x4000>,
 +				      <0x180000	0x2000>;
 +				reg-names = "umem", "dmem";
 +				ti,hwmods = "wkup_m3";
 +				ti,pm-firmware = "am335x-pm-firmware.elf";
 +			};
 +
  			prcm: prcm at 200000 {
  				compatible = "ti,am3-prcm";
  				reg = <0x200000 0x4000>;
@@@ -153,14 -144,6 +153,14 @@@
  					};
  				};
  
 +				wkup_m3_ipc: wkup_m3_ipc at 1324 {
 +					compatible = "ti,am3352-wkup-m3-ipc";
 +					reg = <0x1324 0x24>;
 +					interrupts = <78>;
 +					ti,rproc = <&wkup_m3>;
 +					mboxes = <&mailbox &mbox_wkupm3>;
 +				};
 +
  				scm_clockdomains: clockdomains {
  				};
  			};
@@@ -717,7 -700,7 +717,7 @@@
  		};
  
  		mac: ethernet at 4a100000 {
- 			compatible = "ti,cpsw";
+ 			compatible = "ti,am335x-cpsw","ti,cpsw";
  			ti,hwmods = "cpgmac0";
  			clocks = <&cpsw_125mhz_gclk>, <&cpsw_cpts_rft_clk>;
  			clock-names = "fck", "cpts";
@@@ -779,6 -762,14 +779,6 @@@
  			reg = <0x40300000 0x10000>; /* 64k */
  		};
  
 -		wkup_m3: wkup_m3 at 44d00000 {
 -			compatible = "ti,am3353-wkup-m3";
 -			reg = <0x44d00000 0x4000	/* M3 UMEM */
 -			       0x44d80000 0x2000>;	/* M3 DMEM */
 -			ti,hwmods = "wkup_m3";
 -			ti,no-reset-on-init;
 -		};
 -
  		elm: elm at 48080000 {
  			compatible = "ti,am3352-elm";
  			reg = <0x48080000 0x2000>;
diff --combined arch/arm/boot/dts/dra7.dtsi
index e4c4380,0001e95..007e16b
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@@ -116,7 -116,7 +116,7 @@@
  				ranges = <0 0x2000 0x2000>;
  
  				scm_conf: scm_conf at 0 {
 -					compatible = "syscon";
 +					compatible = "syscon", "simple-bus";
  					reg = <0x0 0x1400>;
  					#address-cells = <1>;
  					#size-cells = <1>;
@@@ -141,7 -141,7 +141,7 @@@
  				dra7_pmx_core: pinmux at 1400 {
  					compatible = "ti,dra7-padconf",
  						     "pinctrl-single";
 -					reg = <0x1400 0x0464>;
 +					reg = <0x1400 0x0468>;
  					#address-cells = <1>;
  					#size-cells = <0>;
  					#interrupt-cells = <1>;
@@@ -149,11 -149,6 +149,11 @@@
  					pinctrl-single,register-width = <32>;
  					pinctrl-single,function-mask = <0x3fffffff>;
  				};
 +
 +				scm_conf1: scm_conf at 1c04 {
 +					compatible = "syscon";
 +					reg = <0x1c04 0x0020>;
 +				};
  			};
  
  			cm_core_aon: cm_core_aon at 5000 {
@@@ -216,7 -211,7 +216,7 @@@
  			#address-cells = <1>;
  			ranges = <0x51000000 0x51000000 0x3000
  				  0x0	     0x20000000 0x10000000>;
 -			pcie at 51000000 {
 +			pcie1: pcie at 51000000 {
  				compatible = "ti,dra7-pcie";
  				reg = <0x51000000 0x2000>, <0x51002000 0x14c>, <0x1000 0x2000>;
  				reg-names = "rc_dbics", "ti_conf", "config";
@@@ -291,6 -286,16 +291,6 @@@
  				#thermal-sensor-cells = <1>;
  		};
  
 -		dra7_ctrl_core: ctrl_core at 4a002000 {
 -			compatible = "syscon";
 -			reg = <0x4a002000 0x6d0>;
 -		};
 -
 -		dra7_ctrl_general: tisyscon at 4a002e00 {
 -			compatible = "syscon";
 -			reg = <0x4a002e00 0x7c>;
 -		};
 -
  		sdma: dma-controller at 4a056000 {
  			compatible = "ti,omap4430-sdma";
  			reg = <0x4a056000 0x1000>;
@@@ -303,15 -308,6 +303,15 @@@
  			dma-requests = <127>;
  		};
  
 +		sdma_xbar: dma-router at 4a002b78 {
 +			compatible = "ti,dra7-dma-crossbar";
 +			reg = <0x4a002b78 0xfc>;
 +			#dma-cells = <1>;
 +			dma-requests = <205>;
 +			ti,dma-safe-map = <0>;
 +			dma-masters = <&sdma>;
 +		};
 +
  		gpio1: gpio at 4ae10000 {
  			compatible = "ti,omap4-gpio";
  			reg = <0x4ae10000 0x200>;
@@@ -407,7 -403,7 +407,7 @@@
  			ti,hwmods = "uart1";
  			clock-frequency = <48000000>;
  			status = "disabled";
 -			dmas = <&sdma 49>, <&sdma 50>;
 +			dmas = <&sdma_xbar 49>, <&sdma_xbar 50>;
  			dma-names = "tx", "rx";
  		};
  
@@@ -418,7 -414,7 +418,7 @@@
  			ti,hwmods = "uart2";
  			clock-frequency = <48000000>;
  			status = "disabled";
 -			dmas = <&sdma 51>, <&sdma 52>;
 +			dmas = <&sdma_xbar 51>, <&sdma_xbar 52>;
  			dma-names = "tx", "rx";
  		};
  
@@@ -429,7 -425,7 +429,7 @@@
  			ti,hwmods = "uart3";
  			clock-frequency = <48000000>;
  			status = "disabled";
 -			dmas = <&sdma 53>, <&sdma 54>;
 +			dmas = <&sdma_xbar 53>, <&sdma_xbar 54>;
  			dma-names = "tx", "rx";
  		};
  
@@@ -440,7 -436,7 +440,7 @@@
  			ti,hwmods = "uart4";
  			clock-frequency = <48000000>;
                          status = "disabled";
 -			dmas = <&sdma 55>, <&sdma 56>;
 +			dmas = <&sdma_xbar 55>, <&sdma_xbar 56>;
  			dma-names = "tx", "rx";
  		};
  
@@@ -451,7 -447,7 +451,7 @@@
  			ti,hwmods = "uart5";
  			clock-frequency = <48000000>;
  			status = "disabled";
 -			dmas = <&sdma 63>, <&sdma 64>;
 +			dmas = <&sdma_xbar 63>, <&sdma_xbar 64>;
  			dma-names = "tx", "rx";
  		};
  
@@@ -462,7 -458,7 +462,7 @@@
  			ti,hwmods = "uart6";
  			clock-frequency = <48000000>;
  			status = "disabled";
 -			dmas = <&sdma 79>, <&sdma 80>;
 +			dmas = <&sdma_xbar 79>, <&sdma_xbar 80>;
  			dma-names = "tx", "rx";
  		};
  
@@@ -871,7 -867,7 +871,7 @@@
  			ti,hwmods = "mmc1";
  			ti,dual-volt;
  			ti,needs-special-reset;
 -			dmas = <&sdma 61>, <&sdma 62>;
 +			dmas = <&sdma_xbar 61>, <&sdma_xbar 62>;
  			dma-names = "tx", "rx";
  			status = "disabled";
  			pbias-supply = <&pbias_mmc_reg>;
@@@ -883,7 -879,7 +883,7 @@@
  			interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
  			ti,hwmods = "mmc2";
  			ti,needs-special-reset;
 -			dmas = <&sdma 47>, <&sdma 48>;
 +			dmas = <&sdma_xbar 47>, <&sdma_xbar 48>;
  			dma-names = "tx", "rx";
  			status = "disabled";
  		};
@@@ -894,7 -890,7 +894,7 @@@
  			interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
  			ti,hwmods = "mmc3";
  			ti,needs-special-reset;
 -			dmas = <&sdma 77>, <&sdma 78>;
 +			dmas = <&sdma_xbar 77>, <&sdma_xbar 78>;
  			dma-names = "tx", "rx";
  			status = "disabled";
  		};
@@@ -905,7 -901,7 +905,7 @@@
  			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
  			ti,hwmods = "mmc4";
  			ti,needs-special-reset;
 -			dmas = <&sdma 57>, <&sdma 58>;
 +			dmas = <&sdma_xbar 57>, <&sdma_xbar 58>;
  			dma-names = "tx", "rx";
  			status = "disabled";
  		};
@@@ -1050,14 -1046,14 +1050,14 @@@
  			#size-cells = <0>;
  			ti,hwmods = "mcspi1";
  			ti,spi-num-cs = <4>;
 -			dmas = <&sdma 35>,
 -			       <&sdma 36>,
 -			       <&sdma 37>,
 -			       <&sdma 38>,
 -			       <&sdma 39>,
 -			       <&sdma 40>,
 -			       <&sdma 41>,
 -			       <&sdma 42>;
 +			dmas = <&sdma_xbar 35>,
 +			       <&sdma_xbar 36>,
 +			       <&sdma_xbar 37>,
 +			       <&sdma_xbar 38>,
 +			       <&sdma_xbar 39>,
 +			       <&sdma_xbar 40>,
 +			       <&sdma_xbar 41>,
 +			       <&sdma_xbar 42>;
  			dma-names = "tx0", "rx0", "tx1", "rx1",
  				    "tx2", "rx2", "tx3", "rx3";
  			status = "disabled";
@@@ -1071,10 -1067,10 +1071,10 @@@
  			#size-cells = <0>;
  			ti,hwmods = "mcspi2";
  			ti,spi-num-cs = <2>;
 -			dmas = <&sdma 43>,
 -			       <&sdma 44>,
 -			       <&sdma 45>,
 -			       <&sdma 46>;
 +			dmas = <&sdma_xbar 43>,
 +			       <&sdma_xbar 44>,
 +			       <&sdma_xbar 45>,
 +			       <&sdma_xbar 46>;
  			dma-names = "tx0", "rx0", "tx1", "rx1";
  			status = "disabled";
  		};
@@@ -1087,7 -1083,7 +1087,7 @@@
  			#size-cells = <0>;
  			ti,hwmods = "mcspi3";
  			ti,spi-num-cs = <2>;
 -			dmas = <&sdma 15>, <&sdma 16>;
 +			dmas = <&sdma_xbar 15>, <&sdma_xbar 16>;
  			dma-names = "tx0", "rx0";
  			status = "disabled";
  		};
@@@ -1100,7 -1096,7 +1100,7 @@@
  			#size-cells = <0>;
  			ti,hwmods = "mcspi4";
  			ti,spi-num-cs = <1>;
 -			dmas = <&sdma 70>, <&sdma 71>;
 +			dmas = <&sdma_xbar 70>, <&sdma_xbar 71>;
  			dma-names = "tx0", "rx0";
  			status = "disabled";
  		};
@@@ -1300,12 -1296,7 +1300,12 @@@
  			usb1: usb at 48890000 {
  				compatible = "snps,dwc3";
  				reg = <0x48890000 0x17000>;
 -				interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 +				interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
 +					     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
 +					     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
 +				interrupt-names = "peripheral",
 +						  "host",
 +						  "otg";
  				phys = <&usb2_phy1>, <&usb3_phy1>;
  				phy-names = "usb2-phy", "usb3-phy";
  				tx-fifo-resize;
@@@ -1328,12 -1319,7 +1328,12 @@@
  			usb2: usb at 488d0000 {
  				compatible = "snps,dwc3";
  				reg = <0x488d0000 0x17000>;
 -				interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 +				interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
 +					     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
 +					     <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
 +				interrupt-names = "peripheral",
 +						  "host",
 +						  "otg";
  				phys = <&usb2_phy2>;
  				phy-names = "usb2-phy";
  				tx-fifo-resize;
@@@ -1358,12 -1344,7 +1358,12 @@@
  			usb3: usb at 48910000 {
  				compatible = "snps,dwc3";
  				reg = <0x48910000 0x17000>;
 -				interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
 +				interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
 +					     <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
 +					     <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>;
 +				interrupt-names = "peripheral",
 +						  "host",
 +						  "otg";
  				tx-fifo-resize;
  				maximum-speed = "high-speed";
  				dr_mode = "otg";
@@@ -1418,7 -1399,7 +1418,7 @@@
  		};
  
  		mac: ethernet at 4a100000 {
- 			compatible = "ti,cpsw";
+ 			compatible = "ti,dra7-cpsw","ti,cpsw";
  			ti,hwmods = "gmac";
  			clocks = <&dpll_gmac_ck>, <&gmac_gmii_ref_clk_div>;
  			clock-names = "fck", "cpts";
diff --combined drivers/base/property.c
index 37a7bb7,2e8cd14..73c601b
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@@ -16,6 -16,8 +16,8 @@@
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/property.h>
+ #include <linux/etherdevice.h>
+ #include <linux/phy.h>
  
  /**
   * device_add_property_set - Add a collection of properties to a device object.
@@@ -27,10 -29,9 +29,10 @@@
   */
  void device_add_property_set(struct device *dev, struct property_set *pset)
  {
 -	if (pset)
 -		pset->fwnode.type = FWNODE_PDATA;
 +	if (!pset)
 +		return;
  
 +	pset->fwnode.type = FWNODE_PDATA;
  	set_secondary_fwnode(dev, &pset->fwnode);
  }
  EXPORT_SYMBOL_GPL(device_add_property_set);
@@@ -534,3 -535,74 +536,74 @@@ bool device_dma_is_coherent(struct devi
  	return coherent;
  }
  EXPORT_SYMBOL_GPL(device_dma_is_coherent);
+ 
+ /**
+  * device_get_phy_mode - Get phy mode for given device_node
+  * @dev:	Pointer to the given device
+  *
+  * The function gets phy interface string from property 'phy-mode' or
+  * 'phy-connection-type', and return its index in phy_modes table, or errno in
+  * error case.
+  */
+ int device_get_phy_mode(struct device *dev)
+ {
+ 	const char *pm;
+ 	int err, i;
+ 
+ 	err = device_property_read_string(dev, "phy-mode", &pm);
+ 	if (err < 0)
+ 		err = device_property_read_string(dev,
+ 						  "phy-connection-type", &pm);
+ 	if (err < 0)
+ 		return err;
+ 
+ 	for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
+ 		if (!strcasecmp(pm, phy_modes(i)))
+ 			return i;
+ 
+ 	return -ENODEV;
+ }
+ EXPORT_SYMBOL_GPL(device_get_phy_mode);
+ 
+ static void *device_get_mac_addr(struct device *dev,
+ 				 const char *name, char *addr,
+ 				 int alen)
+ {
+ 	int ret = device_property_read_u8_array(dev, name, addr, alen);
+ 
+ 	if (ret == 0 && is_valid_ether_addr(addr))
+ 		return addr;
+ 	return NULL;
+ }
+ 
+ /**
+  * Search the device tree for the best MAC address to use.  'mac-address' is
+  * checked first, because that is supposed to contain to "most recent" MAC
+  * address. If that isn't set, then 'local-mac-address' is checked next,
+  * because that is the default address.  If that isn't set, then the obsolete
+  * 'address' is checked, just in case we're using an old device tree.
+  *
+  * Note that the 'address' property is supposed to contain a virtual address of
+  * the register set, but some DTS files have redefined that property to be the
+  * MAC address.
+  *
+  * All-zero MAC addresses are rejected, because those could be properties that
+  * exist in the device tree, but were not set by U-Boot.  For example, the
+  * DTS could define 'mac-address' and 'local-mac-address', with zero MAC
+  * addresses.  Some older U-Boots only initialized 'local-mac-address'.  In
+  * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
+  * but is all zeros.
+ */
+ void *device_get_mac_address(struct device *dev, char *addr, int alen)
+ {
+ 	addr = device_get_mac_addr(dev, "mac-address", addr, alen);
+ 	if (addr)
+ 		return addr;
+ 
+ 	addr = device_get_mac_addr(dev, "local-mac-address", addr, alen);
+ 	if (addr)
+ 		return addr;
+ 
+ 	return device_get_mac_addr(dev, "address", addr, alen);
+ }
+ EXPORT_SYMBOL(device_get_mac_address);
diff --combined drivers/net/ethernet/emulex/benet/be_main.c
index 6ca693b,15cc3a1..12687bf
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@@ -681,11 -681,14 +681,14 @@@ void be_link_status_update(struct be_ad
  static void be_tx_stats_update(struct be_tx_obj *txo, struct sk_buff *skb)
  {
  	struct be_tx_stats *stats = tx_stats(txo);
+ 	u64 tx_pkts = skb_shinfo(skb)->gso_segs ? : 1;
  
  	u64_stats_update_begin(&stats->sync);
  	stats->tx_reqs++;
  	stats->tx_bytes += skb->len;
- 	stats->tx_pkts += (skb_shinfo(skb)->gso_segs ? : 1);
+ 	stats->tx_pkts += tx_pkts;
+ 	if (skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL)
+ 		stats->tx_vxlan_offload_pkts += tx_pkts;
  	u64_stats_update_end(&stats->sync);
  }
  
@@@ -1258,7 -1261,7 +1261,7 @@@ static bool be_send_pkt_to_bmc(struct b
  	if (is_udp_pkt((*skb))) {
  		struct udphdr *udp = udp_hdr((*skb));
  
- 		switch (udp->dest) {
+ 		switch (ntohs(udp->dest)) {
  		case DHCP_CLIENT_PORT:
  			os2bmc = is_dhcp_client_filt_enabled(adapter);
  			goto done;
@@@ -1961,6 -1964,8 +1964,8 @@@ static void be_rx_stats_update(struct b
  	stats->rx_compl++;
  	stats->rx_bytes += rxcp->pkt_size;
  	stats->rx_pkts++;
+ 	if (rxcp->tunneled)
+ 		stats->rx_vxlan_offload_pkts++;
  	if (rxcp->pkt_type == BE_MULTICAST_PACKET)
  		stats->rx_mcast_pkts++;
  	if (rxcp->err)
@@@ -3610,15 -3615,15 +3615,15 @@@ err
  
  static int be_setup_wol(struct be_adapter *adapter, bool enable)
  {
+ 	struct device *dev = &adapter->pdev->dev;
  	struct be_dma_mem cmd;
- 	int status = 0;
  	u8 mac[ETH_ALEN];
+ 	int status;
  
  	eth_zero_addr(mac);
  
  	cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
- 	cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
- 				     GFP_KERNEL);
+ 	cmd.va = dma_zalloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
  	if (!cmd.va)
  		return -ENOMEM;
  
@@@ -3627,24 -3632,18 +3632,18 @@@
  						PCICFG_PM_CONTROL_OFFSET,
  						PCICFG_PM_CONTROL_MASK);
  		if (status) {
- 			dev_err(&adapter->pdev->dev,
- 				"Could not enable Wake-on-lan\n");
- 			dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
- 					  cmd.dma);
- 			return status;
+ 			dev_err(dev, "Could not enable Wake-on-lan\n");
+ 			goto err;
  		}
- 		status = be_cmd_enable_magic_wol(adapter,
- 						 adapter->netdev->dev_addr,
- 						 &cmd);
- 		pci_enable_wake(adapter->pdev, PCI_D3hot, 1);
- 		pci_enable_wake(adapter->pdev, PCI_D3cold, 1);
  	} else {
- 		status = be_cmd_enable_magic_wol(adapter, mac, &cmd);
- 		pci_enable_wake(adapter->pdev, PCI_D3hot, 0);
- 		pci_enable_wake(adapter->pdev, PCI_D3cold, 0);
+ 		ether_addr_copy(mac, adapter->netdev->dev_addr);
  	}
  
- 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
+ 	status = be_cmd_enable_magic_wol(adapter, mac, &cmd);
+ 	pci_enable_wake(adapter->pdev, PCI_D3hot, enable);
+ 	pci_enable_wake(adapter->pdev, PCI_D3cold, enable);
+ err:
+ 	dma_free_coherent(dev, cmd.size, cmd.va, cmd.dma);
  	return status;
  }
  
@@@ -4977,7 -4976,7 +4976,7 @@@ static bool be_check_ufi_compatibility(
  {
  	if (!fhdr) {
  		dev_err(&adapter->pdev->dev, "Invalid FW UFI file");
- 		return -1;
+ 		return false;
  	}
  
  	/* First letter of the build version is used to identify
@@@ -5132,9 -5131,6 +5131,6 @@@ static int be_ndo_bridge_getlink(struc
  	int status = 0;
  	u8 hsw_mode;
  
- 	if (!sriov_enabled(adapter))
- 		return 0;
- 
  	/* BE and Lancer chips support VEB mode only */
  	if (BEx_chip(adapter) || lancer_chip(adapter)) {
  		hsw_mode = PORT_FWD_TYPE_VEB;
@@@ -5144,6 -5140,9 +5140,9 @@@
  					       NULL);
  		if (status)
  			return 0;
+ 
+ 		if (hsw_mode == PORT_FWD_TYPE_PASSTHRU)
+ 			return 0;
  	}
  
  	return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
@@@ -5174,7 -5173,7 +5173,7 @@@ static void be_add_vxlan_port(struct ne
  	struct device *dev = &adapter->pdev->dev;
  	int status;
  
 -	if (lancer_chip(adapter) || BEx_chip(adapter))
 +	if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
  		return;
  
  	if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) {
@@@ -5221,7 -5220,7 +5220,7 @@@ static void be_del_vxlan_port(struct ne
  {
  	struct be_adapter *adapter = netdev_priv(netdev);
  
 -	if (lancer_chip(adapter) || BEx_chip(adapter))
 +	if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
  		return;
  
  	if (adapter->vxlan_port != port)
@@@ -5278,6 -5277,27 +5277,27 @@@ static netdev_features_t be_features_ch
  }
  #endif
  
+ static int be_get_phys_port_id(struct net_device *dev,
+ 			       struct netdev_phys_item_id *ppid)
+ {
+ 	int i, id_len = CNTL_SERIAL_NUM_WORDS * CNTL_SERIAL_NUM_WORD_SZ + 1;
+ 	struct be_adapter *adapter = netdev_priv(dev);
+ 	u8 *id;
+ 
+ 	if (MAX_PHYS_ITEM_ID_LEN < id_len)
+ 		return -ENOSPC;
+ 
+ 	ppid->id[0] = adapter->hba_port_num + 1;
+ 	id = &ppid->id[1];
+ 	for (i = CNTL_SERIAL_NUM_WORDS - 1; i >= 0;
+ 	     i--, id += CNTL_SERIAL_NUM_WORD_SZ)
+ 		memcpy(id, &adapter->serial_num[i], CNTL_SERIAL_NUM_WORD_SZ);
+ 
+ 	ppid->id_len = id_len;
+ 
+ 	return 0;
+ }
+ 
  static const struct net_device_ops be_netdev_ops = {
  	.ndo_open		= be_open,
  	.ndo_stop		= be_close,
@@@ -5308,6 -5328,7 +5328,7 @@@
  	.ndo_del_vxlan_port	= be_del_vxlan_port,
  	.ndo_features_check	= be_features_check,
  #endif
+ 	.ndo_get_phys_port_id   = be_get_phys_port_id,
  };
  
  static void be_netdev_init(struct net_device *netdev)
@@@ -5866,7 -5887,6 +5887,6 @@@ static int be_pci_resume(struct pci_de
  	if (status)
  		return status;
  
- 	pci_set_power_state(pdev, PCI_D0);
  	pci_restore_state(pdev);
  
  	status = be_resume(adapter);
@@@ -5946,7 -5966,6 +5966,6 @@@ static pci_ers_result_t be_eeh_reset(st
  		return PCI_ERS_RESULT_DISCONNECT;
  
  	pci_set_master(pdev);
- 	pci_set_power_state(pdev, PCI_D0);
  	pci_restore_state(pdev);
  
  	/* Check if card is ok and fw is ready */
diff --combined drivers/net/ethernet/freescale/gianfar.c
index 10b3bbbb,087ffcd..4b69d061
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@@ -109,15 -109,15 +109,15 @@@
  
  #define TX_TIMEOUT      (1*HZ)
  
- const char gfar_driver_version[] = "1.3";
+ const char gfar_driver_version[] = "2.0";
  
  static int gfar_enet_open(struct net_device *dev);
  static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
  static void gfar_reset_task(struct work_struct *work);
  static void gfar_timeout(struct net_device *dev);
  static int gfar_close(struct net_device *dev);
- static struct sk_buff *gfar_new_skb(struct net_device *dev,
- 				    dma_addr_t *bufaddr);
+ static void gfar_alloc_rx_buffs(struct gfar_priv_rx_q *rx_queue,
+ 				int alloc_cnt);
  static int gfar_set_mac_address(struct net_device *dev);
  static int gfar_change_mtu(struct net_device *dev, int new_mtu);
  static irqreturn_t gfar_error(int irq, void *dev_id);
@@@ -141,8 -141,7 +141,7 @@@ static void gfar_netpoll(struct net_dev
  #endif
  int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
  static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
- static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
- 			       int amount_pull, struct napi_struct *napi);
+ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb);
  static void gfar_halt_nodisable(struct gfar_private *priv);
  static void gfar_clear_exact_match(struct net_device *dev);
  static void gfar_set_mac_for_addr(struct net_device *dev, int num,
@@@ -169,17 -168,15 +168,15 @@@ static void gfar_init_rxbdp(struct gfar
  	bdp->lstatus = cpu_to_be32(lstatus);
  }
  
- static int gfar_init_bds(struct net_device *ndev)
+ static void gfar_init_bds(struct net_device *ndev)
  {
  	struct gfar_private *priv = netdev_priv(ndev);
  	struct gfar __iomem *regs = priv->gfargrp[0].regs;
  	struct gfar_priv_tx_q *tx_queue = NULL;
  	struct gfar_priv_rx_q *rx_queue = NULL;
  	struct txbd8 *txbdp;
- 	struct rxbd8 *rxbdp;
  	u32 __iomem *rfbptr;
  	int i, j;
- 	dma_addr_t bufaddr;
  
  	for (i = 0; i < priv->num_tx_queues; i++) {
  		tx_queue = priv->tx_queue[i];
@@@ -207,40 -204,26 +204,26 @@@
  	rfbptr = &regs->rfbptr0;
  	for (i = 0; i < priv->num_rx_queues; i++) {
  		rx_queue = priv->rx_queue[i];
- 		rx_queue->cur_rx = rx_queue->rx_bd_base;
- 		rx_queue->skb_currx = 0;
- 		rxbdp = rx_queue->rx_bd_base;
  
- 		for (j = 0; j < rx_queue->rx_ring_size; j++) {
- 			struct sk_buff *skb = rx_queue->rx_skbuff[j];
+ 		rx_queue->next_to_clean = 0;
+ 		rx_queue->next_to_use = 0;
+ 		rx_queue->next_to_alloc = 0;
  
- 			if (skb) {
- 				bufaddr = be32_to_cpu(rxbdp->bufPtr);
- 			} else {
- 				skb = gfar_new_skb(ndev, &bufaddr);
- 				if (!skb) {
- 					netdev_err(ndev, "Can't allocate RX buffers\n");
- 					return -ENOMEM;
- 				}
- 				rx_queue->rx_skbuff[j] = skb;
- 			}
- 
- 			gfar_init_rxbdp(rx_queue, rxbdp, bufaddr);
- 			rxbdp++;
- 		}
+ 		/* make sure next_to_clean != next_to_use after this
+ 		 * by leaving at least 1 unused descriptor
+ 		 */
+ 		gfar_alloc_rx_buffs(rx_queue, gfar_rxbd_unused(rx_queue));
  
  		rx_queue->rfbptr = rfbptr;
  		rfbptr += 2;
  	}
- 
- 	return 0;
  }
  
  static int gfar_alloc_skb_resources(struct net_device *ndev)
  {
  	void *vaddr;
  	dma_addr_t addr;
- 	int i, j, k;
+ 	int i, j;
  	struct gfar_private *priv = netdev_priv(ndev);
  	struct device *dev = priv->dev;
  	struct gfar_priv_tx_q *tx_queue = NULL;
@@@ -279,7 -262,8 +262,8 @@@
  		rx_queue = priv->rx_queue[i];
  		rx_queue->rx_bd_base = vaddr;
  		rx_queue->rx_bd_dma_base = addr;
- 		rx_queue->dev = ndev;
+ 		rx_queue->ndev = ndev;
+ 		rx_queue->dev = dev;
  		addr  += sizeof(struct rxbd8) * rx_queue->rx_ring_size;
  		vaddr += sizeof(struct rxbd8) * rx_queue->rx_ring_size;
  	}
@@@ -294,25 -278,20 +278,20 @@@
  		if (!tx_queue->tx_skbuff)
  			goto cleanup;
  
- 		for (k = 0; k < tx_queue->tx_ring_size; k++)
- 			tx_queue->tx_skbuff[k] = NULL;
+ 		for (j = 0; j < tx_queue->tx_ring_size; j++)
+ 			tx_queue->tx_skbuff[j] = NULL;
  	}
  
  	for (i = 0; i < priv->num_rx_queues; i++) {
  		rx_queue = priv->rx_queue[i];
- 		rx_queue->rx_skbuff =
- 			kmalloc_array(rx_queue->rx_ring_size,
- 				      sizeof(*rx_queue->rx_skbuff),
- 				      GFP_KERNEL);
- 		if (!rx_queue->rx_skbuff)
+ 		rx_queue->rx_buff = kcalloc(rx_queue->rx_ring_size,
+ 					    sizeof(*rx_queue->rx_buff),
+ 					    GFP_KERNEL);
+ 		if (!rx_queue->rx_buff)
  			goto cleanup;
- 
- 		for (j = 0; j < rx_queue->rx_ring_size; j++)
- 			rx_queue->rx_skbuff[j] = NULL;
  	}
  
- 	if (gfar_init_bds(ndev))
- 		goto cleanup;
+ 	gfar_init_bds(ndev);
  
  	return 0;
  
@@@ -354,10 -333,8 +333,8 @@@ static void gfar_init_rqprm(struct gfar
  	}
  }
  
- static void gfar_rx_buff_size_config(struct gfar_private *priv)
+ static void gfar_rx_offload_en(struct gfar_private *priv)
  {
- 	int frame_size = priv->ndev->mtu + ETH_HLEN + ETH_FCS_LEN;
- 
  	/* set this when rx hw offload (TOE) functions are being used */
  	priv->uses_rxfcb = 0;
  
@@@ -366,16 -343,6 +343,6 @@@
  
  	if (priv->hwts_rx_en)
  		priv->uses_rxfcb = 1;
- 
- 	if (priv->uses_rxfcb)
- 		frame_size += GMAC_FCB_LEN;
- 
- 	frame_size += priv->padding;
- 
- 	frame_size = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
- 		     INCREMENTAL_BUFFER_SIZE;
- 
- 	priv->rx_buffer_size = frame_size;
  }
  
  static void gfar_mac_rx_config(struct gfar_private *priv)
@@@ -593,9 -560,8 +560,8 @@@ static int gfar_alloc_rx_queues(struct 
  		if (!priv->rx_queue[i])
  			return -ENOMEM;
  
- 		priv->rx_queue[i]->rx_skbuff = NULL;
  		priv->rx_queue[i]->qindex = i;
- 		priv->rx_queue[i]->dev = priv->ndev;
+ 		priv->rx_queue[i]->ndev = priv->ndev;
  	}
  	return 0;
  }
@@@ -1187,12 -1153,11 +1153,11 @@@ void gfar_mac_reset(struct gfar_privat
  
  	udelay(3);
  
- 	/* Compute rx_buff_size based on config flags */
- 	gfar_rx_buff_size_config(priv);
+ 	gfar_rx_offload_en(priv);
  
  	/* Initialize the max receive frame/buffer lengths */
- 	gfar_write(&regs->maxfrm, priv->rx_buffer_size);
- 	gfar_write(&regs->mrblr, priv->rx_buffer_size);
+ 	gfar_write(&regs->maxfrm, GFAR_JUMBO_FRAME_SIZE);
+ 	gfar_write(&regs->mrblr, GFAR_RXB_SIZE);
  
  	/* Initialize the Minimum Frame Length Register */
  	gfar_write(&regs->minflr, MINFLR_INIT_SETTINGS);
@@@ -1200,12 -1165,11 +1165,11 @@@
  	/* Initialize MACCFG2. */
  	tempval = MACCFG2_INIT_SETTINGS;
  
- 	/* If the mtu is larger than the max size for standard
- 	 * ethernet frames (ie, a jumbo frame), then set maccfg2
- 	 * to allow huge frames, and to check the length
+ 	/* eTSEC74 erratum: Rx frames of length MAXFRM or MAXFRM-1
+ 	 * are marked as truncated.  Avoid this by MACCFG2[Huge Frame]=1,
+ 	 * and by checking RxBD[LG] and discarding larger than MAXFRM.
  	 */
- 	if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE ||
- 	    gfar_has_errata(priv, GFAR_ERRATA_74))
+ 	if (gfar_has_errata(priv, GFAR_ERRATA_74))
  		tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK;
  
  	gfar_write(&regs->maccfg2, tempval);
@@@ -1415,8 -1379,6 +1379,6 @@@ static int gfar_probe(struct platform_d
  	    priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
  		dev->needed_headroom = GMAC_FCB_LEN;
  
- 	priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
- 
  	/* Initializing some of the rx/tx queue level parameters */
  	for (i = 0; i < priv->num_tx_queues; i++) {
  		priv->tx_queue[i]->tx_ring_size = DEFAULT_TX_RING_SIZE;
@@@ -1599,10 -1561,7 +1561,7 @@@ static int gfar_restore(struct device *
  		return 0;
  	}
  
- 	if (gfar_init_bds(ndev)) {
- 		free_skb_resources(priv);
- 		return -ENOMEM;
- 	}
+ 	gfar_init_bds(ndev);
  
  	gfar_mac_reset(priv);
  
@@@ -1893,26 -1852,32 +1852,32 @@@ static void free_skb_tx_queue(struct gf
  
  static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
  {
- 	struct rxbd8 *rxbdp;
- 	struct gfar_private *priv = netdev_priv(rx_queue->dev);
  	int i;
  
- 	rxbdp = rx_queue->rx_bd_base;
+ 	struct rxbd8 *rxbdp = rx_queue->rx_bd_base;
+ 
+ 	if (rx_queue->skb)
+ 		dev_kfree_skb(rx_queue->skb);
  
  	for (i = 0; i < rx_queue->rx_ring_size; i++) {
- 		if (rx_queue->rx_skbuff[i]) {
- 			dma_unmap_single(priv->dev, be32_to_cpu(rxbdp->bufPtr),
- 					 priv->rx_buffer_size,
- 					 DMA_FROM_DEVICE);
- 			dev_kfree_skb_any(rx_queue->rx_skbuff[i]);
- 			rx_queue->rx_skbuff[i] = NULL;
- 		}
+ 		struct	gfar_rx_buff *rxb = &rx_queue->rx_buff[i];
+ 
  		rxbdp->lstatus = 0;
  		rxbdp->bufPtr = 0;
  		rxbdp++;
+ 
+ 		if (!rxb->page)
+ 			continue;
+ 
+ 		dma_unmap_single(rx_queue->dev, rxb->dma,
+ 				 PAGE_SIZE, DMA_FROM_DEVICE);
+ 		__free_page(rxb->page);
+ 
+ 		rxb->page = NULL;
  	}
- 	kfree(rx_queue->rx_skbuff);
- 	rx_queue->rx_skbuff = NULL;
+ 
+ 	kfree(rx_queue->rx_buff);
+ 	rx_queue->rx_buff = NULL;
  }
  
  /* If there are any tx skbs or rx skbs still around, free them.
@@@ -1937,7 -1902,7 +1902,7 @@@ static void free_skb_resources(struct g
  
  	for (i = 0; i < priv->num_rx_queues; i++) {
  		rx_queue = priv->rx_queue[i];
- 		if (rx_queue->rx_skbuff)
+ 		if (rx_queue->rx_buff)
  			free_skb_rx_queue(rx_queue);
  	}
  
@@@ -2102,11 -2067,6 +2067,11 @@@ int startup_gfar(struct net_device *nde
  	/* Start Rx/Tx DMA and enable the interrupts */
  	gfar_start(priv);
  
 +	/* force link state update after mac reset */
 +	priv->oldlink = 0;
 +	priv->oldspeed = 0;
 +	priv->oldduplex = -1;
 +
  	phy_start(priv->phydev);
  
  	enable_napi(priv);
@@@ -2500,7 -2460,7 +2465,7 @@@ static int gfar_change_mtu(struct net_d
  	struct gfar_private *priv = netdev_priv(dev);
  	int frame_size = new_mtu + ETH_HLEN;
  
- 	if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
+ 	if ((frame_size < 64) || (frame_size > GFAR_JUMBO_FRAME_SIZE)) {
  		netif_err(priv, drv, dev, "Invalid MTU setting\n");
  		return -EINVAL;
  	}
@@@ -2554,15 -2514,6 +2519,6 @@@ static void gfar_timeout(struct net_dev
  	schedule_work(&priv->reset_task);
  }
  
- static void gfar_align_skb(struct sk_buff *skb)
- {
- 	/* We need the data buffer to be aligned properly.  We will reserve
- 	 * as many bytes as needed to align the data properly
- 	 */
- 	skb_reserve(skb, RXBUF_ALIGNMENT -
- 		    (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1)));
- }
- 
  /* Interrupt Handler for Transmit complete */
  static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
  {
@@@ -2620,7 -2571,8 +2576,8 @@@
  
  		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
  			struct skb_shared_hwtstamps shhwtstamps;
- 			u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
+ 			u64 *ns = (u64 *)(((uintptr_t)skb->data + 0x10) &
+ 					  ~0x7UL);
  
  			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
  			shhwtstamps.hwtstamp = ns_to_ktime(*ns);
@@@ -2669,49 -2621,85 +2626,85 @@@
  	netdev_tx_completed_queue(txq, howmany, bytes_sent);
  }
  
- static struct sk_buff *gfar_alloc_skb(struct net_device *dev)
+ static bool gfar_new_page(struct gfar_priv_rx_q *rxq, struct gfar_rx_buff *rxb)
  {
- 	struct gfar_private *priv = netdev_priv(dev);
- 	struct sk_buff *skb;
+ 	struct page *page;
+ 	dma_addr_t addr;
  
- 	skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
- 	if (!skb)
- 		return NULL;
+ 	page = dev_alloc_page();
+ 	if (unlikely(!page))
+ 		return false;
  
- 	gfar_align_skb(skb);
+ 	addr = dma_map_page(rxq->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+ 	if (unlikely(dma_mapping_error(rxq->dev, addr))) {
+ 		__free_page(page);
  
- 	return skb;
+ 		return false;
+ 	}
+ 
+ 	rxb->dma = addr;
+ 	rxb->page = page;
+ 	rxb->page_offset = 0;
+ 
+ 	return true;
  }
  
- static struct sk_buff *gfar_new_skb(struct net_device *dev, dma_addr_t *bufaddr)
+ static void gfar_rx_alloc_err(struct gfar_priv_rx_q *rx_queue)
  {
- 	struct gfar_private *priv = netdev_priv(dev);
- 	struct sk_buff *skb;
- 	dma_addr_t addr;
+ 	struct gfar_private *priv = netdev_priv(rx_queue->ndev);
+ 	struct gfar_extra_stats *estats = &priv->extra_stats;
  
- 	skb = gfar_alloc_skb(dev);
- 	if (!skb)
- 		return NULL;
+ 	netdev_err(rx_queue->ndev, "Can't alloc RX buffers\n");
+ 	atomic64_inc(&estats->rx_alloc_err);
+ }
  
- 	addr = dma_map_single(priv->dev, skb->data,
- 			      priv->rx_buffer_size, DMA_FROM_DEVICE);
- 	if (unlikely(dma_mapping_error(priv->dev, addr))) {
- 		dev_kfree_skb_any(skb);
- 		return NULL;
+ static void gfar_alloc_rx_buffs(struct gfar_priv_rx_q *rx_queue,
+ 				int alloc_cnt)
+ {
+ 	struct rxbd8 *bdp;
+ 	struct gfar_rx_buff *rxb;
+ 	int i;
+ 
+ 	i = rx_queue->next_to_use;
+ 	bdp = &rx_queue->rx_bd_base[i];
+ 	rxb = &rx_queue->rx_buff[i];
+ 
+ 	while (alloc_cnt--) {
+ 		/* try reuse page */
+ 		if (unlikely(!rxb->page)) {
+ 			if (unlikely(!gfar_new_page(rx_queue, rxb))) {
+ 				gfar_rx_alloc_err(rx_queue);
+ 				break;
+ 			}
+ 		}
+ 
+ 		/* Setup the new RxBD */
+ 		gfar_init_rxbdp(rx_queue, bdp,
+ 				rxb->dma + rxb->page_offset + RXBUF_ALIGNMENT);
+ 
+ 		/* Update to the next pointer */
+ 		bdp++;
+ 		rxb++;
+ 
+ 		if (unlikely(++i == rx_queue->rx_ring_size)) {
+ 			i = 0;
+ 			bdp = rx_queue->rx_bd_base;
+ 			rxb = rx_queue->rx_buff;
+ 		}
  	}
  
- 	*bufaddr = addr;
- 	return skb;
+ 	rx_queue->next_to_use = i;
+ 	rx_queue->next_to_alloc = i;
  }
  
- static inline void count_errors(unsigned short status, struct net_device *dev)
+ static void count_errors(u32 lstatus, struct net_device *ndev)
  {
- 	struct gfar_private *priv = netdev_priv(dev);
- 	struct net_device_stats *stats = &dev->stats;
+ 	struct gfar_private *priv = netdev_priv(ndev);
+ 	struct net_device_stats *stats = &ndev->stats;
  	struct gfar_extra_stats *estats = &priv->extra_stats;
  
  	/* If the packet was truncated, none of the other errors matter */
- 	if (status & RXBD_TRUNCATED) {
+ 	if (lstatus & BD_LFLAG(RXBD_TRUNCATED)) {
  		stats->rx_length_errors++;
  
  		atomic64_inc(&estats->rx_trunc);
@@@ -2719,25 -2707,25 +2712,25 @@@
  		return;
  	}
  	/* Count the errors, if there were any */
- 	if (status & (RXBD_LARGE | RXBD_SHORT)) {
+ 	if (lstatus & BD_LFLAG(RXBD_LARGE | RXBD_SHORT)) {
  		stats->rx_length_errors++;
  
- 		if (status & RXBD_LARGE)
+ 		if (lstatus & BD_LFLAG(RXBD_LARGE))
  			atomic64_inc(&estats->rx_large);
  		else
  			atomic64_inc(&estats->rx_short);
  	}
- 	if (status & RXBD_NONOCTET) {
+ 	if (lstatus & BD_LFLAG(RXBD_NONOCTET)) {
  		stats->rx_frame_errors++;
  		atomic64_inc(&estats->rx_nonoctet);
  	}
- 	if (status & RXBD_CRCERR) {
+ 	if (lstatus & BD_LFLAG(RXBD_CRCERR)) {
  		atomic64_inc(&estats->rx_crcerr);
  		stats->rx_crc_errors++;
  	}
- 	if (status & RXBD_OVERRUN) {
+ 	if (lstatus & BD_LFLAG(RXBD_OVERRUN)) {
  		atomic64_inc(&estats->rx_overrun);
- 		stats->rx_crc_errors++;
+ 		stats->rx_over_errors++;
  	}
  }
  
@@@ -2788,6 -2776,93 +2781,93 @@@ static irqreturn_t gfar_transmit(int ir
  	return IRQ_HANDLED;
  }
  
+ static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus,
+ 			     struct sk_buff *skb, bool first)
+ {
+ 	unsigned int size = lstatus & BD_LENGTH_MASK;
+ 	struct page *page = rxb->page;
+ 
+ 	/* Remove the FCS from the packet length */
+ 	if (likely(lstatus & BD_LFLAG(RXBD_LAST)))
+ 		size -= ETH_FCS_LEN;
+ 
+ 	if (likely(first))
+ 		skb_put(skb, size);
+ 	else
+ 		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
+ 				rxb->page_offset + RXBUF_ALIGNMENT,
+ 				size, GFAR_RXB_TRUESIZE);
+ 
+ 	/* try reuse page */
+ 	if (unlikely(page_count(page) != 1))
+ 		return false;
+ 
+ 	/* change offset to the other half */
+ 	rxb->page_offset ^= GFAR_RXB_TRUESIZE;
+ 
+ 	atomic_inc(&page->_count);
+ 
+ 	return true;
+ }
+ 
+ static void gfar_reuse_rx_page(struct gfar_priv_rx_q *rxq,
+ 			       struct gfar_rx_buff *old_rxb)
+ {
+ 	struct gfar_rx_buff *new_rxb;
+ 	u16 nta = rxq->next_to_alloc;
+ 
+ 	new_rxb = &rxq->rx_buff[nta];
+ 
+ 	/* find next buf that can reuse a page */
+ 	nta++;
+ 	rxq->next_to_alloc = (nta < rxq->rx_ring_size) ? nta : 0;
+ 
+ 	/* copy page reference */
+ 	*new_rxb = *old_rxb;
+ 
+ 	/* sync for use by the device */
+ 	dma_sync_single_range_for_device(rxq->dev, old_rxb->dma,
+ 					 old_rxb->page_offset,
+ 					 GFAR_RXB_TRUESIZE, DMA_FROM_DEVICE);
+ }
+ 
+ static struct sk_buff *gfar_get_next_rxbuff(struct gfar_priv_rx_q *rx_queue,
+ 					    u32 lstatus, struct sk_buff *skb)
+ {
+ 	struct gfar_rx_buff *rxb = &rx_queue->rx_buff[rx_queue->next_to_clean];
+ 	struct page *page = rxb->page;
+ 	bool first = false;
+ 
+ 	if (likely(!skb)) {
+ 		void *buff_addr = page_address(page) + rxb->page_offset;
+ 
+ 		skb = build_skb(buff_addr, GFAR_SKBFRAG_SIZE);
+ 		if (unlikely(!skb)) {
+ 			gfar_rx_alloc_err(rx_queue);
+ 			return NULL;
+ 		}
+ 		skb_reserve(skb, RXBUF_ALIGNMENT);
+ 		first = true;
+ 	}
+ 
+ 	dma_sync_single_range_for_cpu(rx_queue->dev, rxb->dma, rxb->page_offset,
+ 				      GFAR_RXB_TRUESIZE, DMA_FROM_DEVICE);
+ 
+ 	if (gfar_add_rx_frag(rxb, lstatus, skb, first)) {
+ 		/* reuse the free half of the page */
+ 		gfar_reuse_rx_page(rx_queue, rxb);
+ 	} else {
+ 		/* page cannot be reused, unmap it */
+ 		dma_unmap_page(rx_queue->dev, rxb->dma,
+ 			       PAGE_SIZE, DMA_FROM_DEVICE);
+ 	}
+ 
+ 	/* clear rxb content */
+ 	rxb->page = NULL;
+ 
+ 	return skb;
+ }
+ 
  static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
  {
  	/* If valid headers were found, and valid sums
@@@ -2802,10 -2877,9 +2882,9 @@@
  }
  
  /* gfar_process_frame() -- handle one incoming packet if skb isn't NULL. */
- static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
- 			       int amount_pull, struct napi_struct *napi)
+ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb)
  {
- 	struct gfar_private *priv = netdev_priv(dev);
+ 	struct gfar_private *priv = netdev_priv(ndev);
  	struct rxfcb *fcb = NULL;
  
  	/* fcb is at the beginning if exists */
@@@ -2814,10 -2888,8 +2893,8 @@@
  	/* Remove the FCB from the skb
  	 * Remove the padded bytes, if there are any
  	 */
- 	if (amount_pull) {
- 		skb_record_rx_queue(skb, fcb->rq);
- 		skb_pull(skb, amount_pull);
- 	}
+ 	if (priv->uses_rxfcb)
+ 		skb_pull(skb, GMAC_FCB_LEN);
  
  	/* Get receive timestamp from the skb */
  	if (priv->hwts_rx_en) {
@@@ -2831,24 -2903,20 +2908,20 @@@
  	if (priv->padding)
  		skb_pull(skb, priv->padding);
  
- 	if (dev->features & NETIF_F_RXCSUM)
+ 	if (ndev->features & NETIF_F_RXCSUM)
  		gfar_rx_checksum(skb, fcb);
  
  	/* Tell the skb what kind of packet this is */
- 	skb->protocol = eth_type_trans(skb, dev);
+ 	skb->protocol = eth_type_trans(skb, ndev);
  
  	/* There's need to check for NETIF_F_HW_VLAN_CTAG_RX here.
  	 * Even if vlan rx accel is disabled, on some chips
  	 * RXFCB_VLN is pseudo randomly set.
  	 */
- 	if (dev->features & NETIF_F_HW_VLAN_CTAG_RX &&
+ 	if (ndev->features & NETIF_F_HW_VLAN_CTAG_RX &&
  	    be16_to_cpu(fcb->flags) & RXFCB_VLN)
  		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
  				       be16_to_cpu(fcb->vlctl));
- 
- 	/* Send the packet up the stack */
- 	napi_gro_receive(napi, skb);
- 
  }
  
  /* gfar_clean_rx_ring() -- Processes each frame in the rx ring
@@@ -2857,91 -2925,89 +2930,89 @@@
   */
  int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
  {
- 	struct net_device *dev = rx_queue->dev;
- 	struct rxbd8 *bdp, *base;
- 	struct sk_buff *skb;
- 	int pkt_len;
- 	int amount_pull;
- 	int howmany = 0;
- 	struct gfar_private *priv = netdev_priv(dev);
+ 	struct net_device *ndev = rx_queue->ndev;
+ 	struct gfar_private *priv = netdev_priv(ndev);
+ 	struct rxbd8 *bdp;
+ 	int i, howmany = 0;
+ 	struct sk_buff *skb = rx_queue->skb;
+ 	int cleaned_cnt = gfar_rxbd_unused(rx_queue);
+ 	unsigned int total_bytes = 0, total_pkts = 0;
  
  	/* Get the first full descriptor */
- 	bdp = rx_queue->cur_rx;
- 	base = rx_queue->rx_bd_base;
+ 	i = rx_queue->next_to_clean;
  
- 	amount_pull = priv->uses_rxfcb ? GMAC_FCB_LEN : 0;
+ 	while (rx_work_limit--) {
+ 		u32 lstatus;
+ 
+ 		if (cleaned_cnt >= GFAR_RX_BUFF_ALLOC) {
+ 			gfar_alloc_rx_buffs(rx_queue, cleaned_cnt);
+ 			cleaned_cnt = 0;
+ 		}
  
- 	while (!(be16_to_cpu(bdp->status) & RXBD_EMPTY) && rx_work_limit--) {
- 		struct sk_buff *newskb;
- 		dma_addr_t bufaddr;
+ 		bdp = &rx_queue->rx_bd_base[i];
+ 		lstatus = be32_to_cpu(bdp->lstatus);
+ 		if (lstatus & BD_LFLAG(RXBD_EMPTY))
+ 			break;
  
+ 		/* order rx buffer descriptor reads */
  		rmb();
  
- 		/* Add another skb for the future */
- 		newskb = gfar_new_skb(dev, &bufaddr);
+ 		/* fetch next to clean buffer from the ring */
+ 		skb = gfar_get_next_rxbuff(rx_queue, lstatus, skb);
+ 		if (unlikely(!skb))
+ 			break;
  
- 		skb = rx_queue->rx_skbuff[rx_queue->skb_currx];
+ 		cleaned_cnt++;
+ 		howmany++;
  
- 		dma_unmap_single(priv->dev, be32_to_cpu(bdp->bufPtr),
- 				 priv->rx_buffer_size, DMA_FROM_DEVICE);
- 
- 		if (unlikely(!(be16_to_cpu(bdp->status) & RXBD_ERR) &&
- 			     be16_to_cpu(bdp->length) > priv->rx_buffer_size))
- 			bdp->status = cpu_to_be16(RXBD_LARGE);
- 
- 		/* We drop the frame if we failed to allocate a new buffer */
- 		if (unlikely(!newskb ||
- 			     !(be16_to_cpu(bdp->status) & RXBD_LAST) ||
- 			     be16_to_cpu(bdp->status) & RXBD_ERR)) {
- 			count_errors(be16_to_cpu(bdp->status), dev);
- 
- 			if (unlikely(!newskb)) {
- 				newskb = skb;
- 				bufaddr = be32_to_cpu(bdp->bufPtr);
- 			} else if (skb)
- 				dev_kfree_skb(skb);
- 		} else {
- 			/* Increment the number of packets */
- 			rx_queue->stats.rx_packets++;
- 			howmany++;
- 
- 			if (likely(skb)) {
- 				pkt_len = be16_to_cpu(bdp->length) -
- 					  ETH_FCS_LEN;
- 				/* Remove the FCS from the packet length */
- 				skb_put(skb, pkt_len);
- 				rx_queue->stats.rx_bytes += pkt_len;
- 				skb_record_rx_queue(skb, rx_queue->qindex);
- 				gfar_process_frame(dev, skb, amount_pull,
- 						   &rx_queue->grp->napi_rx);
+ 		if (unlikely(++i == rx_queue->rx_ring_size))
+ 			i = 0;
  
- 			} else {
- 				netif_warn(priv, rx_err, dev, "Missing skb!\n");
- 				rx_queue->stats.rx_dropped++;
- 				atomic64_inc(&priv->extra_stats.rx_skbmissing);
- 			}
+ 		rx_queue->next_to_clean = i;
+ 
+ 		/* fetch next buffer if not the last in frame */
+ 		if (!(lstatus & BD_LFLAG(RXBD_LAST)))
+ 			continue;
+ 
+ 		if (unlikely(lstatus & BD_LFLAG(RXBD_ERR))) {
+ 			count_errors(lstatus, ndev);
  
+ 			/* discard faulty buffer */
+ 			dev_kfree_skb(skb);
+ 			skb = NULL;
+ 			rx_queue->stats.rx_dropped++;
+ 			continue;
  		}
  
- 		rx_queue->rx_skbuff[rx_queue->skb_currx] = newskb;
+ 		/* Increment the number of packets */
+ 		total_pkts++;
+ 		total_bytes += skb->len;
  
- 		/* Setup the new bdp */
- 		gfar_init_rxbdp(rx_queue, bdp, bufaddr);
+ 		skb_record_rx_queue(skb, rx_queue->qindex);
  
- 		/* Update Last Free RxBD pointer for LFC */
- 		if (unlikely(rx_queue->rfbptr && priv->tx_actual_en))
- 			gfar_write(rx_queue->rfbptr, (u32)bdp);
+ 		gfar_process_frame(ndev, skb);
  
- 		/* Update to the next pointer */
- 		bdp = next_bd(bdp, base, rx_queue->rx_ring_size);
+ 		/* Send the packet up the stack */
+ 		napi_gro_receive(&rx_queue->grp->napi_rx, skb);
  
- 		/* update to point at the next skb */
- 		rx_queue->skb_currx = (rx_queue->skb_currx + 1) &
- 				      RX_RING_MOD_MASK(rx_queue->rx_ring_size);
+ 		skb = NULL;
  	}
  
- 	/* Update the current rxbd pointer to be the next one */
- 	rx_queue->cur_rx = bdp;
+ 	/* Store incomplete frames for completion */
+ 	rx_queue->skb = skb;
+ 
+ 	rx_queue->stats.rx_packets += total_pkts;
+ 	rx_queue->stats.rx_bytes += total_bytes;
+ 
+ 	if (cleaned_cnt)
+ 		gfar_alloc_rx_buffs(rx_queue, cleaned_cnt);
+ 
+ 	/* Update Last Free RxBD pointer for LFC */
+ 	if (unlikely(priv->tx_actual_en)) {
+ 		u32 bdp_dma = gfar_rxbd_dma_lastfree(rx_queue);
+ 
+ 		gfar_write(rx_queue->rfbptr, bdp_dma);
+ 	}
  
  	return howmany;
  }
@@@ -3459,7 -3525,6 +3530,6 @@@ static noinline void gfar_update_link_s
  	struct phy_device *phydev = priv->phydev;
  	struct gfar_priv_rx_q *rx_queue = NULL;
  	int i;
- 	struct rxbd8 *bdp;
  
  	if (unlikely(test_bit(GFAR_RESETTING, &priv->state)))
  		return;
@@@ -3516,15 -3581,11 +3586,11 @@@
  		/* Turn last free buffer recording on */
  		if ((tempval1 & MACCFG1_TX_FLOW) && !tx_flow_oldval) {
  			for (i = 0; i < priv->num_rx_queues; i++) {
+ 				u32 bdp_dma;
+ 
  				rx_queue = priv->rx_queue[i];
- 				bdp = rx_queue->cur_rx;
- 				/* skip to previous bd */
- 				bdp = skip_bd(bdp, rx_queue->rx_ring_size - 1,
- 					      rx_queue->rx_bd_base,
- 					      rx_queue->rx_ring_size);
- 
- 				if (rx_queue->rfbptr)
- 					gfar_write(rx_queue->rfbptr, (u32)bdp);
+ 				bdp_dma = gfar_rxbd_dma_lastfree(rx_queue);
+ 				gfar_write(rx_queue->rfbptr, bdp_dma);
  			}
  
  			priv->tx_actual_en = 1;
diff --combined drivers/net/phy/phy.c
index 1e1fbb0,84b1fba..d972851
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@@ -353,6 -353,8 +353,8 @@@ int phy_ethtool_sset(struct phy_device 
  
  	phydev->duplex = cmd->duplex;
  
+ 	phydev->mdix = cmd->eth_tp_mdix_ctrl;
+ 
  	/* Restart the PHY */
  	phy_start_aneg(phydev);
  
@@@ -377,6 -379,7 +379,7 @@@ int phy_ethtool_gset(struct phy_device 
  	cmd->transceiver = phy_is_internal(phydev) ?
  		XCVR_INTERNAL : XCVR_EXTERNAL;
  	cmd->autoneg = phydev->autoneg;
+ 	cmd->eth_tp_mdix_ctrl = phydev->mdix;
  
  	return 0;
  }
@@@ -811,7 -814,6 +814,7 @@@ void phy_state_machine(struct work_stru
  	bool needs_aneg = false, do_suspend = false;
  	enum phy_state old_state;
  	int err = 0;
 +	int old_link;
  
  	mutex_lock(&phydev->lock);
  
@@@ -897,18 -899,11 +900,18 @@@
  		phydev->adjust_link(phydev->attached_dev);
  		break;
  	case PHY_RUNNING:
 -		/* Only register a CHANGE if we are
 -		 * polling or ignoring interrupts
 +		/* Only register a CHANGE if we are polling or ignoring
 +		 * interrupts and link changed since latest checking.
  		 */
 -		if (!phy_interrupt_is_valid(phydev))
 -			phydev->state = PHY_CHANGELINK;
 +		if (!phy_interrupt_is_valid(phydev)) {
 +			old_link = phydev->link;
 +			err = phy_read_status(phydev);
 +			if (err)
 +				break;
 +
 +			if (old_link != phydev->link)
 +				phydev->state = PHY_CHANGELINK;
 +		}
  		break;
  	case PHY_CHANGELINK:
  		err = phy_read_status(phydev);
diff --combined drivers/net/usb/qmi_wwan.c
index 64a60af,1f7a7cd..6392ae3
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@@ -785,7 -785,7 +785,8 @@@ static const struct usb_device_id produ
  	{QMI_FIXED_INTF(0x413c, 0x81a4, 8)},	/* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
  	{QMI_FIXED_INTF(0x413c, 0x81a8, 8)},	/* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
  	{QMI_FIXED_INTF(0x413c, 0x81a9, 8)},	/* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
+ 	{QMI_FIXED_INTF(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(0x03f0, 0x581d, 4)},	/* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
  
  	/* 4. Gobi 1000 devices */
diff --combined include/net/lwtunnel.h
index 0000000,34fd8f7..e25b60e
mode 000000,100644..100644
--- a/include/net/lwtunnel.h
+++ b/include/net/lwtunnel.h
@@@ -1,0 -1,180 +1,175 @@@
+ #ifndef __NET_LWTUNNEL_H
+ #define __NET_LWTUNNEL_H 1
+ 
+ #include <linux/lwtunnel.h>
+ #include <linux/netdevice.h>
+ #include <linux/skbuff.h>
+ #include <linux/types.h>
+ #include <net/route.h>
+ 
+ #define LWTUNNEL_HASH_BITS   7
+ #define LWTUNNEL_HASH_SIZE   (1 << LWTUNNEL_HASH_BITS)
+ 
+ /* lw tunnel state flags */
+ #define LWTUNNEL_STATE_OUTPUT_REDIRECT	BIT(0)
+ #define LWTUNNEL_STATE_INPUT_REDIRECT	BIT(1)
+ 
+ struct lwtunnel_state {
+ 	__u16		type;
+ 	__u16		flags;
+ 	atomic_t	refcnt;
+ 	int		(*orig_output)(struct sock *sk, struct sk_buff *skb);
+ 	int		(*orig_input)(struct sk_buff *);
+ 	int             len;
+ 	__u8            data[0];
+ };
+ 
+ struct lwtunnel_encap_ops {
+ 	int (*build_state)(struct net_device *dev, struct nlattr *encap,
+ 			   struct lwtunnel_state **ts);
+ 	int (*output)(struct sock *sk, struct sk_buff *skb);
+ 	int (*input)(struct sk_buff *skb);
+ 	int (*fill_encap)(struct sk_buff *skb,
+ 			  struct lwtunnel_state *lwtstate);
+ 	int (*get_encap_size)(struct lwtunnel_state *lwtstate);
+ 	int (*cmp_encap)(struct lwtunnel_state *a, struct lwtunnel_state *b);
+ };
+ 
+ #ifdef CONFIG_LWTUNNEL
 -static inline void lwtstate_free(struct lwtunnel_state *lws)
 -{
 -	kfree(lws);
 -}
 -
+ static inline struct lwtunnel_state *
+ lwtstate_get(struct lwtunnel_state *lws)
+ {
+ 	if (lws)
+ 		atomic_inc(&lws->refcnt);
+ 
+ 	return lws;
+ }
+ 
+ static inline void lwtstate_put(struct lwtunnel_state *lws)
+ {
+ 	if (!lws)
+ 		return;
+ 
+ 	if (atomic_dec_and_test(&lws->refcnt))
 -		lwtstate_free(lws);
++		kfree(lws);
+ }
+ 
+ static inline bool lwtunnel_output_redirect(struct lwtunnel_state *lwtstate)
+ {
+ 	if (lwtstate && (lwtstate->flags & LWTUNNEL_STATE_OUTPUT_REDIRECT))
+ 		return true;
+ 
+ 	return false;
+ }
+ 
+ static inline bool lwtunnel_input_redirect(struct lwtunnel_state *lwtstate)
+ {
+ 	if (lwtstate && (lwtstate->flags & LWTUNNEL_STATE_INPUT_REDIRECT))
+ 		return true;
+ 
+ 	return false;
+ }
+ int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op,
+ 			   unsigned int num);
+ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
+ 			   unsigned int num);
+ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
+ 			 struct nlattr *encap,
+ 			 struct lwtunnel_state **lws);
+ int lwtunnel_fill_encap(struct sk_buff *skb,
+ 			struct lwtunnel_state *lwtstate);
+ int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate);
+ struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len);
+ int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b);
+ int lwtunnel_output(struct sock *sk, struct sk_buff *skb);
+ int lwtunnel_output6(struct sock *sk, struct sk_buff *skb);
+ int lwtunnel_input(struct sk_buff *skb);
+ int lwtunnel_input6(struct sk_buff *skb);
+ 
+ #else
+ 
+ static inline struct lwtunnel_state *
+ lwtstate_get(struct lwtunnel_state *lws)
+ {
+ 	return lws;
+ }
+ 
+ static inline void lwtstate_put(struct lwtunnel_state *lws)
+ {
+ }
+ 
+ static inline bool lwtunnel_output_redirect(struct lwtunnel_state *lwtstate)
+ {
+ 	return false;
+ }
+ 
+ static inline bool lwtunnel_input_redirect(struct lwtunnel_state *lwtstate)
+ {
+ 	return false;
+ }
+ 
+ static inline int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op,
+ 					 unsigned int num)
+ {
+ 	return -EOPNOTSUPP;
+ 
+ }
+ 
+ static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
+ 					 unsigned int num)
+ {
+ 	return -EOPNOTSUPP;
+ }
+ 
+ static inline int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
+ 				       struct nlattr *encap,
+ 				       struct lwtunnel_state **lws)
+ {
+ 	return -EOPNOTSUPP;
+ }
+ 
+ static inline int lwtunnel_fill_encap(struct sk_buff *skb,
+ 				      struct lwtunnel_state *lwtstate)
+ {
+ 	return 0;
+ }
+ 
+ static inline int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate)
+ {
+ 	return 0;
+ }
+ 
+ static inline struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len)
+ {
+ 	return NULL;
+ }
+ 
+ static inline int lwtunnel_cmp_encap(struct lwtunnel_state *a,
+ 				     struct lwtunnel_state *b)
+ {
+ 	return 0;
+ }
+ 
+ static inline int lwtunnel_output(struct sock *sk, struct sk_buff *skb)
+ {
+ 	return -EOPNOTSUPP;
+ }
+ 
+ static inline int lwtunnel_output6(struct sock *sk, struct sk_buff *skb)
+ {
+ 	return -EOPNOTSUPP;
+ }
+ 
+ static inline int lwtunnel_input(struct sk_buff *skb)
+ {
+ 	return -EOPNOTSUPP;
+ }
+ 
+ static inline int lwtunnel_input6(struct sk_buff *skb)
+ {
+ 	return -EOPNOTSUPP;
+ }
+ 
+ #endif
+ 
+ #endif /* __NET_LWTUNNEL_H */
diff --combined kernel/events/core.c
index e6feb51,e2c6a88..a1339b1
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@@ -1868,6 -1868,8 +1868,6 @@@ event_sched_in(struct perf_event *event
  
  	perf_pmu_disable(event->pmu);
  
 -	event->tstamp_running += tstamp - event->tstamp_stopped;
 -
  	perf_set_shadow_time(event, ctx, tstamp);
  
  	perf_log_itrace_start(event);
@@@ -1879,8 -1881,6 +1879,8 @@@
  		goto out;
  	}
  
 +	event->tstamp_running += tstamp - event->tstamp_stopped;
 +
  	if (!is_software_event(event))
  		cpuctx->active_oncpu++;
  	if (!ctx->nr_active++)
@@@ -3212,6 -3212,59 +3212,59 @@@ static inline u64 perf_event_count(stru
  	return __perf_event_count(event);
  }
  
+ /*
+  * NMI-safe method to read a local event, that is an event that
+  * is:
+  *   - either for the current task, or for this CPU
+  *   - does not have inherit set, for inherited task events
+  *     will not be local and we cannot read them atomically
+  *   - must not have a pmu::count method
+  */
+ u64 perf_event_read_local(struct perf_event *event)
+ {
+ 	unsigned long flags;
+ 	u64 val;
+ 
+ 	/*
+ 	 * Disabling interrupts avoids all counter scheduling (context
+ 	 * switches, timer based rotation and IPIs).
+ 	 */
+ 	local_irq_save(flags);
+ 
+ 	/* If this is a per-task event, it must be for current */
+ 	WARN_ON_ONCE((event->attach_state & PERF_ATTACH_TASK) &&
+ 		     event->hw.target != current);
+ 
+ 	/* If this is a per-CPU event, it must be for this CPU */
+ 	WARN_ON_ONCE(!(event->attach_state & PERF_ATTACH_TASK) &&
+ 		     event->cpu != smp_processor_id());
+ 
+ 	/*
+ 	 * It must not be an event with inherit set, we cannot read
+ 	 * all child counters from atomic context.
+ 	 */
+ 	WARN_ON_ONCE(event->attr.inherit);
+ 
+ 	/*
+ 	 * It must not have a pmu::count method, those are not
+ 	 * NMI safe.
+ 	 */
+ 	WARN_ON_ONCE(event->pmu->count);
+ 
+ 	/*
+ 	 * If the event is currently on this CPU, its either a per-task event,
+ 	 * or local to this CPU. Furthermore it means its ACTIVE (otherwise
+ 	 * oncpu == -1).
+ 	 */
+ 	if (event->oncpu == smp_processor_id())
+ 		event->pmu->read(event);
+ 
+ 	val = local64_read(&event->count);
+ 	local_irq_restore(flags);
+ 
+ 	return val;
+ }
+ 
  static u64 perf_event_read(struct perf_event *event)
  {
  	/*
@@@ -3958,21 -4011,28 +4011,21 @@@ static void perf_event_for_each(struct 
  		perf_event_for_each_child(sibling, func);
  }
  
 -static int perf_event_period(struct perf_event *event, u64 __user *arg)
 -{
 -	struct perf_event_context *ctx = event->ctx;
 -	int ret = 0, active;
 +struct period_event {
 +	struct perf_event *event;
  	u64 value;
 +};
  
 -	if (!is_sampling_event(event))
 -		return -EINVAL;
 -
 -	if (copy_from_user(&value, arg, sizeof(value)))
 -		return -EFAULT;
 -
 -	if (!value)
 -		return -EINVAL;
 +static int __perf_event_period(void *info)
 +{
 +	struct period_event *pe = info;
 +	struct perf_event *event = pe->event;
 +	struct perf_event_context *ctx = event->ctx;
 +	u64 value = pe->value;
 +	bool active;
  
 -	raw_spin_lock_irq(&ctx->lock);
 +	raw_spin_lock(&ctx->lock);
  	if (event->attr.freq) {
 -		if (value > sysctl_perf_event_sample_rate) {
 -			ret = -EINVAL;
 -			goto unlock;
 -		}
 -
  		event->attr.sample_freq = value;
  	} else {
  		event->attr.sample_period = value;
@@@ -3991,53 -4051,11 +4044,53 @@@
  		event->pmu->start(event, PERF_EF_RELOAD);
  		perf_pmu_enable(ctx->pmu);
  	}
 +	raw_spin_unlock(&ctx->lock);
  
 -unlock:
 +	return 0;
 +}
 +
 +static int perf_event_period(struct perf_event *event, u64 __user *arg)
 +{
 +	struct period_event pe = { .event = event, };
 +	struct perf_event_context *ctx = event->ctx;
 +	struct task_struct *task;
 +	u64 value;
 +
 +	if (!is_sampling_event(event))
 +		return -EINVAL;
 +
 +	if (copy_from_user(&value, arg, sizeof(value)))
 +		return -EFAULT;
 +
 +	if (!value)
 +		return -EINVAL;
 +
 +	if (event->attr.freq && value > sysctl_perf_event_sample_rate)
 +		return -EINVAL;
 +
 +	task = ctx->task;
 +	pe.value = value;
 +
 +	if (!task) {
 +		cpu_function_call(event->cpu, __perf_event_period, &pe);
 +		return 0;
 +	}
 +
 +retry:
 +	if (!task_function_call(task, __perf_event_period, &pe))
 +		return 0;
 +
 +	raw_spin_lock_irq(&ctx->lock);
 +	if (ctx->is_active) {
 +		raw_spin_unlock_irq(&ctx->lock);
 +		task = ctx->task;
 +		goto retry;
 +	}
 +
 +	__perf_event_period(&pe);
  	raw_spin_unlock_irq(&ctx->lock);
  
 -	return ret;
 +	return 0;
  }
  
  static const struct file_operations perf_fops;
@@@ -4775,20 -4793,12 +4828,20 @@@ static const struct file_operations per
   * to user-space before waking everybody up.
   */
  
 +static inline struct fasync_struct **perf_event_fasync(struct perf_event *event)
 +{
 +	/* only the parent has fasync state */
 +	if (event->parent)
 +		event = event->parent;
 +	return &event->fasync;
 +}
 +
  void perf_event_wakeup(struct perf_event *event)
  {
  	ring_buffer_wakeup(event);
  
  	if (event->pending_kill) {
 -		kill_fasync(&event->fasync, SIGIO, event->pending_kill);
 +		kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill);
  		event->pending_kill = 0;
  	}
  }
@@@ -6167,7 -6177,7 +6220,7 @@@ static int __perf_event_overflow(struc
  	else
  		perf_event_output(event, data, regs);
  
 -	if (event->fasync && event->pending_kill) {
 +	if (*perf_event_fasync(event) && event->pending_kill) {
  		event->pending_wakeup = 1;
  		irq_work_queue(&event->pending);
  	}
@@@ -8617,6 -8627,31 +8670,31 @@@ void perf_event_delayed_put(struct task
  		WARN_ON_ONCE(task->perf_event_ctxp[ctxn]);
  }
  
+ struct perf_event *perf_event_get(unsigned int fd)
+ {
+ 	int err;
+ 	struct fd f;
+ 	struct perf_event *event;
+ 
+ 	err = perf_fget_light(fd, &f);
+ 	if (err)
+ 		return ERR_PTR(err);
+ 
+ 	event = f.file->private_data;
+ 	atomic_long_inc(&event->refcount);
+ 	fdput(f);
+ 
+ 	return event;
+ }
+ 
+ const struct perf_event_attr *perf_event_attrs(struct perf_event *event)
+ {
+ 	if (!event)
+ 		return ERR_PTR(-EINVAL);
+ 
+ 	return &event->attr;
+ }
+ 
  /*
   * inherit a event from parent task to child task:
   */
diff --combined net/batman-adv/translation-table.c
index 5809b39,db06de2..c1eb7b7
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@@ -19,6 -19,7 +19,7 @@@
  #include "main.h"
  
  #include <linux/atomic.h>
+ #include <linux/bitops.h>
  #include <linux/bug.h>
  #include <linux/byteorder/generic.h>
  #include <linux/compiler.h>
@@@ -595,11 -596,8 +596,11 @@@ bool batadv_tt_local_add(struct net_dev
  	/* increase the refcounter of the related vlan */
  	vlan = batadv_softif_vlan_get(bat_priv, vid);
  	if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d",
 -		 addr, BATADV_PRINT_VID(vid)))
 +		 addr, BATADV_PRINT_VID(vid))) {
 +		kfree(tt_local);
 +		tt_local = NULL;
  		goto out;
 +	}
  
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
  		   "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
@@@ -1882,7 -1880,7 +1883,7 @@@ void batadv_tt_global_del_orig(struct b
  		}
  		spin_unlock_bh(list_lock);
  	}
- 	orig_node->capa_initialized &= ~BATADV_ORIG_CAPA_HAS_TT;
+ 	clear_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
  }
  
  static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
@@@ -2215,7 -2213,7 +2216,7 @@@ static void batadv_tt_req_list_free(str
  	spin_lock_bh(&bat_priv->tt.req_list_lock);
  
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
- 		list_del(&node->list);
+ 		list_del_init(&node->list);
  		kfree(node);
  	}
  
@@@ -2251,7 -2249,7 +2252,7 @@@ static void batadv_tt_req_purge(struct 
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
  		if (batadv_has_timed_out(node->issued_at,
  					 BATADV_TT_REQUEST_TIMEOUT)) {
- 			list_del(&node->list);
+ 			list_del_init(&node->list);
  			kfree(node);
  		}
  	}
@@@ -2533,7 -2531,8 +2534,8 @@@ out
  		batadv_hardif_free_ref(primary_if);
  	if (ret && tt_req_node) {
  		spin_lock_bh(&bat_priv->tt.req_list_lock);
- 		list_del(&tt_req_node->list);
+ 		/* list_del_init() verifies tt_req_node still is in the list */
+ 		list_del_init(&tt_req_node->list);
  		spin_unlock_bh(&bat_priv->tt.req_list_lock);
  		kfree(tt_req_node);
  	}
@@@ -2841,7 -2840,7 +2843,7 @@@ static void _batadv_tt_update_changes(s
  				return;
  		}
  	}
- 	orig_node->capa_initialized |= BATADV_ORIG_CAPA_HAS_TT;
+ 	set_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
  }
  
  static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
@@@ -2970,7 -2969,7 +2972,7 @@@ static void batadv_handle_tt_response(s
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
  		if (!batadv_compare_eth(node->addr, resp_src))
  			continue;
- 		list_del(&node->list);
+ 		list_del_init(&node->list);
  		kfree(node);
  	}
  
@@@ -3343,7 -3342,8 +3345,8 @@@ static void batadv_tt_update_orig(struc
  	bool has_tt_init;
  
  	tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
- 	has_tt_init = orig_node->capa_initialized & BATADV_ORIG_CAPA_HAS_TT;
+ 	has_tt_init = test_bit(BATADV_ORIG_CAPA_HAS_TT,
+ 			       &orig_node->capa_initialized);
  
  	/* orig table not initialised AND first diff is in the OGM OR the ttvn
  	 * increased by one -> we can apply the attached changes
diff --combined net/bridge/br_multicast.c
index 1285eaf,0752796..66efdc2
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@@ -283,6 -283,8 +283,8 @@@ static void br_multicast_del_pg(struct 
  		rcu_assign_pointer(*pp, p->next);
  		hlist_del_init(&p->mglist);
  		del_timer(&p->timer);
+ 		br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB,
+ 			      p->state);
  		call_rcu_bh(&p->rcu, br_multicast_free_pg);
  
  		if (!mp->ports && !mp->mglist &&
@@@ -704,7 -706,7 +706,7 @@@ static int br_multicast_add_group(struc
  	if (unlikely(!p))
  		goto err;
  	rcu_assign_pointer(*pp, p);
- 	br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
+ 	br_mdb_notify(br->dev, port, group, RTM_NEWMDB, MDB_TEMPORARY);
  
  found:
  	mod_timer(&p->timer, now + br->multicast_membership_interval);
@@@ -764,6 -766,7 +766,7 @@@ static void br_multicast_router_expired
  		goto out;
  
  	hlist_del_init_rcu(&port->rlist);
+ 	br_rtr_notify(br->dev, port, RTM_DELMDB);
  
  out:
  	spin_unlock(&br->multicast_lock);
@@@ -924,6 -927,15 +927,15 @@@ void br_multicast_add_port(struct net_b
  
  void br_multicast_del_port(struct net_bridge_port *port)
  {
+ 	struct net_bridge *br = port->br;
+ 	struct net_bridge_port_group *pg;
+ 	struct hlist_node *n;
+ 
+ 	/* Take care of the remaining groups, only perm ones should be left */
+ 	spin_lock_bh(&br->multicast_lock);
+ 	hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
+ 		br_multicast_del_pg(br, pg);
+ 	spin_unlock_bh(&br->multicast_lock);
  	del_timer_sync(&port->multicast_router_timer);
  }
  
@@@ -963,10 -975,13 +975,13 @@@ void br_multicast_disable_port(struct n
  
  	spin_lock(&br->multicast_lock);
  	hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
- 		br_multicast_del_pg(br, pg);
+ 		if (pg->state == MDB_TEMPORARY)
+ 			br_multicast_del_pg(br, pg);
  
- 	if (!hlist_unhashed(&port->rlist))
+ 	if (!hlist_unhashed(&port->rlist)) {
  		hlist_del_init_rcu(&port->rlist);
+ 		br_rtr_notify(br->dev, port, RTM_DELMDB);
+ 	}
  	del_timer(&port->multicast_router_timer);
  	del_timer(&port->ip4_own_query.timer);
  #if IS_ENABLED(CONFIG_IPV6)
@@@ -1204,6 -1219,7 +1219,7 @@@ static void br_multicast_add_router(str
  		hlist_add_behind_rcu(&port->rlist, slot);
  	else
  		hlist_add_head_rcu(&port->rlist, &br->router_list);
+ 	br_rtr_notify(br->dev, port, RTM_NEWMDB);
  }
  
  static void br_multicast_mark_router(struct net_bridge *br,
@@@ -1437,7 -1453,8 +1453,8 @@@ br_multicast_leave_group(struct net_bri
  			hlist_del_init(&p->mglist);
  			del_timer(&p->timer);
  			call_rcu_bh(&p->rcu, br_multicast_free_pg);
- 			br_mdb_notify(br->dev, port, group, RTM_DELMDB);
+ 			br_mdb_notify(br->dev, port, group, RTM_DELMDB,
+ 				      p->state);
  
  			if (!mp->ports && !mp->mglist &&
  			    netif_running(br->dev))
@@@ -1591,7 -1608,7 +1608,7 @@@ static int br_multicast_ipv4_rcv(struc
  		break;
  	}
  
 -	if (skb_trimmed)
 +	if (skb_trimmed && skb_trimmed != skb)
  		kfree_skb(skb_trimmed);
  
  	return err;
@@@ -1636,7 -1653,7 +1653,7 @@@ static int br_multicast_ipv6_rcv(struc
  		break;
  	}
  
 -	if (skb_trimmed)
 +	if (skb_trimmed && skb_trimmed != skb)
  		kfree_skb(skb_trimmed);
  
  	return err;
@@@ -1754,12 -1771,6 +1771,6 @@@ void br_multicast_open(struct net_bridg
  
  void br_multicast_stop(struct net_bridge *br)
  {
- 	struct net_bridge_mdb_htable *mdb;
- 	struct net_bridge_mdb_entry *mp;
- 	struct hlist_node *n;
- 	u32 ver;
- 	int i;
- 
  	del_timer_sync(&br->multicast_router_timer);
  	del_timer_sync(&br->ip4_other_query.timer);
  	del_timer_sync(&br->ip4_own_query.timer);
@@@ -1767,6 -1778,15 +1778,15 @@@
  	del_timer_sync(&br->ip6_other_query.timer);
  	del_timer_sync(&br->ip6_own_query.timer);
  #endif
+ }
+ 
+ void br_multicast_dev_del(struct net_bridge *br)
+ {
+ 	struct net_bridge_mdb_htable *mdb;
+ 	struct net_bridge_mdb_entry *mp;
+ 	struct hlist_node *n;
+ 	u32 ver;
+ 	int i;
  
  	spin_lock_bh(&br->multicast_lock);
  	mdb = mlock_dereference(br->mdb, br);
@@@ -1834,8 -1854,10 +1854,10 @@@ int br_multicast_set_port_router(struc
  		p->multicast_router = val;
  		err = 0;
  
- 		if (val < 2 && !hlist_unhashed(&p->rlist))
+ 		if (val < 2 && !hlist_unhashed(&p->rlist)) {
  			hlist_del_init_rcu(&p->rlist);
+ 			br_rtr_notify(br->dev, p, RTM_DELMDB);
+ 		}
  
  		if (val == 1)
  			break;
diff --combined net/ipv4/fib_semantics.c
index 3a06586,d525307..c802585
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@@ -42,6 -42,7 +42,7 @@@
  #include <net/ip_fib.h>
  #include <net/netlink.h>
  #include <net/nexthop.h>
+ #include <net/lwtunnel.h>
  
  #include "fib_lookup.h"
  
@@@ -208,6 -209,7 +209,7 @@@ static void free_fib_info_rcu(struct rc
  	change_nexthops(fi) {
  		if (nexthop_nh->nh_dev)
  			dev_put(nexthop_nh->nh_dev);
+ 		lwtstate_put(nexthop_nh->nh_lwtstate);
  		free_nh_exceptions(nexthop_nh);
  		rt_fibinfo_free_cpus(nexthop_nh->nh_pcpu_rth_output);
  		rt_fibinfo_free(&nexthop_nh->nh_rth_input);
@@@ -266,6 -268,7 +268,7 @@@ static inline int nh_comp(const struct 
  #ifdef CONFIG_IP_ROUTE_CLASSID
  		    nh->nh_tclassid != onh->nh_tclassid ||
  #endif
+ 		    lwtunnel_cmp_encap(nh->nh_lwtstate, onh->nh_lwtstate) ||
  		    ((nh->nh_flags ^ onh->nh_flags) & ~RTNH_COMPARE_MASK))
  			return -1;
  		onh++;
@@@ -366,6 -369,7 +369,7 @@@ static inline size_t fib_nlmsg_size(str
  	payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
  
  	if (fi->fib_nhs) {
+ 		size_t nh_encapsize = 0;
  		/* Also handles the special case fib_nhs == 1 */
  
  		/* each nexthop is packed in an attribute */
@@@ -374,8 -378,21 +378,21 @@@
  		/* may contain flow and gateway attribute */
  		nhsize += 2 * nla_total_size(4);
  
+ 		/* grab encap info */
+ 		for_nexthops(fi) {
+ 			if (nh->nh_lwtstate) {
+ 				/* RTA_ENCAP_TYPE */
+ 				nh_encapsize += lwtunnel_get_encap_size(
+ 						nh->nh_lwtstate);
+ 				/* RTA_ENCAP */
+ 				nh_encapsize +=  nla_total_size(2);
+ 			}
+ 		} endfor_nexthops(fi);
+ 
  		/* all nexthops are packed in a nested attribute */
- 		payload += nla_total_size(fi->fib_nhs * nhsize);
+ 		payload += nla_total_size((fi->fib_nhs * nhsize) +
+ 					  nh_encapsize);
+ 
  	}
  
  	return payload;
@@@ -421,13 -438,15 +438,15 @@@ static int fib_detect_death(struct fib_
  	if (n) {
  		state = n->nud_state;
  		neigh_release(n);
+ 	} else {
+ 		return 0;
  	}
  	if (state == NUD_REACHABLE)
  		return 0;
  	if ((state & NUD_VALID) && order != dflt)
  		return 0;
  	if ((state & NUD_VALID) ||
- 	    (*last_idx < 0 && order > dflt)) {
+ 	    (*last_idx < 0 && order > dflt && state != NUD_INCOMPLETE)) {
  		*last_resort = fi;
  		*last_idx = order;
  	}
@@@ -452,6 -471,9 +471,9 @@@ static int fib_count_nexthops(struct rt
  static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
  		       int remaining, struct fib_config *cfg)
  {
+ 	struct net *net = cfg->fc_nlinfo.nl_net;
+ 	int ret;
+ 
  	change_nexthops(fi) {
  		int attrlen;
  
@@@ -475,18 -497,68 +497,66 @@@
  			if (nexthop_nh->nh_tclassid)
  				fi->fib_net->ipv4.fib_num_tclassid_users++;
  #endif
+ 			nla = nla_find(attrs, attrlen, RTA_ENCAP);
+ 			if (nla) {
+ 				struct lwtunnel_state *lwtstate;
+ 				struct net_device *dev = NULL;
+ 				struct nlattr *nla_entype;
+ 
+ 				nla_entype = nla_find(attrs, attrlen,
+ 						      RTA_ENCAP_TYPE);
+ 				if (!nla_entype)
+ 					goto err_inval;
+ 				if (cfg->fc_oif)
+ 					dev = __dev_get_by_index(net, cfg->fc_oif);
+ 				ret = lwtunnel_build_state(dev, nla_get_u16(
+ 							   nla_entype),
+ 							   nla, &lwtstate);
+ 				if (ret)
+ 					goto errout;
+ 				nexthop_nh->nh_lwtstate =
+ 					lwtstate_get(lwtstate);
+ 			}
  		}
  
  		rtnh = rtnh_next(rtnh, &remaining);
  	} endfor_nexthops(fi);
  
  	return 0;
+ 
+ err_inval:
+ 	ret = -EINVAL;
+ 
+ errout:
+ 	return ret;
  }
  
  #endif
  
+ int fib_encap_match(struct net *net, u16 encap_type,
+ 		    struct nlattr *encap,
+ 		    int oif, const struct fib_nh *nh)
+ {
+ 	struct lwtunnel_state *lwtstate;
+ 	struct net_device *dev = NULL;
 -	int ret, result = 0;
++	int ret;
+ 
+ 	if (encap_type == LWTUNNEL_ENCAP_NONE)
+ 		return 0;
+ 
+ 	if (oif)
+ 		dev = __dev_get_by_index(net, oif);
+ 	ret = lwtunnel_build_state(dev, encap_type,
+ 				   encap, &lwtstate);
 -	if (!ret) {
 -		result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate);
 -		lwtstate_free(lwtstate);
 -	}
++	if (!ret)
++		return lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate);
+ 
 -	return result;
++	return 0;
+ }
+ 
  int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
  {
+ 	struct net *net = cfg->fc_nlinfo.nl_net;
  #ifdef CONFIG_IP_ROUTE_MULTIPATH
  	struct rtnexthop *rtnh;
  	int remaining;
@@@ -496,6 -568,12 +566,12 @@@
  		return 1;
  
  	if (cfg->fc_oif || cfg->fc_gw) {
+ 		if (cfg->fc_encap) {
+ 			if (fib_encap_match(net, cfg->fc_encap_type,
+ 					    cfg->fc_encap, cfg->fc_oif,
+ 					    fi->fib_nh))
+ 			    return 1;
+ 		}
  		if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) &&
  		    (!cfg->fc_gw  || cfg->fc_gw == fi->fib_nh->nh_gw))
  			return 0;
@@@ -594,16 -672,18 +670,18 @@@ static int fib_check_nh(struct fib_conf
  		struct fib_result res;
  
  		if (nh->nh_flags & RTNH_F_ONLINK) {
+ 			unsigned int addr_type;
  
  			if (cfg->fc_scope >= RT_SCOPE_LINK)
  				return -EINVAL;
- 			if (inet_addr_type(net, nh->nh_gw) != RTN_UNICAST)
- 				return -EINVAL;
  			dev = __dev_get_by_index(net, nh->nh_oif);
  			if (!dev)
  				return -ENODEV;
  			if (!(dev->flags & IFF_UP))
  				return -ENETDOWN;
+ 			addr_type = inet_addr_type_dev_table(net, dev, nh->nh_gw);
+ 			if (addr_type != RTN_UNICAST)
+ 				return -EINVAL;
  			if (!netif_carrier_ok(dev))
  				nh->nh_flags |= RTNH_F_LINKDOWN;
  			nh->nh_dev = dev;
@@@ -613,6 -693,7 +691,7 @@@
  		}
  		rcu_read_lock();
  		{
+ 			struct fib_table *tbl = NULL;
  			struct flowi4 fl4 = {
  				.daddr = nh->nh_gw,
  				.flowi4_scope = cfg->fc_scope + 1,
@@@ -623,8 -704,17 +702,17 @@@
  			/* It is not necessary, but requires a bit of thinking */
  			if (fl4.flowi4_scope < RT_SCOPE_LINK)
  				fl4.flowi4_scope = RT_SCOPE_LINK;
- 			err = fib_lookup(net, &fl4, &res,
- 					 FIB_LOOKUP_IGNORE_LINKSTATE);
+ 
+ 			if (cfg->fc_table)
+ 				tbl = fib_get_table(net, cfg->fc_table);
+ 
+ 			if (tbl)
+ 				err = fib_table_lookup(tbl, &fl4, &res,
+ 						       FIB_LOOKUP_IGNORE_LINKSTATE |
+ 						       FIB_LOOKUP_NOREF);
+ 			else
+ 				err = fib_lookup(net, &fl4, &res,
+ 						 FIB_LOOKUP_IGNORE_LINKSTATE);
  			if (err) {
  				rcu_read_unlock();
  				return err;
@@@ -760,6 -850,23 +848,23 @@@ __be32 fib_info_update_nh_saddr(struct 
  	return nh->nh_saddr;
  }
  
+ static bool fib_valid_prefsrc(struct fib_config *cfg, __be32 fib_prefsrc)
+ {
+ 	if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
+ 	    fib_prefsrc != cfg->fc_dst) {
+ 		int tb_id = cfg->fc_table;
+ 
+ 		if (tb_id == RT_TABLE_MAIN)
+ 			tb_id = RT_TABLE_LOCAL;
+ 
+ 		if (inet_addr_type_table(cfg->fc_nlinfo.nl_net,
+ 					 fib_prefsrc, tb_id) != RTN_LOCAL) {
+ 			return false;
+ 		}
+ 	}
+ 	return true;
+ }
+ 
  struct fib_info *fib_create_info(struct fib_config *cfg)
  {
  	int err;
@@@ -882,6 -989,21 +987,21 @@@
  	} else {
  		struct fib_nh *nh = fi->fib_nh;
  
+ 		if (cfg->fc_encap) {
+ 			struct lwtunnel_state *lwtstate;
+ 			struct net_device *dev = NULL;
+ 
+ 			if (cfg->fc_encap_type == LWTUNNEL_ENCAP_NONE)
+ 				goto err_inval;
+ 			if (cfg->fc_oif)
+ 				dev = __dev_get_by_index(net, cfg->fc_oif);
+ 			err = lwtunnel_build_state(dev, cfg->fc_encap_type,
+ 						   cfg->fc_encap, &lwtstate);
+ 			if (err)
+ 				goto failure;
+ 
+ 			nh->nh_lwtstate = lwtstate_get(lwtstate);
+ 		}
  		nh->nh_oif = cfg->fc_oif;
  		nh->nh_gw = cfg->fc_gw;
  		nh->nh_flags = cfg->fc_flags;
@@@ -940,12 -1062,8 +1060,8 @@@
  			fi->fib_flags |= RTNH_F_LINKDOWN;
  	}
  
- 	if (fi->fib_prefsrc) {
- 		if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
- 		    fi->fib_prefsrc != cfg->fc_dst)
- 			if (inet_addr_type(net, fi->fib_prefsrc) != RTN_LOCAL)
- 				goto err_inval;
- 	}
+ 	if (fi->fib_prefsrc && !fib_valid_prefsrc(cfg, fi->fib_prefsrc))
+ 		goto err_inval;
  
  	change_nexthops(fi) {
  		fib_info_update_nh_saddr(net, nexthop_nh);
@@@ -1055,6 -1173,8 +1171,8 @@@ int fib_dump_info(struct sk_buff *skb, 
  		    nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid))
  			goto nla_put_failure;
  #endif
+ 		if (fi->fib_nh->nh_lwtstate)
+ 			lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate);
  	}
  #ifdef CONFIG_IP_ROUTE_MULTIPATH
  	if (fi->fib_nhs > 1) {
@@@ -1090,6 -1210,8 +1208,8 @@@
  			    nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
  				goto nla_put_failure;
  #endif
+ 			if (nh->nh_lwtstate)
+ 				lwtunnel_fill_encap(skb, nh->nh_lwtstate);
  			/* length of rtnetlink header + attributes */
  			rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh;
  		} endfor_nexthops(fi);
diff --combined net/ipv4/fib_trie.c
index b0c6258,1243c79..5154f81
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@@ -1423,8 -1423,11 +1423,11 @@@ found
  			    nh->nh_flags & RTNH_F_LINKDOWN &&
  			    !(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
  				continue;
- 			if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
- 				continue;
+ 			if (!(flp->flowi4_flags & FLOWI_FLAG_VRFSRC)) {
+ 				if (flp->flowi4_oif &&
+ 				    flp->flowi4_oif != nh->nh_oif)
+ 					continue;
+ 			}
  
  			if (!(fib_flags & FIB_LOOKUP_NOREF))
  				atomic_inc(&fi->fib_clntref);
@@@ -2465,7 -2468,7 +2468,7 @@@ static struct key_vector *fib_route_get
  		key = l->key + 1;
  		iter->pos++;
  
 -		if (pos-- <= 0)
 +		if (--pos <= 0)
  			break;
  
  		l = NULL;
diff --combined net/ipv6/ip6_fib.c
index 548c623,5693b5e..20a1b85
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@@ -32,6 -32,7 +32,7 @@@
  #include <net/ipv6.h>
  #include <net/ndisc.h>
  #include <net/addrconf.h>
+ #include <net/lwtunnel.h>
  
  #include <net/ip6_fib.h>
  #include <net/ip6_route.h>
@@@ -172,13 -173,12 +173,14 @@@ static void rt6_free_pcpu(struct rt6_in
  			*ppcpu_rt = NULL;
  		}
  	}
 +
 +	non_pcpu_rt->rt6i_pcpu = NULL;
  }
  
  static void rt6_release(struct rt6_info *rt)
  {
  	if (atomic_dec_and_test(&rt->rt6i_ref)) {
+ 		lwtstate_put(rt->rt6i_lwtstate);
  		rt6_free_pcpu(rt);
  		dst_free(&rt->dst);
  	}
diff --combined net/ipv6/route.c
index d155864,c373304..8c985a1
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@@ -58,6 -58,7 +58,7 @@@
  #include <net/netevent.h>
  #include <net/netlink.h>
  #include <net/nexthop.h>
+ #include <net/lwtunnel.h>
  
  #include <asm/uaccess.h>
  
@@@ -318,7 -319,8 +319,7 @@@ static const struct rt6_info ip6_blk_ho
  /* allocate dst with ip6_dst_ops */
  static struct rt6_info *__ip6_dst_alloc(struct net *net,
  					struct net_device *dev,
 -					int flags,
 -					struct fib6_table *table)
 +					int flags)
  {
  	struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
  					0, DST_OBSOLETE_FORCE_CHK, flags);
@@@ -335,9 -337,10 +336,9 @@@
  
  static struct rt6_info *ip6_dst_alloc(struct net *net,
  				      struct net_device *dev,
 -				      int flags,
 -				      struct fib6_table *table)
 +				      int flags)
  {
 -	struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags, table);
 +	struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags);
  
  	if (rt) {
  		rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC);
@@@ -542,6 -545,7 +543,7 @@@ static void rt6_probe_deferred(struct w
  
  static void rt6_probe(struct rt6_info *rt)
  {
+ 	struct __rt6_probe_work *work;
  	struct neighbour *neigh;
  	/*
  	 * Okay, this does not seem to be appropriate
@@@ -556,34 -560,33 +558,33 @@@
  	rcu_read_lock_bh();
  	neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
  	if (neigh) {
- 		write_lock(&neigh->lock);
  		if (neigh->nud_state & NUD_VALID)
  			goto out;
- 	}
- 
- 	if (!neigh ||
- 	    time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
- 		struct __rt6_probe_work *work;
  
+ 		work = NULL;
+ 		write_lock(&neigh->lock);
+ 		if (!(neigh->nud_state & NUD_VALID) &&
+ 		    time_after(jiffies,
+ 			       neigh->updated +
+ 			       rt->rt6i_idev->cnf.rtr_probe_interval)) {
+ 			work = kmalloc(sizeof(*work), GFP_ATOMIC);
+ 			if (work)
+ 				__neigh_set_probe_once(neigh);
+ 		}
+ 		write_unlock(&neigh->lock);
+ 	} else {
  		work = kmalloc(sizeof(*work), GFP_ATOMIC);
+ 	}
  
- 		if (neigh && work)
- 			__neigh_set_probe_once(neigh);
- 
- 		if (neigh)
- 			write_unlock(&neigh->lock);
+ 	if (work) {
+ 		INIT_WORK(&work->work, rt6_probe_deferred);
+ 		work->target = rt->rt6i_gateway;
+ 		dev_hold(rt->dst.dev);
+ 		work->dev = rt->dst.dev;
+ 		schedule_work(&work->work);
+ 	}
  
- 		if (work) {
- 			INIT_WORK(&work->work, rt6_probe_deferred);
- 			work->target = rt->rt6i_gateway;
- 			dev_hold(rt->dst.dev);
- 			work->dev = rt->dst.dev;
- 			schedule_work(&work->work);
- 		}
- 	} else {
  out:
- 		write_unlock(&neigh->lock);
- 	}
  	rcu_read_unlock_bh();
  }
  #else
@@@ -662,6 -665,12 +663,12 @@@ static struct rt6_info *find_match(stru
  {
  	int m;
  	bool match_do_rr = false;
+ 	struct inet6_dev *idev = rt->rt6i_idev;
+ 	struct net_device *dev = rt->dst.dev;
+ 
+ 	if (dev && !netif_carrier_ok(dev) &&
+ 	    idev->cnf.ignore_routes_with_linkdown)
+ 		goto out;
  
  	if (rt6_check_expired(rt))
  		goto out;
@@@ -948,7 -957,8 +955,7 @@@ static struct rt6_info *ip6_rt_cache_al
  	if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
  		ort = (struct rt6_info *)ort->dst.from;
  
 -	rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev,
 -			     0, ort->rt6i_table);
 +	rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0);
  
  	if (!rt)
  		return NULL;
@@@ -980,7 -990,8 +987,7 @@@ static struct rt6_info *ip6_rt_pcpu_all
  	struct rt6_info *pcpu_rt;
  
  	pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev),
 -				  rt->dst.dev, rt->dst.flags,
 -				  rt->rt6i_table);
 +				  rt->dst.dev, rt->dst.flags);
  
  	if (!pcpu_rt)
  		return NULL;
@@@ -993,53 -1004,32 +1000,53 @@@
  /* It should be called with read_lock_bh(&tb6_lock) acquired */
  static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt)
  {
 -	struct rt6_info *pcpu_rt, *prev, **p;
 +	struct rt6_info *pcpu_rt, **p;
  
  	p = this_cpu_ptr(rt->rt6i_pcpu);
  	pcpu_rt = *p;
  
 -	if (pcpu_rt)
 -		goto done;
 +	if (pcpu_rt) {
 +		dst_hold(&pcpu_rt->dst);
 +		rt6_dst_from_metrics_check(pcpu_rt);
 +	}
 +	return pcpu_rt;
 +}
 +
 +static struct rt6_info *rt6_make_pcpu_route(struct rt6_info *rt)
 +{
 +	struct fib6_table *table = rt->rt6i_table;
 +	struct rt6_info *pcpu_rt, *prev, **p;
  
  	pcpu_rt = ip6_rt_pcpu_alloc(rt);
  	if (!pcpu_rt) {
  		struct net *net = dev_net(rt->dst.dev);
  
 -		pcpu_rt = net->ipv6.ip6_null_entry;
 -		goto done;
 +		dst_hold(&net->ipv6.ip6_null_entry->dst);
 +		return net->ipv6.ip6_null_entry;
  	}
  
 -	prev = cmpxchg(p, NULL, pcpu_rt);
 -	if (prev) {
 -		/* If someone did it before us, return prev instead */
 +	read_lock_bh(&table->tb6_lock);
 +	if (rt->rt6i_pcpu) {
 +		p = this_cpu_ptr(rt->rt6i_pcpu);
 +		prev = cmpxchg(p, NULL, pcpu_rt);
 +		if (prev) {
 +			/* If someone did it before us, return prev instead */
 +			dst_destroy(&pcpu_rt->dst);
 +			pcpu_rt = prev;
 +		}
 +	} else {
 +		/* rt has been removed from the fib6 tree
 +		 * before we have a chance to acquire the read_lock.
 +		 * In this case, don't brother to create a pcpu rt
 +		 * since rt is going away anyway.  The next
 +		 * dst_check() will trigger a re-lookup.
 +		 */
  		dst_destroy(&pcpu_rt->dst);
 -		pcpu_rt = prev;
 +		pcpu_rt = rt;
  	}
 -
 -done:
  	dst_hold(&pcpu_rt->dst);
  	rt6_dst_from_metrics_check(pcpu_rt);
 +	read_unlock_bh(&table->tb6_lock);
  	return pcpu_rt;
  }
  
@@@ -1114,22 -1104,9 +1121,22 @@@ redo_rt6_select
  		rt->dst.lastuse = jiffies;
  		rt->dst.__use++;
  		pcpu_rt = rt6_get_pcpu_route(rt);
 -		read_unlock_bh(&table->tb6_lock);
 +
 +		if (pcpu_rt) {
 +			read_unlock_bh(&table->tb6_lock);
 +		} else {
 +			/* We have to do the read_unlock first
 +			 * because rt6_make_pcpu_route() may trigger
 +			 * ip6_dst_gc() which will take the write_lock.
 +			 */
 +			dst_hold(&rt->dst);
 +			read_unlock_bh(&table->tb6_lock);
 +			pcpu_rt = rt6_make_pcpu_route(rt);
 +			dst_release(&rt->dst);
 +		}
  
  		return pcpu_rt;
 +
  	}
  }
  
@@@ -1585,7 -1562,7 +1592,7 @@@ struct dst_entry *icmp6_dst_alloc(struc
  	if (unlikely(!idev))
  		return ERR_PTR(-ENODEV);
  
 -	rt = ip6_dst_alloc(net, dev, 0, NULL);
 +	rt = ip6_dst_alloc(net, dev, 0);
  	if (unlikely(!rt)) {
  		in6_dev_put(idev);
  		dst = ERR_PTR(-ENOMEM);
@@@ -1772,8 -1749,7 +1779,8 @@@ int ip6_route_add(struct fib6_config *c
  	if (!table)
  		goto out;
  
 -	rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table);
 +	rt = ip6_dst_alloc(net, NULL,
 +			   (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT);
  
  	if (!rt) {
  		err = -ENOMEM;
@@@ -1801,6 -1777,24 +1808,24 @@@
  
  	rt->dst.output = ip6_output;
  
+ 	if (cfg->fc_encap) {
+ 		struct lwtunnel_state *lwtstate;
+ 
+ 		err = lwtunnel_build_state(dev, cfg->fc_encap_type,
+ 					   cfg->fc_encap, &lwtstate);
+ 		if (err)
+ 			goto out;
+ 		rt->rt6i_lwtstate = lwtstate_get(lwtstate);
+ 		if (lwtunnel_output_redirect(rt->rt6i_lwtstate)) {
+ 			rt->rt6i_lwtstate->orig_output = rt->dst.output;
+ 			rt->dst.output = lwtunnel_output6;
+ 		}
+ 		if (lwtunnel_input_redirect(rt->rt6i_lwtstate)) {
+ 			rt->rt6i_lwtstate->orig_input = rt->dst.input;
+ 			rt->dst.input = lwtunnel_input6;
+ 		}
+ 	}
+ 
  	ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
  	rt->rt6i_dst.plen = cfg->fc_dst_len;
  	if (rt->rt6i_dst.plen == 128)
@@@ -2180,6 -2174,7 +2205,7 @@@ static void ip6_rt_copy_init(struct rt6
  #endif
  	rt->rt6i_prefsrc = ort->rt6i_prefsrc;
  	rt->rt6i_table = ort->rt6i_table;
+ 	rt->rt6i_lwtstate = lwtstate_get(ort->rt6i_lwtstate);
  }
  
  #ifdef CONFIG_IPV6_ROUTE_INFO
@@@ -2430,7 -2425,7 +2456,7 @@@ struct rt6_info *addrconf_dst_alloc(str
  {
  	struct net *net = dev_net(idev->dev);
  	struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
 -					    DST_NOCOUNT, NULL);
 +					    DST_NOCOUNT);
  	if (!rt)
  		return ERR_PTR(-ENOMEM);
  
@@@ -2628,6 -2623,8 +2654,8 @@@ static const struct nla_policy rtm_ipv6
  	[RTA_METRICS]           = { .type = NLA_NESTED },
  	[RTA_MULTIPATH]		= { .len = sizeof(struct rtnexthop) },
  	[RTA_PREF]              = { .type = NLA_U8 },
+ 	[RTA_ENCAP_TYPE]	= { .type = NLA_U16 },
+ 	[RTA_ENCAP]		= { .type = NLA_NESTED },
  };
  
  static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@@ -2722,6 -2719,12 +2750,12 @@@
  		cfg->fc_flags |= RTF_PREF(pref);
  	}
  
+ 	if (tb[RTA_ENCAP])
+ 		cfg->fc_encap = tb[RTA_ENCAP];
+ 
+ 	if (tb[RTA_ENCAP_TYPE])
+ 		cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]);
+ 
  	err = 0;
  errout:
  	return err;
@@@ -2754,6 -2757,10 +2788,10 @@@ beginning
  				r_cfg.fc_gateway = nla_get_in6_addr(nla);
  				r_cfg.fc_flags |= RTF_GATEWAY;
  			}
+ 			r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP);
+ 			nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
+ 			if (nla)
+ 				r_cfg.fc_encap_type = nla_get_u16(nla);
  		}
  		err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
  		if (err) {
@@@ -2816,7 -2823,7 +2854,7 @@@ static int inet6_rtm_newroute(struct sk
  		return ip6_route_add(&cfg);
  }
  
- static inline size_t rt6_nlmsg_size(void)
+ static inline size_t rt6_nlmsg_size(struct rt6_info *rt)
  {
  	return NLMSG_ALIGN(sizeof(struct rtmsg))
  	       + nla_total_size(16) /* RTA_SRC */
@@@ -2830,7 -2837,8 +2868,8 @@@
  	       + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
  	       + nla_total_size(sizeof(struct rta_cacheinfo))
  	       + nla_total_size(TCP_CA_NAME_MAX) /* RTAX_CC_ALGO */
- 	       + nla_total_size(1); /* RTA_PREF */
+ 	       + nla_total_size(1) /* RTA_PREF */
+ 	       + lwtunnel_get_encap_size(rt->rt6i_lwtstate);
  }
  
  static int rt6_fill_node(struct net *net,
@@@ -2891,6 -2899,11 +2930,11 @@@
  	else
  		rtm->rtm_type = RTN_UNICAST;
  	rtm->rtm_flags = 0;
+ 	if (!netif_carrier_ok(rt->dst.dev)) {
+ 		rtm->rtm_flags |= RTNH_F_LINKDOWN;
+ 		if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
+ 			rtm->rtm_flags |= RTNH_F_DEAD;
+ 	}
  	rtm->rtm_scope = RT_SCOPE_UNIVERSE;
  	rtm->rtm_protocol = rt->rt6i_protocol;
  	if (rt->rt6i_flags & RTF_DYNAMIC)
@@@ -2978,6 -2991,8 +3022,8 @@@
  	if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
  		goto nla_put_failure;
  
+ 	lwtunnel_fill_encap(skb, rt->rt6i_lwtstate);
+ 
  	nlmsg_end(skb, nlh);
  	return 0;
  
@@@ -3104,7 -3119,7 +3150,7 @@@ void inet6_rt_notify(int event, struct 
  	err = -ENOBUFS;
  	seq = info->nlh ? info->nlh->nlmsg_seq : 0;
  
- 	skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
+ 	skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
  	if (!skb)
  		goto errout;
  

-- 
LinuxNextTracking


More information about the linux-merge mailing list