The following commit has been merged in the master branch: commit 6ecee3711fc9b00d7b74f866e8ed9fdedfe8050c Merge: 481b1d1fed58b2f9e62efd789a7f97e5418a989b 6bc8038035267d12df2bf78a8e1a5f07069fabb8 Author: Stephen Rothwell sfr@canb.auug.org.au Date: Fri Jan 17 10:46:14 2020 +1100
Merge remote-tracking branch 'net-next/master'
diff --combined MAINTAINERS index beea971b6ed0,2549f10eb0b1..0fb22de7096e --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -345,7 -345,7 +345,7 @@@ F: drivers/acpi/apei
ACPI COMPONENT ARCHITECTURE (ACPICA) M: Robert Moore robert.moore@intel.com -M: Erik Schmauss erik.schmauss@intel.com +M: Erik Kaneda erik.kaneda@intel.com M: "Rafael J. Wysocki" rafael.j.wysocki@intel.com L: linux-acpi@vger.kernel.org L: devel@acpica.org @@@ -694,14 -694,6 +694,14 @@@ L: linux-crypto@vger.kernel.or S: Maintained F: drivers/crypto/allwinner/
+ALLWINNER THERMAL DRIVER +M: Vasily Khoruzhick anarsoul@gmail.com +M: Yangtao Li tiny.windzz@gmail.com +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml +F: drivers/thermal/sun8i_thermal.c + ALLWINNER VPU DRIVER M: Maxime Ripard mripard@kernel.org M: Paul Kocialkowski paul.kocialkowski@bootlin.com @@@ -728,7 -720,7 +728,7 @@@ F: Documentation/devicetree/bindings/i2 F: drivers/i2c/busses/i2c-altera.c
ALTERA MAILBOX DRIVER -M: Ley Foon Tan lftan@altera.com +M: Ley Foon Tan ley.foon.tan@intel.com L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) S: Maintained F: drivers/mailbox/mailbox-altera.c @@@ -985,15 -977,6 +985,15 @@@ W: http://ez.analog.com/community/linux F: drivers/iio/imu/adis16460.c F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
+ANALOG DEVICES INC ADM1177 DRIVER +M: Beniamin Bia beniamin.bia@analog.com +M: Michael Hennerich Michael.Hennerich@analog.com +L: linux-hwmon@vger.kernel.org +W: http://ez.analog.com/community/linux-device-drivers +S: Supported +F: drivers/hwmon/adm1177.c +F: Documentation/devicetree/bindings/hwmon/adi,adm1177.yaml + ANALOG DEVICES INC ADP5061 DRIVER M: Stefan Popa stefan.popa@analog.com L: linux-pm@vger.kernel.org @@@ -2077,7 -2060,6 +2077,7 @@@ F: drivers/rtc/rtc-pl031. F: drivers/watchdog/coh901327_wdt.c F: Documentation/devicetree/bindings/arm/ste-* F: Documentation/devicetree/bindings/arm/ux500/ +F: Documentation/devicetree/bindings/arm/ux500.yaml T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git
ARM/NUVOTON NPCM ARCHITECTURE @@@ -2223,8 -2205,6 +2223,8 @@@ M: Andreas Färber <afaerber@suse.de L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-realtek-soc@lists.infradead.org (moderated for non-subscribers) S: Maintained +F: arch/arm/boot/dts/rtd* +F: arch/arm/mach-realtek/ F: arch/arm64/boot/dts/realtek/ F: Documentation/devicetree/bindings/arm/realtek.yaml
@@@ -3170,7 -3150,7 +3170,7 @@@ S: Maintaine F: arch/mips/net/
BPF JIT for NFP NICs -M: Jakub Kicinski jakub.kicinski@netronome.com +M: Jakub Kicinski kuba@kernel.org L: netdev@vger.kernel.org L: bpf@vger.kernel.org S: Supported @@@ -3616,7 -3596,6 +3616,7 @@@ F: sound/pci/oxygen
C-SKY ARCHITECTURE M: Guo Ren guoren@kernel.org +L: linux-csky@vger.kernel.org T: git https://github.com/c-sky/csky-linux.git S: Supported F: arch/csky/ @@@ -4451,10 -4430,13 +4451,10 @@@ F: drivers/net/wireless/st/cw1200
CX18 VIDEO4LINUX DRIVER M: Andy Walls awalls@md.metrocast.net -L: ivtv-devel@ivtvdriver.org (subscribers-only) L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git W: https://linuxtv.org -W: http://www.ivtvdriver.org/index.php/Cx18 S: Maintained -F: Documentation/media/v4l-drivers/cx18* F: drivers/media/pci/cx18/ F: include/uapi/linux/ivtv*
@@@ -4866,6 -4848,7 +4866,7 @@@ S: Supporte F: net/core/devlink.c F: include/net/devlink.h F: include/uapi/linux/devlink.h + F: Documentation/networking/devlink
DIALOG SEMICONDUCTOR DRIVERS M: Support Opensource support.opensource@diasemi.com @@@ -7743,7 -7726,9 +7744,7 @@@ M: Jean Delvare <jdelvare@suse.com L: linux-i2c@vger.kernel.org S: Maintained F: Documentation/i2c/busses/i2c-parport.rst -F: Documentation/i2c/busses/i2c-parport-light.rst F: drivers/i2c/busses/i2c-parport.c -F: drivers/i2c/busses/i2c-parport-light.c
I2C SUBSYSTEM M: Wolfram Sang wsa@the-dreams.de @@@ -7857,10 -7842,10 +7858,10 @@@ F: Documentation/devicetree/bindings/i3 F: drivers/i3c/master/dw*
I3C DRIVER FOR CADENCE I3C MASTER IP -M: Przemysław Gaj pgaj@cadence.com -S: Maintained -F: Documentation/devicetree/bindings/i3c/cdns,i3c-master.txt -F: drivers/i3c/master/i3c-master-cdns.c +M: Przemysław Gaj pgaj@cadence.com +S: Maintained +F: Documentation/devicetree/bindings/i3c/cdns,i3c-master.txt +F: drivers/i3c/master/i3c-master-cdns.c
IA64 (Itanium) PLATFORM M: Tony Luck tony.luck@intel.com @@@ -8124,7 -8109,8 +8125,7 @@@ F: Documentation/devicetree/bindings/au F: drivers/auxdisplay/img-ascii-lcd.c
IMGTEC IR DECODER DRIVER -M: James Hogan jhogan@kernel.org -S: Maintained +S: Orphan F: drivers/media/rc/img-ir/
IMON SOUNDGRAPH USB IR RECEIVER @@@ -8584,7 -8570,7 +8585,7 @@@ S: Maintaine F: drivers/platform/x86/intel-vbtn.c
INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy) -M: Stanislaw Gruszka sgruszka@redhat.com +M: Stanislaw Gruszka stf_xl@wp.pl L: linux-wireless@vger.kernel.org S: Supported F: drivers/net/wireless/intel/iwlegacy/ @@@ -8857,9 -8843,10 +8858,9 @@@ F: drivers/media/tuners/it913x
IVTV VIDEO4LINUX DRIVER M: Andy Walls awalls@md.metrocast.net -L: ivtv-devel@ivtvdriver.org (subscribers-only) L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git -W: http://www.ivtvdriver.org +W: https://linuxtv.org S: Maintained F: Documentation/media/v4l-drivers/ivtv* F: drivers/media/pci/ivtv/ @@@ -9903,7 -9890,7 +9904,7 @@@ S: Maintaine F: drivers/net/dsa/mv88e6xxx/ F: include/linux/platform_data/mv88e6xxx.h F: Documentation/devicetree/bindings/net/dsa/marvell.txt - F: Documentation/networking/devlink-params-mv88e6xxx.txt + F: Documentation/networking/devlink/mv88e6xxx.rst
MARVELL ARMADA DRM SUPPORT M: Russell King linux@armlinux.org.uk @@@ -9974,7 -9961,7 +9975,7 @@@ F: drivers/net/ethernet/marvell/mvneta. MARVELL MWIFIEX WIRELESS DRIVER M: Amitkumar Karwar amitkarwar@gmail.com M: Nishant Sarmukadam nishants@marvell.com - M: Ganapathi Bhat gbhat@marvell.com + M: Ganapathi Bhat ganapathi.bhat@nxp.com M: Xinming Hu huxinming820@gmail.com L: linux-wireless@vger.kernel.org S: Maintained @@@ -11016,6 -11003,7 +11017,6 @@@ F: drivers/usb/image/microtek. MIPS M: Ralf Baechle ralf@linux-mips.org M: Paul Burton paulburton@kernel.org -M: James Hogan jhogan@kernel.org L: linux-mips@vger.kernel.org W: http://www.linux-mips.org/ T: git git://git.linux-mips.org/pub/scm/ralf/linux.git @@@ -11444,7 -11432,7 +11445,7 @@@ F: include/uapi/linux/netrom. F: net/netrom/
NETRONOME ETHERNET DRIVERS -M: Jakub Kicinski jakub.kicinski@netronome.com +M: Jakub Kicinski kuba@kernel.org L: oss-drivers@netronome.com S: Maintained F: drivers/net/ethernet/netronome/ @@@ -11586,6 -11574,16 +11587,16 @@@ F: net/ipv6/calipso. F: net/netfilter/xt_CONNSECMARK.c F: net/netfilter/xt_SECMARK.c
+ NETWORKING [MPTCP] + M: Mat Martineau mathew.j.martineau@linux.intel.com + M: Matthieu Baerts matthieu.baerts@tessares.net + L: netdev@vger.kernel.org + L: mptcp@lists.01.org + W: https://github.com/multipath-tcp/mptcp_net-next/wiki + B: https://github.com/multipath-tcp/mptcp_net-next/issues + S: Maintained + F: include/net/mptcp.h + NETWORKING [TCP] M: Eric Dumazet edumazet@google.com L: netdev@vger.kernel.org @@@ -11604,7 -11602,7 +11615,7 @@@ M: Boris Pismenny <borisp@mellanox.com M: Aviad Yehezkel aviadye@mellanox.com M: John Fastabend john.fastabend@gmail.com M: Daniel Borkmann daniel@iogearbox.net -M: Jakub Kicinski jakub.kicinski@netronome.com +M: Jakub Kicinski kuba@kernel.org L: netdev@vger.kernel.org S: Maintained F: net/tls/* @@@ -11616,7 -11614,7 +11627,7 @@@ L: linux-wireless@vger.kernel.or Q: http://patchwork.kernel.org/project/linux-wireless/list/
NETDEVSIM -M: Jakub Kicinski jakub.kicinski@netronome.com +M: Jakub Kicinski kuba@kernel.org S: Maintained F: drivers/net/netdevsim/*
@@@ -11693,7 -11691,7 +11704,7 @@@ F: Documentation/scsi/NinjaSCSI.tx F: drivers/scsi/nsp32*
NIOS2 ARCHITECTURE -M: Ley Foon Tan lftan@altera.com +M: Ley Foon Tan ley.foon.tan@intel.com L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) T: git git://git.kernel.org/pub/scm/linux/kernel/git/lftan/nios2.git S: Maintained @@@ -12577,7 -12575,7 +12588,7 @@@ F: Documentation/devicetree/bindings/pc F: drivers/pci/controller/pci-aardvark.c
PCI DRIVER FOR ALTERA PCIE IP -M: Ley Foon Tan lftan@altera.com +M: Ley Foon Tan ley.foon.tan@intel.com L: rfi@lists.rocketboards.org (moderated for non-subscribers) L: linux-pci@vger.kernel.org S: Supported @@@ -12756,7 -12754,7 +12767,7 @@@ S: Supporte F: Documentation/PCI/pci-error-recovery.rst
PCI MSI DRIVER FOR ALTERA MSI IP -M: Ley Foon Tan lftan@altera.com +M: Ley Foon Tan ley.foon.tan@intel.com L: rfi@lists.rocketboards.org (moderated for non-subscribers) L: linux-pci@vger.kernel.org S: Supported @@@ -13662,6 -13660,13 +13673,13 @@@ T: git git://git.kernel.org/pub/scm/lin S: Supported F: drivers/net/wireless/ath/ath10k/
+ QUALCOMM ATHEROS ATH11K WIRELESS DRIVER + M: Kalle Valo kvalo@codeaurora.org + L: ath11k@lists.infradead.org + T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git + S: Supported + F: drivers/net/wireless/ath/ath11k/ + QUALCOMM ATHEROS ATH9K WIRELESS DRIVER M: QCA ath9k Development ath9k-devel@qca.qualcomm.com L: linux-wireless@vger.kernel.org @@@ -13684,14 -13689,6 +13702,14 @@@ S: Maintaine F: Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt F: drivers/cpufreq/qcom-cpufreq-nvmem.c
+QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER +M: Niklas Cassel nks@flawful.org +L: linux-pm@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt +F: drivers/power/avs/qcom-cpr.c + QUALCOMM EMAC GIGABIT ETHERNET DRIVER M: Timur Tabi timur@kernel.org L: netdev@vger.kernel.org @@@ -13841,7 -13838,7 +13859,7 @@@ S: Maintaine F: arch/mips/ralink
RALINK RT2X00 WIRELESS LAN DRIVER -M: Stanislaw Gruszka sgruszka@redhat.com +M: Stanislaw Gruszka stf_xl@wp.pl M: Helmut Schaa helmut.schaa@googlemail.com L: linux-wireless@vger.kernel.org S: Maintained @@@ -14156,12 -14153,6 +14174,12 @@@ F: drivers/hid/hid-roccat F: include/linux/hid-roccat* F: Documentation/ABI/*/sysfs-driver-hid-roccat*
+ROCKCHIP ISP V1 DRIVER +M: Helen Koike helen.koike@collabora.com +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/staging/media/rkisp1/ + ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER M: Jacob Chen jacob-chen@iotwrt.com M: Ezequiel Garcia ezequiel@collabora.com @@@ -15795,6 -15786,7 +15813,7 @@@ M: Jose Abreu <joabreu@synopsys.com L: netdev@vger.kernel.org W: http://www.stlinux.com S: Supported + F: Documentation/networking/device_drivers/stmicro/ F: drivers/net/ethernet/stmicro/stmmac/
SUN3/3X @@@ -16004,7 -15996,6 +16023,7 @@@ F: drivers/firmware/arm_scpi. F: drivers/firmware/arm_scmi/ F: drivers/reset/reset-scmi.c F: include/linux/sc[mp]i_protocol.h +F: include/trace/events/scmi.h
SYSTEM RESET/SHUTDOWN DRIVERS M: Sebastian Reichel sre@kernel.org @@@ -16368,15 -16359,12 +16387,15 @@@ F: Documentation/devicetree/bindings/th
THERMAL/CPU_COOLING M: Amit Daniel Kachhap amit.kachhap@gmail.com +M: Daniel Lezcano daniel.lezcano@linaro.org M: Viresh Kumar viresh.kumar@linaro.org M: Javi Merino javi.merino@kernel.org L: linux-pm@vger.kernel.org S: Supported F: Documentation/driver-api/thermal/cpu-cooling-api.rst -F: drivers/thermal/cpu_cooling.c +F: Documentation/driver-api/thermal/cpu-idle-cooling.rst +F: drivers/thermal/cpufreq_cooling.c +F: drivers/thermal/cpuidle_cooling.c F: include/linux/cpu_cooling.h
THERMAL DRIVER FOR AMLOGIC SOCS @@@ -16603,7 -16591,6 +16622,7 @@@ Q: http://patchwork.linuxtv.org/project S: Maintained F: drivers/media/platform/ti-vpe/ F: Documentation/devicetree/bindings/media/ti,vpe.yaml + Documentation/devicetree/bindings/media/ti,cal.yaml
TI WILINK WIRELESS DRIVERS L: linux-wireless@vger.kernel.org @@@ -17406,7 -17393,7 +17425,7 @@@ F: drivers/mtd/nand/raw/vf610_nfc. VFAT/FAT/MSDOS FILESYSTEM M: OGAWA Hirofumi hirofumi@mail.parknet.co.jp S: Maintained -F: Documentation/filesystems/vfat.txt +F: Documentation/filesystems/vfat.rst F: fs/fat/
VFIO DRIVER @@@ -17529,6 -17516,7 +17548,7 @@@ F: net/vmw_vsock/diag. F: net/vmw_vsock/af_vsock_tap.c F: net/vmw_vsock/virtio_transport_common.c F: net/vmw_vsock/virtio_transport.c + F: net/vmw_vsock/vsock_loopback.c F: drivers/net/vsockmon.c F: drivers/vhost/vsock.c F: tools/testing/vsock/ @@@ -17899,6 -17887,14 +17919,14 @@@ L: linux-gpio@vger.kernel.or S: Maintained F: drivers/gpio/gpio-ws16c48.c
+ WIREGUARD SECURE NETWORK TUNNEL + M: Jason A. Donenfeld Jason@zx2c4.com + S: Maintained + F: drivers/net/wireguard/ + F: tools/testing/selftests/wireguard/ + L: wireguard@lists.zx2c4.com + L: netdev@vger.kernel.org + WISTRON LAPTOP BUTTON DRIVER M: Miloslav Trmac mitr@volny.cz S: Maintained @@@ -18074,7 -18070,7 +18102,7 @@@ XDP (eXpress Data Path M: Alexei Starovoitov ast@kernel.org M: Daniel Borkmann daniel@iogearbox.net M: David S. Miller davem@davemloft.net -M: Jakub Kicinski jakub.kicinski@netronome.com +M: Jakub Kicinski kuba@kernel.org M: Jesper Dangaard Brouer hawk@kernel.org M: John Fastabend john.fastabend@gmail.com L: netdev@vger.kernel.org @@@ -18333,16 -18329,6 +18361,16 @@@ L: linux-kernel@vger.kernel.or S: Maintained F: arch/x86/kernel/cpu/zhaoxin.c
+ZONEFS FILESYSTEM +M: Damien Le Moal damien.lemoal@wdc.com +M: Naohiro Aota naohiro.aota@wdc.com +R: Johannes Thumshirn jth@kernel.org +L: linux-fsdevel@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs.git +S: Maintained +F: fs/zonefs/ +F: Documentation/filesystems/zonefs.txt + ZPOOL COMPRESSED PAGE STORAGE API M: Dan Streetman ddstreet@ieee.org L: linux-mm@kvack.org diff --combined arch/arm64/Kconfig index 40a91220a05f,29d03459de20..3dd07a923115 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@@ -69,6 -69,7 +69,7 @@@ config ARM6 select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && (GCC_VERSION >= 50000 || CC_IS_CLANG) select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT + select ARCH_WANT_DEFAULT_BPF_JIT select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_HUGE_PMD_SHARE if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36) @@@ -138,7 -139,6 +139,7 @@@ select HAVE_CMPXCHG_DOUBLE select HAVE_CMPXCHG_LOCAL select HAVE_CONTEXT_TRACKING + select HAVE_COPY_THREAD_TLS select HAVE_DEBUG_BUGVERBOSE select HAVE_DEBUG_KMEMLEAK select HAVE_DMA_CONTIGUOUS @@@ -302,9 -302,6 +303,9 @@@ config ARCH_SUPPORTS_UPROBE config ARCH_PROC_KCORE_TEXT def_bool y
+config BROKEN_GAS_INST + def_bool !$(as-instr,1:\n.inst 0\n.rept . - 1b\n\nnop\n.endr\n) + config KASAN_SHADOW_OFFSET hex depends on KASAN @@@ -518,13 -515,9 +519,13 @@@ config ARM64_ERRATUM_141804
If unsure, say Y.
+config ARM64_WORKAROUND_SPECULATIVE_AT_VHE + bool + config ARM64_ERRATUM_1165522 bool "Cortex-A76: Speculative AT instruction using out-of-context translation regime could cause subsequent request to generate an incorrect translation" default y + select ARM64_WORKAROUND_SPECULATIVE_AT_VHE help This option adds a workaround for ARM Cortex-A76 erratum 1165522.
@@@ -534,19 -527,6 +535,19 @@@
If unsure, say Y.
+config ARM64_ERRATUM_1530923 + bool "Cortex-A55: Speculative AT instruction using out-of-context translation regime could cause subsequent request to generate an incorrect translation" + default y + select ARM64_WORKAROUND_SPECULATIVE_AT_VHE + help + This option adds a workaround for ARM Cortex-A55 erratum 1530923. + + Affected Cortex-A55 cores (r0p0, r0p1, r1p0, r2p0) could end-up with + corrupted TLBs by speculating an AT instruction during a guest + context switch. + + If unsure, say Y. + config ARM64_ERRATUM_1286807 bool "Cortex-A76: Modification of the translation table for a virtual address might lead to read-after-read ordering violation" default y @@@ -563,13 -543,9 +564,13 @@@ invalidated has been observed by other observers. The workaround repeats the TLBI+DSB operation.
+config ARM64_WORKAROUND_SPECULATIVE_AT_NVHE + bool + config ARM64_ERRATUM_1319367 bool "Cortex-A57/A72: Speculative AT instruction using out-of-context translation regime could cause subsequent request to generate an incorrect translation" default y + select ARM64_WORKAROUND_SPECULATIVE_AT_NVHE help This option adds work arounds for ARM Cortex-A57 erratum 1319537 and A72 erratum 1319367 @@@ -1388,11 -1364,6 +1389,11 @@@ config ARM64_PA instruction if the cpu does not implement the feature.
config ARM64_LSE_ATOMICS + bool + default ARM64_USE_LSE_ATOMICS + depends on $(as-instr,.arch_extension lse) + +config ARM64_USE_LSE_ATOMICS bool "Atomic instructions" depends on JUMP_LABEL default y @@@ -1514,22 -1485,6 +1515,22 @@@ config ARM64_PTR_AUT
endmenu
+menu "ARMv8.5 architectural features" + +config ARM64_E0PD + bool "Enable support for E0PD" + default y + help + E0PD (part of the ARMv8.5 extensions) allows us to ensure + that EL0 accesses made via TTBR1 always fault in constant time, + providing similar benefits to KASLR as those provided by KPTI, but + with lower overhead and without disrupting legitimate access to + kernel memory such as SPE. + + This option enables E0PD for TTBR1 where available. + +endmenu + config ARM64_SVE bool "ARM Scalable Vector Extension support" default y @@@ -1590,7 -1545,7 +1591,7 @@@ config ARM64_MODULE_PLT
config ARM64_PSEUDO_NMI bool "Support for NMI-like interrupts" - select CONFIG_ARM_GIC_V3 + select ARM_GIC_V3 help Adds support for mimicking Non-Maskable Interrupts through the use of GIC interrupt priority. This support requires version 3 or later of diff --combined drivers/net/ethernet/cadence/macb_main.c index f7d87c71aaa9,1c547ee0d444..7a2fe63d1136 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@@ -337,11 -337,30 +337,30 @@@ static int macb_mdio_read(struct mii_bu if (status < 0) goto mdio_read_exit;
- macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) - | MACB_BF(RW, MACB_MAN_READ) - | MACB_BF(PHYA, mii_id) - | MACB_BF(REGA, regnum) - | MACB_BF(CODE, MACB_MAN_CODE))); + if (regnum & MII_ADDR_C45) { + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF) + | MACB_BF(RW, MACB_MAN_C45_ADDR) + | MACB_BF(PHYA, mii_id) + | MACB_BF(REGA, (regnum >> 16) & 0x1F) + | MACB_BF(DATA, regnum & 0xFFFF) + | MACB_BF(CODE, MACB_MAN_C45_CODE))); + + status = macb_mdio_wait_for_idle(bp); + if (status < 0) + goto mdio_read_exit; + + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF) + | MACB_BF(RW, MACB_MAN_C45_READ) + | MACB_BF(PHYA, mii_id) + | MACB_BF(REGA, (regnum >> 16) & 0x1F) + | MACB_BF(CODE, MACB_MAN_C45_CODE))); + } else { + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF) + | MACB_BF(RW, MACB_MAN_C22_READ) + | MACB_BF(PHYA, mii_id) + | MACB_BF(REGA, regnum) + | MACB_BF(CODE, MACB_MAN_C22_CODE))); + }
status = macb_mdio_wait_for_idle(bp); if (status < 0) @@@ -370,12 -389,32 +389,32 @@@ static int macb_mdio_write(struct mii_b if (status < 0) goto mdio_write_exit;
- macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) - | MACB_BF(RW, MACB_MAN_WRITE) - | MACB_BF(PHYA, mii_id) - | MACB_BF(REGA, regnum) - | MACB_BF(CODE, MACB_MAN_CODE) - | MACB_BF(DATA, value))); + if (regnum & MII_ADDR_C45) { + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF) + | MACB_BF(RW, MACB_MAN_C45_ADDR) + | MACB_BF(PHYA, mii_id) + | MACB_BF(REGA, (regnum >> 16) & 0x1F) + | MACB_BF(DATA, regnum & 0xFFFF) + | MACB_BF(CODE, MACB_MAN_C45_CODE))); + + status = macb_mdio_wait_for_idle(bp); + if (status < 0) + goto mdio_write_exit; + + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C45_SOF) + | MACB_BF(RW, MACB_MAN_C45_WRITE) + | MACB_BF(PHYA, mii_id) + | MACB_BF(REGA, (regnum >> 16) & 0x1F) + | MACB_BF(CODE, MACB_MAN_C45_CODE) + | MACB_BF(DATA, value))); + } else { + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_C22_SOF) + | MACB_BF(RW, MACB_MAN_C22_WRITE) + | MACB_BF(PHYA, mii_id) + | MACB_BF(REGA, regnum) + | MACB_BF(CODE, MACB_MAN_C22_CODE) + | MACB_BF(DATA, value))); + }
status = macb_mdio_wait_for_idle(bp); if (status < 0) @@@ -611,24 -650,21 +650,24 @@@ static const struct phylink_mac_ops mac .mac_link_up = macb_mac_link_up, };
+static bool macb_phy_handle_exists(struct device_node *dn) +{ + dn = of_parse_phandle(dn, "phy-handle", 0); + of_node_put(dn); + return dn != NULL; +} + static int macb_phylink_connect(struct macb *bp) { + struct device_node *dn = bp->pdev->dev.of_node; struct net_device *dev = bp->dev; struct phy_device *phydev; int ret;
- if (bp->pdev->dev.of_node && - of_parse_phandle(bp->pdev->dev.of_node, "phy-handle", 0)) { - ret = phylink_of_phy_connect(bp->phylink, bp->pdev->dev.of_node, - 0); - if (ret) { - netdev_err(dev, "Could not attach PHY (%d)\n", ret); - return ret; - } - } else { + if (dn) + ret = phylink_of_phy_connect(bp->phylink, dn, 0); + + if (!dn || (ret && !macb_phy_handle_exists(dn))) { phydev = phy_find_first(bp->mii_bus); if (!phydev) { netdev_err(dev, "no PHY found\n"); @@@ -637,11 -673,10 +676,11 @@@
/* attach the mac to the phy */ ret = phylink_connect_phy(bp->phylink, phydev); - if (ret) { - netdev_err(dev, "Could not attach to PHY (%d)\n", ret); - return ret; - } + } + + if (ret) { + netdev_err(dev, "Could not attach PHY (%d)\n", ret); + return ret; }
phylink_start(bp->phylink); diff --combined drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index b3deb5e5ce29,e240d99f7ca8..914a7630ac48 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@@ -24,6 -24,12 +24,12 @@@
#include "hnae3.h" #include "hns3_enet.h" + /* All hns3 tracepoints are defined by the include below, which + * must be included exactly once across the whole kernel with + * CREATE_TRACE_POINTS defined + */ + #define CREATE_TRACE_POINTS + #include "hns3_trace.h"
#define hns3_set_field(origin, shift, val) ((origin) |= ((val) << (shift))) #define hns3_tx_bd_count(S) DIV_ROUND_UP(S, HNS3_MAX_BD_SIZE) @@@ -54,8 -60,6 +60,8 @@@ MODULE_PARM_DESC(debug, " Network inter #define HNS3_INNER_VLAN_TAG 1 #define HNS3_OUTER_VLAN_TAG 2
+#define HNS3_MIN_TX_LEN 33U + /* hns3_pci_tbl - PCI Device ID Table * * Last entry must be all 0s @@@ -129,18 -133,21 +135,21 @@@ static int hns3_nic_init_irq(struct hns continue;
if (tqp_vectors->tx_group.ring && tqp_vectors->rx_group.ring) { - snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN - 1, - "%s-%s-%d", priv->netdev->name, "TxRx", - txrx_int_idx++); + snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN, + "%s-%s-%s-%d", hns3_driver_name, + pci_name(priv->ae_handle->pdev), + "TxRx", txrx_int_idx++); txrx_int_idx++; } else if (tqp_vectors->rx_group.ring) { - snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN - 1, - "%s-%s-%d", priv->netdev->name, "Rx", - rx_int_idx++); + snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN, + "%s-%s-%s-%d", hns3_driver_name, + pci_name(priv->ae_handle->pdev), + "Rx", rx_int_idx++); } else if (tqp_vectors->tx_group.ring) { - snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN - 1, - "%s-%s-%d", priv->netdev->name, "Tx", - tx_int_idx++); + snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN, + "%s-%s-%s-%d", hns3_driver_name, + pci_name(priv->ae_handle->pdev), + "Tx", tx_int_idx++); } else { /* Skip this unused q_vector */ continue; @@@ -157,6 -164,8 +166,8 @@@ return ret; }
+ disable_irq(tqp_vectors->vector_irq); + irq_set_affinity_hint(tqp_vectors->vector_irq, &tqp_vectors->affinity_mask);
@@@ -175,6 -184,7 +186,7 @@@ static void hns3_mask_vector_irq(struc static void hns3_vector_enable(struct hns3_enet_tqp_vector *tqp_vector) { napi_enable(&tqp_vector->napi); + enable_irq(tqp_vector->vector_irq);
/* enable vector */ hns3_mask_vector_irq(tqp_vector, 1); @@@ -374,18 -384,6 +386,6 @@@ static int hns3_nic_net_up(struct net_d if (ret) return ret;
- /* the device can work without cpu rmap, only aRFS needs it */ - ret = hns3_set_rx_cpu_rmap(netdev); - if (ret) - netdev_warn(netdev, "set rx cpu rmap fail, ret=%d!\n", ret); - - /* get irq resource for all vectors */ - ret = hns3_nic_init_irq(priv); - if (ret) { - netdev_err(netdev, "init irq failed! ret=%d\n", ret); - goto free_rmap; - } - clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
/* enable the vectors */ @@@ -398,22 -396,15 +398,15 @@@
/* start the ae_dev */ ret = h->ae_algo->ops->start ? h->ae_algo->ops->start(h) : 0; - if (ret) - goto out_start_err; - - return 0; - - out_start_err: - set_bit(HNS3_NIC_STATE_DOWN, &priv->state); - while (j--) - hns3_tqp_disable(h->kinfo.tqp[j]); + if (ret) { + set_bit(HNS3_NIC_STATE_DOWN, &priv->state); + while (j--) + hns3_tqp_disable(h->kinfo.tqp[j]);
- for (j = i - 1; j >= 0; j--) - hns3_vector_disable(&priv->tqp_vector[j]); + for (j = i - 1; j >= 0; j--) + hns3_vector_disable(&priv->tqp_vector[j]); + }
- hns3_nic_uninit_irq(priv); - free_rmap: - hns3_free_rx_cpu_rmap(netdev); return ret; }
@@@ -510,11 -501,6 +503,6 @@@ static void hns3_nic_net_down(struct ne if (ops->stop) ops->stop(priv->ae_handle);
- hns3_free_rx_cpu_rmap(netdev); - - /* free irq resources */ - hns3_nic_uninit_irq(priv); - /* delay ring buffer clearing to hns3_reset_notify_uninit_enet * during reset process, because driver may not be able * to disable the ring through firmware when downing the netdev. @@@ -736,6 -722,8 +724,8 @@@ static int hns3_set_tso(struct sk_buff /* get MSS for TSO */ *mss = skb_shinfo(skb)->gso_size;
+ trace_hns3_tso(skb); + return 0; }
@@@ -1140,6 -1128,7 +1130,7 @@@ static int hns3_fill_desc(struct hns3_e desc->tx.bdtp_fe_sc_vld_ra_ri = cpu_to_le16(BIT(HNS3_TXD_VLD_B));
+ trace_hns3_tx_desc(ring, ring->next_to_use); ring_ptr_move_fw(ring, next_to_use); return HNS3_LIKELY_BD_NUM; } @@@ -1163,6 -1152,7 +1154,7 @@@ desc->tx.bdtp_fe_sc_vld_ra_ri = cpu_to_le16(BIT(HNS3_TXD_VLD_B));
+ trace_hns3_tx_desc(ring, ring->next_to_use); /* move ring pointer to next */ ring_ptr_move_fw(ring, next_to_use);
@@@ -1288,6 -1278,14 +1280,14 @@@ static bool hns3_skb_need_linearized(st return false; }
+ void hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size) + { + int i = 0; + + for (i = 0; i < MAX_SKB_FRAGS; i++) + size[i] = skb_frag_size(&shinfo->frags[i]); + } + static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, struct net_device *netdev, struct sk_buff *skb) @@@ -1299,8 -1297,10 +1299,10 @@@ bd_num = hns3_tx_bd_num(skb, bd_size); if (unlikely(bd_num > HNS3_MAX_NON_TSO_BD_NUM)) { if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) && - !hns3_skb_need_linearized(skb, bd_size, bd_num)) + !hns3_skb_need_linearized(skb, bd_size, bd_num)) { + trace_hns3_over_8bd(skb); goto out; + }
if (__skb_linearize(skb)) return -ENOMEM; @@@ -1308,8 -1308,10 +1310,10 @@@ bd_num = hns3_tx_bd_count(skb->len); if ((skb_is_gso(skb) && bd_num > HNS3_MAX_TSO_BD_NUM) || (!skb_is_gso(skb) && - bd_num > HNS3_MAX_NON_TSO_BD_NUM)) + bd_num > HNS3_MAX_NON_TSO_BD_NUM)) { + trace_hns3_over_8bd(skb); return -ENOMEM; + }
u64_stats_update_begin(&ring->syncp); ring->stats.tx_copy++; @@@ -1407,10 -1409,6 +1411,10 @@@ netdev_tx_t hns3_nic_net_xmit(struct sk int bd_num = 0; int ret;
+ /* Hardware can only handle short frames above 32 bytes */ + if (skb_put_padto(skb, HNS3_MIN_TX_LEN)) + return NETDEV_TX_OK; + /* Prefetch the data used later */ prefetch(skb->data);
@@@ -1454,6 -1452,7 +1458,7 @@@ out (ring->desc_num - 1); ring->desc[pre_ntu].tx.bdtp_fe_sc_vld_ra_ri |= cpu_to_le16(BIT(HNS3_TXD_FE_B)); + trace_hns3_tx_desc(ring, pre_ntu);
/* Complete translate all packets */ dev_queue = netdev_get_tx_queue(netdev, ring->queue_index); @@@ -1562,6 -1561,37 +1567,37 @@@ static int hns3_nic_set_features(struc return 0; }
+ static netdev_features_t hns3_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) + { + #define HNS3_MAX_HDR_LEN 480U + #define HNS3_MAX_L4_HDR_LEN 60U + + size_t len; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return features; + + if (skb->encapsulation) + len = skb_inner_transport_header(skb) - skb->data; + else + len = skb_transport_header(skb) - skb->data; + + /* Assume L4 is 60 byte as TCP is the only protocol with a + * a flexible value, and it's max len is 60 bytes. + */ + len += HNS3_MAX_L4_HDR_LEN; + + /* Hardware only supports checksum on the skb with a max header + * len of 480 bytes. + */ + if (len > HNS3_MAX_HDR_LEN) + features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); + + return features; + } + static void hns3_nic_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) { @@@ -1875,7 -1905,7 +1911,7 @@@ static bool hns3_get_tx_timeo_queue_inf return true; }
- static void hns3_nic_net_timeout(struct net_device *ndev) + static void hns3_nic_net_timeout(struct net_device *ndev, unsigned int txqueue) { struct hns3_nic_priv *priv = netdev_priv(ndev); struct hnae3_handle *h = priv->ae_handle; @@@ -1976,6 -2006,7 +2012,7 @@@ static const struct net_device_ops hns3 .ndo_do_ioctl = hns3_nic_do_ioctl, .ndo_change_mtu = hns3_nic_change_mtu, .ndo_set_features = hns3_nic_set_features, + .ndo_features_check = hns3_features_check, .ndo_get_stats64 = hns3_nic_get_stats64, .ndo_setup_tc = hns3_nic_setup_tc, .ndo_set_rx_mode = hns3_nic_set_rx_mode, @@@ -2674,6 -2705,9 +2711,9 @@@ static int hns3_gro_complete(struct sk_ skb->csum_start = (unsigned char *)th - skb->head; skb->csum_offset = offsetof(struct tcphdr, check); skb->ip_summed = CHECKSUM_PARTIAL; + + trace_hns3_gro(skb); + return 0; }
@@@ -2794,7 -2828,6 +2834,6 @@@ static bool hns3_parse_vlan_tag(struct static int hns3_alloc_skb(struct hns3_enet_ring *ring, unsigned int length, unsigned char *va) { - #define HNS3_NEED_ADD_FRAG 1 struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_clean]; struct net_device *netdev = ring_to_netdev(ring); struct sk_buff *skb; @@@ -2811,6 -2844,7 +2850,7 @@@ return -ENOMEM; }
+ trace_hns3_rx_desc(ring); prefetchw(skb->data);
ring->pending_buf = 1; @@@ -2838,33 -2872,19 +2878,19 @@@ desc_cb); ring_ptr_move_fw(ring, next_to_clean);
- return HNS3_NEED_ADD_FRAG; + return 0; }
- static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc, - bool pending) + static int hns3_add_frag(struct hns3_enet_ring *ring) { struct sk_buff *skb = ring->skb; struct sk_buff *head_skb = skb; struct sk_buff *new_skb; struct hns3_desc_cb *desc_cb; - struct hns3_desc *pre_desc; + struct hns3_desc *desc; u32 bd_base_info; - int pre_bd;
- /* if there is pending bd, the SW param next_to_clean has moved - * to next and the next is NULL - */ - if (pending) { - pre_bd = (ring->next_to_clean - 1 + ring->desc_num) % - ring->desc_num; - pre_desc = &ring->desc[pre_bd]; - bd_base_info = le32_to_cpu(pre_desc->rx.bd_base_info); - } else { - bd_base_info = le32_to_cpu(desc->rx.bd_base_info); - } - - while (!(bd_base_info & BIT(HNS3_RXD_FE_B))) { + do { desc = &ring->desc[ring->next_to_clean]; desc_cb = &ring->desc_cb[ring->next_to_clean]; bd_base_info = le32_to_cpu(desc->rx.bd_base_info); @@@ -2899,9 -2919,10 +2925,10 @@@ }
hns3_nic_reuse_page(skb, ring->frag_num++, ring, 0, desc_cb); + trace_hns3_rx_desc(ring); ring_ptr_move_fw(ring, next_to_clean); ring->pending_buf++; - } + } while (!(bd_base_info & BIT(HNS3_RXD_FE_B)));
return 0; } @@@ -3069,28 -3090,23 +3096,23 @@@ static int hns3_handle_rx_bd(struct hns
if (ret < 0) /* alloc buffer fail */ return ret; - if (ret > 0) { /* need add frag */ - ret = hns3_add_frag(ring, desc, false); + if (!(bd_base_info & BIT(HNS3_RXD_FE_B))) { /* need add frag */ + ret = hns3_add_frag(ring); if (ret) return ret; - - /* As the head data may be changed when GRO enable, copy - * the head data in after other data rx completed - */ - memcpy(skb->data, ring->va, - ALIGN(ring->pull_len, sizeof(long))); } } else { - ret = hns3_add_frag(ring, desc, true); + ret = hns3_add_frag(ring); if (ret) return ret; + }
- /* As the head data may be changed when GRO enable, copy - * the head data in after other data rx completed - */ + /* As the head data may be changed when GRO enable, copy + * the head data in after other data rx completed + */ + if (skb->len > HNS3_RX_HEAD_SIZE) memcpy(skb->data, ring->va, ALIGN(ring->pull_len, sizeof(long))); - }
ret = hns3_handle_bdinfo(ring, skb); if (unlikely(ret)) { @@@ -3596,26 -3612,25 +3618,25 @@@ static void hns3_nic_uninit_vector_data if (!tqp_vector->rx_group.ring && !tqp_vector->tx_group.ring) continue;
- hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain); + /* Since the mapping can be overwritten, when fail to get the + * chain between vector and ring, we should go on to deal with + * the remaining options. + */ + if (hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain)) + dev_warn(priv->dev, "failed to get ring chain\n");
h->ae_algo->ops->unmap_ring_from_vector(h, tqp_vector->vector_irq, &vector_ring_chain);
hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain);
- if (tqp_vector->irq_init_flag == HNS3_VECTOR_INITED) { - irq_set_affinity_hint(tqp_vector->vector_irq, NULL); - free_irq(tqp_vector->vector_irq, tqp_vector); - tqp_vector->irq_init_flag = HNS3_VECTOR_NOT_INITED; - } - hns3_clear_ring_group(&tqp_vector->rx_group); hns3_clear_ring_group(&tqp_vector->tx_group); netif_napi_del(&priv->tqp_vector[i].napi); } }
- static int hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv) + static void hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv) { struct hnae3_handle *h = priv->ae_handle; struct pci_dev *pdev = h->pdev; @@@ -3627,11 -3642,10 +3648,10 @@@ tqp_vector = &priv->tqp_vector[i]; ret = h->ae_algo->ops->put_vector(h, tqp_vector->vector_irq); if (ret) - return ret; + return; }
devm_kfree(&pdev->dev, priv->tqp_vector); - return 0; }
static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, @@@ -4030,6 -4044,18 +4050,18 @@@ static int hns3_client_init(struct hnae goto out_reg_netdev_fail; }
+ /* the device can work without cpu rmap, only aRFS needs it */ + ret = hns3_set_rx_cpu_rmap(netdev); + if (ret) + dev_warn(priv->dev, "set rx cpu rmap fail, ret=%d\n", ret); + + ret = hns3_nic_init_irq(priv); + if (ret) { + dev_err(priv->dev, "init irq failed! ret=%d\n", ret); + hns3_free_rx_cpu_rmap(netdev); + goto out_init_irq_fail; + } + ret = hns3_client_start(handle); if (ret) { dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret); @@@ -4051,6 -4077,9 +4083,9 @@@ return ret;
out_client_start: + hns3_free_rx_cpu_rmap(netdev); + hns3_nic_uninit_irq(priv); + out_init_irq_fail: unregister_netdev(netdev); out_reg_netdev_fail: hns3_uninit_phy(netdev); @@@ -4088,15 -4117,17 +4123,17 @@@ static void hns3_client_uninit(struct h goto out_netdev_free; }
+ hns3_free_rx_cpu_rmap(netdev); + + hns3_nic_uninit_irq(priv); + hns3_del_all_fd_rules(netdev, true);
hns3_clear_all_ring(handle, true);
hns3_nic_uninit_vector_data(priv);
- ret = hns3_nic_dealloc_vector_data(priv); - if (ret) - netdev_err(netdev, "dealloc vector error\n"); + hns3_nic_dealloc_vector_data(priv);
ret = hns3_uninit_all_ring(priv); if (ret) @@@ -4423,17 -4454,32 +4460,32 @@@ static int hns3_reset_notify_init_enet( if (ret) goto err_uninit_vector;
+ /* the device can work without cpu rmap, only aRFS needs it */ + ret = hns3_set_rx_cpu_rmap(netdev); + if (ret) + dev_warn(priv->dev, "set rx cpu rmap fail, ret=%d\n", ret); + + ret = hns3_nic_init_irq(priv); + if (ret) { + dev_err(priv->dev, "init irq failed! ret=%d\n", ret); + hns3_free_rx_cpu_rmap(netdev); + goto err_init_irq_fail; + } + ret = hns3_client_start(handle); if (ret) { dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret); - goto err_uninit_ring; + goto err_client_start_fail; }
set_bit(HNS3_NIC_STATE_INITED, &priv->state);
return ret;
- err_uninit_ring: + err_client_start_fail: + hns3_free_rx_cpu_rmap(netdev); + hns3_nic_uninit_irq(priv); + err_init_irq_fail: hns3_uninit_all_ring(priv); err_uninit_vector: hns3_nic_uninit_vector_data(priv); @@@ -4483,6 -4529,8 +4535,8 @@@ static int hns3_reset_notify_uninit_ene return 0; }
+ hns3_free_rx_cpu_rmap(netdev); + hns3_nic_uninit_irq(priv); hns3_clear_all_ring(handle, true); hns3_reset_tx_queue(priv->ae_handle);
@@@ -4490,9 -4538,7 +4544,7 @@@
hns3_store_coal(priv);
- ret = hns3_nic_dealloc_vector_data(priv); - if (ret) - netdev_err(netdev, "dealloc vector error\n"); + hns3_nic_dealloc_vector_data(priv);
ret = hns3_uninit_all_ring(priv); if (ret) diff --combined drivers/net/ethernet/intel/e1000e/netdev.c index 7c5b18d87b49,8797913b2702..db4ea58bac82 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@@ -1780,7 -1780,8 +1780,7 @@@ static irqreturn_t e1000_intr_msi(int _ } /* guard against interrupt when we're going down */ if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_delayed_work(adapter->e1000_workqueue, - &adapter->watchdog_task, HZ); + mod_timer(&adapter->watchdog_timer, jiffies + 1); }
/* Reset on uncorrectable ECC error */ @@@ -1860,7 -1861,8 +1860,7 @@@ static irqreturn_t e1000_intr(int __alw } /* guard against interrupt when we're going down */ if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_delayed_work(adapter->e1000_workqueue, - &adapter->watchdog_task, HZ); + mod_timer(&adapter->watchdog_timer, jiffies + 1); }
/* Reset on uncorrectable ECC error */ @@@ -1905,7 -1907,8 +1905,7 @@@ static irqreturn_t e1000_msix_other(in hw->mac.get_link_status = true; /* guard against interrupt when we're going down */ if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_delayed_work(adapter->e1000_workqueue, - &adapter->watchdog_task, HZ); + mod_timer(&adapter->watchdog_timer, jiffies + 1); }
if (!test_bit(__E1000_DOWN, &adapter->state)) @@@ -4281,7 -4284,6 +4281,7 @@@ void e1000e_down(struct e1000_adapter *
napi_synchronize(&adapter->napi);
+ del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer);
spin_lock(&adapter->stats64_lock); @@@ -4721,7 -4723,7 +4721,7 @@@ int e1000e_close(struct net_device *net e1000_free_irq(adapter);
/* Link status message must follow this format */ - pr_info("%s NIC Link is Down\n", netdev->name); + netdev_info(netdev, "NIC Link is Down\n"); }
napi_disable(&adapter->napi); @@@ -5071,12 -5073,13 +5071,13 @@@ static void e1000_print_link_info(struc u32 ctrl = er32(CTRL);
/* Link status message must follow this format for user tools */ - pr_info("%s NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n", - adapter->netdev->name, adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half", - (ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE) ? "Rx/Tx" : - (ctrl & E1000_CTRL_RFCE) ? "Rx" : - (ctrl & E1000_CTRL_TFCE) ? "Tx" : "None"); + netdev_info(adapter->netdev, + "NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n", + adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half", + (ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE) ? "Rx/Tx" : + (ctrl & E1000_CTRL_RFCE) ? "Rx" : + (ctrl & E1000_CTRL_TFCE) ? "Tx" : "None"); }
static bool e1000e_has_link(struct e1000_adapter *adapter) @@@ -5153,25 -5156,11 +5154,25 @@@ static void e1000e_check_82574_phy_work } }
+/** + * e1000_watchdog - Timer Call-back + * @data: pointer to adapter cast into an unsigned long + **/ +static void e1000_watchdog(struct timer_list *t) +{ + struct e1000_adapter *adapter = from_timer(adapter, t, watchdog_timer); + + /* Do the rest outside of interrupt context */ + schedule_work(&adapter->watchdog_task); + + /* TODO: make this use queue_delayed_work() */ +} + static void e1000_watchdog_task(struct work_struct *work) { struct e1000_adapter *adapter = container_of(work, struct e1000_adapter, - watchdog_task.work); + watchdog_task); struct net_device *netdev = adapter->netdev; struct e1000_mac_info *mac = &adapter->hw.mac; struct e1000_phy_info *phy = &adapter->hw.phy; @@@ -5319,7 -5308,7 +5320,7 @@@ adapter->link_speed = 0; adapter->link_duplex = 0; /* Link status message must follow this format */ - pr_info("%s NIC Link is Down\n", adapter->netdev->name); + netdev_info(netdev, "NIC Link is Down\n"); netif_carrier_off(netdev); netif_stop_queue(netdev); if (!test_bit(__E1000_DOWN, &adapter->state)) @@@ -5419,8 -5408,9 +5420,8 @@@ link_up
/* Reset the timer */ if (!test_bit(__E1000_DOWN, &adapter->state)) - queue_delayed_work(adapter->e1000_workqueue, - &adapter->watchdog_task, - round_jiffies(2 * HZ)); + mod_timer(&adapter->watchdog_timer, + round_jiffies(jiffies + 2 * HZ)); }
#define E1000_TX_FLAGS_CSUM 0x00000001 @@@ -5940,7 -5930,7 +5941,7 @@@ static netdev_tx_t e1000_xmit_frame(str * e1000_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure **/ - static void e1000_tx_timeout(struct net_device *netdev) + static void e1000_tx_timeout(struct net_device *netdev, unsigned int txqueue) { struct e1000_adapter *adapter = netdev_priv(netdev);
@@@ -7460,11 -7450,21 +7461,11 @@@ static int e1000_probe(struct pci_dev * goto err_eeprom; }
- adapter->e1000_workqueue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, - e1000e_driver_name); - - if (!adapter->e1000_workqueue) { - err = -ENOMEM; - goto err_workqueue; - } - - INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog_task); - queue_delayed_work(adapter->e1000_workqueue, &adapter->watchdog_task, - 0); - + timer_setup(&adapter->watchdog_timer, e1000_watchdog, 0); timer_setup(&adapter->phy_info_timer, e1000_update_phy_info, 0);
INIT_WORK(&adapter->reset_task, e1000_reset_task); + INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task); INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang); @@@ -7558,6 -7558,9 +7559,6 @@@ return 0;
err_register: - flush_workqueue(adapter->e1000_workqueue); - destroy_workqueue(adapter->e1000_workqueue); -err_workqueue: if (!(adapter->flags & FLAG_HAS_AMT)) e1000e_release_hw_control(adapter); err_eeprom: @@@ -7602,15 -7605,17 +7603,15 @@@ static void e1000_remove(struct pci_de * from being rescheduled. */ set_bit(__E1000_DOWN, &adapter->state); + del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer);
cancel_work_sync(&adapter->reset_task); + cancel_work_sync(&adapter->watchdog_task); cancel_work_sync(&adapter->downshift_task); cancel_work_sync(&adapter->update_phy_task); cancel_work_sync(&adapter->print_hang_task);
- cancel_delayed_work(&adapter->watchdog_task); - flush_workqueue(adapter->e1000_workqueue); - destroy_workqueue(adapter->e1000_workqueue); - if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) { cancel_work_sync(&adapter->tx_hwtstamp_work); if (adapter->tx_hwtstamp_skb) { diff --combined drivers/net/ethernet/intel/iavf/iavf_main.c index 8e16be960e96,0a8824871618..62fe56ddcb6e --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@@ -159,7 -159,7 +159,7 @@@ void iavf_schedule_reset(struct iavf_ad * iavf_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure **/ - static void iavf_tx_timeout(struct net_device *netdev) + static void iavf_tx_timeout(struct net_device *netdev, unsigned int txqueue) { struct iavf_adapter *adapter = netdev_priv(netdev);
@@@ -743,8 -743,9 +743,8 @@@ iavf_mac_filter *iavf_find_filter(struc * * Returns ptr to the filter object or NULL when no memory available. **/ -static struct -iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter, - const u8 *macaddr) +struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter, + const u8 *macaddr) { struct iavf_mac_filter *f;
@@@ -2064,9 -2065,9 +2064,9 @@@ static void iavf_reset_task(struct work struct virtchnl_vf_resource *vfres = adapter->vf_res; struct net_device *netdev = adapter->netdev; struct iavf_hw *hw = &adapter->hw; + struct iavf_mac_filter *f, *ftmp; struct iavf_vlan_filter *vlf; struct iavf_cloud_filter *cf; - struct iavf_mac_filter *f; u32 reg_val; int i = 0, err; bool running; @@@ -2180,16 -2181,6 +2180,16 @@@ continue_reset
spin_lock_bh(&adapter->mac_vlan_list_lock);
+ /* Delete filter for the current MAC address, it could have + * been changed by the PF via administratively set MAC. + * Will be re-added via VIRTCHNL_OP_GET_VF_RESOURCES. + */ + list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) { + if (ether_addr_equal(f->macaddr, adapter->hw.mac.addr)) { + list_del(&f->list); + kfree(f); + } + } /* re-add all MAC filters */ list_for_each_entry(f, &adapter->mac_filter_list, list) { f->add = true; diff --combined drivers/net/ethernet/intel/igb/igb_ethtool.c index 445fbdce3e25,43c438365389..f96ffa83efbe --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@@ -181,7 -181,7 +181,7 @@@ static int igb_get_link_ksettings(struc advertising &= ~ADVERTISED_1000baseKX_Full; } } - if (eth_flags->e100_base_fx) { + if (eth_flags->e100_base_fx || eth_flags->e100_base_lx) { supported |= SUPPORTED_100baseT_Full; advertising |= ADVERTISED_100baseT_Full; } @@@ -396,6 -396,7 +396,7 @@@ static int igb_set_pauseparam(struct ne struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; int retval = 0; + int i;
/* 100basefx does not support setting link flow control */ if (hw->dev_spec._82575.eth_flags.e100_base_fx) @@@ -428,6 -429,13 +429,13 @@@
retval = ((hw->phy.media_type == e1000_media_type_copper) ? igb_force_mac_fc(hw) : igb_setup_link(hw)); + + /* Make sure SRRCTL considers new fc settings for each ring */ + for (i = 0; i < adapter->num_rx_queues; i++) { + struct igb_ring *ring = adapter->rx_ring[i]; + + igb_setup_srrctl(adapter, ring); + } }
clear_bit(__IGB_RESETTING, &adapter->state); diff --combined drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index a2b2ad1f60b1,4c13cca656b2..718931d951bc --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@@ -5239,7 -5239,7 +5239,7 @@@ static void ixgbe_fdir_filter_restore(s struct ixgbe_hw *hw = &adapter->hw; struct hlist_node *node2; struct ixgbe_fdir_filter *filter; - u64 action; + u8 queue;
spin_lock(&adapter->fdir_perfect_lock);
@@@ -5248,34 -5248,17 +5248,34 @@@
hlist_for_each_entry_safe(filter, node2, &adapter->fdir_filter_list, fdir_node) { - action = filter->action; - if (action != IXGBE_FDIR_DROP_QUEUE && action != 0) - action = - (action >> ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF) - 1; + if (filter->action == IXGBE_FDIR_DROP_QUEUE) { + queue = IXGBE_FDIR_DROP_QUEUE; + } else { + u32 ring = ethtool_get_flow_spec_ring(filter->action); + u8 vf = ethtool_get_flow_spec_ring_vf(filter->action); + + if (!vf && (ring >= adapter->num_rx_queues)) { + e_err(drv, "FDIR restore failed without VF, ring: %u\n", + ring); + continue; + } else if (vf && + ((vf > adapter->num_vfs) || + ring >= adapter->num_rx_queues_per_pool)) { + e_err(drv, "FDIR restore failed with VF, vf: %hhu, ring: %u\n", + vf, ring); + continue; + } + + /* Map the ring onto the absolute queue index */ + if (!vf) + queue = adapter->rx_ring[ring]->reg_idx; + else + queue = ((vf - 1) * + adapter->num_rx_queues_per_pool) + ring; + }
ixgbe_fdir_write_perfect_filter_82599(hw, - &filter->filter, - filter->sw_idx, - (action == IXGBE_FDIR_DROP_QUEUE) ? - IXGBE_FDIR_DROP_QUEUE : - adapter->rx_ring[action]->reg_idx); + &filter->filter, filter->sw_idx, queue); }
spin_unlock(&adapter->fdir_perfect_lock); @@@ -6175,7 -6158,7 +6175,7 @@@ static void ixgbe_set_eee_capable(struc * ixgbe_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure **/ - static void ixgbe_tx_timeout(struct net_device *netdev) + static void ixgbe_tx_timeout(struct net_device *netdev, unsigned int txqueue) { struct ixgbe_adapter *adapter = netdev_priv(netdev);
diff --combined drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 64ec0e7c64b4,fa286694ac2c..4622c4ea2e46 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@@ -250,7 -250,7 +250,7 @@@ static void ixgbevf_tx_timeout_reset(st * ixgbevf_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure **/ - static void ixgbevf_tx_timeout(struct net_device *netdev) + static void ixgbevf_tx_timeout(struct net_device *netdev, unsigned int txqueue) { struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@@ -2081,6 -2081,11 +2081,6 @@@ static int ixgbevf_write_uc_addr_list(s struct ixgbe_hw *hw = &adapter->hw; int count = 0;
- if ((netdev_uc_count(netdev)) > 10) { - pr_err("Too many unicast filters - No Space\n"); - return -ENOSPC; - } - if (!netdev_uc_empty(netdev)) { struct netdev_hw_addr *ha;
diff --combined drivers/net/ethernet/marvell/mvneta.c index 67ad8b8b127d,587e35d10dc7..0449d4b28ade --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@@ -2081,11 -2081,7 +2081,11 @@@ static in mvneta_run_xdp(struct mvneta_port *pp, struct mvneta_rx_queue *rxq, struct bpf_prog *prog, struct xdp_buff *xdp) { - u32 ret, act = bpf_prog_run_xdp(prog, xdp); + unsigned int len; + u32 ret, act; + + len = xdp->data_end - xdp->data_hard_start - pp->rx_offset_correction; + act = bpf_prog_run_xdp(prog, xdp);
switch (act) { case XDP_PASS: @@@ -2098,8 -2094,9 +2098,8 @@@ if (err) { ret = MVNETA_XDP_DROPPED; __page_pool_put_page(rxq->page_pool, - virt_to_head_page(xdp->data), - xdp->data_end - xdp->data_hard_start, - true); + virt_to_head_page(xdp->data), + len, true); } else { ret = MVNETA_XDP_REDIR; } @@@ -2109,8 -2106,9 +2109,8 @@@ ret = mvneta_xdp_xmit_back(pp, xdp); if (ret != MVNETA_XDP_TX) __page_pool_put_page(rxq->page_pool, - virt_to_head_page(xdp->data), - xdp->data_end - xdp->data_hard_start, - true); + virt_to_head_page(xdp->data), + len, true); break; default: bpf_warn_invalid_xdp_action(act); @@@ -2121,7 -2119,8 +2121,7 @@@ case XDP_DROP: __page_pool_put_page(rxq->page_pool, virt_to_head_page(xdp->data), - xdp->data_end - xdp->data_hard_start, - true); + len, true); ret = MVNETA_XDP_DROPPED; break; } @@@ -3072,7 -3071,7 +3072,7 @@@ static int mvneta_create_page_pool(stru .order = 0, .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, .pool_size = size, - .nid = cpu_to_node(0), + .nid = NUMA_NO_NODE, .dev = pp->dev->dev.parent, .dma_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE, .offset = pp->rx_offset_correction, diff --combined drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 8ed15199eb4f,2f0b516ee03f..4f58d6574a4c --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@@ -45,11 -45,9 +45,9 @@@ #include "spectrum_ptp.h" #include "../mlxfw/mlxfw.h"
- #define MLXSW_SP_FWREV_MINOR_TO_BRANCH(minor) ((minor) / 100) - #define MLXSW_SP1_FWREV_MAJOR 13 #define MLXSW_SP1_FWREV_MINOR 2000 - #define MLXSW_SP1_FWREV_SUBMINOR 2308 + #define MLXSW_SP1_FWREV_SUBMINOR 2714 #define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702
static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = { @@@ -66,7 -64,7 +64,7 @@@
#define MLXSW_SP2_FWREV_MAJOR 29 #define MLXSW_SP2_FWREV_MINOR 2000 - #define MLXSW_SP2_FWREV_SUBMINOR 2308 + #define MLXSW_SP2_FWREV_SUBMINOR 2714
static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = { .major = MLXSW_SP2_FWREV_MAJOR, @@@ -423,13 -421,12 +421,12 @@@ static int mlxsw_sp_fw_rev_validate(str rev->major, req_rev->major); return -EINVAL; } - if (MLXSW_SP_FWREV_MINOR_TO_BRANCH(rev->minor) == - MLXSW_SP_FWREV_MINOR_TO_BRANCH(req_rev->minor) && - mlxsw_core_fw_rev_minor_subminor_validate(rev, req_rev)) + if (mlxsw_core_fw_rev_minor_subminor_validate(rev, req_rev)) return 0;
- dev_info(mlxsw_sp->bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver\n", - rev->major, rev->minor, rev->subminor); + dev_err(mlxsw_sp->bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver (required >= %d.%d.%d)\n", + rev->major, rev->minor, rev->subminor, req_rev->major, + req_rev->minor, req_rev->subminor); dev_info(mlxsw_sp->bus_info->dev, "Flashing firmware using file %s\n", fw_filename);
@@@ -860,17 -857,23 +857,17 @@@ static netdev_tx_t mlxsw_sp_port_xmit(s u64 len; int err;
+ if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) { + this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped); + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info)) return NETDEV_TX_BUSY;
- if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) { - struct sk_buff *skb_orig = skb; - - skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN); - if (!skb) { - this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped); - dev_kfree_skb_any(skb_orig); - return NETDEV_TX_OK; - } - dev_consume_skb_any(skb_orig); - } - if (eth_skb_pad(skb)) { this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped); return NETDEV_TX_OK; @@@ -1209,9 -1212,6 +1206,9 @@@ static void update_stats_cache(struct w periodic_hw_stats.update_dw.work);
if (!netif_carrier_ok(mlxsw_sp_port->dev)) + /* Note: mlxsw_sp_port_down_wipe_counters() clears the cache as + * necessary when port goes down. + */ goto out;
mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev, @@@ -1793,6 -1793,8 +1790,8 @@@ static int mlxsw_sp_setup_tc(struct net return mlxsw_sp_setup_tc_red(mlxsw_sp_port, type_data); case TC_SETUP_QDISC_PRIO: return mlxsw_sp_setup_tc_prio(mlxsw_sp_port, type_data); + case TC_SETUP_QDISC_ETS: + return mlxsw_sp_setup_tc_ets(mlxsw_sp_port, type_data); default: return -EOPNOTSUPP; } @@@ -3599,26 -3601,25 +3598,25 @@@ static int mlxsw_sp_port_ets_init(struc * one subgroup, which are all member in the same group. */ err = mlxsw_sp_port_ets_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_GROUP, 0, 0, false, - 0); + MLXSW_REG_QEEC_HR_GROUP, 0, 0, false, 0); if (err) return err; for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { err = mlxsw_sp_port_ets_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_SUBGROUP, i, + MLXSW_REG_QEEC_HR_SUBGROUP, i, 0, false, 0); if (err) return err; } for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { err = mlxsw_sp_port_ets_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_TC, i, i, + MLXSW_REG_QEEC_HR_TC, i, i, false, 0); if (err) return err;
err = mlxsw_sp_port_ets_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_TC, + MLXSW_REG_QEEC_HR_TC, i + 8, i, true, 100); if (err) @@@ -3630,13 -3631,13 +3628,13 @@@ * for the initial configuration. */ err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_PORT, 0, 0, + MLXSW_REG_QEEC_HR_PORT, 0, 0, MLXSW_REG_QEEC_MAS_DIS); if (err) return err; for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_SUBGROUP, + MLXSW_REG_QEEC_HR_SUBGROUP, i, 0, MLXSW_REG_QEEC_MAS_DIS); if (err) @@@ -3644,14 -3645,14 +3642,14 @@@ } for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_TC, + MLXSW_REG_QEEC_HR_TC, i, i, MLXSW_REG_QEEC_MAS_DIS); if (err) return err;
err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_TC, + MLXSW_REG_QEEC_HR_TC, i + 8, i, MLXSW_REG_QEEC_MAS_DIS); if (err) @@@ -3661,7 -3662,7 +3659,7 @@@ /* Configure the min shaper for multicast TCs. */ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { err = mlxsw_sp_port_min_bw_set(mlxsw_sp_port, - MLXSW_REG_QEEC_HIERARCY_TC, + MLXSW_REG_QEEC_HR_TC, i + 8, i, MLXSW_REG_QEEC_MIS_MIN); if (err) @@@ -4321,15 -4322,6 +4319,15 @@@ static int mlxsw_sp_port_unsplit(struc return 0; }
+static void +mlxsw_sp_port_down_wipe_counters(struct mlxsw_sp_port *mlxsw_sp_port) +{ + int i; + + for (i = 0; i < TC_MAX_QUEUE; i++) + mlxsw_sp_port->periodic_hw_stats.xstats.backlog[i] = 0; +} + static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, char *pude_pl, void *priv) { @@@ -4351,7 -4343,6 +4349,7 @@@ } else { netdev_info(mlxsw_sp_port->dev, "link down\n"); netif_carrier_off(mlxsw_sp_port->dev); + mlxsw_sp_port_down_wipe_counters(mlxsw_sp_port); } }
@@@ -4551,6 -4542,14 +4549,14 @@@ static const struct mlxsw_listener mlxs MLXSW_SP_RXL_MARK(DECAP_ECN0, TRAP_TO_CPU, ROUTER_EXP, false), MLXSW_SP_RXL_MARK(IPV4_VRRP, TRAP_TO_CPU, VRRP, false), MLXSW_SP_RXL_MARK(IPV6_VRRP, TRAP_TO_CPU, VRRP, false), + MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_CLASS_E, FORWARD, + ROUTER_EXP, false), + MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_MC_DMAC, FORWARD, + ROUTER_EXP, false), + MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_DIP, FORWARD, + ROUTER_EXP, false), + MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_DIP_LINK_LOCAL, FORWARD, + ROUTER_EXP, false), /* PKT Sample trap */ MLXSW_RXL(mlxsw_sp_rx_listener_sample_func, PKT_SAMPLE, MIRROR_TO_CPU, false, SP_IP2ME, DISCARD), @@@ -5139,27 -5138,6 +5145,27 @@@ static int mlxsw_sp2_init(struct mlxsw_ return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack); }
+static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + + mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops; + mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops; + mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops; + mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops; + mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops; + mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr; + mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask; + mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr; + mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals; + mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops; + mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops; + + return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack); +} + static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); @@@ -5662,7 -5640,7 +5668,7 @@@ static struct mlxsw_driver mlxsw_sp2_dr static struct mlxsw_driver mlxsw_sp3_driver = { .kind = mlxsw_sp3_driver_name, .priv_size = sizeof(struct mlxsw_sp), - .init = mlxsw_sp2_init, + .init = mlxsw_sp3_init, .fini = mlxsw_sp_fini, .basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set, .port_split = mlxsw_sp_port_split, diff --combined drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c index 0124bfe1963b,54807b4930fe..d57c9b15f45e --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c @@@ -18,6 -18,7 +18,7 @@@ enum mlxsw_sp_qdisc_type MLXSW_SP_QDISC_NO_QDISC, MLXSW_SP_QDISC_RED, MLXSW_SP_QDISC_PRIO, + MLXSW_SP_QDISC_ETS, };
struct mlxsw_sp_qdisc_ops { @@@ -195,20 -196,6 +196,20 @@@ mlxsw_sp_qdisc_get_xstats(struct mlxsw_ return -EOPNOTSUPP; }
+static u64 +mlxsw_sp_xstats_backlog(struct mlxsw_sp_port_xstats *xstats, int tclass_num) +{ + return xstats->backlog[tclass_num] + + xstats->backlog[tclass_num + 8]; +} + +static u64 +mlxsw_sp_xstats_tail_drop(struct mlxsw_sp_port_xstats *xstats, int tclass_num) +{ + return xstats->tail_drop[tclass_num] + + xstats->tail_drop[tclass_num + 8]; +} + static void mlxsw_sp_qdisc_bstats_per_priority_get(struct mlxsw_sp_port_xstats *xstats, u8 prio_bitmap, u64 *tx_packets, @@@ -283,7 -270,7 +284,7 @@@ mlxsw_sp_setup_tc_qdisc_red_clean_stats &stats_base->tx_bytes); red_base->prob_mark = xstats->ecn; red_base->prob_drop = xstats->wred_drop[tclass_num]; - red_base->pdrop = xstats->tail_drop[tclass_num]; + red_base->pdrop = mlxsw_sp_xstats_tail_drop(xstats, tclass_num);
stats_base->overlimits = red_base->prob_drop + red_base->prob_mark; stats_base->drops = red_base->prob_drop + red_base->pdrop; @@@ -384,8 -371,7 +385,8 @@@ mlxsw_sp_qdisc_get_red_xstats(struct ml
early_drops = xstats->wred_drop[tclass_num] - xstats_base->prob_drop; marks = xstats->ecn - xstats_base->prob_mark; - pdrops = xstats->tail_drop[tclass_num] - xstats_base->pdrop; + pdrops = mlxsw_sp_xstats_tail_drop(xstats, tclass_num) - + xstats_base->pdrop;
res->pdrop += pdrops; res->prob_drop += early_drops; @@@ -418,10 -404,9 +419,10 @@@ mlxsw_sp_qdisc_get_red_stats(struct mlx
overlimits = xstats->wred_drop[tclass_num] + xstats->ecn - stats_base->overlimits; - drops = xstats->wred_drop[tclass_num] + xstats->tail_drop[tclass_num] - + drops = xstats->wred_drop[tclass_num] + + mlxsw_sp_xstats_tail_drop(xstats, tclass_num) - stats_base->drops; - backlog = xstats->backlog[tclass_num]; + backlog = mlxsw_sp_xstats_backlog(xstats, tclass_num);
_bstats_update(stats_ptr->bstats, tx_bytes, tx_packets); stats_ptr->qstats->overlimits += overlimits; @@@ -487,14 -472,16 +488,16 @@@ int mlxsw_sp_setup_tc_red(struct mlxsw_ }
static int - mlxsw_sp_qdisc_prio_destroy(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_qdisc *mlxsw_sp_qdisc) + __mlxsw_sp_qdisc_ets_destroy(struct mlxsw_sp_port *mlxsw_sp_port) { int i;
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, MLXSW_SP_PORT_DEFAULT_TCLASS); + mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HR_SUBGROUP, + i, 0, false, 0); mlxsw_sp_qdisc_destroy(mlxsw_sp_port, &mlxsw_sp_port->tclass_qdiscs[i]); mlxsw_sp_port->tclass_qdiscs[i].prio_bitmap = 0; @@@ -504,36 -491,58 +507,58 @@@ }
static int - mlxsw_sp_qdisc_prio_check_params(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, - void *params) + mlxsw_sp_qdisc_prio_destroy(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc) { - struct tc_prio_qopt_offload_params *p = params; + return __mlxsw_sp_qdisc_ets_destroy(mlxsw_sp_port); + }
- if (p->bands > IEEE_8021QAZ_MAX_TCS) + static int + __mlxsw_sp_qdisc_ets_check_params(unsigned int nbands) + { + if (nbands > IEEE_8021QAZ_MAX_TCS) return -EOPNOTSUPP;
return 0; }
static int - mlxsw_sp_qdisc_prio_replace(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, - void *params) + mlxsw_sp_qdisc_prio_check_params(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, + void *params) { struct tc_prio_qopt_offload_params *p = params; + + return __mlxsw_sp_qdisc_ets_check_params(p->bands); + } + + static int + __mlxsw_sp_qdisc_ets_replace(struct mlxsw_sp_port *mlxsw_sp_port, + unsigned int nbands, + const unsigned int *quanta, + const unsigned int *weights, + const u8 *priomap) + { struct mlxsw_sp_qdisc *child_qdisc; int tclass, i, band, backlog; u8 old_priomap; int err;
- for (band = 0; band < p->bands; band++) { + for (band = 0; band < nbands; band++) { tclass = MLXSW_SP_PRIO_BAND_TO_TCLASS(band); child_qdisc = &mlxsw_sp_port->tclass_qdiscs[tclass]; old_priomap = child_qdisc->prio_bitmap; child_qdisc->prio_bitmap = 0; + + err = mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HR_SUBGROUP, + tclass, 0, !!quanta[band], + weights[band]); + if (err) + return err; + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { - if (p->priomap[i] == band) { + if (priomap[i] == band) { child_qdisc->prio_bitmap |= BIT(i); if (BIT(i) & old_priomap) continue; @@@ -556,21 -565,46 +581,46 @@@ child_qdisc = &mlxsw_sp_port->tclass_qdiscs[tclass]; child_qdisc->prio_bitmap = 0; mlxsw_sp_qdisc_destroy(mlxsw_sp_port, child_qdisc); + mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HR_SUBGROUP, + tclass, 0, false, 0); } return 0; }
+ static int + mlxsw_sp_qdisc_prio_replace(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, + void *params) + { + struct tc_prio_qopt_offload_params *p = params; + unsigned int zeroes[TCQ_ETS_MAX_BANDS] = {0}; + + return __mlxsw_sp_qdisc_ets_replace(mlxsw_sp_port, p->bands, + zeroes, zeroes, p->priomap); + } + + static void + __mlxsw_sp_qdisc_ets_unoffload(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, + struct gnet_stats_queue *qstats) + { + u64 backlog; + + backlog = mlxsw_sp_cells_bytes(mlxsw_sp_port->mlxsw_sp, + mlxsw_sp_qdisc->stats_base.backlog); + qstats->backlog -= backlog; + } + static void mlxsw_sp_qdisc_prio_unoffload(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, void *params) { struct tc_prio_qopt_offload_params *p = params; - u64 backlog;
- backlog = mlxsw_sp_cells_bytes(mlxsw_sp_port->mlxsw_sp, - mlxsw_sp_qdisc->stats_base.backlog); - p->qstats->backlog -= backlog; + __mlxsw_sp_qdisc_ets_unoffload(mlxsw_sp_port, mlxsw_sp_qdisc, + p->qstats); }
static int @@@ -592,9 -626,9 +642,9 @@@ mlxsw_sp_qdisc_get_prio_stats(struct ml tx_packets = stats->tx_packets - stats_base->tx_packets;
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { - drops += xstats->tail_drop[i]; + drops += mlxsw_sp_xstats_tail_drop(xstats, i); drops += xstats->wred_drop[i]; - backlog += xstats->backlog[i]; + backlog += mlxsw_sp_xstats_backlog(xstats, i); } drops = drops - stats_base->drops;
@@@ -630,7 -664,7 +680,7 @@@ mlxsw_sp_setup_tc_qdisc_prio_clean_stat
stats_base->drops = 0; for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { - stats_base->drops += xstats->tail_drop[i]; + stats_base->drops += mlxsw_sp_xstats_tail_drop(xstats, i); stats_base->drops += xstats->wred_drop[i]; }
@@@ -647,27 -681,93 +697,93 @@@ static struct mlxsw_sp_qdisc_ops mlxsw_ .clean_stats = mlxsw_sp_setup_tc_qdisc_prio_clean_stats, };
- /* Grafting is not supported in mlxsw. It will result in un-offloading of the - * grafted qdisc as well as the qdisc in the qdisc new location. - * (However, if the graft is to the location where the qdisc is already at, it - * will be ignored completely and won't cause un-offloading). + static int + mlxsw_sp_qdisc_ets_check_params(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, + void *params) + { + struct tc_ets_qopt_offload_replace_params *p = params; + + return __mlxsw_sp_qdisc_ets_check_params(p->bands); + } + + static int + mlxsw_sp_qdisc_ets_replace(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, + void *params) + { + struct tc_ets_qopt_offload_replace_params *p = params; + + return __mlxsw_sp_qdisc_ets_replace(mlxsw_sp_port, p->bands, + p->quanta, p->weights, p->priomap); + } + + static void + mlxsw_sp_qdisc_ets_unoffload(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, + void *params) + { + struct tc_ets_qopt_offload_replace_params *p = params; + + __mlxsw_sp_qdisc_ets_unoffload(mlxsw_sp_port, mlxsw_sp_qdisc, + p->qstats); + } + + static int + mlxsw_sp_qdisc_ets_destroy(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc) + { + return __mlxsw_sp_qdisc_ets_destroy(mlxsw_sp_port); + } + + static struct mlxsw_sp_qdisc_ops mlxsw_sp_qdisc_ops_ets = { + .type = MLXSW_SP_QDISC_ETS, + .check_params = mlxsw_sp_qdisc_ets_check_params, + .replace = mlxsw_sp_qdisc_ets_replace, + .unoffload = mlxsw_sp_qdisc_ets_unoffload, + .destroy = mlxsw_sp_qdisc_ets_destroy, + .get_stats = mlxsw_sp_qdisc_get_prio_stats, + .clean_stats = mlxsw_sp_setup_tc_qdisc_prio_clean_stats, + }; + + /* Linux allows linking of Qdiscs to arbitrary classes (so long as the resulting + * graph is free of cycles). These operations do not change the parent handle + * though, which means it can be incomplete (if there is more than one class + * where the Qdisc in question is grafted) or outright wrong (if the Qdisc was + * linked to a different class and then removed from the original class). + * + * E.g. consider this sequence of operations: + * + * # tc qdisc add dev swp1 root handle 1: prio + * # tc qdisc add dev swp1 parent 1:3 handle 13: red limit 1000000 avpkt 10000 + * RED: set bandwidth to 10Mbit + * # tc qdisc link dev swp1 handle 13: parent 1:2 + * + * At this point, both 1:2 and 1:3 have the same RED Qdisc instance as their + * child. But RED will still only claim that 1:3 is its parent. If it's removed + * from that band, its only parent will be 1:2, but it will continue to claim + * that it is in fact 1:3. + * + * The notification for child Qdisc replace (e.g. TC_RED_REPLACE) comes before + * the notification for parent graft (e.g. TC_PRIO_GRAFT). We take the replace + * notification to offload the child Qdisc, based on its parent handle, and use + * the graft operation to validate that the class where the child is actually + * grafted corresponds to the parent handle. If the two don't match, we + * unoffload the child. */ static int - mlxsw_sp_qdisc_prio_graft(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, - struct tc_prio_qopt_offload_graft_params *p) + __mlxsw_sp_qdisc_ets_graft(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, + u8 band, u32 child_handle) { - int tclass_num = MLXSW_SP_PRIO_BAND_TO_TCLASS(p->band); + int tclass_num = MLXSW_SP_PRIO_BAND_TO_TCLASS(band); struct mlxsw_sp_qdisc *old_qdisc;
- /* Check if the grafted qdisc is already in its "new" location. If so - - * nothing needs to be done. - */ - if (p->band < IEEE_8021QAZ_MAX_TCS && - mlxsw_sp_port->tclass_qdiscs[tclass_num].handle == p->child_handle) + if (band < IEEE_8021QAZ_MAX_TCS && + mlxsw_sp_port->tclass_qdiscs[tclass_num].handle == child_handle) return 0;
- if (!p->child_handle) { + if (!child_handle) { /* This is an invisible FIFO replacing the original Qdisc. * Ignore it--the original Qdisc's destroy will follow. */ @@@ -678,7 -778,7 +794,7 @@@ * unoffload it. */ old_qdisc = mlxsw_sp_qdisc_find_by_handle(mlxsw_sp_port, - p->child_handle); + child_handle); if (old_qdisc) mlxsw_sp_qdisc_destroy(mlxsw_sp_port, old_qdisc);
@@@ -687,6 -787,15 +803,15 @@@ return -EOPNOTSUPP; }
+ static int + mlxsw_sp_qdisc_prio_graft(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc, + struct tc_prio_qopt_offload_graft_params *p) + { + return __mlxsw_sp_qdisc_ets_graft(mlxsw_sp_port, mlxsw_sp_qdisc, + p->band, p->child_handle); + } + int mlxsw_sp_setup_tc_prio(struct mlxsw_sp_port *mlxsw_sp_port, struct tc_prio_qopt_offload *p) { @@@ -720,6 -829,40 +845,40 @@@ } }
+ int mlxsw_sp_setup_tc_ets(struct mlxsw_sp_port *mlxsw_sp_port, + struct tc_ets_qopt_offload *p) + { + struct mlxsw_sp_qdisc *mlxsw_sp_qdisc; + + mlxsw_sp_qdisc = mlxsw_sp_qdisc_find(mlxsw_sp_port, p->parent, true); + if (!mlxsw_sp_qdisc) + return -EOPNOTSUPP; + + if (p->command == TC_ETS_REPLACE) + return mlxsw_sp_qdisc_replace(mlxsw_sp_port, p->handle, + mlxsw_sp_qdisc, + &mlxsw_sp_qdisc_ops_ets, + &p->replace_params); + + if (!mlxsw_sp_qdisc_compare(mlxsw_sp_qdisc, p->handle, + MLXSW_SP_QDISC_ETS)) + return -EOPNOTSUPP; + + switch (p->command) { + case TC_ETS_DESTROY: + return mlxsw_sp_qdisc_destroy(mlxsw_sp_port, mlxsw_sp_qdisc); + case TC_ETS_STATS: + return mlxsw_sp_qdisc_get_stats(mlxsw_sp_port, mlxsw_sp_qdisc, + &p->stats); + case TC_ETS_GRAFT: + return __mlxsw_sp_qdisc_ets_graft(mlxsw_sp_port, mlxsw_sp_qdisc, + p->graft_params.band, + p->graft_params.child_handle); + default: + return -EOPNOTSUPP; + } + } + int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port) { struct mlxsw_sp_qdisc *mlxsw_sp_qdisc; diff --combined drivers/net/ethernet/renesas/sh_eth.c index 3591285250e1,cdd8ab2eb910..c922d7a553f2 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@@ -2204,28 -2204,24 +2204,28 @@@ static size_t __sh_eth_get_regs(struct if (cd->tsu) { add_tsu_reg(ARSTR); add_tsu_reg(TSU_CTRST); - add_tsu_reg(TSU_FWEN0); - add_tsu_reg(TSU_FWEN1); - add_tsu_reg(TSU_FCM); - add_tsu_reg(TSU_BSYSL0); - add_tsu_reg(TSU_BSYSL1); - add_tsu_reg(TSU_PRISL0); - add_tsu_reg(TSU_PRISL1); - add_tsu_reg(TSU_FWSL0); - add_tsu_reg(TSU_FWSL1); + if (cd->dual_port) { + add_tsu_reg(TSU_FWEN0); + add_tsu_reg(TSU_FWEN1); + add_tsu_reg(TSU_FCM); + add_tsu_reg(TSU_BSYSL0); + add_tsu_reg(TSU_BSYSL1); + add_tsu_reg(TSU_PRISL0); + add_tsu_reg(TSU_PRISL1); + add_tsu_reg(TSU_FWSL0); + add_tsu_reg(TSU_FWSL1); + } add_tsu_reg(TSU_FWSLC); - add_tsu_reg(TSU_QTAGM0); - add_tsu_reg(TSU_QTAGM1); - add_tsu_reg(TSU_FWSR); - add_tsu_reg(TSU_FWINMK); - add_tsu_reg(TSU_ADQT0); - add_tsu_reg(TSU_ADQT1); - add_tsu_reg(TSU_VTAG0); - add_tsu_reg(TSU_VTAG1); + if (cd->dual_port) { + add_tsu_reg(TSU_QTAGM0); + add_tsu_reg(TSU_QTAGM1); + add_tsu_reg(TSU_FWSR); + add_tsu_reg(TSU_FWINMK); + add_tsu_reg(TSU_ADQT0); + add_tsu_reg(TSU_ADQT1); + add_tsu_reg(TSU_VTAG0); + add_tsu_reg(TSU_VTAG1); + } add_tsu_reg(TSU_ADSBSY); add_tsu_reg(TSU_TEN); add_tsu_reg(TSU_POST1); @@@ -2482,7 -2478,7 +2482,7 @@@ out_napi_off }
/* Timeout function */ - static void sh_eth_tx_timeout(struct net_device *ndev) + static void sh_eth_tx_timeout(struct net_device *ndev, unsigned int txqueue) { struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_rxdesc *rxdesc; diff --combined drivers/net/ethernet/sgi/ioc3-eth.c index fa1c16f96065,06637b03deed..e61eb891c0f7 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@@ -14,6 -14,7 +14,6 @@@ * o Use prefetching for large packets. What is a good lower limit for * prefetching? * o Use hardware checksums. - * o Convert to using a IOC3 meta driver. * o Which PHYs might possibly be attached to the IOC3 in real live, * which workarounds are required for them? Do we ever have Lucent's? * o For the 2.5 branch kill the mii-tool ioctls. @@@ -27,8 -28,7 +27,8 @@@ #include <linux/mm.h> #include <linux/errno.h> #include <linux/module.h> -#include <linux/pci.h> +#include <linux/init.h> +#include <linux/crc16.h> #include <linux/crc32.h> #include <linux/mii.h> #include <linux/in.h> @@@ -37,22 -37,28 +37,22 @@@ #include <linux/tcp.h> #include <linux/udp.h> #include <linux/gfp.h> - -#ifdef CONFIG_SERIAL_8250 -#include <linux/serial_core.h> -#include <linux/serial_8250.h> -#include <linux/serial_reg.h> -#endif - #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/skbuff.h> #include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/nvmem-consumer.h>
#include <net/ip.h>
-#include <asm/byteorder.h> -#include <asm/pgtable.h> -#include <linux/uaccess.h> -#include <asm/sn/types.h> #include <asm/sn/ioc3.h> #include <asm/pci/bridge.h>
+#define CRC16_INIT 0 +#define CRC16_VALID 0xb001 + /* Number of RX buffers. This is tunable in the range of 16 <= x < 512. * The value must be a power of two. */ @@@ -79,6 -85,7 +79,6 @@@ /* Private per NIC data of the driver. */ struct ioc3_private { struct ioc3_ethregs *regs; - struct ioc3 *all_regs; struct device *dma_dev; u32 *ssram; unsigned long *rxr; /* pointer to receiver ring */ @@@ -97,6 -104,9 +97,6 @@@ spinlock_t ioc3_lock; struct mii_if_info mii;
- struct net_device *dev; - struct pci_dev *pdev; - /* Members used by autonegotiation */ struct timer_list ioc3_timer; }; @@@ -104,7 -114,7 +104,7 @@@ static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void ioc3_set_multicast_list(struct net_device *dev); static netdev_tx_t ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev); - static void ioc3_timeout(struct net_device *dev); + static void ioc3_timeout(struct net_device *dev, unsigned int txqueue); static inline unsigned int ioc3_hash(const unsigned char *addr); static void ioc3_start(struct ioc3_private *ip); static inline void ioc3_stop(struct ioc3_private *ip); @@@ -113,8 -123,10 +113,8 @@@ static int ioc3_alloc_rx_bufs(struct ne static void ioc3_free_rx_bufs(struct ioc3_private *ip); static inline void ioc3_clean_tx_ring(struct ioc3_private *ip);
-static const char ioc3_str[] = "IOC3 Ethernet"; static const struct ethtool_ops ioc3_ethtool_ops;
- static inline unsigned long aligned_rx_skb_addr(unsigned long addr) { return (~addr + 1) & (IOC3_DMA_XFER_LEN - 1UL); @@@ -167,61 -179,225 +167,61 @@@ static inline unsigned long ioc3_map(dm #define ERBAR_VAL 0 #endif
-#define IOC3_SIZE 0x100000 - -static inline u32 mcr_pack(u32 pulse, u32 sample) -{ - return (pulse << 10) | (sample << 2); -} - -static int nic_wait(u32 __iomem *mcr) -{ - u32 m; - - do { - m = readl(mcr); - } while (!(m & 2)); - - return m & 1; -} - -static int nic_reset(u32 __iomem *mcr) -{ - int presence; - - writel(mcr_pack(500, 65), mcr); - presence = nic_wait(mcr); - - writel(mcr_pack(0, 500), mcr); - nic_wait(mcr); - - return presence; -} - -static inline int nic_read_bit(u32 __iomem *mcr) -{ - int result; - - writel(mcr_pack(6, 13), mcr); - result = nic_wait(mcr); - writel(mcr_pack(0, 100), mcr); - nic_wait(mcr); - - return result; -} - -static inline void nic_write_bit(u32 __iomem *mcr, int bit) +static int ioc3eth_nvmem_match(struct device *dev, const void *data) { - if (bit) - writel(mcr_pack(6, 110), mcr); - else - writel(mcr_pack(80, 30), mcr); + const char *name = dev_name(dev); + const char *prefix = data; + int prefix_len;
- nic_wait(mcr); -} - -/* Read a byte from an iButton device - */ -static u32 nic_read_byte(u32 __iomem *mcr) -{ - u32 result = 0; - int i; + prefix_len = strlen(prefix); + if (strlen(name) < (prefix_len + 3)) + return 0;
- for (i = 0; i < 8; i++) - result = (result >> 1) | (nic_read_bit(mcr) << 7); + if (memcmp(prefix, name, prefix_len) != 0) + return 0;
- return result; -} - -/* Write a byte to an iButton device - */ -static void nic_write_byte(u32 __iomem *mcr, int byte) -{ - int i, bit; - - for (i = 8; i; i--) { - bit = byte & 1; - byte >>= 1; - - nic_write_bit(mcr, bit); - } -} - -static u64 nic_find(u32 __iomem *mcr, int *last) -{ - int a, b, index, disc; - u64 address = 0; - - nic_reset(mcr); - /* Search ROM. */ - nic_write_byte(mcr, 0xf0); - - /* Algorithm from ``Book of iButton Standards''. */ - for (index = 0, disc = 0; index < 64; index++) { - a = nic_read_bit(mcr); - b = nic_read_bit(mcr); - - if (a && b) { - pr_warn("NIC search failed (not fatal).\n"); - *last = 0; - return 0; - } - - if (!a && !b) { - if (index == *last) { - address |= 1UL << index; - } else if (index > *last) { - address &= ~(1UL << index); - disc = index; - } else if ((address & (1UL << index)) == 0) { - disc = index; - } - nic_write_bit(mcr, address & (1UL << index)); - continue; - } else { - if (a) - address |= 1UL << index; - else - address &= ~(1UL << index); - nic_write_bit(mcr, a); - continue; - } - } - - *last = disc; - - return address; -} - -static int nic_init(u32 __iomem *mcr) -{ - const char *unknown = "unknown"; - const char *type = unknown; - u8 crc; - u8 serial[6]; - int save = 0, i; - - while (1) { - u64 reg; - - reg = nic_find(mcr, &save); - - switch (reg & 0xff) { - case 0x91: - type = "DS1981U"; - break; - default: - if (save == 0) { - /* Let the caller try again. */ - return -1; - } - continue; - } - - nic_reset(mcr); - - /* Match ROM. */ - nic_write_byte(mcr, 0x55); - for (i = 0; i < 8; i++) - nic_write_byte(mcr, (reg >> (i << 3)) & 0xff); - - reg >>= 8; /* Shift out type. */ - for (i = 0; i < 6; i++) { - serial[i] = reg & 0xff; - reg >>= 8; - } - crc = reg & 0xff; - break; - } - - pr_info("Found %s NIC", type); - if (type != unknown) - pr_cont(" registration number %pM, CRC %02x", serial, crc); - pr_cont(".\n"); + /* found nvmem device which is attached to our ioc3 + * now check for one wire family code 09, 89 and 91 + */ + if (memcmp(name + prefix_len, "09-", 3) == 0) + return 1; + if (memcmp(name + prefix_len, "89-", 3) == 0) + return 1; + if (memcmp(name + prefix_len, "91-", 3) == 0) + return 1;
return 0; }
-/* Read the NIC (Number-In-a-Can) device used to store the MAC address on - * SN0 / SN00 nodeboards and PCI cards. - */ -static void ioc3_get_eaddr_nic(struct ioc3_private *ip) +static int ioc3eth_get_mac_addr(struct resource *res, u8 mac_addr[6]) { - u32 __iomem *mcr = &ip->all_regs->mcr; - int tries = 2; /* There may be some problem with the battery? */ - u8 nic[14]; + struct nvmem_device *nvmem; + char prefix[24]; + u8 prom[16]; + int ret; int i;
- writel(1 << 21, &ip->all_regs->gpcr_s); + snprintf(prefix, sizeof(prefix), "ioc3-%012llx-", + res->start & ~0xffff);
- while (tries--) { - if (!nic_init(mcr)) - break; - udelay(500); - } - - if (tries < 0) { - pr_err("Failed to read MAC address\n"); - return; - } + nvmem = nvmem_device_find(prefix, ioc3eth_nvmem_match); + if (IS_ERR(nvmem)) + return PTR_ERR(nvmem);
- /* Read Memory. */ - nic_write_byte(mcr, 0xf0); - nic_write_byte(mcr, 0x00); - nic_write_byte(mcr, 0x00); + ret = nvmem_device_read(nvmem, 0, 16, prom); + nvmem_device_put(nvmem); + if (ret < 0) + return ret;
- for (i = 13; i >= 0; i--) - nic[i] = nic_read_byte(mcr); + /* check, if content is valid */ + if (prom[0] != 0x0a || + crc16(CRC16_INIT, prom, 13) != CRC16_VALID) + return -EINVAL;
- for (i = 2; i < 8; i++) - ip->dev->dev_addr[i - 2] = nic[i]; -} - -/* Ok, this is hosed by design. It's necessary to know what machine the - * NIC is in in order to know how to read the NIC address. We also have - * to know if it's a PCI card or a NIC in on the node board ... - */ -static void ioc3_get_eaddr(struct ioc3_private *ip) -{ - ioc3_get_eaddr_nic(ip); + for (i = 0; i < 6; i++) + mac_addr[i] = prom[10 - i];
- pr_info("Ethernet address is %pM.\n", ip->dev->dev_addr); + return 0; }
static void __ioc3_set_mac_address(struct net_device *dev) @@@ -594,7 -770,7 +594,7 @@@ static int ioc3_mii_init(struct ioc3_pr u16 word;
for (i = 0; i < 32; i++) { - word = ioc3_mdio_read(ip->dev, i, MII_PHYSID1); + word = ioc3_mdio_read(ip->mii.dev, i, MII_PHYSID1);
if (word != 0xffff && word != 0x0000) { found = 1; @@@ -799,6 -975,12 +799,6 @@@ static int ioc3_open(struct net_device { struct ioc3_private *ip = netdev_priv(dev);
- if (request_irq(dev->irq, ioc3_interrupt, IRQF_SHARED, ioc3_str, dev)) { - netdev_err(dev, "Can't get irq %d\n", dev->irq); - - return -EAGAIN; - } - ip->ehar_h = 0; ip->ehar_l = 0;
@@@ -831,6 -1013,147 +831,6 @@@ static int ioc3_close(struct net_devic return 0; }
-/* MENET cards have four IOC3 chips, which are attached to two sets of - * PCI slot resources each: the primary connections are on slots - * 0..3 and the secondaries are on 4..7 - * - * All four ethernets are brought out to connectors; six serial ports - * (a pair from each of the first three IOC3s) are brought out to - * MiniDINs; all other subdevices are left swinging in the wind, leave - * them disabled. - */ - -static int ioc3_adjacent_is_ioc3(struct pci_dev *pdev, int slot) -{ - struct pci_dev *dev = pci_get_slot(pdev->bus, PCI_DEVFN(slot, 0)); - int ret = 0; - - if (dev) { - if (dev->vendor == PCI_VENDOR_ID_SGI && - dev->device == PCI_DEVICE_ID_SGI_IOC3) - ret = 1; - pci_dev_put(dev); - } - - return ret; -} - -static int ioc3_is_menet(struct pci_dev *pdev) -{ - return !pdev->bus->parent && - ioc3_adjacent_is_ioc3(pdev, 0) && - ioc3_adjacent_is_ioc3(pdev, 1) && - ioc3_adjacent_is_ioc3(pdev, 2); -} - -#ifdef CONFIG_SERIAL_8250 -/* Note about serial ports and consoles: - * For console output, everyone uses the IOC3 UARTA (offset 0x178) - * connected to the master node (look in ip27_setup_console() and - * ip27prom_console_write()). - * - * For serial (/dev/ttyS0 etc), we can not have hardcoded serial port - * addresses on a partitioned machine. Since we currently use the ioc3 - * serial ports, we use dynamic serial port discovery that the serial.c - * driver uses for pci/pnp ports (there is an entry for the SGI ioc3 - * boards in pci_boards[]). Unfortunately, UARTA's pio address is greater - * than UARTB's, although UARTA on o200s has traditionally been known as - * port 0. So, we just use one serial port from each ioc3 (since the - * serial driver adds addresses to get to higher ports). - * - * The first one to do a register_console becomes the preferred console - * (if there is no kernel command line console= directive). /dev/console - * (ie 5, 1) is then "aliased" into the device number returned by the - * "device" routine referred to in this console structure - * (ip27prom_console_dev). - * - * Also look in ip27-pci.c:pci_fixup_ioc3() for some comments on working - * around ioc3 oddities in this respect. - * - * The IOC3 serials use a 22MHz clock rate with an additional divider which - * can be programmed in the SCR register if the DLAB bit is set. - * - * Register to interrupt zero because we share the interrupt with - * the serial driver which we don't properly support yet. - * - * Can't use UPF_IOREMAP as the whole of IOC3 resources have already been - * registered. - */ -static void ioc3_8250_register(struct ioc3_uartregs __iomem *uart) -{ -#define COSMISC_CONSTANT 6 - - struct uart_8250_port port = { - .port = { - .irq = 0, - .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, - .iotype = UPIO_MEM, - .regshift = 0, - .uartclk = (22000000 << 1) / COSMISC_CONSTANT, - - .membase = (unsigned char __iomem *)uart, - .mapbase = (unsigned long)uart, - } - }; - unsigned char lcr; - - lcr = readb(&uart->iu_lcr); - writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr); - writeb(COSMISC_CONSTANT, &uart->iu_scr); - writeb(lcr, &uart->iu_lcr); - readb(&uart->iu_lcr); - serial8250_register_8250_port(&port); -} - -static void ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3) -{ - u32 sio_iec; - - /* We need to recognice and treat the fourth MENET serial as it - * does not have an SuperIO chip attached to it, therefore attempting - * to access it will result in bus errors. We call something an - * MENET if PCI slot 0, 1, 2 and 3 of a master PCI bus all have an IOC3 - * in it. This is paranoid but we want to avoid blowing up on a - * showhorn PCI box that happens to have 4 IOC3 cards in it so it's - * not paranoid enough ... - */ - if (ioc3_is_menet(pdev) && PCI_SLOT(pdev->devfn) == 3) - return; - - /* Switch IOC3 to PIO mode. It probably already was but let's be - * paranoid - */ - writel(GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL, &ioc3->gpcr_s); - readl(&ioc3->gpcr_s); - writel(0, &ioc3->gppr[6]); - readl(&ioc3->gppr[6]); - writel(0, &ioc3->gppr[7]); - readl(&ioc3->gppr[7]); - writel(readl(&ioc3->port_a.sscr) & ~SSCR_DMA_EN, &ioc3->port_a.sscr); - readl(&ioc3->port_a.sscr); - writel(readl(&ioc3->port_b.sscr) & ~SSCR_DMA_EN, &ioc3->port_b.sscr); - readl(&ioc3->port_b.sscr); - /* Disable all SA/B interrupts except for SA/B_INT in SIO_IEC. */ - sio_iec = readl(&ioc3->sio_iec); - sio_iec &= ~(SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL | - SIO_IR_SA_RX_HIGH | SIO_IR_SA_RX_TIMER | - SIO_IR_SA_DELTA_DCD | SIO_IR_SA_DELTA_CTS | - SIO_IR_SA_TX_EXPLICIT | SIO_IR_SA_MEMERR); - sio_iec |= SIO_IR_SA_INT; - sio_iec &= ~(SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL | - SIO_IR_SB_RX_HIGH | SIO_IR_SB_RX_TIMER | - SIO_IR_SB_DELTA_DCD | SIO_IR_SB_DELTA_CTS | - SIO_IR_SB_TX_EXPLICIT | SIO_IR_SB_MEMERR); - sio_iec |= SIO_IR_SB_INT; - writel(sio_iec, &ioc3->sio_iec); - writel(0, &ioc3->port_a.sscr); - writel(0, &ioc3->port_b.sscr); - - ioc3_8250_register(&ioc3->sregs.uarta); - ioc3_8250_register(&ioc3->sregs.uartb); -} -#endif - static const struct net_device_ops ioc3_netdev_ops = { .ndo_open = ioc3_open, .ndo_stop = ioc3_close, @@@ -843,52 -1166,61 +843,52 @@@ .ndo_set_mac_address = ioc3_set_mac_address, };
-static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int ioc3eth_probe(struct platform_device *pdev) { - unsigned int sw_physid1, sw_physid2; - struct net_device *dev = NULL; + u32 sw_physid1, sw_physid2, vendor, model, rev; struct ioc3_private *ip; - struct ioc3 *ioc3; - unsigned long ioc3_base, ioc3_size; - u32 vendor, model, rev; + struct net_device *dev; + struct resource *regs; + u8 mac_addr[6]; int err;
- /* Configure DMA attributes. */ - err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); - if (err) { - pr_err("%s: No usable DMA configuration, aborting.\n", - pci_name(pdev)); - goto out; - } - - if (pci_enable_device(pdev)) - return -ENODEV; + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + /* get mac addr from one wire prom */ + if (ioc3eth_get_mac_addr(regs, mac_addr)) + return -EPROBE_DEFER; /* not available yet */
dev = alloc_etherdev(sizeof(struct ioc3_private)); - if (!dev) { - err = -ENOMEM; - goto out_disable; - } - - err = pci_request_regions(pdev, "ioc3"); - if (err) - goto out_free; + if (!dev) + return -ENOMEM;
SET_NETDEV_DEV(dev, &pdev->dev);
ip = netdev_priv(dev); - ip->dev = dev; - ip->dma_dev = &pdev->dev; - - dev->irq = pdev->irq; + ip->dma_dev = pdev->dev.parent; + ip->regs = devm_platform_ioremap_resource(pdev, 0); + if (!ip->regs) { + err = -ENOMEM; + goto out_free; + }
- ioc3_base = pci_resource_start(pdev, 0); - ioc3_size = pci_resource_len(pdev, 0); - ioc3 = (struct ioc3 *)ioremap(ioc3_base, ioc3_size); - if (!ioc3) { - pr_err("ioc3eth(%s): ioremap failed, goodbye.\n", - pci_name(pdev)); + ip->ssram = devm_platform_ioremap_resource(pdev, 1); + if (!ip->ssram) { err = -ENOMEM; - goto out_res; + goto out_free; } - ip->regs = &ioc3->eth; - ip->ssram = ioc3->ssram; - ip->all_regs = ioc3;
-#ifdef CONFIG_SERIAL_8250 - ioc3_serial_probe(pdev, ioc3); -#endif + dev->irq = platform_get_irq(pdev, 0); + if (dev->irq < 0) { + err = dev->irq; + goto out_free; + } + + if (devm_request_irq(&pdev->dev, dev->irq, ioc3_interrupt, + IRQF_SHARED, "ioc3-eth", dev)) { + dev_err(&pdev->dev, "Can't get irq %d\n", dev->irq); + err = -ENODEV; + goto out_free; + }
spin_lock_init(&ip->ioc3_lock); timer_setup(&ip->ioc3_timer, ioc3_timer, 0); @@@ -918,6 -1250,8 +918,6 @@@
ioc3_init(dev);
- ip->pdev = pdev; - ip->mii.phy_id_mask = 0x1f; ip->mii.reg_num_mask = 0x1f; ip->mii.dev = dev; @@@ -927,14 -1261,15 +927,14 @@@ ioc3_mii_init(ip);
if (ip->mii.phy_id == -1) { - pr_err("ioc3-eth(%s): Didn't find a PHY, goodbye.\n", - pci_name(pdev)); + netdev_err(dev, "Didn't find a PHY, goodbye.\n"); err = -ENODEV; goto out_stop; }
ioc3_mii_start(ip); ioc3_ssram_disc(ip); - ioc3_get_eaddr(ip); + memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
/* The IOC3-specific entries in the device structure. */ dev->watchdog_timeo = 5 * HZ; @@@ -971,14 -1306,21 +971,14 @@@ out_stop if (ip->tx_ring) dma_free_coherent(ip->dma_dev, TX_RING_SIZE, ip->tx_ring, ip->txr_dma); -out_res: - pci_release_regions(pdev); out_free: free_netdev(dev); -out_disable: - /* We should call pci_disable_device(pdev); here if the IOC3 wasn't - * such a weird device ... - */ -out: return err; }
-static void ioc3_remove_one(struct pci_dev *pdev) +static int ioc3eth_remove(struct platform_device *pdev) { - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = platform_get_drvdata(pdev); struct ioc3_private *ip = netdev_priv(dev);
dma_free_coherent(ip->dma_dev, RX_RING_SIZE, ip->rxr, ip->rxr_dma); @@@ -986,11 -1328,27 +986,11 @@@
unregister_netdev(dev); del_timer_sync(&ip->ioc3_timer); - - iounmap(ip->all_regs); - pci_release_regions(pdev); free_netdev(dev); - /* We should call pci_disable_device(pdev); here if the IOC3 wasn't - * such a weird device ... - */ -}
-static const struct pci_device_id ioc3_pci_tbl[] = { - { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, ioc3_pci_tbl); + return 0; +}
-static struct pci_driver ioc3_driver = { - .name = "ioc3-eth", - .id_table = ioc3_pci_tbl, - .probe = ioc3_probe, - .remove = ioc3_remove_one, -};
static netdev_tx_t ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@@ -1121,7 -1479,7 +1121,7 @@@ drop_packet return NETDEV_TX_OK; }
- static void ioc3_timeout(struct net_device *dev) + static void ioc3_timeout(struct net_device *dev, unsigned int txqueue) { struct ioc3_private *ip = netdev_priv(dev);
@@@ -1172,10 -1530,11 +1172,10 @@@ static inline unsigned int ioc3_hash(co static void ioc3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct ioc3_private *ip = netdev_priv(dev); - strlcpy(info->driver, IOC3_NAME, sizeof(info->driver)); strlcpy(info->version, IOC3_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(ip->pdev), sizeof(info->bus_info)); + strlcpy(info->bus_info, pci_name(to_pci_dev(dev->dev.parent)), + sizeof(info->bus_info)); }
static int ioc3_get_link_ksettings(struct net_device *dev, @@@ -1287,16 -1646,7 +1287,16 @@@ static void ioc3_set_multicast_list(str spin_unlock_irq(&ip->ioc3_lock); }
-module_pci_driver(ioc3_driver); +static struct platform_driver ioc3eth_driver = { + .probe = ioc3eth_probe, + .remove = ioc3eth_remove, + .driver = { + .name = "ioc3-eth", + } +}; + +module_platform_driver(ioc3eth_driver); + MODULE_AUTHOR("Ralf Baechle ralf@linux-mips.org"); MODULE_DESCRIPTION("SGI IOC3 Ethernet driver"); MODULE_LICENSE("GPL"); diff --combined drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index 450d7dac3ea6,5a3aea628fc2..2aba2673d6c3 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@@ -14,6 -14,7 +14,7 @@@ #include <linux/phy.h> #include <linux/udp.h> #include <net/pkt_cls.h> + #include <net/pkt_sched.h> #include <net/tcp.h> #include <net/udp.h> #include <net/tc_act/tc_gact.h> @@@ -50,6 -51,7 +51,7 @@@ struct stmmac_packet_attrs u8 id; int sarc; u16 queue_mapping; + u64 timestamp; };
static u8 stmmac_test_next_id; @@@ -80,7 -82,7 +82,7 @@@ static struct sk_buff *stmmac_test_get_ if (attr->max_size && (attr->max_size > size)) size = attr->max_size;
- skb = netdev_alloc_skb_ip_align(priv->dev, size); + skb = netdev_alloc_skb(priv->dev, size); if (!skb) return NULL;
@@@ -208,6 -210,9 +210,9 @@@ skb->pkt_type = PACKET_HOST; skb->dev = priv->dev;
+ if (attr->timestamp) + skb->tstamp = ns_to_ktime(attr->timestamp); + return skb; }
@@@ -244,8 -249,6 +249,8 @@@ static int stmmac_test_loopback_validat struct net_device *orig_ndev) { struct stmmac_test_priv *tpriv = pt->af_packet_priv; + unsigned char *src = tpriv->packet->src; + unsigned char *dst = tpriv->packet->dst; struct stmmachdr *shdr; struct ethhdr *ehdr; struct udphdr *uhdr; @@@ -262,15 -265,15 +267,15 @@@ goto out;
ehdr = (struct ethhdr *)skb_mac_header(skb); - if (tpriv->packet->dst) { - if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst)) + if (dst) { + if (!ether_addr_equal_unaligned(ehdr->h_dest, dst)) goto out; } if (tpriv->packet->sarc) { - if (!ether_addr_equal(ehdr->h_source, ehdr->h_dest)) + if (!ether_addr_equal_unaligned(ehdr->h_source, ehdr->h_dest)) goto out; - } else if (tpriv->packet->src) { - if (!ether_addr_equal(ehdr->h_source, tpriv->packet->src)) + } else if (src) { + if (!ether_addr_equal_unaligned(ehdr->h_source, src)) goto out; }
@@@ -341,8 -344,7 +346,7 @@@ static int __stmmac_test_loopback(struc goto cleanup; }
- skb_set_queue_mapping(skb, attr->queue_mapping); - ret = dev_queue_xmit(skb); + ret = dev_direct_xmit(skb, attr->queue_mapping); if (ret) goto cleanup;
@@@ -716,7 -718,7 +720,7 @@@ static int stmmac_test_flowctrl_validat struct ethhdr *ehdr;
ehdr = (struct ethhdr *)skb_mac_header(skb); - if (!ether_addr_equal(ehdr->h_source, orig_ndev->dev_addr)) + if (!ether_addr_equal_unaligned(ehdr->h_source, orig_ndev->dev_addr)) goto out; if (ehdr->h_proto != htons(ETH_P_PAUSE)) goto out; @@@ -853,16 -855,12 +857,16 @@@ static int stmmac_test_vlan_validate(st if (tpriv->vlan_id) { if (skb->vlan_proto != htons(proto)) goto out; - if (skb->vlan_tci != tpriv->vlan_id) + if (skb->vlan_tci != tpriv->vlan_id) { + /* Means filter did not work. */ + tpriv->ok = false; + complete(&tpriv->comp); goto out; + } }
ehdr = (struct ethhdr *)skb_mac_header(skb); - if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst)) + if (!ether_addr_equal_unaligned(ehdr->h_dest, tpriv->packet->dst)) goto out;
ihdr = ip_hdr(skb); @@@ -932,8 -930,7 +936,7 @@@ static int __stmmac_test_vlanfilt(struc goto vlan_del; }
- skb_set_queue_mapping(skb, 0); - ret = dev_queue_xmit(skb); + ret = dev_direct_xmit(skb, 0); if (ret) goto vlan_del;
@@@ -971,9 -968,6 +974,9 @@@ static int stmmac_test_vlanfilt_perfect { int ret, prev_cap = priv->dma_cap.vlhash;
+ if (!(priv->dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) + return -EOPNOTSUPP; + priv->dma_cap.vlhash = 0; ret = __stmmac_test_vlanfilt(priv); priv->dma_cap.vlhash = prev_cap; @@@ -1027,8 -1021,7 +1030,7 @@@ static int __stmmac_test_dvlanfilt(stru goto vlan_del; }
- skb_set_queue_mapping(skb, 0); - ret = dev_queue_xmit(skb); + ret = dev_direct_xmit(skb, 0); if (ret) goto vlan_del;
@@@ -1066,9 -1059,6 +1068,9 @@@ static int stmmac_test_dvlanfilt_perfec { int ret, prev_cap = priv->dma_cap.vlhash;
+ if (!(priv->dev->features & NETIF_F_HW_VLAN_STAG_FILTER)) + return -EOPNOTSUPP; + priv->dma_cap.vlhash = 0; ret = __stmmac_test_dvlanfilt(priv); priv->dma_cap.vlhash = prev_cap; @@@ -1298,8 -1288,7 +1300,7 @@@ static int stmmac_test_vlanoff_common(s __vlan_hwaccel_put_tag(skb, htons(proto), tpriv->vlan_id); skb->protocol = htons(proto);
- skb_set_queue_mapping(skb, 0); - ret = dev_queue_xmit(skb); + ret = dev_direct_xmit(skb, 0); if (ret) goto vlan_del;
@@@ -1335,19 -1324,16 +1336,19 @@@ static int __stmmac_test_l3filt(struct struct stmmac_packet_attrs attr = { }; struct flow_dissector *dissector; struct flow_cls_offload *cls; + int ret, old_enable = 0; struct flow_rule *rule; - int ret;
if (!tc_can_offload(priv->dev)) return -EOPNOTSUPP; if (!priv->dma_cap.l3l4fnum) return -EOPNOTSUPP; - if (priv->rss.enable) + if (priv->rss.enable) { + old_enable = priv->rss.enable; + priv->rss.enable = false; stmmac_rss_configure(priv, priv->hw, NULL, priv->plat->rx_queues_to_use); + }
dissector = kzalloc(sizeof(*dissector), GFP_KERNEL); if (!dissector) { @@@ -1414,8 -1400,7 +1415,8 @@@ cleanup_cls cleanup_dissector: kfree(dissector); cleanup_rss: - if (priv->rss.enable) { + if (old_enable) { + priv->rss.enable = old_enable; stmmac_rss_configure(priv, priv->hw, &priv->rss, priv->plat->rx_queues_to_use); } @@@ -1460,19 -1445,16 +1461,19 @@@ static int __stmmac_test_l4filt(struct struct stmmac_packet_attrs attr = { }; struct flow_dissector *dissector; struct flow_cls_offload *cls; + int ret, old_enable = 0; struct flow_rule *rule; - int ret;
if (!tc_can_offload(priv->dev)) return -EOPNOTSUPP; if (!priv->dma_cap.l3l4fnum) return -EOPNOTSUPP; - if (priv->rss.enable) + if (priv->rss.enable) { + old_enable = priv->rss.enable; + priv->rss.enable = false; stmmac_rss_configure(priv, priv->hw, NULL, priv->plat->rx_queues_to_use); + }
dissector = kzalloc(sizeof(*dissector), GFP_KERNEL); if (!dissector) { @@@ -1544,8 -1526,7 +1545,8 @@@ cleanup_cls cleanup_dissector: kfree(dissector); cleanup_rss: - if (priv->rss.enable) { + if (old_enable) { + priv->rss.enable = old_enable; stmmac_rss_configure(priv, priv->hw, &priv->rss, priv->plat->rx_queues_to_use); } @@@ -1598,7 -1579,7 +1599,7 @@@ static int stmmac_test_arp_validate(str struct arphdr *ahdr;
ehdr = (struct ethhdr *)skb_mac_header(skb); - if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->src)) + if (!ether_addr_equal_unaligned(ehdr->h_dest, tpriv->packet->src)) goto out;
ahdr = arp_hdr(skb); @@@ -1659,8 -1640,7 +1660,7 @@@ static int stmmac_test_arpoffload(struc if (ret) goto cleanup;
- skb_set_queue_mapping(skb, 0); - ret = dev_queue_xmit(skb); + ret = dev_direct_xmit(skb, 0); if (ret) goto cleanup_promisc;
@@@ -1748,6 -1728,68 +1748,68 @@@ static int stmmac_test_sph(struct stmma return 0; }
+ static int stmmac_test_tbs(struct stmmac_priv *priv) + { + #define STMMAC_TBS_LT_OFFSET (500 * 1000 * 1000) /* 500 ms*/ + struct stmmac_packet_attrs attr = { }; + struct tc_etf_qopt_offload qopt; + u64 start_time, curr_time = 0; + unsigned long flags; + int ret, i; + + if (!priv->hwts_tx_en) + return -EOPNOTSUPP; + + /* Find first TBS enabled Queue, if any */ + for (i = 0; i < priv->plat->tx_queues_to_use; i++) + if (priv->tx_queue[i].tbs & STMMAC_TBS_AVAIL) + break; + + if (i >= priv->plat->tx_queues_to_use) + return -EOPNOTSUPP; + + qopt.enable = true; + qopt.queue = i; + + ret = stmmac_tc_setup_etf(priv, priv, &qopt); + if (ret) + return ret; + + spin_lock_irqsave(&priv->ptp_lock, flags); + stmmac_get_systime(priv, priv->ptpaddr, &curr_time); + spin_unlock_irqrestore(&priv->ptp_lock, flags); + + if (!curr_time) { + ret = -EOPNOTSUPP; + goto fail_disable; + } + + start_time = curr_time; + curr_time += STMMAC_TBS_LT_OFFSET; + + attr.dst = priv->dev->dev_addr; + attr.timestamp = curr_time; + attr.timeout = nsecs_to_jiffies(2 * STMMAC_TBS_LT_OFFSET); + attr.queue_mapping = i; + + ret = __stmmac_test_loopback(priv, &attr); + if (ret) + goto fail_disable; + + /* Check if expected time has elapsed */ + spin_lock_irqsave(&priv->ptp_lock, flags); + stmmac_get_systime(priv, priv->ptpaddr, &curr_time); + spin_unlock_irqrestore(&priv->ptp_lock, flags); + + if ((curr_time - start_time) < STMMAC_TBS_LT_OFFSET) + ret = -EINVAL; + + fail_disable: + qopt.enable = false; + stmmac_tc_setup_etf(priv, priv, &qopt); + return ret; + } + #define STMMAC_LOOPBACK_NONE 0 #define STMMAC_LOOPBACK_MAC 1 #define STMMAC_LOOPBACK_PHY 2 @@@ -1881,6 -1923,10 +1943,10 @@@ static const struct stmmac_test .name = "Split Header ", .lb = STMMAC_LOOPBACK_PHY, .fn = stmmac_test_sph, + }, { + .name = "TBS (ETF Scheduler) ", + .lb = STMMAC_LOOPBACK_PHY, + .fn = stmmac_test_tbs, }, };
@@@ -1889,7 -1935,6 +1955,6 @@@ void stmmac_selftest_run(struct net_dev { struct stmmac_priv *priv = netdev_priv(dev); int count = stmmac_selftest_get_count(priv); - int carrier = netif_carrier_ok(dev); int i, ret;
memset(buf, 0, sizeof(*buf) * count); @@@ -1899,15 -1944,12 +1964,12 @@@ netdev_err(priv->dev, "Only offline tests are supported\n"); etest->flags |= ETH_TEST_FL_FAILED; return; - } else if (!carrier) { + } else if (!netif_carrier_ok(dev)) { netdev_err(priv->dev, "You need valid Link to execute tests\n"); etest->flags |= ETH_TEST_FL_FAILED; return; }
- /* We don't want extra traffic */ - netif_carrier_off(dev); - /* Wait for queues drain */ msleep(200);
@@@ -1962,10 -2004,6 +2024,6 @@@ break; } } - - /* Restart everything */ - if (carrier) - netif_carrier_on(dev); }
void stmmac_selftest_get_strings(struct stmmac_priv *priv, u8 *data) diff --combined drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 9ffae12a2122,a4ce165af36b..7a01dee2f9a8 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@@ -577,10 -577,6 +577,10 @@@ static int tc_setup_cls(struct stmmac_p { int ret = 0;
+ /* When RSS is enabled, the filtering will be bypassed */ + if (priv->rss.enable) + return -EBUSY; + switch (cls->command) { case FLOW_CLS_REPLACE: ret = tc_add_flow(priv, cls); @@@ -595,9 -591,167 +595,167 @@@ return ret; }
+ static int tc_setup_taprio(struct stmmac_priv *priv, + struct tc_taprio_qopt_offload *qopt) + { + u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep; + struct plat_stmmacenet_data *plat = priv->plat; + struct timespec64 time; + bool fpe = false; + int i, ret = 0; + u64 ctr; + + if (!priv->dma_cap.estsel) + return -EOPNOTSUPP; + + switch (wid) { + case 0x1: + wid = 16; + break; + case 0x2: + wid = 20; + break; + case 0x3: + wid = 24; + break; + default: + return -EOPNOTSUPP; + } + + switch (dep) { + case 0x1: + dep = 64; + break; + case 0x2: + dep = 128; + break; + case 0x3: + dep = 256; + break; + case 0x4: + dep = 512; + break; + case 0x5: + dep = 1024; + break; + default: + return -EOPNOTSUPP; + } + + if (!qopt->enable) + goto disable; + if (qopt->num_entries >= dep) + return -EINVAL; + if (!qopt->base_time) + return -ERANGE; + if (!qopt->cycle_time) + return -ERANGE; + + if (!plat->est) { + plat->est = devm_kzalloc(priv->device, sizeof(*plat->est), + GFP_KERNEL); + if (!plat->est) + return -ENOMEM; + } else { + memset(plat->est, 0, sizeof(*plat->est)); + } + + size = qopt->num_entries; + + priv->plat->est->gcl_size = size; + priv->plat->est->enable = qopt->enable; + + for (i = 0; i < size; i++) { + s64 delta_ns = qopt->entries[i].interval; + u32 gates = qopt->entries[i].gate_mask; + + if (delta_ns > GENMASK(wid, 0)) + return -ERANGE; + if (gates > GENMASK(31 - wid, 0)) + return -ERANGE; + + switch (qopt->entries[i].command) { + case TC_TAPRIO_CMD_SET_GATES: + if (fpe) + return -EINVAL; + break; + case TC_TAPRIO_CMD_SET_AND_HOLD: + gates |= BIT(0); + fpe = true; + break; + case TC_TAPRIO_CMD_SET_AND_RELEASE: + gates &= ~BIT(0); + fpe = true; + break; + default: + return -EOPNOTSUPP; + } + + priv->plat->est->gcl[i] = delta_ns | (gates << wid); + } + + /* Adjust for real system time */ + time = ktime_to_timespec64(qopt->base_time); + priv->plat->est->btr[0] = (u32)time.tv_nsec; + priv->plat->est->btr[1] = (u32)time.tv_sec; + + ctr = qopt->cycle_time; + priv->plat->est->ctr[0] = do_div(ctr, NSEC_PER_SEC); + priv->plat->est->ctr[1] = (u32)ctr; + + if (fpe && !priv->dma_cap.fpesel) + return -EOPNOTSUPP; + + ret = stmmac_fpe_configure(priv, priv->ioaddr, + priv->plat->tx_queues_to_use, + priv->plat->rx_queues_to_use, fpe); + if (ret && fpe) { + netdev_err(priv->dev, "failed to enable Frame Preemption\n"); + return ret; + } + + ret = stmmac_est_configure(priv, priv->ioaddr, priv->plat->est, + priv->plat->clk_ptp_rate); + if (ret) { + netdev_err(priv->dev, "failed to configure EST\n"); + goto disable; + } + + netdev_info(priv->dev, "configured EST\n"); + return 0; + + disable: + priv->plat->est->enable = false; + stmmac_est_configure(priv, priv->ioaddr, priv->plat->est, + priv->plat->clk_ptp_rate); + return ret; + } + + static int tc_setup_etf(struct stmmac_priv *priv, + struct tc_etf_qopt_offload *qopt) + { + if (!priv->dma_cap.tbssel) + return -EOPNOTSUPP; + if (qopt->queue >= priv->plat->tx_queues_to_use) + return -EINVAL; + if (!(priv->tx_queue[qopt->queue].tbs & STMMAC_TBS_AVAIL)) + return -EINVAL; + + if (qopt->enable) + priv->tx_queue[qopt->queue].tbs |= STMMAC_TBS_EN; + else + priv->tx_queue[qopt->queue].tbs &= ~STMMAC_TBS_EN; + + netdev_info(priv->dev, "%s ETF for Queue %d\n", + qopt->enable ? "enabled" : "disabled", qopt->queue); + return 0; + } + const struct stmmac_tc_ops dwmac510_tc_ops = { .init = tc_init, .setup_cls_u32 = tc_setup_cls_u32, .setup_cbs = tc_setup_cbs, .setup_cls = tc_setup_cls, + .setup_taprio = tc_setup_taprio, + .setup_etf = tc_setup_etf, }; diff --combined drivers/net/macvlan.c index c5bf61565726,67a830dd0d30..81aa7adf4801 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@@ -259,7 -259,7 +259,7 @@@ static void macvlan_broadcast(struct sk struct net_device *src, enum macvlan_mode mode) { - const struct ethhdr *eth = skb_eth_hdr(skb); + const struct ethhdr *eth = eth_hdr(skb); const struct macvlan_dev *vlan; struct sk_buff *nskb; unsigned int i; @@@ -513,11 -513,10 +513,11 @@@ static int macvlan_queue_xmit(struct sk const struct macvlan_dev *dest;
if (vlan->mode == MACVLAN_MODE_BRIDGE) { - const struct ethhdr *eth = (void *)skb->data; + const struct ethhdr *eth = skb_eth_hdr(skb);
/* send to other bridge ports directly */ if (is_multicast_ether_addr(eth->h_dest)) { + skb_reset_mac_header(skb); macvlan_broadcast(skb, port, dev, MACVLAN_MODE_BRIDGE); goto xmit_world; } @@@ -1037,8 -1036,8 +1037,8 @@@ static int macvlan_ethtool_get_ts_info( const struct ethtool_ops *ops = real_dev->ethtool_ops; struct phy_device *phydev = real_dev->phydev;
- if (phydev && phydev->drv && phydev->drv->ts_info) { - return phydev->drv->ts_info(phydev, info); + if (phy_has_tsinfo(phydev)) { + return phy_ts_info(phydev, info); } else if (ops->get_ts_info) { return ops->get_ts_info(real_dev, info); } else { diff --combined drivers/net/netdevsim/dev.c index 4b39aba2e9c4,c572960bb54e..b53fbc06e104 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@@ -53,7 -53,7 +53,7 @@@ static ssize_t nsim_dev_take_snapshot_w
get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE);
- id = devlink_region_shapshot_id_get(priv_to_devlink(nsim_dev)); + id = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev)); err = devlink_region_snapshot_create(nsim_dev->dummy_region, dummy_data, id, kfree); if (err) { @@@ -270,7 -270,7 +270,7 @@@ struct nsim_trap_data };
/* All driver-specific traps must be documented in - * Documentation/networking/devlink-trap-netdevsim.rst + * Documentation/networking/devlink/netdevsim.rst */ enum { NSIM_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX, diff --combined drivers/net/phy/Kconfig index 8dc461f7574b,ac82ff959b7c..6b5ee26795a2 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@@ -324,6 -324,12 +324,12 @@@ config BROADCOM_PH Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464, BCM5481, BCM54810 and BCM5482 PHYs.
+ config BCM84881_PHY + bool "Broadcom BCM84881 PHY" + depends on PHYLIB=y + ---help--- + Support the Broadcom BCM84881 PHY. + config CICADA_PHY tristate "Cicada PHYs" ---help--- @@@ -340,14 -346,14 +346,14 @@@ config DAVICOM_PH Currently supports dm9161e and dm9131
config DP83822_PHY - tristate "Texas Instruments DP83822 PHY" + tristate "Texas Instruments DP83822/825 PHYs" ---help--- - Supports the DP83822 PHY. + Supports the DP83822 and DP83825I PHYs.
config DP83TC811_PHY - tristate "Texas Instruments DP83TC822 PHY" + tristate "Texas Instruments DP83TC811 PHY" ---help--- - Supports the DP83TC822 PHY. + Supports the DP83TC811 PHY.
config DP83848_PHY tristate "Texas Instruments DP83848 PHY" @@@ -431,6 -437,9 +437,9 @@@ config MICROCHIP_T1_PH
config MICROSEMI_PHY tristate "Microsemi PHYs" + depends on MACSEC || MACSEC=n + select CRYPTO_AES + select CRYPTO_ECB ---help--- Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
diff --combined drivers/net/usb/lan78xx.c index 75bdfae5f3e2,d3239b49c3bb..c391f2521ba1 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@@ -3660,7 -3660,7 +3660,7 @@@ static void lan78xx_disconnect(struct u usb_put_dev(udev); }
- static void lan78xx_tx_timeout(struct net_device *net) + static void lan78xx_tx_timeout(struct net_device *net, unsigned int txqueue) { struct lan78xx_net *dev = netdev_priv(net);
@@@ -3750,7 -3750,6 +3750,7 @@@ static int lan78xx_probe(struct usb_int
/* MTU range: 68 - 9000 */ netdev->max_mtu = MAX_SINGLE_PACKET_SIZE; + netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER);
dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0; dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1; diff --combined drivers/net/usb/r8152.c index 031cb8fff909,fe22a582373b..36051288034a --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@@ -1897,8 -1897,8 +1897,8 @@@ static void r8152_csum_workaround(struc { if (skb_shinfo(skb)->gso_size) { netdev_features_t features = tp->netdev->features; + struct sk_buff *segs, *seg, *next; struct sk_buff_head seg_list; - struct sk_buff *segs, *nskb;
features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6); segs = skb_gso_segment(skb, features); @@@ -1907,12 -1907,10 +1907,10 @@@
__skb_queue_head_init(&seg_list);
- do { - nskb = segs; - segs = segs->next; - nskb->next = NULL; - __skb_queue_tail(&seg_list, nskb); - } while (segs); + skb_list_walk_safe(segs, seg, next) { + skb_mark_not_on_list(seg); + __skb_queue_tail(&seg_list, seg); + }
skb_queue_splice(&seg_list, list); dev_kfree_skb(skb); @@@ -2507,7 -2505,7 +2505,7 @@@ static void rtl_drop_queued_tx(struct r } }
- static void rtl8152_tx_timeout(struct net_device *netdev) + static void rtl8152_tx_timeout(struct net_device *netdev, unsigned int txqueue) { struct r8152 *tp = netdev_priv(netdev);
@@@ -6597,9 -6595,6 +6595,9 @@@ static int rtl8152_probe(struct usb_int return -ENODEV; }
+ if (intf->cur_altsetting->desc.bNumEndpoints < 3) + return -ENODEV; + usb_reset_device(udev); netdev = alloc_etherdev(sizeof(struct r8152)); if (!netdev) { diff --combined drivers/net/wan/fsl_ucc_hdlc.c index 76333b36f288,c28f8409067e..9edd94679283 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@@ -73,7 -73,7 +73,7 @@@ static struct ucc_tdm_info utdm_primary }, };
-static struct ucc_tdm_info utdm_info[MAX_HDLC_NUM]; +static struct ucc_tdm_info utdm_info[UCC_MAX_NUM];
static int uhdlc_init(struct ucc_hdlc_private *priv) { @@@ -84,8 -84,8 +84,8 @@@ int ret, i; void *bd_buffer; dma_addr_t bd_dma_addr; - u32 riptr; - u32 tiptr; + s32 riptr; + s32 tiptr; u32 gumr;
ut_info = priv->ut_info; @@@ -195,7 -195,7 +195,7 @@@ priv->ucc_pram_offset = qe_muram_alloc(sizeof(struct ucc_hdlc_param), ALIGNMENT_OF_UCC_HDLC_PRAM);
- if (IS_ERR_VALUE(priv->ucc_pram_offset)) { + if (priv->ucc_pram_offset < 0) { dev_err(priv->dev, "Can not allocate MURAM for hdlc parameter.\n"); ret = -ENOMEM; goto free_tx_bd; @@@ -233,23 -233,18 +233,23 @@@
/* Alloc riptr, tiptr */ riptr = qe_muram_alloc(32, 32); - if (IS_ERR_VALUE(riptr)) { + if (riptr < 0) { dev_err(priv->dev, "Cannot allocate MURAM mem for Receive internal temp data pointer\n"); ret = -ENOMEM; goto free_tx_skbuff; }
tiptr = qe_muram_alloc(32, 32); - if (IS_ERR_VALUE(tiptr)) { + if (tiptr < 0) { dev_err(priv->dev, "Cannot allocate MURAM mem for Transmit internal temp data pointer\n"); ret = -ENOMEM; goto free_riptr; } + if (riptr != (u16)riptr || tiptr != (u16)tiptr) { + dev_err(priv->dev, "MURAM allocation out of addressable range\n"); + ret = -ENOMEM; + goto free_tiptr; + }
/* Set RIPTR, TIPTR */ iowrite16be(riptr, &priv->ucc_pram->riptr); @@@ -628,8 -623,8 +628,8 @@@ static int ucc_hdlc_poll(struct napi_st
if (howmany < budget) { napi_complete_done(napi, howmany); - qe_setbits32(priv->uccf->p_uccm, - (UCCE_HDLC_RX_EVENTS | UCCE_HDLC_TX_EVENTS) << 16); + qe_setbits_be32(priv->uccf->p_uccm, + (UCCE_HDLC_RX_EVENTS | UCCE_HDLC_TX_EVENTS) << 16); }
return howmany; @@@ -640,11 -635,9 +640,9 @@@ static irqreturn_t ucc_hdlc_irq_handler struct ucc_hdlc_private *priv = (struct ucc_hdlc_private *)dev_id; struct net_device *dev = priv->ndev; struct ucc_fast_private *uccf; - struct ucc_tdm_info *ut_info; u32 ucce; u32 uccm;
- ut_info = priv->ut_info; uccf = priv->uccf;
ucce = ioread32be(uccf->p_ucce); @@@ -737,8 -730,8 +735,8 @@@ static int uhdlc_open(struct net_devic
static void uhdlc_memclean(struct ucc_hdlc_private *priv) { - qe_muram_free(priv->ucc_pram->riptr); - qe_muram_free(priv->ucc_pram->tiptr); + qe_muram_free(ioread16be(&priv->ucc_pram->riptr)); + qe_muram_free(ioread16be(&priv->ucc_pram->tiptr));
if (priv->rx_bd_base) { dma_free_coherent(priv->dev, @@@ -877,7 -870,6 +875,6 @@@ static void resume_clk_config(struct uc static int uhdlc_suspend(struct device *dev) { struct ucc_hdlc_private *priv = dev_get_drvdata(dev); - struct ucc_tdm_info *ut_info; struct ucc_fast __iomem *uf_regs;
if (!priv) @@@ -889,7 -881,6 +886,6 @@@ netif_device_detach(priv->ndev); napi_disable(&priv->napi);
- ut_info = priv->ut_info; uf_regs = priv->uf_regs;
/* backup gumr guemr*/ @@@ -922,7 -913,7 +918,7 @@@ static int uhdlc_resume(struct device * struct ucc_fast __iomem *uf_regs; struct ucc_fast_private *uccf; struct ucc_fast_info *uf_info; - int ret, i; + int i; u32 cecr_subblock; u16 bd_status;
@@@ -967,16 -958,16 +963,16 @@@
/* Write to QE CECR, UCCx channel to Stop Transmission */ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num); - ret = qe_issue_cmd(QE_STOP_TX, cecr_subblock, - (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0); + qe_issue_cmd(QE_STOP_TX, cecr_subblock, + (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0);
/* Set UPSMR normal mode */ iowrite32be(0, &uf_regs->upsmr);
/* init parameter base */ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num); - ret = qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock, - QE_CR_PROTOCOL_UNSPECIFIED, priv->ucc_pram_offset); + qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock, + QE_CR_PROTOCOL_UNSPECIFIED, priv->ucc_pram_offset);
priv->ucc_pram = (struct ucc_hdlc_param __iomem *) qe_muram_addr(priv->ucc_pram_offset); @@@ -1044,7 -1035,7 +1040,7 @@@ static const struct dev_pm_ops uhdlc_pm #define HDLC_PM_OPS NULL
#endif - static void uhdlc_tx_timeout(struct net_device *ndev) + static void uhdlc_tx_timeout(struct net_device *ndev, unsigned int txqueue) { netdev_err(ndev, "%s\n", __func__); } diff --combined drivers/ptp/ptp_clock.c index b84f16bbd6f2,da97a5bab26e..ac1f2bf9e888 --- a/drivers/ptp/ptp_clock.c +++ b/drivers/ptp/ptp_clock.c @@@ -170,7 -170,6 +170,7 @@@ static void ptp_clock_release(struct de { struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
+ ptp_cleanup_pin_groups(ptp); mutex_destroy(&ptp->tsevq_mux); mutex_destroy(&ptp->pincfg_mux); ida_simple_remove(&ptp_clocks_map, ptp->index); @@@ -303,8 -302,9 +303,8 @@@ int ptp_clock_unregister(struct ptp_clo if (ptp->pps_source) pps_unregister_source(ptp->pps_source);
- ptp_cleanup_pin_groups(ptp); - posix_clock_unregister(&ptp->clock); + return 0; } EXPORT_SYMBOL(ptp_clock_unregister); @@@ -368,6 -368,12 +368,12 @@@ int ptp_schedule_worker(struct ptp_cloc } EXPORT_SYMBOL(ptp_schedule_worker);
+ void ptp_cancel_worker_sync(struct ptp_clock *ptp) + { + kthread_cancel_delayed_work_sync(&ptp->aux_work); + } + EXPORT_SYMBOL(ptp_cancel_worker_sync); + /* module operations */
static void __exit ptp_exit(void) diff --combined include/net/devlink.h index 38b4acb93f74,a6856f1d5d1f..5e9a901fbaed --- a/include/net/devlink.h +++ b/include/net/devlink.h @@@ -485,6 -485,8 +485,8 @@@ enum devlink_param_generic_id #define DEVLINK_INFO_VERSION_GENERIC_FW_UNDI "fw.undi" /* NCSI support/handler version */ #define DEVLINK_INFO_VERSION_GENERIC_FW_NCSI "fw.ncsi" + /* FW parameter set id */ + #define DEVLINK_INFO_VERSION_GENERIC_FW_PSID "fw.psid"
struct devlink_region; struct devlink_info_req; @@@ -562,7 -564,7 +564,7 @@@ struct devlink_trap };
/* All traps must be documented in - * Documentation/networking/devlink-trap.rst + * Documentation/networking/devlink/devlink-trap.rst */ enum devlink_trap_generic_id { DEVLINK_TRAP_GENERIC_ID_SMAC_MC, @@@ -596,7 -598,7 +598,7 @@@ };
/* All trap groups must be documented in - * Documentation/networking/devlink-trap.rst + * Documentation/networking/devlink/devlink-trap.rst */ enum devlink_trap_group_generic_id { DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS, @@@ -938,7 -940,7 +940,7 @@@ struct devlink_region *devlink_region_c u32 region_max_snapshots, u64 region_size); void devlink_region_destroy(struct devlink_region *region); -u32 devlink_region_shapshot_id_get(struct devlink *devlink); +u32 devlink_region_snapshot_id_get(struct devlink *devlink); int devlink_region_snapshot_create(struct devlink_region *region, u8 *data, u32 snapshot_id, devlink_snapshot_data_dest_t *data_destructor); @@@ -1000,6 -1002,8 +1002,8 @@@ int devlink_health_report(struct devlin void devlink_health_reporter_state_update(struct devlink_health_reporter *reporter, enum devlink_health_reporter_state state); + void + devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter);
bool devlink_is_reload_failed(const struct devlink *devlink);
diff --combined include/net/tcp.h index e6f48384dc71,5e4133d09b9d..2869d28ed5d8 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@@ -39,6 -39,7 +39,7 @@@ #include <net/tcp_states.h> #include <net/inet_ecn.h> #include <net/dst.h> + #include <net/mptcp.h>
#include <linux/seq_file.h> #include <linux/memcontrol.h> @@@ -182,6 -183,7 +183,7 @@@ void tcp_time_wait(struct sock *sk, in #define TCPOPT_SACK 5 /* SACK Block */ #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ #define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */ + #define TCPOPT_MPTCP 30 /* Multipath TCP (RFC6824) */ #define TCPOPT_FASTOPEN 34 /* Fast open (RFC7413) */ #define TCPOPT_EXP 254 /* Experimental */ /* Magic number to be after the option value for sharing TCP @@@ -328,6 -330,9 +330,9 @@@ int tcp_sendpage_locked(struct sock *sk size_t size, int flags); ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, size_t size, int flags); + int tcp_send_mss(struct sock *sk, int *size_goal, int flags); + void tcp_push(struct sock *sk, int flags, int mss_now, int nonagle, + int size_goal); void tcp_release_cb(struct sock *sk); void tcp_wfree(struct sk_buff *skb); void tcp_write_timer_handler(struct sock *sk); @@@ -977,6 -982,13 +982,13 @@@ static inline bool tcp_skb_can_collapse return likely(!TCP_SKB_CB(skb)->eor); }
+ static inline bool tcp_skb_can_collapse(const struct sk_buff *to, + const struct sk_buff *from) + { + return likely(tcp_skb_can_collapse_to(to) && + mptcp_skb_can_collapse(to, from)); + } + /* Events passed to congestion control interface */ enum tcp_ca_event { CA_EVENT_TX_START, /* first transmit when no packets in flight */ @@@ -1532,8 -1544,9 +1544,9 @@@ struct tcp_md5sig_key struct hlist_node node; u8 keylen; u8 family; /* AF_INET or AF_INET6 */ - union tcp_md5_addr addr; u8 prefixlen; + union tcp_md5_addr addr; + int l3index; /* set if key added with L3 scope */ u8 key[TCP_MD5SIG_MAXKEYLEN]; struct rcu_head rcu; }; @@@ -1577,34 -1590,33 +1590,33 @@@ struct tcp_md5sig_pool int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, const struct sock *sk, const struct sk_buff *skb); int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, - int family, u8 prefixlen, const u8 *newkey, u8 newkeylen, - gfp_t gfp); + int family, u8 prefixlen, int l3index, + const u8 *newkey, u8 newkeylen, gfp_t gfp); int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, - int family, u8 prefixlen); + int family, u8 prefixlen, int l3index); struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk, const struct sock *addr_sk);
#ifdef CONFIG_TCP_MD5SIG #include <linux/jump_label.h> extern struct static_key_false tcp_md5_needed; - struct tcp_md5sig_key *__tcp_md5_do_lookup(const struct sock *sk, + struct tcp_md5sig_key *__tcp_md5_do_lookup(const struct sock *sk, int l3index, const union tcp_md5_addr *addr, int family); static inline struct tcp_md5sig_key * - tcp_md5_do_lookup(const struct sock *sk, - const union tcp_md5_addr *addr, - int family) + tcp_md5_do_lookup(const struct sock *sk, int l3index, + const union tcp_md5_addr *addr, int family) { if (!static_branch_unlikely(&tcp_md5_needed)) return NULL; - return __tcp_md5_do_lookup(sk, addr, family); + return __tcp_md5_do_lookup(sk, l3index, addr, family); }
#define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_key) #else - static inline struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk, - const union tcp_md5_addr *addr, - int family) + static inline struct tcp_md5sig_key * + tcp_md5_do_lookup(const struct sock *sk, int l3index, + const union tcp_md5_addr *addr, int family) { return NULL; } @@@ -2002,6 -2014,11 +2014,11 @@@ struct tcp_request_sock_ops enum tcp_synack_type synack_type); };
+ extern const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops; + #if IS_ENABLED(CONFIG_IPV6) + extern const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops; + #endif + #ifdef CONFIG_SYN_COOKIES static inline __u32 cookie_init_sequence(const struct tcp_request_sock_ops *ops, const struct sock *sk, struct sk_buff *skb, @@@ -2147,13 -2164,15 +2164,16 @@@ struct tcp_ulp_ops /* initialize ulp */ int (*init)(struct sock *sk); /* update ulp */ - void (*update)(struct sock *sk, struct proto *p); + void (*update)(struct sock *sk, struct proto *p, + void (*write_space)(struct sock *sk)); /* cleanup ulp */ void (*release)(struct sock *sk); /* diagnostic */ int (*get_info)(const struct sock *sk, struct sk_buff *skb); size_t (*get_info_size)(const struct sock *sk); + /* clone ulp */ + void (*clone)(const struct request_sock *req, struct sock *newsk, + const gfp_t priority);
char name[TCP_ULP_NAME_MAX]; struct module *owner; @@@ -2163,8 -2182,7 +2183,8 @@@ void tcp_unregister_ulp(struct tcp_ulp_ int tcp_set_ulp(struct sock *sk, const char *name); void tcp_get_available_ulp(char *buf, size_t len); void tcp_cleanup_ulp(struct sock *sk); -void tcp_update_ulp(struct sock *sk, struct proto *p); +void tcp_update_ulp(struct sock *sk, struct proto *p, + void (*write_space)(struct sock *sk));
#define MODULE_ALIAS_TCP_ULP(name) \ __MODULE_INFO(alias, alias_userspace, name); \ diff --combined net/batman-adv/distributed-arp-table.c index ec7bf5a4a9fc,906011b60d66..3d21dd83f8cc --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@@ -1,5 -1,5 +1,5 @@@ // SPDX-License-Identifier: GPL-2.0 - /* Copyright (C) 2011-2019 B.A.T.M.A.N. contributors: + /* Copyright (C) 2011-2020 B.A.T.M.A.N. contributors: * * Antonio Quartulli */ @@@ -246,7 -246,7 +246,7 @@@ static u8 *batadv_arp_hw_src(struct sk_ */ static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) { - return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN); + return *(__force __be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN); }
/** @@@ -270,7 -270,9 +270,9 @@@ static u8 *batadv_arp_hw_dst(struct sk_ */ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) { - return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4); + u8 *dst = batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4; + + return *(__force __be32 *)dst; }
/** @@@ -285,18 -287,16 +287,18 @@@ static u32 batadv_hash_dat(const void * u32 hash = 0; const struct batadv_dat_entry *dat = data; const unsigned char *key; + __be16 vid; u32 i;
- key = (const unsigned char *)&dat->ip; + key = (__force const unsigned char *)&dat->ip; for (i = 0; i < sizeof(dat->ip); i++) { hash += key[i]; hash += (hash << 10); hash ^= (hash >> 6); }
- key = (const unsigned char *)&dat->vid; + vid = htons(dat->vid); + key = (__force const unsigned char *)&vid; for (i = 0; i < sizeof(dat->vid); i++) { hash += key[i]; hash += (hash << 10); diff --combined net/core/devlink.c index f76219bf0c21,d30aa47052aa..cf72e7744879 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@@ -4844,21 -4844,12 +4844,12 @@@ devlink_health_reporter_destroy(struct EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
void - devlink_health_reporter_state_update(struct devlink_health_reporter *reporter, - enum devlink_health_reporter_state state) + devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter) { - if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY && - state != DEVLINK_HEALTH_REPORTER_STATE_ERROR)) - return; - - if (reporter->health_state == state) - return; - - reporter->health_state = state; - trace_devlink_health_reporter_state_update(reporter->devlink, - reporter->ops->name, state); + reporter->recovery_count++; + reporter->last_recovery_ts = jiffies; } - EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update); + EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done);
static int devlink_health_reporter_recover(struct devlink_health_reporter *reporter, @@@ -4876,9 -4867,8 +4867,8 @@@ if (err) return err;
- reporter->recovery_count++; + devlink_health_reporter_recovery_done(reporter); reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY; - reporter->last_recovery_ts = jiffies;
return 0; } @@@ -5090,6 -5080,48 +5080,48 @@@ genlmsg_cancel return -EMSGSIZE; }
+ static void devlink_recover_notify(struct devlink_health_reporter *reporter, + enum devlink_command cmd) + { + struct sk_buff *msg; + int err; + + WARN_ON(cmd != DEVLINK_CMD_HEALTH_REPORTER_RECOVER); + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return; + + err = devlink_nl_health_reporter_fill(msg, reporter->devlink, + reporter, cmd, 0, 0, 0); + if (err) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(&devlink_nl_family, + devlink_net(reporter->devlink), + msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); + } + + void + devlink_health_reporter_state_update(struct devlink_health_reporter *reporter, + enum devlink_health_reporter_state state) + { + if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY && + state != DEVLINK_HEALTH_REPORTER_STATE_ERROR)) + return; + + if (reporter->health_state == state) + return; + + reporter->health_state = state; + trace_devlink_health_reporter_state_update(reporter->devlink, + reporter->ops->name, state); + devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER); + } + EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update); + static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb, struct genl_info *info) { @@@ -6406,7 -6438,7 +6438,7 @@@ static bool devlink_port_type_should_wa devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA; }
-#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 30) +#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600)
static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port) { @@@ -7563,7 -7595,7 +7595,7 @@@ void devlink_region_destroy(struct devl EXPORT_SYMBOL_GPL(devlink_region_destroy);
/** - * devlink_region_shapshot_id_get - get snapshot ID + * devlink_region_snapshot_id_get - get snapshot ID * * This callback should be called when adding a new snapshot, * Driver should use the same id for multiple snapshots taken @@@ -7571,7 -7603,7 +7603,7 @@@ * * @devlink: devlink */ -u32 devlink_region_shapshot_id_get(struct devlink *devlink) +u32 devlink_region_snapshot_id_get(struct devlink *devlink) { u32 id;
@@@ -7581,7 -7613,7 +7613,7 @@@
return id; } -EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); +EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
/** * devlink_region_snapshot_create - create a new snapshot diff --combined net/core/filter.c index 538f6a735a19,ef01c5599501..1012b70a7c84 --- a/net/core/filter.c +++ b/net/core/filter.c @@@ -2231,10 -2231,10 +2231,10 @@@ BPF_CALL_4(bpf_msg_pull_data, struct sk /* First find the starting scatterlist element */ i = msg->sg.start; do { + offset += len; len = sk_msg_elem(msg, i)->length; if (start < offset + len) break; - offset += len; sk_msg_iter_var_next(i); } while (i != msg->sg.end);
@@@ -2346,7 -2346,7 +2346,7 @@@ BPF_CALL_4(bpf_msg_push_data, struct sk u32, len, u64, flags) { struct scatterlist sge, nsge, nnsge, rsge = {0}, *psge; - u32 new, i = 0, l, space, copy = 0, offset = 0; + u32 new, i = 0, l = 0, space, copy = 0, offset = 0; u8 *raw, *to, *from; struct page *page;
@@@ -2356,11 -2356,11 +2356,11 @@@ /* First find the starting scatterlist element */ i = msg->sg.start; do { + offset += l; l = sk_msg_elem(msg, i)->length;
if (start < offset + l) break; - offset += l; sk_msg_iter_var_next(i); } while (i != msg->sg.end);
@@@ -2415,7 -2415,6 +2415,7 @@@
sk_msg_iter_var_next(i); sg_unmark_end(psge); + sg_unmark_end(&rsge); sk_msg_iter_next(msg, end); }
@@@ -2507,7 -2506,7 +2507,7 @@@ static void sk_msg_shift_right(struct s BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, u32, len, u64, flags) { - u32 i = 0, l, space, offset = 0; + u32 i = 0, l = 0, space, offset = 0; u64 last = start + len; int pop;
@@@ -2517,11 -2516,11 +2517,11 @@@ /* First find the starting scatterlist element */ i = msg->sg.start; do { + offset += l; l = sk_msg_elem(msg, i)->length;
if (start < offset + l) break; - offset += l; sk_msg_iter_var_next(i); } while (i != msg->sg.end);
@@@ -3512,36 -3511,16 +3512,16 @@@ err }
static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd, - struct bpf_map *map, - struct xdp_buff *xdp, - u32 index) + struct bpf_map *map, struct xdp_buff *xdp) { - int err; - switch (map->map_type) { case BPF_MAP_TYPE_DEVMAP: - case BPF_MAP_TYPE_DEVMAP_HASH: { - struct bpf_dtab_netdev *dst = fwd; - - err = dev_map_enqueue(dst, xdp, dev_rx); - if (unlikely(err)) - return err; - break; - } - case BPF_MAP_TYPE_CPUMAP: { - struct bpf_cpu_map_entry *rcpu = fwd; - - err = cpu_map_enqueue(rcpu, xdp, dev_rx); - if (unlikely(err)) - return err; - break; - } - case BPF_MAP_TYPE_XSKMAP: { - struct xdp_sock *xs = fwd; - - err = __xsk_map_redirect(map, xdp, xs); - return err; - } + case BPF_MAP_TYPE_DEVMAP_HASH: + return dev_map_enqueue(fwd, xdp, dev_rx); + case BPF_MAP_TYPE_CPUMAP: + return cpu_map_enqueue(fwd, xdp, dev_rx); + case BPF_MAP_TYPE_XSKMAP: + return __xsk_map_redirect(fwd, xdp); default: break; } @@@ -3550,26 -3529,9 +3530,9 @@@
void xdp_do_flush_map(void) { - struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); - struct bpf_map *map = ri->map_to_flush; - - ri->map_to_flush = NULL; - if (map) { - switch (map->map_type) { - case BPF_MAP_TYPE_DEVMAP: - case BPF_MAP_TYPE_DEVMAP_HASH: - __dev_map_flush(map); - break; - case BPF_MAP_TYPE_CPUMAP: - __cpu_map_flush(map); - break; - case BPF_MAP_TYPE_XSKMAP: - __xsk_map_flush(map); - break; - default: - break; - } - } + __dev_map_flush(); + __cpu_map_flush(); + __xsk_map_flush(); } EXPORT_SYMBOL_GPL(xdp_do_flush_map);
@@@ -3618,14 -3580,10 +3581,10 @@@ static int xdp_do_redirect_map(struct n ri->tgt_value = NULL; WRITE_ONCE(ri->map, NULL);
- if (ri->map_to_flush && unlikely(ri->map_to_flush != map)) - xdp_do_flush_map(); - - err = __bpf_tx_xdp_map(dev, fwd, map, xdp, index); + err = __bpf_tx_xdp_map(dev, fwd, map, xdp); if (unlikely(err)) goto err;
- ri->map_to_flush = map; _trace_xdp_redirect_map(dev, xdp_prog, fwd, map, index); return 0; err: @@@ -5319,7 -5277,8 +5278,7 @@@ __bpf_sk_lookup(struct sk_buff *skb, st if (sk) { sk = sk_to_full_sk(sk); if (!sk_fullsock(sk)) { - if (!sock_flag(sk, SOCK_RCU_FREE)) - sock_gen_put(sk); + sock_gen_put(sk); return NULL; } } @@@ -5356,7 -5315,8 +5315,7 @@@ bpf_sk_lookup(struct sk_buff *skb, stru if (sk) { sk = sk_to_full_sk(sk); if (!sk_fullsock(sk)) { - if (!sock_flag(sk, SOCK_RCU_FREE)) - sock_gen_put(sk); + sock_gen_put(sk); return NULL; } } @@@ -5423,8 -5383,7 +5382,8 @@@ static const struct bpf_func_proto bpf_
BPF_CALL_1(bpf_sk_release, struct sock *, sk) { - if (!sock_flag(sk, SOCK_RCU_FREE)) + /* Only full sockets have sk->sk_flags. */ + if (!sk_fullsock(sk) || !sock_flag(sk, SOCK_RCU_FREE)) sock_gen_put(sk); return 0; } @@@ -7648,21 -7607,21 +7607,21 @@@ u32 bpf_sock_convert_ctx_access(enum bp break;
case offsetof(struct bpf_sock, type): - BUILD_BUG_ON(HWEIGHT32(SK_FL_TYPE_MASK) != BITS_PER_BYTE * 2); - *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg, - offsetof(struct sock, __sk_flags_offset)); - *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_TYPE_MASK); - *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_TYPE_SHIFT); - *target_size = 2; + *insn++ = BPF_LDX_MEM( + BPF_FIELD_SIZEOF(struct sock, sk_type), + si->dst_reg, si->src_reg, + bpf_target_off(struct sock, sk_type, + sizeof_field(struct sock, sk_type), + target_size)); break;
case offsetof(struct bpf_sock, protocol): - BUILD_BUG_ON(HWEIGHT32(SK_FL_PROTO_MASK) != BITS_PER_BYTE); - *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg, - offsetof(struct sock, __sk_flags_offset)); - *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK); - *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_PROTO_SHIFT); - *target_size = 1; + *insn++ = BPF_LDX_MEM( + BPF_FIELD_SIZEOF(struct sock, sk_protocol), + si->dst_reg, si->src_reg, + bpf_target_off(struct sock, sk_protocol, + sizeof_field(struct sock, sk_protocol), + target_size)); break;
case offsetof(struct bpf_sock, src_ip4): @@@ -7944,20 -7903,13 +7903,13 @@@ static u32 sock_addr_convert_ctx_access break;
case offsetof(struct bpf_sock_addr, type): - SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF( - struct bpf_sock_addr_kern, struct sock, sk, - __sk_flags_offset, BPF_W, 0); - *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_TYPE_MASK); - *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_TYPE_SHIFT); + SOCK_ADDR_LOAD_NESTED_FIELD(struct bpf_sock_addr_kern, + struct sock, sk, sk_type); break;
case offsetof(struct bpf_sock_addr, protocol): - SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF( - struct bpf_sock_addr_kern, struct sock, sk, - __sk_flags_offset, BPF_W, 0); - *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK); - *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, - SK_FL_PROTO_SHIFT); + SOCK_ADDR_LOAD_NESTED_FIELD(struct bpf_sock_addr_kern, + struct sock, sk, sk_protocol); break;
case offsetof(struct bpf_sock_addr, msg_src_ip4): @@@ -8876,11 -8828,11 +8828,11 @@@ sk_reuseport_is_valid_access(int off, i skb, \ SKB_FIELD)
- #define SK_REUSEPORT_LOAD_SK_FIELD_SIZE_OFF(SK_FIELD, BPF_SIZE, EXTRA_OFF) \ - SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF(struct sk_reuseport_kern, \ - struct sock, \ - sk, \ - SK_FIELD, BPF_SIZE, EXTRA_OFF) + #define SK_REUSEPORT_LOAD_SK_FIELD(SK_FIELD) \ + SOCK_ADDR_LOAD_NESTED_FIELD(struct sk_reuseport_kern, \ + struct sock, \ + sk, \ + SK_FIELD)
static u32 sk_reuseport_convert_ctx_access(enum bpf_access_type type, const struct bpf_insn *si, @@@ -8904,16 -8856,7 +8856,7 @@@ break;
case offsetof(struct sk_reuseport_md, ip_protocol): - BUILD_BUG_ON(HWEIGHT32(SK_FL_PROTO_MASK) != BITS_PER_BYTE); - SK_REUSEPORT_LOAD_SK_FIELD_SIZE_OFF(__sk_flags_offset, - BPF_W, 0); - *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK); - *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, - SK_FL_PROTO_SHIFT); - /* SK_FL_PROTO_MASK and SK_FL_PROTO_SHIFT are endian - * aware. No further narrowing or masking is needed. - */ - *target_size = 1; + SK_REUSEPORT_LOAD_SK_FIELD(sk_protocol); break;
case offsetof(struct sk_reuseport_md, data_end): @@@ -8941,3 -8884,11 +8884,11 @@@ const struct bpf_verifier_ops sk_reusep const struct bpf_prog_ops sk_reuseport_prog_ops = { }; #endif /* CONFIG_INET */ + + DEFINE_BPF_DISPATCHER(bpf_dispatcher_xdp) + + void bpf_prog_change_xdp(struct bpf_prog *prev_prog, struct bpf_prog *prog) + { + bpf_dispatcher_change_prog(BPF_DISPATCHER_PTR(bpf_dispatcher_xdp), + prev_prog, prog); + } diff --combined net/ipv4/fib_trie.c index 195469a13371,6ce1f2bbffd0..ff0c24371e33 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@@ -980,9 -980,12 +980,12 @@@ static struct key_vector *fib_find_node
/* Return the first fib alias matching TOS with * priority less than or equal to PRIO. + * If 'find_first' is set, return the first matching + * fib alias, regardless of TOS and priority. */ static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen, - u8 tos, u32 prio, u32 tb_id) + u8 tos, u32 prio, u32 tb_id, + bool find_first) { struct fib_alias *fa;
@@@ -998,6 -1001,8 +1001,8 @@@ continue; if (fa->tb_id != tb_id) break; + if (find_first) + return fa; if (fa->fa_tos > tos) continue; if (fa->fa_info->fib_priority >= prio || fa->fa_tos < tos) @@@ -1007,6 -1012,52 +1012,52 @@@ return NULL; }
+ static struct fib_alias * + fib_find_matching_alias(struct net *net, const struct fib_rt_info *fri) + { + u8 slen = KEYLENGTH - fri->dst_len; + struct key_vector *l, *tp; + struct fib_table *tb; + struct fib_alias *fa; + struct trie *t; + + tb = fib_get_table(net, fri->tb_id); + if (!tb) + return NULL; + + t = (struct trie *)tb->tb_data; + l = fib_find_node(t, &tp, be32_to_cpu(fri->dst)); + if (!l) + return NULL; + + hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) { + if (fa->fa_slen == slen && fa->tb_id == fri->tb_id && + fa->fa_tos == fri->tos && fa->fa_info == fri->fi && + fa->fa_type == fri->type) + return fa; + } + + return NULL; + } + + void fib_alias_hw_flags_set(struct net *net, const struct fib_rt_info *fri) + { + struct fib_alias *fa_match; + + rcu_read_lock(); + + fa_match = fib_find_matching_alias(net, fri); + if (!fa_match) + goto out; + + fa_match->offload = fri->offload; + fa_match->trap = fri->trap; + + out: + rcu_read_unlock(); + } + EXPORT_SYMBOL_GPL(fib_alias_hw_flags_set); + static void trie_rebalance(struct trie *t, struct key_vector *tn) { while (!IS_TRIE(tn)) @@@ -1063,9 -1114,6 +1114,6 @@@ noleaf return -ENOMEM; }
- /* fib notifier for ADD is sent before calling fib_insert_alias with - * the expectation that the only possible failure ENOMEM - */ static int fib_insert_alias(struct trie *t, struct key_vector *tp, struct key_vector *l, struct fib_alias *new, struct fib_alias *fa, t_key key) @@@ -1118,11 -1166,13 +1166,13 @@@ static bool fib_valid_key_len(u32 key, return true; }
+ static void fib_remove_alias(struct trie *t, struct key_vector *tp, + struct key_vector *l, struct fib_alias *old); + /* Caller must hold RTNL. */ int fib_table_insert(struct net *net, struct fib_table *tb, struct fib_config *cfg, struct netlink_ext_ack *extack) { - enum fib_event_type event = FIB_EVENT_ENTRY_ADD; struct trie *t = (struct trie *)tb->tb_data; struct fib_alias *fa, *new_fa; struct key_vector *l, *tp; @@@ -1149,7 -1199,7 +1199,7 @@@
l = fib_find_node(t, &tp, key); fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority, - tb->tb_id) : NULL; + tb->tb_id, false) : NULL;
/* Now fa, if non-NULL, points to the first fib alias * with the same keys [prefix,tos,priority], if such key already @@@ -1216,19 -1266,29 +1266,29 @@@ new_fa->fa_slen = fa->fa_slen; new_fa->tb_id = tb->tb_id; new_fa->fa_default = -1; + new_fa->offload = 0; + new_fa->trap = 0;
- err = call_fib_entry_notifiers(net, - FIB_EVENT_ENTRY_REPLACE, - key, plen, new_fa, - extack); - if (err) - goto out_free_new_fa; + hlist_replace_rcu(&fa->fa_list, &new_fa->fa_list); + + if (fib_find_alias(&l->leaf, fa->fa_slen, 0, 0, + tb->tb_id, true) == new_fa) { + enum fib_event_type fib_event; + + fib_event = FIB_EVENT_ENTRY_REPLACE; + err = call_fib_entry_notifiers(net, fib_event, + key, plen, + new_fa, extack); + if (err) { + hlist_replace_rcu(&new_fa->fa_list, + &fa->fa_list); + goto out_free_new_fa; + } + }
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, &cfg->fc_nlinfo, nlflags);
- hlist_replace_rcu(&fa->fa_list, &new_fa->fa_list); - alias_free_mem_rcu(fa);
fib_release_info(fi_drop); @@@ -1244,12 -1304,10 +1304,10 @@@ if (fa_match) goto out;
- if (cfg->fc_nlflags & NLM_F_APPEND) { - event = FIB_EVENT_ENTRY_APPEND; + if (cfg->fc_nlflags & NLM_F_APPEND) nlflags |= NLM_F_APPEND; - } else { + else fa = fa_first; - } } err = -ENOENT; if (!(cfg->fc_nlflags & NLM_F_CREATE)) @@@ -1268,15 -1326,29 +1326,29 @@@ new_fa->fa_slen = slen; new_fa->tb_id = tb->tb_id; new_fa->fa_default = -1; - - err = call_fib_entry_notifiers(net, event, key, plen, new_fa, extack); - if (err) - goto out_free_new_fa; + new_fa->offload = 0; + new_fa->trap = 0;
/* Insert new entry to the list. */ err = fib_insert_alias(t, tp, l, new_fa, fa, key); if (err) - goto out_fib_notif; + goto out_free_new_fa; + + /* The alias was already inserted, so the node must exist. */ + l = l ? l : fib_find_node(t, &tp, key); + if (WARN_ON_ONCE(!l)) + goto out_free_new_fa; + + if (fib_find_alias(&l->leaf, new_fa->fa_slen, 0, 0, tb->tb_id, true) == + new_fa) { + enum fib_event_type fib_event; + + fib_event = FIB_EVENT_ENTRY_REPLACE; + err = call_fib_entry_notifiers(net, fib_event, key, plen, + new_fa, extack); + if (err) + goto out_remove_new_fa; + }
if (!plen) tb->tb_num_default++; @@@ -1287,14 -1359,8 +1359,8 @@@ succeeded: return 0;
- out_fib_notif: - /* notifier was sent that entry would be added to trie, but - * the add failed and need to recover. Only failure for - * fib_insert_alias is ENOMEM. - */ - NL_SET_ERR_MSG(extack, "Failed to insert route into trie"); - call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, key, - plen, new_fa, NULL); + out_remove_new_fa: + fib_remove_alias(t, tp, l, new_fa); out_free_new_fa: kmem_cache_free(fn_alias_kmem, new_fa); out: @@@ -1545,6 -1611,36 +1611,36 @@@ static void fib_remove_alias(struct tri node_pull_suffix(tp, fa->fa_slen); }
+ static void fib_notify_alias_delete(struct net *net, u32 key, + struct hlist_head *fah, + struct fib_alias *fa_to_delete, + struct netlink_ext_ack *extack) + { + struct fib_alias *fa_next, *fa_to_notify; + u32 tb_id = fa_to_delete->tb_id; + u8 slen = fa_to_delete->fa_slen; + enum fib_event_type fib_event; + + /* Do not notify if we do not care about the route. */ + if (fib_find_alias(fah, slen, 0, 0, tb_id, true) != fa_to_delete) + return; + + /* Determine if the route should be replaced by the next route in the + * list. + */ + fa_next = hlist_entry_safe(fa_to_delete->fa_list.next, + struct fib_alias, fa_list); + if (fa_next && fa_next->fa_slen == slen && fa_next->tb_id == tb_id) { + fib_event = FIB_EVENT_ENTRY_REPLACE; + fa_to_notify = fa_next; + } else { + fib_event = FIB_EVENT_ENTRY_DEL; + fa_to_notify = fa_to_delete; + } + call_fib_entry_notifiers(net, fib_event, key, KEYLENGTH - slen, + fa_to_notify, extack); + } + /* Caller must hold RTNL. */ int fib_table_delete(struct net *net, struct fib_table *tb, struct fib_config *cfg, struct netlink_ext_ack *extack) @@@ -1566,7 -1662,7 +1662,7 @@@ if (!l) return -ESRCH;
- fa = fib_find_alias(&l->leaf, slen, tos, 0, tb->tb_id); + fa = fib_find_alias(&l->leaf, slen, tos, 0, tb->tb_id, false); if (!fa) return -ESRCH;
@@@ -1598,8 -1694,7 +1694,7 @@@ if (!fa_to_delete) return -ESRCH;
- call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, key, plen, - fa_to_delete, extack); + fib_notify_alias_delete(net, key, &l->leaf, fa_to_delete, extack); rtmsg_fib(RTM_DELROUTE, htonl(key), fa_to_delete, plen, tb->tb_id, &cfg->fc_nlinfo, 0);
@@@ -1923,10 -2018,8 +2018,8 @@@ int fib_table_flush(struct net *net, st continue; }
- call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, - n->key, - KEYLENGTH - fa->fa_slen, fa, - NULL); + fib_notify_alias_delete(net, n->key, &n->leaf, fa, + NULL); hlist_del_rcu(&fa->fa_list); fib_release_info(fa->fa_info); alias_free_mem_rcu(fa); @@@ -2022,6 -2115,7 +2115,7 @@@ static int fib_leaf_notify(struct key_v struct netlink_ext_ack *extack) { struct fib_alias *fa; + int last_slen = -1; int err;
hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) { @@@ -2036,8 -2130,12 +2130,12 @@@ if (tb->tb_id != fa->tb_id) continue;
- err = call_fib_entry_notifier(nb, FIB_EVENT_ENTRY_ADD, l->key, - KEYLENGTH - fa->fa_slen, + if (fa->fa_slen == last_slen) + continue; + + last_slen = fa->fa_slen; + err = call_fib_entry_notifier(nb, FIB_EVENT_ENTRY_REPLACE, + l->key, KEYLENGTH - fa->fa_slen, fa, extack); if (err) return err; @@@ -2146,14 -2244,20 +2244,20 @@@ static int fn_trie_dump_leaf(struct key
if (filter->dump_routes) { if (!s_fa) { + struct fib_rt_info fri; + + fri.fi = fi; + fri.tb_id = tb->tb_id; + fri.dst = xkey; + fri.dst_len = KEYLENGTH - fa->fa_slen; + fri.tos = fa->fa_tos; + fri.type = fa->fa_type; + fri.offload = fa->offload; + fri.trap = fa->trap; err = fib_dump_info(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, - RTM_NEWROUTE, - tb->tb_id, fa->fa_type, - xkey, - KEYLENGTH - fa->fa_slen, - fa->fa_tos, fi, flags); + RTM_NEWROUTE, &fri, flags); if (err < 0) goto stop; } @@@ -2193,12 -2297,6 +2297,12 @@@ int fib_table_dump(struct fib_table *tb int count = cb->args[2]; t_key key = cb->args[3];
+ /* First time here, count and key are both always 0. Count > 0 + * and key == 0 means the dump has wrapped around and we are done. + */ + if (count && !key) + return skb->len; + while ((l = leaf_walk_rcu(&tp, key)) != NULL) { int err;
diff --combined net/ipv4/tcp_input.c index 5347ab2c9c58,2914fdf1d543..358365598216 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@@ -915,10 -915,9 +915,10 @@@ static void tcp_check_sack_reordering(s /* This must be called before lost_out is incremented */ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) { - if (!tp->retransmit_skb_hint || - before(TCP_SKB_CB(skb)->seq, - TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) + if ((!tp->retransmit_skb_hint && tp->retrans_out >= tp->lost_out) || + (tp->retransmit_skb_hint && + before(TCP_SKB_CB(skb)->seq, + TCP_SKB_CB(tp->retransmit_skb_hint)->seq))) tp->retransmit_skb_hint = skb; }
@@@ -1423,7 -1422,7 +1423,7 @@@ static struct sk_buff *tcp_shift_skb_da if ((TCP_SKB_CB(prev)->sacked & TCPCB_TAGBITS) != TCPCB_SACKED_ACKED) goto fallback;
- if (!tcp_skb_can_collapse_to(prev)) + if (!tcp_skb_can_collapse(prev, skb)) goto fallback;
in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && @@@ -3554,7 -3553,7 +3554,7 @@@ static void tcp_xmit_recovery(struct so if (rexmit == REXMIT_NONE || sk->sk_state == TCP_SYN_SENT) return;
- if (unlikely(rexmit == 2)) { + if (unlikely(rexmit == REXMIT_NEW)) { __tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF); if (after(tp->snd_nxt, tp->high_seq)) @@@ -4424,6 -4423,9 +4424,9 @@@ static bool tcp_try_coalesce(struct soc if (TCP_SKB_CB(from)->seq != TCP_SKB_CB(to)->end_seq) return false;
+ if (!mptcp_skb_can_collapse(to, from)) + return false; + #ifdef CONFIG_TLS_DEVICE if (from->decrypted != to->decrypted) return false; @@@ -4933,7 -4935,7 +4936,7 @@@ restart /* The first skb to collapse is: * - not SYN/FIN and * - bloated or contains data before "start" or - * overlaps to the next one. + * overlaps to the next one and mptcp allow collapsing. */ if (!(TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)) && (tcp_win_from_space(sk, skb->truesize) > skb->len || @@@ -4942,7 -4944,7 +4945,7 @@@ break; }
- if (n && n != tail && + if (n && n != tail && mptcp_skb_can_collapse(skb, n) && TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(n)->seq) { end_of_skbs = false; break; @@@ -4975,6 -4977,7 +4978,7 @@@ else __skb_queue_tail(&tmp, nskb); /* defer rbtree insertion */ skb_set_owner_r(nskb, sk); + mptcp_skb_ext_move(nskb, skb);
/* Copy data, releasing collapsed skbs. */ while (copy > 0) { @@@ -4994,6 -4997,7 +4998,7 @@@ skb = tcp_collapse_one(sk, skb, list, root); if (!skb || skb == tail || + !mptcp_skb_can_collapse(nskb, skb) || (TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN))) goto end; #ifdef CONFIG_TLS_DEVICE diff --combined net/netfilter/nft_tunnel.c index 5284fcf16be7,23cd163689d5..4c3f2e24c7cb --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@@ -76,7 -76,7 +76,7 @@@ static int nft_tunnel_get_init(const st struct nft_tunnel *priv = nft_expr_priv(expr); u32 len;
- if (!tb[NFTA_TUNNEL_KEY] && + if (!tb[NFTA_TUNNEL_KEY] || !tb[NFTA_TUNNEL_DREG]) return -EINVAL;
@@@ -248,8 -248,9 +248,9 @@@ static int nft_tunnel_obj_vxlan_init(co }
static const struct nla_policy nft_tunnel_opts_erspan_policy[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1] = { + [NFTA_TUNNEL_KEY_ERSPAN_VERSION] = { .type = NLA_U32 }, [NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX] = { .type = NLA_U32 }, - [NFTA_TUNNEL_KEY_ERSPAN_V2_DIR] = { .type = NLA_U8 }, + [NFTA_TUNNEL_KEY_ERSPAN_V2_DIR] = { .type = NLA_U8 }, [NFTA_TUNNEL_KEY_ERSPAN_V2_HWID] = { .type = NLA_U8 }, };
@@@ -266,9 -267,6 +267,9 @@@ static int nft_tunnel_obj_erspan_init(c if (err < 0) return err;
+ if (!tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]) + return -EINVAL; + version = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION])); switch (version) { case ERSPAN_VERSION: @@@ -445,10 -443,15 +446,15 @@@ static int nft_tunnel_ip_dump(struct sk if (!nest) return -1;
- if (nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_SRC, &info->key.u.ipv6.src) < 0 || - nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_DST, &info->key.u.ipv6.dst) < 0 || - nla_put_be32(skb, NFTA_TUNNEL_KEY_IP6_FLOWLABEL, info->key.label)) + if (nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_SRC, + &info->key.u.ipv6.src) < 0 || + nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_DST, + &info->key.u.ipv6.dst) < 0 || + nla_put_be32(skb, NFTA_TUNNEL_KEY_IP6_FLOWLABEL, + info->key.label)) { + nla_nest_cancel(skb, nest); return -1; + }
nla_nest_end(skb, nest); } else { @@@ -456,9 -459,13 +462,13 @@@ if (!nest) return -1;
- if (nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_SRC, info->key.u.ipv4.src) < 0 || - nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_DST, info->key.u.ipv4.dst) < 0) + if (nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_SRC, + info->key.u.ipv4.src) < 0 || + nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_DST, + info->key.u.ipv4.dst) < 0) { + nla_nest_cancel(skb, nest); return -1; + }
nla_nest_end(skb, nest); } @@@ -470,42 -477,58 +480,58 @@@ static int nft_tunnel_opts_dump(struct struct nft_tunnel_obj *priv) { struct nft_tunnel_opts *opts = &priv->opts; - struct nlattr *nest; + struct nlattr *nest, *inner;
nest = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS); if (!nest) return -1;
if (opts->flags & TUNNEL_VXLAN_OPT) { + inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_VXLAN); + if (!inner) + goto failure; if (nla_put_be32(skb, NFTA_TUNNEL_KEY_VXLAN_GBP, htonl(opts->u.vxlan.gbp))) - return -1; + goto inner_failure; + nla_nest_end(skb, inner); } else if (opts->flags & TUNNEL_ERSPAN_OPT) { + inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_ERSPAN); + if (!inner) + goto failure; + if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_VERSION, + htonl(opts->u.erspan.version))) + goto inner_failure; switch (opts->u.erspan.version) { case ERSPAN_VERSION: if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX, opts->u.erspan.u.index)) - return -1; + goto inner_failure; break; case ERSPAN_VERSION2: if (nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID, get_hwid(&opts->u.erspan.u.md2)) || nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR, opts->u.erspan.u.md2.dir)) - return -1; + goto inner_failure; break; } + nla_nest_end(skb, inner); } nla_nest_end(skb, nest); - return 0; + + inner_failure: + nla_nest_cancel(skb, inner); + failure: + nla_nest_cancel(skb, nest); + return -1; }
static int nft_tunnel_ports_dump(struct sk_buff *skb, struct ip_tunnel_info *info) { - if (nla_put_be16(skb, NFTA_TUNNEL_KEY_SPORT, htons(info->key.tp_src)) < 0 || - nla_put_be16(skb, NFTA_TUNNEL_KEY_DPORT, htons(info->key.tp_dst)) < 0) + if (nla_put_be16(skb, NFTA_TUNNEL_KEY_SPORT, info->key.tp_src) < 0 || + nla_put_be16(skb, NFTA_TUNNEL_KEY_DPORT, info->key.tp_dst) < 0) return -1;
return 0; diff --combined net/wireless/nl80211.c index 1e97ac5435b2,fa3526592c51..123b8d720a59 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@@ -10843,7 -10843,6 +10843,7 @@@ static int cfg80211_cqm_rssi_update(str if (err) return err;
+ cfg80211_sinfo_release_content(&sinfo); if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) wdev->cqm_config->last_rssi_event_value = (s8) sinfo.rx_beacon_signal_avg; @@@ -12901,8 -12900,7 +12901,7 @@@ static int nl80211_vendor_check_policy( return -EINVAL; }
- return nl80211_validate_nested(attr, vcmd->maxattr, vcmd->policy, - extack); + return nla_validate_nested(attr, vcmd->maxattr, vcmd->policy, extack); }
static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info) @@@ -13797,8 -13795,6 +13796,8 @@@ static int nl80211_probe_mesh_link(stru if (err) return err;
+ cfg80211_sinfo_release_content(&sinfo); + return rdev_probe_mesh_link(rdev, dev, dest, buf, len); }