The following commit has been merged in the master branch: commit 9ca9278d854b5b23dcc8e5c1f4a4a67f28e281d7 Merge: a9e258064e89cce9fca9f790a1b1a8ae24375a85 4bc61b0b16955322576265724ab0a0075a30dc84 Author: Stephen Rothwell sfr@canb.auug.org.au Date: Mon Sep 2 13:04:43 2019 +1000
Merge remote-tracking branch 'net-next/master'
# Conflicts: # drivers/net/usb/r8152.c # drivers/pci/Kconfig # drivers/pci/controller/pci-hyperv.c # scripts/link-vmlinux.sh
diff --combined Documentation/devicetree/bindings/net/dsa/ksz.txt index 113e7ac79aad,5e8429b6f9ca..95e91e84151c --- a/Documentation/devicetree/bindings/net/dsa/ksz.txt +++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt @@@ -5,6 -5,9 +5,9 @@@ Required properties
- compatible: For external switch chips, compatible string must be exactly one of the following: + - "microchip,ksz8765" + - "microchip,ksz8794" + - "microchip,ksz8795" - "microchip,ksz9477" - "microchip,ksz9897" - "microchip,ksz9896" @@@ -12,7 -15,6 +15,7 @@@ - "microchip,ksz8565" - "microchip,ksz9893" - "microchip,ksz9563" + - "microchip,ksz8563"
Optional properties:
diff --combined Documentation/networking/index.rst index 6739066acadb,37eabc17894c..425a3ca01db4 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst @@@ -14,6 -14,8 +14,8 @@@ Contents device_drivers/index dsa/index devlink-info-versions + devlink-trap + devlink-trap-netdevsim ieee802154 kapi z8530book @@@ -31,7 -33,7 +33,7 @@@ tls tls-offload
-.. only:: subproject +.. only:: subproject and html
Indices ======= diff --combined MAINTAINERS index 02c6cd9ff243,68b48de8765b..c63f5c6e782a --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -517,6 -517,14 +517,6 @@@ W: http://ez.analog.com/community/linux S: Supported F: drivers/video/backlight/adp8860_bl.c
-ADS1015 HARDWARE MONITOR DRIVER -M: Dirk Eibach eibach@gdsys.de -L: linux-hwmon@vger.kernel.org -S: Maintained -F: Documentation/hwmon/ads1015.rst -F: drivers/hwmon/ads1015.c -F: include/linux/platform_data/ads1015.h - ADT746X FAN DRIVER M: Colin Leroy colin@colino.net S: Maintained @@@ -658,7 -666,7 +658,7 @@@ ALI1563 I2C DRIVE M: Rudolf Marek r.marek@assembler.cz L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-ali1563 +F: Documentation/i2c/busses/i2c-ali1563.rst F: drivers/i2c/busses/i2c-ali1563.c
ALLEGRO DVT VIDEO IP CORE DRIVER @@@ -668,13 -676,6 +668,13 @@@ L: linux-media@vger.kernel.or S: Maintained F: drivers/staging/media/allegro-dvt/
+ALLWINNER CPUFREQ DRIVER +M: Yangtao Li tiny.windzz@gmail.com +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt +F: drivers/cpufreq/sun50i-cpufreq-nvmem.c + ALLWINNER SECURITY SYSTEM M: Corentin Labbe clabbe.montjoie@gmail.com L: linux-crypto@vger.kernel.org @@@ -682,7 -683,7 +682,7 @@@ S: Maintaine F: drivers/crypto/sunxi-ss/
ALLWINNER VPU DRIVER -M: Maxime Ripard maxime.ripard@bootlin.com +M: Maxime Ripard mripard@kernel.org M: Paul Kocialkowski paul.kocialkowski@bootlin.com L: linux-media@vger.kernel.org S: Maintained @@@ -937,6 -938,14 +937,14 @@@ S: Supporte F: drivers/mux/adgs1408.c F: Documentation/devicetree/bindings/mux/adi,adgs1408.txt
+ ANALOG DEVICES INC ADIN DRIVER + M: Alexandru Ardelean alexaundru.ardelean@analog.com + L: netdev@vger.kernel.org + W: http://ez.analog.com/community/linux-device-drivers + S: Supported + F: drivers/net/phy/adin.c + F: Documentation/devicetree/bindings/net/adi,adin.yaml + ANALOG DEVICES INC ADIS DRIVER LIBRARY M: Alexandru Ardelean alexandru.ardelean@analog.com S: Supported @@@ -1407,7 -1416,7 +1415,7 @@@ S: Maintaine F: drivers/clk/sunxi/
ARM/Allwinner sunXi SoC support -M: Maxime Ripard maxime.ripard@bootlin.com +M: Maxime Ripard mripard@kernel.org M: Chen-Yu Tsai wens@csie.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@@ -1420,14 -1429,6 +1428,14 @@@ F: drivers/pinctrl/sunxi F: drivers/soc/sunxi/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git
+Allwinner A10 CSI driver +M: Maxime Ripard mripard@kernel.org +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +F: drivers/media/platform/sunxi/sun4i-csi/ +F: Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml +S: Maintained + ARM/Amlogic Meson SoC CLOCK FRAMEWORK M: Neil Armstrong narmstrong@baylibre.com M: Jerome Brunet jbrunet@baylibre.com @@@ -1589,8 -1590,8 +1597,8 @@@ R: Suzuki K Poulose <suzuki.poulose@arm L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: drivers/hwtracing/coresight/* -F: Documentation/trace/coresight.txt -F: Documentation/trace/coresight-cpu-debug.txt +F: Documentation/trace/coresight.rst +F: Documentation/trace/coresight-cpu-debug.rst F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* @@@ -1633,18 -1634,6 +1641,18 @@@ F: drivers/clocksource/timer-atlas7. N: [^a-z]sirf X: drivers/gnss
+ARM/CZ.NIC TURRIS MOX SUPPORT +M: Marek Behun marek.behun@nic.cz +W: http://mox.turris.cz +S: Maintained +F: Documentation/ABI/testing/debugfs-moxtet +F: Documentation/ABI/testing/sysfs-bus-moxtet-devices +F: Documentation/devicetree/bindings/bus/moxtet.txt +F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt +F: include/linux/moxtet.h +F: drivers/bus/moxtet.c +F: drivers/gpio/gpio-moxtet.c + ARM/EBSA110 MACHINE SUPPORT M: Russell King linux@armlinux.org.uk L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@@ -1768,11 -1757,20 +1776,11 @@@ L: linux-arm-kernel@lists.infradead.or S: Maintained F: arch/arm/mach-pxa/colibri-pxa270-income.c
-ARM/INTEL IOP13XX ARM ARCHITECTURE -M: Lennert Buytenhek kernel@wantstofly.org -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained - ARM/INTEL IOP32X ARM ARCHITECTURE M: Lennert Buytenhek kernel@wantstofly.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained
-ARM/INTEL IOP33X ARM ARCHITECTURE -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Orphan - ARM/INTEL IQ81342EX MACHINE SUPPORT M: Lennert Buytenhek kernel@wantstofly.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@@ -1931,6 -1929,12 +1939,6 @@@ S: Maintaine F: drivers/phy/mediatek/ F: Documentation/devicetree/bindings/phy/phy-mtk-*
-ARM/MICREL KS8695 ARCHITECTURE -M: Greg Ungerer gerg@uclinux.org -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -F: arch/arm/mach-ks8695/ -S: Odd Fixes - ARM/Microchip (AT91) SoC support M: Nicolas Ferre nicolas.ferre@microchip.com M: Alexandre Belloni alexandre.belloni@bootlin.com @@@ -1972,7 -1976,6 +1980,7 @@@ F: Documentation/devicetree/bindings/i2 F: arch/arm/mach-nomadik/ F: arch/arm/mach-u300/ F: arch/arm/mach-ux500/ +F: drivers/soc/ux500/ F: arch/arm/boot/dts/ste-* F: drivers/clk/clk-nomadik.c F: drivers/clk/clk-u300.c @@@ -2016,6 -2019,22 +2024,6 @@@ F: drivers/*/*npcm F: Documentation/devicetree/bindings/*/*npcm* F: Documentation/devicetree/bindings/*/*/*npcm*
-ARM/NUVOTON W90X900 ARM ARCHITECTURE -M: Wan ZongShun mcuos.com@gmail.com -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -W: http://www.mcuos.com -S: Maintained -F: arch/arm/mach-w90x900/ -F: drivers/input/keyboard/w90p910_keypad.c -F: drivers/input/touchscreen/w90p910_ts.c -F: drivers/watchdog/nuc900_wdt.c -F: drivers/net/ethernet/nuvoton/w90p910_ether.c -F: drivers/mtd/nand/raw/nuc900_nand.c -F: drivers/rtc/rtc-nuc900.c -F: drivers/spi/spi-nuc900.c -F: drivers/usb/host/ehci-w90x900.c -F: drivers/video/fbdev/nuc900fb.c - ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT L: openmoko-kernel@lists.openmoko.org (subscribers-only) W: http://wiki.openmoko.org/wiki/Neo_FreeRunner @@@ -2208,9 -2227,8 +2216,9 @@@ F: drivers/*/*s3c24 F: drivers/*/*/*s3c24* F: drivers/*/*s3c64xx* F: drivers/*/*s5pv210* -F: drivers/memory/samsung/* -F: drivers/soc/samsung/* +F: drivers/memory/samsung/ +F: drivers/soc/samsung/ +F: include/linux/soc/samsung/ F: Documentation/arm/samsung/ F: Documentation/devicetree/bindings/arm/samsung/ F: Documentation/devicetree/bindings/sram/samsung-sram.txt @@@ -2905,6 -2923,7 +2913,7 @@@ BATMAN ADVANCE M: Marek Lindner mareklindner@neomailbox.ch M: Simon Wunderlich sw@simonwunderlich.de M: Antonio Quartulli a@unstable.cc + M: Sven Eckelmann sven@narfation.org L: b.a.t.m.a.n@lists.open-mesh.org (moderated for non-subscribers) W: https://www.open-mesh.org/ B: https://www.open-mesh.org/projects/batman-adv/issues @@@ -3567,7 -3586,7 +3576,7 @@@ F: Documentation/filesystems/caching/ca F: fs/cachefiles/
CADENCE MIPI-CSI2 BRIDGES -M: Maxime Ripard maxime.ripard@bootlin.com +M: Maxime Ripard mripard@kernel.org L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/cdns,*.txt @@@ -3625,9 -3644,12 +3634,12 @@@ S: Maintaine F: Documentation/devicetree/bindings/net/can/ F: drivers/net/can/ F: include/linux/can/dev.h + F: include/linux/can/led.h + F: include/linux/can/rx-offload.h F: include/linux/can/platform/ F: include/uapi/linux/can/error.h F: include/uapi/linux/can/netlink.h + F: include/uapi/linux/can/vxcan.h
CAN NETWORK LAYER M: Oliver Hartkopp socketcan@hartkopp.net @@@ -3640,6 -3662,8 +3652,8 @@@ S: Maintaine F: Documentation/networking/can.rst F: net/can/ F: include/linux/can/core.h + F: include/linux/can/skb.h + F: include/net/netns/can.h F: include/uapi/linux/can.h F: include/uapi/linux/can/bcm.h F: include/uapi/linux/can/raw.h @@@ -4093,7 -4117,7 +4107,7 @@@ L: samba-technical@lists.samba.org (mod W: http://linux-cifs.samba.org/ T: git git://git.samba.org/sfrench/cifs-2.6.git S: Supported -F: Documentation/filesystems/cifs/ +F: Documentation/admin-guide/cifs/ F: fs/cifs/
COMPACTPCI HOTPLUG CORE @@@ -4280,14 -4304,6 +4294,14 @@@ S: Supporte F: drivers/cpuidle/cpuidle-exynos.c F: arch/arm/mach-exynos/pm.c
+CPUIDLE DRIVER - ARM PSCI +M: Lorenzo Pieralisi lorenzo.pieralisi@arm.com +M: Sudeep Holla sudeep.holla@arm.com +L: linux-pm@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org +S: Supported +F: drivers/cpuidle/cpuidle-psci.c + CPU IDLE TIME MANAGEMENT FRAMEWORK M: "Rafael J. Wysocki" rjw@rjwysocki.net M: Daniel Lezcano daniel.lezcano@linaro.org @@@ -4949,9 -4965,7 +4963,9 @@@ M: Jonathan Corbet <corbet@lwn.net L: linux-doc@vger.kernel.org S: Maintained F: Documentation/ +F: scripts/documentation-file-ref-check F: scripts/kernel-doc +F: scripts/sphinx-pre-install X: Documentation/ABI/ X: Documentation/firmware-guide/acpi/ X: Documentation/devicetree/ @@@ -4967,14 -4981,6 +4981,14 @@@ L: linux-doc@vger.kernel.or S: Maintained F: Documentation/translations/it_IT
+DOCUMENTATION SCRIPTS +M: Mauro Carvalho Chehab mchehab@kernel.org +L: linux-doc@vger.kernel.org +S: Maintained +F: scripts/documentation-file-ref-check +F: scripts/sphinx-pre-install +F: Documentation/sphinx/parse-headers.pl + DONGWOON DW9714 LENS VOICE COIL DRIVER M: Sakari Ailus sakari.ailus@linux.intel.com L: linux-media@vger.kernel.org @@@ -5303,7 -5309,7 +5317,7 @@@ F: include/linux/vga
DRM DRIVERS AND MISC GPU PATCHES M: Maarten Lankhorst maarten.lankhorst@linux.intel.com -M: Maxime Ripard maxime.ripard@bootlin.com +M: Maxime Ripard mripard@kernel.org M: Sean Paul sean@poorly.run W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html S: Maintained @@@ -5316,7 -5322,7 +5330,7 @@@ F: include/uapi/drm/drm F: include/linux/vga*
DRM DRIVERS FOR ALLWINNER A10 -M: Maxime Ripard maxime.ripard@bootlin.com +M: Maxime Ripard mripard@kernel.org L: dri-devel@lists.freedesktop.org S: Supported F: drivers/gpu/drm/sun4i/ @@@ -5763,12 -5769,6 +5777,12 @@@ L: linux-edac@vger.kernel.or S: Maintained F: drivers/edac/amd64_edac*
+EDAC-ARMADA +M: Jan Luebbe jlu@pengutronix.de +L: linux-edac@vger.kernel.org +S: Maintained +F: drivers/edac/armada_xp_* + EDAC-AST2500 M: Stefan Schaeckeler sschaeck@cisco.com S: Supported @@@ -6335,7 -6335,7 +6349,7 @@@ FLEXTIMER FTM-QUADDEC DRIVE M: Patrick Havelange patrick.havelange@essensium.com L: linux-iio@vger.kernel.org S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quadddec +F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt F: drivers/counter/ftm-quaddec.c
@@@ -6453,7 -6453,6 +6467,7 @@@ M: Frank Li <Frank.li@nxp.com L: linux-arm-kernel@lists.infradead.org S: Maintained F: drivers/perf/fsl_imx8_ddr_perf.c +F: Documentation/admin-guide/perf/imx-ddr.rst F: Documentation/devicetree/bindings/perf/fsl-imx-ddr.txt
FREESCALE IMX I2C DRIVER @@@ -6626,7 -6625,6 +6640,7 @@@ T: git git://git.kernel.org/pub/scm/fs/ S: Supported F: fs/crypto/ F: include/linux/fscrypt*.h +F: include/uapi/linux/fscrypt.h F: Documentation/filesystems/fscrypt.rst
FSI SUBSYSTEM @@@ -6658,18 -6656,6 +6672,18 @@@ S: Maintaine F: fs/notify/ F: include/linux/fsnotify*.h
+FSVERITY: READ-ONLY FILE-BASED AUTHENTICITY PROTECTION +M: Eric Biggers ebiggers@kernel.org +M: Theodore Y. Ts'o tytso@mit.edu +L: linux-fscrypt@vger.kernel.org +Q: https://patchwork.kernel.org/project/linux-fscrypt/list/ +T: git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git fsverity +S: Supported +F: fs/verity/ +F: include/linux/fsverity.h +F: include/uapi/linux/fsverity.h +F: Documentation/filesystems/fsverity.rst + FUJITSU LAPTOP EXTRAS M: Jonathan Woithe jwoithe@just42.net L: platform-driver-x86@vger.kernel.org @@@ -6760,13 -6746,6 +6774,13 @@@ W: https://linuxtv.or S: Maintained F: drivers/media/radio/radio-gemtek*
+GENERIC ARCHITECTURE TOPOLOGY +M: Sudeep Holla sudeep.holla@arm.com +L: linux-kernel@vger.kernel.org +S: Maintained +F: drivers/base/arch_topology.c +F: include/linux/arch_topology.h + GENERIC GPIO I2C DRIVER M: Wolfram Sang wsa+renesas@sang-engineering.com S: Supported @@@ -6779,7 -6758,7 +6793,7 @@@ L: linux-i2c@vger.kernel.or S: Supported F: drivers/i2c/muxes/i2c-mux-gpio.c F: include/linux/platform_data/i2c-mux-gpio.h -F: Documentation/i2c/muxes/i2c-mux-gpio +F: Documentation/i2c/muxes/i2c-mux-gpio.rst
GENERIC HDLC (WAN) DRIVERS M: Krzysztof Halasa khc@pm.waw.pl @@@ -7491,6 -7470,7 +7505,7 @@@ F: drivers/hid/hid-hyperv. F: drivers/hv/ F: drivers/input/serio/hyperv-keyboard.c F: drivers/pci/controller/pci-hyperv.c + F: drivers/pci/controller/pci-hyperv-intf.c F: drivers/net/hyperv/ F: drivers/scsi/storvsc_drv.c F: drivers/uio/uio_hv_generic.c @@@ -7528,14 -7508,14 +7543,14 @@@ I2C CONTROLLER DRIVER FOR NVIDIA GP M: Ajay Gupta ajayg@nvidia.com L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-nvidia-gpu +F: Documentation/i2c/busses/i2c-nvidia-gpu.rst F: drivers/i2c/busses/i2c-nvidia-gpu.c
I2C MUXES M: Peter Rosin peda@axentia.se L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/i2c-topology +F: Documentation/i2c/i2c-topology.rst F: Documentation/i2c/muxes/ F: Documentation/devicetree/bindings/i2c/i2c-mux* F: Documentation/devicetree/bindings/i2c/i2c-arb* @@@ -7548,15 -7528,15 +7563,15 @@@ I2C MV64XXX MARVELL AND ALLWINNER DRIVE M: Gregory CLEMENT gregory.clement@bootlin.com L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt +F: Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml F: drivers/i2c/busses/i2c-mv64xxx.c
I2C OVER PARALLEL PORT M: Jean Delvare jdelvare@suse.com L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-parport -F: Documentation/i2c/busses/i2c-parport-light +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
@@@ -7590,7 -7570,7 +7605,7 @@@ I2C-TAOS-EVM DRIVE M: Jean Delvare jdelvare@suse.com L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-taos-evm +F: Documentation/i2c/busses/i2c-taos-evm.rst F: drivers/i2c/busses/i2c-taos-evm.c
I2C-TINY-USB DRIVER @@@ -7604,19 -7584,19 +7619,19 @@@ I2C/SMBUS CONTROLLER DRIVERS FOR P M: Jean Delvare jdelvare@suse.com L: linux-i2c@vger.kernel.org S: Maintained -F: Documentation/i2c/busses/i2c-ali1535 -F: Documentation/i2c/busses/i2c-ali1563 -F: Documentation/i2c/busses/i2c-ali15x3 -F: Documentation/i2c/busses/i2c-amd756 -F: Documentation/i2c/busses/i2c-amd8111 -F: Documentation/i2c/busses/i2c-i801 -F: Documentation/i2c/busses/i2c-nforce2 -F: Documentation/i2c/busses/i2c-piix4 -F: Documentation/i2c/busses/i2c-sis5595 -F: Documentation/i2c/busses/i2c-sis630 -F: Documentation/i2c/busses/i2c-sis96x -F: Documentation/i2c/busses/i2c-via -F: Documentation/i2c/busses/i2c-viapro +F: Documentation/i2c/busses/i2c-ali1535.rst +F: Documentation/i2c/busses/i2c-ali1563.rst +F: Documentation/i2c/busses/i2c-ali15x3.rst +F: Documentation/i2c/busses/i2c-amd756.rst +F: Documentation/i2c/busses/i2c-amd8111.rst +F: Documentation/i2c/busses/i2c-i801.rst +F: Documentation/i2c/busses/i2c-nforce2.rst +F: Documentation/i2c/busses/i2c-piix4.rst +F: Documentation/i2c/busses/i2c-sis5595.rst +F: Documentation/i2c/busses/i2c-sis630.rst +F: Documentation/i2c/busses/i2c-sis96x.rst +F: Documentation/i2c/busses/i2c-via.rst +F: Documentation/i2c/busses/i2c-viapro.rst F: drivers/i2c/busses/i2c-ali1535.c F: drivers/i2c/busses/i2c-ali1563.c F: drivers/i2c/busses/i2c-ali15x3.c @@@ -7645,7 -7625,7 +7660,7 @@@ M: Seth Heasley <seth.heasley@intel.com M: Neil Horman nhorman@tuxdriver.com L: linux-i2c@vger.kernel.org F: drivers/i2c/busses/i2c-ismt.c -F: Documentation/i2c/busses/i2c-ismt +F: Documentation/i2c/busses/i2c-ismt.rst
I2C/SMBUS STUB DRIVER M: Jean Delvare jdelvare@suse.com @@@ -7791,12 -7771,6 +7806,12 @@@ S: Maintaine F: drivers/mfd/lpc_ich.c F: drivers/gpio/gpio-ich.c
+ICY I2C DRIVER +M: Max Staudt max@enpas.org +L: linux-i2c@vger.kernel.org +S: Maintained +F: drivers/i2c/busses/i2c-icy.c + IDE SUBSYSTEM M: "David S. Miller" davem@davemloft.net L: linux-ide@vger.kernel.org @@@ -8401,7 -8375,7 +8416,7 @@@ M: linux-wimax@intel.co L: wimax@linuxwimax.org (subscribers-only) S: Supported W: http://linuxwimax.org -F: Documentation/wimax/README.i2400m +F: Documentation/admin-guide/wimax/i2400m.rst F: drivers/net/wimax/i2400m/ F: include/uapi/linux/wimax/i2400m.h
@@@ -8456,6 -8430,12 +8471,6 @@@ L: linux-mips@vger.kernel.or S: Maintained F: drivers/net/ethernet/sgi/ioc3-eth.c
-IOC3 SERIAL DRIVER -M: Pat Gefre pfg@sgi.com -L: linux-serial@vger.kernel.org -S: Maintained -F: drivers/tty/serial/ioc3_serial.c - IOMAP FILESYSTEM LIBRARY M: Christoph Hellwig hch@infradead.org M: Darrick J. Wong darrick.wong@oracle.com @@@ -8692,7 -8672,7 +8707,7 @@@ L: jfs-discussion@lists.sourceforge.ne W: http://jfs.sourceforge.net/ T: git git://github.com/kleikamp/linux-shaggy.git S: Maintained -F: Documentation/filesystems/jfs.txt +F: Documentation/admin-guide/jfs.rst F: fs/jfs/
JME NETWORK DRIVER @@@ -9035,7 -9015,7 +9050,7 @@@ F: kernel/kprobes. KS0108 LCD CONTROLLER DRIVER M: Miguel Ojeda Sandonis miguel.ojeda.sandonis@gmail.com S: Maintained -F: Documentation/auxdisplay/ks0108 +F: Documentation/admin-guide/auxdisplay/ks0108.rst F: drivers/auxdisplay/ks0108.c F: include/linux/ks0108.h
@@@ -9264,18 -9244,6 +9279,18 @@@ F: include/linux/nd. F: include/linux/libnvdimm.h F: include/uapi/linux/ndctl.h
+LICENSES and SPDX stuff +M: Thomas Gleixner tglx@linutronix.de +M: Greg Kroah-Hartman gregkh@linuxfoundation.org +L: linux-spdx@vger.kernel.org +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/spdx.git +F: COPYING +F: Documentation/process/license-rules.rst +F: LICENSES/ +F: scripts/spdxcheck-test.sh +F: scripts/spdxcheck.py + LIGHTNVM PLATFORM SUPPORT M: Matias Bjorling mb@lightnvm.io W: http://github/OpenChannelSSD @@@ -9624,7 -9592,7 +9639,7 @@@ F: Documentation/networking/mac80211-in F: include/net/mac80211.h F: net/mac80211/ F: drivers/net/wireless/mac80211_hwsim.[ch] -F: Documentation/networking/mac80211_hwsim/README +F: Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst
MAILBOX API M: Jassi Brar jassisinghbrar@gmail.com @@@ -10073,8 -10041,8 +10088,8 @@@ L: linux-media@vger.kernel.or L: linux-renesas-soc@vger.kernel.org T: git git://linuxtv.org/media_tree.git S: Supported -F: Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt -F: Documentation/devicetree/bindings/media/rcar_vin.txt +F: Documentation/devicetree/bindings/media/renesas,csi2.txt +F: Documentation/devicetree/bindings/media/renesas,vin.txt F: drivers/media/platform/rcar-vin/
MEDIA DRIVERS FOR RENESAS - VSP1 @@@ -10401,7 -10369,7 +10416,7 @@@ L: linux-i2c@vger.kernel.or S: Supported F: drivers/i2c/busses/i2c-mlxcpld.c F: drivers/i2c/muxes/i2c-mux-mlxcpld.c -F: Documentation/i2c/busses/i2c-mlxcpld +F: Documentation/i2c/busses/i2c-mlxcpld.rst
MELLANOX MLXCPLD LED DRIVER M: Vadim Pasternak vadimp@mellanox.com @@@ -10671,6 -10639,12 +10686,6 @@@ M: Nicolas Ferre <nicolas.ferre@microch S: Supported F: drivers/power/reset/at91-sama5d2_shdwc.c
-MICROCHIP SAMA5D2-COMPATIBLE PIOBU GPIO -M: Andrei Stefanescu andrei.stefanescu@microchip.com -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -L: linux-gpio@vger.kernel.org -F: drivers/gpio/gpio-sama5d2-piobu.c - MICROCHIP SPI DRIVER M: Nicolas Ferre nicolas.ferre@microchip.com S: Supported @@@ -10683,6 -10657,13 +10698,6 @@@ S: Supporte F: drivers/misc/atmel-ssc.c F: include/linux/atmel-ssc.h
-MICROCHIP TIMER COUNTER (TC) AND CLOCKSOURCE DRIVERS -M: Nicolas Ferre nicolas.ferre@microchip.com -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Supported -F: drivers/misc/atmel_tclib.c -F: drivers/clocksource/tcb_clksrc.c - MICROCHIP USBA UDC DRIVER M: Cristian Birsan cristian.birsan@microchip.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@@ -11188,6 -11169,7 +11203,7 @@@ S: Maintaine W: https://fedorahosted.org/dropwatch/ F: net/core/drop_monitor.c F: include/uapi/linux/net_dropmon.h + F: include/net/drop_monitor.h
NETWORKING DRIVERS M: "David S. Miller" davem@davemloft.net @@@ -11367,7 -11349,6 +11383,6 @@@ F: include/net/nfc F: include/uapi/linux/nfc.h F: drivers/nfc/ F: include/linux/platform_data/nfcmrvl.h - F: include/linux/platform_data/nxp-nci.h F: Documentation/devicetree/bindings/net/nfc/
NFS, SUNRPC, AND LOCKD CLIENTS @@@ -11808,7 -11789,6 +11823,7 @@@ S: Maintaine F: arch/arm/mach-omap2/ F: arch/arm/plat-omap/ F: arch/arm/configs/omap2plus_defconfig +F: drivers/bus/ti-sysc.c F: drivers/i2c/busses/i2c-omap.c F: drivers/irqchip/irq-omap-intc.c F: drivers/mfd/*omap*.c @@@ -11829,7 -11809,6 +11844,7 @@@ F: drivers/regulator/tps65910-regulator F: drivers/regulator/twl-regulator.c F: drivers/regulator/twl6030-regulator.c F: include/linux/platform_data/i2c-omap.h +F: include/linux/platform_data/ti-sysc.h
ONION OMEGA2+ BOARD M: Harvey Hunt harveyhuntnexus@gmail.com @@@ -11892,21 -11871,6 +11907,21 @@@ T: git git://linuxtv.org/media_tree.gi S: Maintained F: drivers/media/i2c/ov5647.c
+OMNIVISION OV5670 SENSOR DRIVER +M: Chiranjeevi Rapolu chiranjeevi.rapolu@intel.com +M: Hyungwoo Yang hyungwoo.yang@intel.com +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov5670.c + +OMNIVISION OV5675 SENSOR DRIVER +M: Shawn Tu shawnx.tu@intel.com +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov5675.c + OMNIVISION OV5695 SENSOR DRIVER M: Shunqian Zheng zhengsq@rock-chips.com L: linux-media@vger.kernel.org @@@ -12028,7 -11992,7 +12043,7 @@@ M: Andrew Lunn <andrew@lunn.ch L: linux-i2c@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/i2c/i2c-ocores.txt -F: Documentation/i2c/busses/i2c-ocores +F: Documentation/i2c/busses/i2c-ocores.rst F: drivers/i2c/busses/i2c-ocores.c F: include/linux/platform_data/i2c-ocores.h
@@@ -12151,7 -12115,7 +12166,7 @@@ L: netdev@vger.kernel.or S: Supported F: lib/packing.c F: include/linux/packing.h -F: Documentation/packing.txt +F: Documentation/core-api/packing.rst
PADATA PARALLEL EXECUTION MECHANISM M: Steffen Klassert steffen.klassert@secunet.com @@@ -12741,7 -12705,6 +12756,7 @@@ L: linux-arm-kernel@lists.infradead.or L: linux-gpio@vger.kernel.org S: Supported F: drivers/pinctrl/pinctrl-at91* +F: drivers/gpio/gpio-sama5d2-piobu.c
PIN CONTROLLER - FREESCALE M: Dong Aisheng aisheng.dong@nxp.com @@@ -13280,7 -13243,7 +13295,7 @@@ M: Manish Chopra <manishc@marvell.com M: GR-Linux-NIC-Dev@marvell.com L: netdev@vger.kernel.org S: Supported - F: drivers/net/ethernet/qlogic/qlge/ + F: drivers/staging/qlge/
QM1D1B0004 MEDIA DRIVER M: Akihiro Tsukada tskd08@gmail.com @@@ -13348,8 -13311,8 +13363,8 @@@ QUALCOMM CPUFREQ DRIVER MSM8996/APQ809 M: Ilia Lin ilia.lin@kernel.org L: linux-pm@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/opp/kryo-cpufreq.txt -F: drivers/cpufreq/qcom-cpufreq-kryo.c +F: Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt +F: drivers/cpufreq/qcom-cpufreq-nvmem.c
QUALCOMM EMAC GIGABIT ETHERNET DRIVER M: Timur Tabi timur@kernel.org @@@ -13691,7 -13654,7 +13706,7 @@@ F: drivers/clk/renesas RENESAS EMEV2 I2C DRIVER M: Wolfram Sang wsa+renesas@sang-engineering.com S: Supported -F: Documentation/devicetree/bindings/i2c/i2c-emev2.txt +F: Documentation/devicetree/bindings/i2c/renesas,iic-emev2.txt F: drivers/i2c/busses/i2c-emev2.c
RENESAS ETHERNET DRIVERS @@@ -13713,15 -13676,15 +13728,15 @@@ F: drivers/iio/adc/rcar-gyroadc. RENESAS R-CAR I2C DRIVERS M: Wolfram Sang wsa+renesas@sang-engineering.com S: Supported -F: Documentation/devicetree/bindings/i2c/i2c-rcar.txt -F: Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt +F: Documentation/devicetree/bindings/i2c/renesas,i2c.txt +F: Documentation/devicetree/bindings/i2c/renesas,iic.txt F: drivers/i2c/busses/i2c-rcar.c F: drivers/i2c/busses/i2c-sh_mobile.c
RENESAS RIIC DRIVER M: Chris Brandt chris.brandt@renesas.com S: Supported -F: Documentation/devicetree/bindings/i2c/i2c-riic.txt +F: Documentation/devicetree/bindings/i2c/renesas,riic.txt F: drivers/i2c/busses/i2c-riic.c
RENESAS USB PHY DRIVER @@@ -13807,8 -13770,7 +13822,8 @@@ F: include/linux/hid-roccat F: Documentation/ABI/*/sysfs-driver-hid-roccat*
ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER -M: Jacob chen jacob2.chen@rock-chips.com +M: Jacob Chen jacob-chen@iotwrt.com +M: Ezequiel Garcia ezequiel@collabora.com L: linux-media@vger.kernel.org S: Maintained F: drivers/media/platform/rockchip/rga/ @@@ -13818,7 -13780,7 +13833,7 @@@ HANTRO VPU CODEC DRIVE M: Ezequiel Garcia ezequiel@collabora.com L: linux-media@vger.kernel.org S: Maintained -F: drivers/staging/media/platform/hantro/ +F: drivers/staging/media/hantro/ F: Documentation/devicetree/bindings/media/rockchip-vpu.txt
ROCKER DRIVER @@@ -14176,8 -14138,6 +14191,8 @@@ M: Kamil Konieczny <k.konieczny@partner L: linux-crypto@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained +F: Documentation/devicetree/bindings/crypto/samsung-slimsss.txt +F: Documentation/devicetree/bindings/crypto/samsung-sss.txt F: drivers/crypto/s5p-sss.c
SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS @@@ -14198,8 -14158,6 +14213,8 @@@ T: git git://git.kernel.org/pub/scm/lin F: drivers/clk/samsung/ F: include/dt-bindings/clock/exynos*.h F: Documentation/devicetree/bindings/clock/exynos*.txt +F: Documentation/devicetree/bindings/clock/samsung,s3c* +F: Documentation/devicetree/bindings/clock/samsung,s5p*
SAMSUNG SPI DRIVERS M: Kukjin Kim kgene@kernel.org @@@ -14344,7 -14302,7 +14359,7 @@@ F: net/sctp SCx200 CPU SUPPORT M: Jim Cromie jim.cromie@gmail.com S: Odd Fixes -F: Documentation/i2c/busses/scx200_acb +F: Documentation/i2c/busses/scx200_acb.rst F: arch/x86/platform/scx200/ F: drivers/watchdog/scx200_wdt.c F: drivers/i2c/busses/scx200* @@@ -15620,7 -15578,6 +15635,7 @@@ F: drivers/clk/clk-sc[mp]i. F: drivers/cpufreq/sc[mp]i-cpufreq.c F: drivers/firmware/arm_scpi.c F: drivers/firmware/arm_scmi/ +F: drivers/reset/reset-scmi.c F: include/linux/sc[mp]i_protocol.h
SYSTEM RESET/SHUTDOWN DRIVERS @@@ -15965,7 -15922,6 +15980,7 @@@ THERMA M: Zhang Rui rui.zhang@intel.com M: Eduardo Valentin edubezval@gmail.com R: Daniel Lezcano daniel.lezcano@linaro.org +R: Amit Kucheria amit.kucheria@verdurent.com L: linux-pm@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git @@@ -15983,7 -15939,7 +15998,7 @@@ M: Viresh Kumar <viresh.kumar@linaro.or M: Javi Merino javi.merino@kernel.org L: linux-pm@vger.kernel.org S: Supported -F: Documentation/thermal/cpu-cooling-api.rst +F: Documentation/driver-api/thermal/cpu-cooling-api.rst F: drivers/thermal/cpu_cooling.c F: include/linux/cpu_cooling.h
@@@ -16506,7 -16462,7 +16521,7 @@@ F: drivers/hid/hid-udraw-ps3. UFS FILESYSTEM M: Evgeniy Dushistov dushistov@mail.ru S: Maintained -F: Documentation/filesystems/ufs.txt +F: Documentation/admin-guide/ufs.rst F: fs/ufs/
UHID USERSPACE HID IO DRIVER: @@@ -17424,7 -17380,7 +17439,7 @@@ M: linux-wimax@intel.co L: wimax@linuxwimax.org (subscribers-only) S: Supported W: http://linuxwimax.org -F: Documentation/wimax/README.wimax +F: Documentation/admin-guide/wimax/wimax.rst F: include/linux/wimax/debug.h F: include/net/wimax.h F: include/uapi/linux/wimax.h @@@ -17876,6 -17832,14 +17891,6 @@@ S: Maintaine F: mm/zpool.c F: include/linux/zpool.h
-ZR36067 VIDEO FOR LINUX DRIVER -L: mjpeg-users@lists.sourceforge.net -L: linux-media@vger.kernel.org -W: http://mjpeg.sourceforge.net/driver-zoran/ -T: hg https://linuxtv.org/hg/v4l-dvb -S: Odd Fixes -F: drivers/staging/media/zoran/ - ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER M: Minchan Kim minchan@kernel.org M: Nitin Gupta ngupta@vflare.org diff --combined arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts index 5e14e5a19744,663c4b728c07..d98346da01df --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts @@@ -85,6 -85,26 +85,26 @@@ system-clock-frequency = <25000000>; }; }; + + mdio-mux { + compatible = "mdio-mux-multiplexer"; + mux-controls = <&mux 0>; + mdio-parent-bus = <&enetc_mdio_pf3>; + #address-cells=<1>; + #size-cells = <0>; + + /* on-board RGMII PHY */ + mdio@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + qds_phy1: ethernet-phy@5 { + /* Atheros 8035 */ + reg = <5>; + }; + }; + }; };
&duart0 { @@@ -95,14 -115,6 +115,14 @@@ status = "okay"; };
+&esdhc { + status = "okay"; +}; + +&esdhc1 { + status = "okay"; +}; + &i2c0 { status = "okay";
@@@ -172,6 -184,26 +192,26 @@@ }; }; }; + + fpga@66 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,ls1028aqds-fpga", "fsl,fpga-qixis-i2c", + "simple-mfd"; + reg = <0x66>; + + mux: mux-controller { + compatible = "reg-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x54 0xf0>; /* 0: reg 0x54, bits 7:4 */ + }; + }; + + }; + + &enetc_port1 { + phy-handle = <&qds_phy1>; + phy-connection-type = "rgmii-id"; };
&sai1 { diff --combined arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index b139b29cef87,de71153fda00..72b9a75976a1 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@@ -29,7 -29,6 +29,7 @@@ clocks = <&clockgen 1 0>; next-level-cache = <&l2>; cpu-idle-states = <&CPU_PW20>; + #cooling-cells = <2>; };
cpu1: cpu@1 { @@@ -40,7 -39,6 +40,7 @@@ clocks = <&clockgen 1 0>; next-level-cache = <&l2>; cpu-idle-states = <&CPU_PW20>; + #cooling-cells = <2>; };
l2: l2-cache { @@@ -72,18 -70,11 +72,18 @@@ clock-output-names = "sysclk"; };
- dpclk: clock-dp { + osc_27m: clock-osc-27m { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <27000000>; - clock-output-names= "dpclk"; + clock-output-names = "phy_27m"; + }; + + dpclk: clock-controller@f1f0000 { + compatible = "fsl,ls1028a-plldig"; + reg = <0x0 0xf1f0000 0x0 0xffff>; + #clock-cells = <1>; + clocks = <&osc_27m>; };
aclk: clock-axi { @@@ -180,7 -171,7 +180,7 @@@ #size-cells = <0>; reg = <0x0 0x2000000 0x0 0x10000>; interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clockgen 4 1>; + clocks = <&clockgen 4 3>; status = "disabled"; };
@@@ -190,7 -181,7 +190,7 @@@ #size-cells = <0>; reg = <0x0 0x2010000 0x0 0x10000>; interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clockgen 4 1>; + clocks = <&clockgen 4 3>; status = "disabled"; };
@@@ -200,7 -191,7 +200,7 @@@ #size-cells = <0>; reg = <0x0 0x2020000 0x0 0x10000>; interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clockgen 4 1>; + clocks = <&clockgen 4 3>; status = "disabled"; };
@@@ -210,7 -201,7 +210,7 @@@ #size-cells = <0>; reg = <0x0 0x2030000 0x0 0x10000>; interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clockgen 4 1>; + clocks = <&clockgen 4 3>; status = "disabled"; };
@@@ -220,7 -211,7 +220,7 @@@ #size-cells = <0>; reg = <0x0 0x2040000 0x0 0x10000>; interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clockgen 4 1>; + clocks = <&clockgen 4 3>; status = "disabled"; };
@@@ -230,7 -221,7 +230,7 @@@ #size-cells = <0>; reg = <0x0 0x2050000 0x0 0x10000>; interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clockgen 4 1>; + clocks = <&clockgen 4 3>; status = "disabled"; };
@@@ -240,7 -231,7 +240,7 @@@ #size-cells = <0>; reg = <0x0 0x2060000 0x0 0x10000>; interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clockgen 4 1>; + clocks = <&clockgen 4 3>; status = "disabled"; };
@@@ -250,34 -241,7 +250,34 @@@ #size-cells = <0>; reg = <0x0 0x2070000 0x0 0x10000>; interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clockgen 4 1>; + clocks = <&clockgen 4 3>; + status = "disabled"; + }; + + esdhc: mmc@2140000 { + compatible = "fsl,ls1028a-esdhc", "fsl,esdhc"; + reg = <0x0 0x2140000 0x0 0x10000>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <0>; /* fixed up by bootloader */ + clocks = <&clockgen 2 1>; + voltage-ranges = <1800 1800 3300 3300>; + sdhci,auto-cmd12; + little-endian; + bus-width = <4>; + status = "disabled"; + }; + + esdhc1: mmc@2150000 { + compatible = "fsl,ls1028a-esdhc", "fsl,esdhc"; + reg = <0x0 0x2150000 0x0 0x10000>; + interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <0>; /* fixed up by bootloader */ + clocks = <&clockgen 2 1>; + voltage-ranges = <1800 1800 3300 3300>; + sdhci,auto-cmd12; + broken-cd; + little-endian; + bus-width = <4>; status = "disabled"; };
@@@ -313,36 -277,33 +313,36 @@@ };
gpio1: gpio@2300000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio"; reg = <0x0 0x2300000 0x0 0x10000>; interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + little-endian; };
gpio2: gpio@2310000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio"; reg = <0x0 0x2310000 0x0 0x10000>; interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + little-endian; };
gpio3: gpio@2320000 { - compatible = "fsl,qoriq-gpio"; + compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio"; reg = <0x0 0x2320000 0x0 0x10000>; interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + little-endian; };
usb0: usb@3100000 { @@@ -542,89 -503,6 +542,89 @@@ status = "disabled"; };
+ tmu: tmu@1f00000 { + compatible = "fsl,qoriq-tmu"; + reg = <0x0 0x1f80000 0x0 0x10000>; + interrupts = <0 23 0x4>; + fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>; + fsl,tmu-calibration = <0x00000000 0x00000024 + 0x00000001 0x0000002b + 0x00000002 0x00000031 + 0x00000003 0x00000038 + 0x00000004 0x0000003f + 0x00000005 0x00000045 + 0x00000006 0x0000004c + 0x00000007 0x00000053 + 0x00000008 0x00000059 + 0x00000009 0x00000060 + 0x0000000a 0x00000066 + 0x0000000b 0x0000006d + + 0x00010000 0x0000001c + 0x00010001 0x00000024 + 0x00010002 0x0000002c + 0x00010003 0x00000035 + 0x00010004 0x0000003d + 0x00010005 0x00000045 + 0x00010006 0x0000004d + 0x00010007 0x00000045 + 0x00010008 0x0000005e + 0x00010009 0x00000066 + 0x0001000a 0x0000006e + + 0x00020000 0x00000018 + 0x00020001 0x00000022 + 0x00020002 0x0000002d + 0x00020003 0x00000038 + 0x00020004 0x00000043 + 0x00020005 0x0000004d + 0x00020006 0x00000058 + 0x00020007 0x00000063 + 0x00020008 0x0000006e + + 0x00030000 0x00000010 + 0x00030001 0x0000001c + 0x00030002 0x00000029 + 0x00030003 0x00000036 + 0x00030004 0x00000042 + 0x00030005 0x0000004f + 0x00030006 0x0000005b + 0x00030007 0x00000068>; + little-endian; + #thermal-sensor-cells = <1>; + }; + + thermal-zones { + core-cluster { + polling-delay-passive = <1000>; + polling-delay = <5000>; + thermal-sensors = <&tmu 0>; + + trips { + core_cluster_alert: core-cluster-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + core_cluster_crit: core-cluster-crit { + temperature = <95000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&core_cluster_alert>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; + pcie@1f0000000 { /* Integrated Endpoint Root Complex */ compatible = "pci-host-ecam-generic"; reg = <0x01 0xf0000000 0x0 0x100000>; @@@ -658,6 -536,12 +658,12 @@@ compatible = "fsl,enetc"; reg = <0x000100 0 0 0 0>; }; + enetc_mdio_pf3: mdio@0,3 { + compatible = "fsl,enetc-mdio"; + reg = <0x000300 0 0 0 0>; + #address-cells = <1>; + #size-cells = <0>; + }; ethernet@0,4 { compatible = "fsl,enetc-ptp"; reg = <0x000400 0 0 0 0>; @@@ -673,10 -557,9 +679,10 @@@ interrupts = <0 222 IRQ_TYPE_LEVEL_HIGH>, <0 223 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "DE", "SE"; - clocks = <&dpclk>, <&aclk>, <&aclk>, <&pclk>; + clocks = <&dpclk 0>, <&aclk>, <&aclk>, <&pclk>; clock-names = "pxlclk", "mclk", "aclk", "pclk"; arm,malidp-output-port-lines = /bits/ 8 <8 8 8>; + arm,malidp-arqos-value = <0xd000d000>;
port { dp0_out: endpoint { diff --combined drivers/net/dsa/microchip/ksz9477_spi.c index 098b01e4ed1a,a226b389e12d..2e402e4d866f --- a/drivers/net/dsa/microchip/ksz9477_spi.c +++ b/drivers/net/dsa/microchip/ksz9477_spi.c @@@ -13,7 -13,6 +13,6 @@@ #include <linux/regmap.h> #include <linux/spi/spi.h>
- #include "ksz_priv.h" #include "ksz_common.h"
#define SPI_ADDR_SHIFT 24 @@@ -81,7 -80,6 +80,7 @@@ static const struct of_device_id ksz947 { .compatible = "microchip,ksz9897" }, { .compatible = "microchip,ksz9893" }, { .compatible = "microchip,ksz9563" }, + { .compatible = "microchip,ksz8563" }, {}, }; MODULE_DEVICE_TABLE(of, ksz9477_dt_ids); diff --combined drivers/net/dsa/microchip/ksz_common.h index 72ec250b9540,c44a8d23d973..13d027baaa8b --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@@ -7,9 -7,152 +7,152 @@@ #ifndef __KSZ_COMMON_H #define __KSZ_COMMON_H
+ #include <linux/etherdevice.h> + #include <linux/kernel.h> + #include <linux/mutex.h> + #include <linux/phy.h> #include <linux/regmap.h> + #include <net/dsa.h> + + struct vlan_table { + u32 table[3]; + }; + + struct ksz_port_mib { + struct mutex cnt_mutex; /* structure access */ + u8 cnt_ptr; + u64 *counters; + }; + + struct ksz_port { + u16 member; + u16 vid_member; + int stp_state; + struct phy_device phydev; + + u32 on:1; /* port is not disabled by hardware */ + u32 phy:1; /* port has a PHY */ + u32 fiber:1; /* port is fiber */ + u32 sgmii:1; /* port is SGMII */ + u32 force:1; + u32 read:1; /* read MIB counters in background */ + u32 freeze:1; /* MIB counter freeze is enabled */ + + struct ksz_port_mib mib; + }; + + struct ksz_device { + struct dsa_switch *ds; + struct ksz_platform_data *pdata; + const char *name; + + struct mutex dev_mutex; /* device access */ + struct mutex stats_mutex; /* status access */ + struct mutex alu_mutex; /* ALU access */ + struct mutex vlan_mutex; /* vlan access */ + const struct ksz_dev_ops *dev_ops; + + struct device *dev; + struct regmap *regmap[3]; + + void *priv; + + struct gpio_desc *reset_gpio; /* Optional reset GPIO */ + + /* chip specific data */ + u32 chip_id; + int num_vlans; + int num_alus; + int num_statics; + int cpu_port; /* port connected to CPU */ + int cpu_ports; /* port bitmap can be cpu port */ + int phy_port_cnt; + int port_cnt; + int reg_mib_cnt; + int mib_cnt; + int mib_port_cnt; + int last_port; /* ports after that not used */ + phy_interface_t interface; + u32 regs_size; + bool phy_errata_9477; + bool synclko_125; + + struct vlan_table *vlan_cache; + + struct ksz_port *ports; + struct timer_list mib_read_timer; + struct work_struct mib_read; + unsigned long mib_read_interval; + u16 br_member; + u16 member; + u16 live_ports; + u16 on_ports; /* ports enabled by DSA */ + u16 rx_ports; + u16 tx_ports; + u16 mirror_rx; + u16 mirror_tx; + u32 features; /* chip specific features */ + u32 overrides; /* chip functions set by user */ + u16 host_mask; + u16 port_mask; + }; + + struct alu_struct { + /* entry 1 */ + u8 is_static:1; + u8 is_src_filter:1; + u8 is_dst_filter:1; + u8 prio_age:3; + u32 _reserv_0_1:23; + u8 mstp:3; + /* entry 2 */ + u8 is_override:1; + u8 is_use_fid:1; + u32 _reserv_1_1:23; + u8 port_forward:7; + /* entry 3 & 4*/ + u32 _reserv_2_1:9; + u8 fid:7; + u8 mac[ETH_ALEN]; + }; + + struct ksz_dev_ops { + u32 (*get_port_addr)(int port, int offset); + void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member); + void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); + void (*phy_setup)(struct ksz_device *dev, int port, + struct phy_device *phy); + void (*port_cleanup)(struct ksz_device *dev, int port); + void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); + void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); + void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val); + int (*r_dyn_mac_table)(struct ksz_device *dev, u16 addr, u8 *mac_addr, + u8 *fid, u8 *src_port, u8 *timestamp, + u16 *entries); + int (*r_sta_mac_table)(struct ksz_device *dev, u16 addr, + struct alu_struct *alu); + void (*w_sta_mac_table)(struct ksz_device *dev, u16 addr, + struct alu_struct *alu); + void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr, + u64 *cnt); + void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt); + void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze); + void (*port_init_cnt)(struct ksz_device *dev, int port); + int (*shutdown)(struct ksz_device *dev); + int (*detect)(struct ksz_device *dev); + int (*init)(struct ksz_device *dev); + void (*exit)(struct ksz_device *dev); + }; + + struct ksz_device *ksz_switch_alloc(struct device *base, void *priv); + int ksz_switch_register(struct ksz_device *dev, + const struct ksz_dev_ops *ops); + void ksz_switch_remove(struct ksz_device *dev); + + int ksz8795_switch_register(struct ksz_device *dev); + int ksz9477_switch_register(struct ksz_device *dev);
- void ksz_port_cleanup(struct ksz_device *dev, int port); void ksz_update_port_member(struct ksz_device *dev, int port); void ksz_init_mib_timer(struct ksz_device *dev);
@@@ -68,6 -211,22 +211,22 @@@ static inline int ksz_read32(struct ksz return ret; }
+ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val) + { + u32 value[2]; + int ret; + + ret = regmap_bulk_read(dev->regmap[2], reg, value, 2); + if (!ret) { + /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */ + value[0] = swab32(value[0]); + value[1] = swab32(value[1]); + *val = swab64((u64)*value); + } + + return ret; + } + static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value) { return regmap_write(dev->regmap[0], reg, value); @@@ -83,6 -242,18 +242,18 @@@ static inline int ksz_write32(struct ks return regmap_write(dev->regmap[2], reg, value); }
+ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) + { + u32 val[2]; + + /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */ + value = swab64(value); + val[0] = swab32(value & 0xffffffffULL); + val[1] = swab32(value >> 32ULL); + + return regmap_bulk_write(dev->regmap[2], reg, val, 2); + } + static inline void ksz_pread8(struct ksz_device *dev, int port, int offset, u8 *data) { @@@ -128,7 -299,6 +299,7 @@@ static inline void ksz_pwrite32(struct
#define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign) \ { \ + .name = #width, \ .val_bits = (width), \ .reg_stride = (width) / 8, \ .reg_bits = (regbits) + (regalign), \ diff --combined drivers/net/ethernet/broadcom/genet/bcmgenet.c index b22196880d6d,1586316eb6f1..12cb77ef1081 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@@ -1124,7 -1124,6 +1124,7 @@@ static const struct ethtool_ops bcmgene .set_coalesce = bcmgenet_set_coalesce, .get_link_ksettings = bcmgenet_get_link_ksettings, .set_link_ksettings = bcmgenet_set_link_ksettings, + .get_ts_info = ethtool_op_get_ts_info, };
/* Power down the unimac, based on mode. */ @@@ -2516,19 -2515,14 +2516,14 @@@ static int bcmgenet_dma_teardown(struc static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) { struct netdev_queue *txq; - struct sk_buff *skb; - struct enet_cb *cb; int i;
bcmgenet_fini_rx_napi(priv); bcmgenet_fini_tx_napi(priv);
- for (i = 0; i < priv->num_tx_bds; i++) { - cb = priv->tx_cbs + i; - skb = bcmgenet_free_tx_cb(&priv->pdev->dev, cb); - if (skb) - dev_kfree_skb(skb); - } + for (i = 0; i < priv->num_tx_bds; i++) + dev_kfree_skb(bcmgenet_free_tx_cb(&priv->pdev->dev, + priv->tx_cbs + i));
for (i = 0; i < priv->hw_params->tx_queues; i++) { txq = netdev_get_tx_queue(priv->dev, priv->tx_rings[i].queue); @@@ -3438,7 -3432,6 +3433,6 @@@ static int bcmgenet_probe(struct platfo struct bcmgenet_priv *priv; struct net_device *dev; const void *macaddr; - struct resource *r; unsigned int i; int err = -EIO; const char *phy_mode_str; @@@ -3478,8 -3471,7 +3472,7 @@@ macaddr = pd->mac_address; }
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, r); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { err = PTR_ERR(priv->base); goto err; diff --combined drivers/net/ethernet/ibm/ibmvnic.c index fa4bb940665c,07efa2b40003..4f83f97ffe8b --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@@ -1485,7 -1485,7 +1485,7 @@@ static netdev_tx_t ibmvnic_xmit(struct
memcpy(dst + cur, page_address(skb_frag_page(frag)) + - frag->page_offset, skb_frag_size(frag)); + skb_frag_off(frag), skb_frag_size(frag)); cur += skb_frag_size(frag); } } else { @@@ -1983,10 -1983,6 +1983,10 @@@ static void __ibmvnic_reset(struct work
rwi = get_next_rwi(adapter); while (rwi) { + if (adapter->state == VNIC_REMOVING || + adapter->state == VNIC_REMOVED) + goto out; + if (adapter->force_reset_recovery) { adapter->force_reset_recovery = false; rc = do_hard_reset(adapter, rwi, reset_state); @@@ -2011,7 -2007,7 +2011,7 @@@ netdev_dbg(adapter->netdev, "Reset failed\n"); free_all_rwi(adapter); } - +out: adapter->resetting = false; if (we_lock_rtnl) rtnl_unlock(); diff --combined drivers/net/ethernet/jme.c index 57e8aea98969,6d52cf5ce20e..25aa400e2e3c --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@@ -14,6 -14,7 +14,6 @@@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/pci.h> -#include <linux/pci-aspm.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> @@@ -2029,23 -2030,22 +2029,22 @@@ jme_map_tx_skb(struct jme_adapter *jme bool hidma = jme->dev->features & NETIF_F_HIGHDMA; int i, nr_frags = skb_shinfo(skb)->nr_frags; int mask = jme->tx_ring_mask; - const struct skb_frag_struct *frag; u32 len; int ret = 0;
for (i = 0 ; i < nr_frags ; ++i) { - frag = &skb_shinfo(skb)->frags[i]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + ctxdesc = txdesc + ((idx + i + 2) & (mask)); ctxbi = txbi + ((idx + i + 2) & (mask));
ret = jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, - skb_frag_page(frag), - frag->page_offset, skb_frag_size(frag), hidma); + skb_frag_page(frag), skb_frag_off(frag), + skb_frag_size(frag), hidma); if (ret) { jme_drop_tx_map(jme, idx, i); goto out; } - }
len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len; @@@ -3192,8 -3192,7 +3191,7 @@@ jme_shutdown(struct pci_dev *pdev static int jme_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct jme_adapter *jme = netdev_priv(netdev);
if (!netif_running(netdev)) @@@ -3235,8 -3234,7 +3233,7 @@@ static int jme_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); + struct net_device *netdev = dev_get_drvdata(dev); struct jme_adapter *jme = netdev_priv(netdev);
if (!netif_running(netdev)) diff --combined drivers/net/ethernet/marvell/sky2.c index e0363870f3a5,c2e00bb587cd..5f56ee83e3b1 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@@ -4931,13 -4931,6 +4931,13 @@@ static const struct dmi_system_id msi_b DMI_MATCH(DMI_BOARD_NAME, "P6T"), }, }, + { + .ident = "ASUS P6X", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "P6X"), + }, + }, {} };
@@@ -5174,8 -5167,7 +5174,7 @@@ static void sky2_remove(struct pci_dev
static int sky2_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct sky2_hw *hw = pci_get_drvdata(pdev); + struct sky2_hw *hw = dev_get_drvdata(dev); int i;
if (!hw) diff --combined drivers/net/ethernet/netronome/nfp/flower/offload.c index 457bdc60f3ee,b0708460e342..987ae221f6be --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@@ -61,6 -61,11 +61,11 @@@ NFP_FLOWER_LAYER_IPV4 | \ NFP_FLOWER_LAYER_IPV6)
+ #define NFP_FLOWER_PRE_TUN_RULE_FIELDS \ + (NFP_FLOWER_LAYER_PORT | \ + NFP_FLOWER_LAYER_MAC | \ + NFP_FLOWER_LAYER_IPV4) + struct nfp_flower_merge_check { union { struct { @@@ -489,6 -494,7 +494,7 @@@ nfp_flower_allocate_new(struct nfp_fl_k flow_pay->meta.flags = 0; INIT_LIST_HEAD(&flow_pay->linked_flows); flow_pay->in_hw = false; + flow_pay->pre_tun_rule.dev = NULL;
return flow_pay;
@@@ -732,28 -738,62 +738,62 @@@ nfp_flower_copy_pre_actions(char *act_d return act_off; }
- static int nfp_fl_verify_post_tun_acts(char *acts, int len) + static int + nfp_fl_verify_post_tun_acts(char *acts, int len, struct nfp_fl_push_vlan **vlan) { struct nfp_fl_act_head *a; unsigned int act_off = 0;
while (act_off < len) { a = (struct nfp_fl_act_head *)&acts[act_off]; - if (a->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT) + + if (a->jump_id == NFP_FL_ACTION_OPCODE_PUSH_VLAN && !act_off) + *vlan = (struct nfp_fl_push_vlan *)a; + else if (a->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT) return -EOPNOTSUPP;
act_off += a->len_lw << NFP_FL_LW_SIZ; }
+ /* Ensure any VLAN push also has an egress action. */ + if (*vlan && act_off <= sizeof(struct nfp_fl_push_vlan)) + return -EOPNOTSUPP; + return 0; }
static int + nfp_fl_push_vlan_after_tun(char *acts, int len, struct nfp_fl_push_vlan *vlan) + { + struct nfp_fl_set_ipv4_tun *tun; + struct nfp_fl_act_head *a; + unsigned int act_off = 0; + + while (act_off < len) { + a = (struct nfp_fl_act_head *)&acts[act_off]; + + if (a->jump_id == NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL) { + tun = (struct nfp_fl_set_ipv4_tun *)a; + tun->outer_vlan_tpid = vlan->vlan_tpid; + tun->outer_vlan_tci = vlan->vlan_tci; + + return 0; + } + + act_off += a->len_lw << NFP_FL_LW_SIZ; + } + + /* Return error if no tunnel action is found. */ + return -EOPNOTSUPP; + } + + static int nfp_flower_merge_action(struct nfp_fl_payload *sub_flow1, struct nfp_fl_payload *sub_flow2, struct nfp_fl_payload *merge_flow) { unsigned int sub1_act_len, sub2_act_len, pre_off1, pre_off2; + struct nfp_fl_push_vlan *post_tun_push_vlan = NULL; bool tunnel_act = false; char *merge_act; int err; @@@ -790,18 -830,36 +830,36 @@@ sub2_act_len -= pre_off2;
/* FW does a tunnel push when egressing, therefore, if sub_flow 1 pushes - * a tunnel, sub_flow 2 can only have output actions for a valid merge. + * a tunnel, there are restrictions on what sub_flow 2 actions lead to a + * valid merge. */ if (tunnel_act) { char *post_tun_acts = &sub_flow2->action_data[pre_off2];
- err = nfp_fl_verify_post_tun_acts(post_tun_acts, sub2_act_len); + err = nfp_fl_verify_post_tun_acts(post_tun_acts, sub2_act_len, + &post_tun_push_vlan); if (err) return err; + + if (post_tun_push_vlan) { + pre_off2 += sizeof(*post_tun_push_vlan); + sub2_act_len -= sizeof(*post_tun_push_vlan); + } }
/* Copy remaining actions from sub_flows 1 and 2. */ memcpy(merge_act, sub_flow1->action_data + pre_off1, sub1_act_len); + + if (post_tun_push_vlan) { + /* Update tunnel action in merge to include VLAN push. */ + err = nfp_fl_push_vlan_after_tun(merge_act, sub1_act_len, + post_tun_push_vlan); + if (err) + return err; + + merge_flow->meta.act_len -= sizeof(*post_tun_push_vlan); + } + merge_act += sub1_act_len; memcpy(merge_act, sub_flow2->action_data + pre_off2, sub2_act_len);
@@@ -945,6 -1003,106 +1003,106 @@@ err_destroy_merge_flow }
/** + * nfp_flower_validate_pre_tun_rule() + * @app: Pointer to the APP handle + * @flow: Pointer to NFP flow representation of rule + * @extack: Netlink extended ACK report + * + * Verifies the flow as a pre-tunnel rule. + * + * Return: negative value on error, 0 if verified. + */ + static int + nfp_flower_validate_pre_tun_rule(struct nfp_app *app, + struct nfp_fl_payload *flow, + struct netlink_ext_ack *extack) + { + struct nfp_flower_meta_tci *meta_tci; + struct nfp_flower_mac_mpls *mac; + struct nfp_fl_act_head *act; + u8 *mask = flow->mask_data; + bool vlan = false; + int act_offset; + u8 key_layer; + + meta_tci = (struct nfp_flower_meta_tci *)flow->unmasked_data; + if (meta_tci->tci & cpu_to_be16(NFP_FLOWER_MASK_VLAN_PRESENT)) { + u16 vlan_tci = be16_to_cpu(meta_tci->tci); + + vlan_tci &= ~NFP_FLOWER_MASK_VLAN_PRESENT; + flow->pre_tun_rule.vlan_tci = cpu_to_be16(vlan_tci); + vlan = true; + } else { + flow->pre_tun_rule.vlan_tci = cpu_to_be16(0xffff); + } + + key_layer = meta_tci->nfp_flow_key_layer; + if (key_layer & ~NFP_FLOWER_PRE_TUN_RULE_FIELDS) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: too many match fields"); + return -EOPNOTSUPP; + } + + if (!(key_layer & NFP_FLOWER_LAYER_MAC)) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: MAC fields match required"); + return -EOPNOTSUPP; + } + + /* Skip fields known to exist. */ + mask += sizeof(struct nfp_flower_meta_tci); + mask += sizeof(struct nfp_flower_in_port); + + /* Ensure destination MAC address is fully matched. */ + mac = (struct nfp_flower_mac_mpls *)mask; + if (!is_broadcast_ether_addr(&mac->mac_dst[0])) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: dest MAC field must not be masked"); + return -EOPNOTSUPP; + } + + if (key_layer & NFP_FLOWER_LAYER_IPV4) { + int ip_flags = offsetof(struct nfp_flower_ipv4, ip_ext.flags); + int ip_proto = offsetof(struct nfp_flower_ipv4, ip_ext.proto); + int i; + + mask += sizeof(struct nfp_flower_mac_mpls); + + /* Ensure proto and flags are the only IP layer fields. */ + for (i = 0; i < sizeof(struct nfp_flower_ipv4); i++) + if (mask[i] && i != ip_flags && i != ip_proto) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: only flags and proto can be matched in ip header"); + return -EOPNOTSUPP; + } + } + + /* Action must be a single egress or pop_vlan and egress. */ + act_offset = 0; + act = (struct nfp_fl_act_head *)&flow->action_data[act_offset]; + if (vlan) { + if (act->jump_id != NFP_FL_ACTION_OPCODE_POP_VLAN) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: match on VLAN must have VLAN pop as first action"); + return -EOPNOTSUPP; + } + + act_offset += act->len_lw << NFP_FL_LW_SIZ; + act = (struct nfp_fl_act_head *)&flow->action_data[act_offset]; + } + + if (act->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: non egress action detected where egress was expected"); + return -EOPNOTSUPP; + } + + act_offset += act->len_lw << NFP_FL_LW_SIZ; + + /* Ensure there are no more actions after egress. */ + if (act_offset != flow->meta.act_len) { + NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: egress is not the last action"); + return -EOPNOTSUPP; + } + + return 0; + } + + /** * nfp_flower_add_offload() - Adds a new flow to hardware. * @app: Pointer to the APP handle * @netdev: netdev structure. @@@ -994,6 -1152,12 +1152,12 @@@ nfp_flower_add_offload(struct nfp_app * if (err) goto err_destroy_flow;
+ if (flow_pay->pre_tun_rule.dev) { + err = nfp_flower_validate_pre_tun_rule(app, flow_pay, extack); + if (err) + goto err_destroy_flow; + } + err = nfp_compile_flow_metadata(app, flow, flow_pay, netdev, extack); if (err) goto err_destroy_flow; @@@ -1006,8 -1170,11 +1170,11 @@@ goto err_release_metadata; }
- err = nfp_flower_xmit_flow(app, flow_pay, - NFP_FLOWER_CMSG_TYPE_FLOW_ADD); + if (flow_pay->pre_tun_rule.dev) + err = nfp_flower_xmit_pre_tun_flow(app, flow_pay); + else + err = nfp_flower_xmit_flow(app, flow_pay, + NFP_FLOWER_CMSG_TYPE_FLOW_ADD); if (err) goto err_remove_rhash;
@@@ -1149,8 -1316,11 +1316,11 @@@ nfp_flower_del_offload(struct nfp_app * goto err_free_merge_flow; }
- err = nfp_flower_xmit_flow(app, nfp_flow, - NFP_FLOWER_CMSG_TYPE_FLOW_DEL); + if (nfp_flow->pre_tun_rule.dev) + err = nfp_flower_xmit_pre_tun_del_flow(app, nfp_flow); + else + err = nfp_flower_xmit_flow(app, nfp_flow, + NFP_FLOWER_CMSG_TYPE_FLOW_DEL); /* Fall through on error. */
err_free_merge_flow: @@@ -1409,10 -1579,9 +1579,10 @@@ nfp_flower_setup_indr_tc_block(struct n struct nfp_flower_priv *priv = app->priv; struct flow_block_cb *block_cb;
- if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS && - !(f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS && - nfp_flower_internal_port_can_offload(app, netdev))) + if ((f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS && + !nfp_flower_internal_port_can_offload(app, netdev)) || + (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS && + nfp_flower_internal_port_can_offload(app, netdev))) return -EOPNOTSUPP;
switch (f->command) { @@@ -1487,16 -1656,17 +1657,17 @@@ int nfp_flower_reg_indir_block_handler( return NOTIFY_OK;
if (event == NETDEV_REGISTER) { - err = __tc_indr_block_cb_register(netdev, app, - nfp_flower_indr_setup_tc_cb, - app); + err = __flow_indr_block_cb_register(netdev, app, + nfp_flower_indr_setup_tc_cb, + app); if (err) nfp_flower_cmsg_warn(app, "Indirect block reg failed - %s\n", netdev->name); } else if (event == NETDEV_UNREGISTER) { - __tc_indr_block_cb_unregister(netdev, - nfp_flower_indr_setup_tc_cb, app); + __flow_indr_block_cb_unregister(netdev, + nfp_flower_indr_setup_tc_cb, + app); }
return NOTIFY_OK; diff --combined drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index f0ee982eb1b5,def8c198b016..2600ce476d6b --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@@ -15,6 -15,24 +15,24 @@@
#define NFP_FL_MAX_ROUTES 32
+ #define NFP_TUN_PRE_TUN_RULE_LIMIT 32 + #define NFP_TUN_PRE_TUN_RULE_DEL 0x1 + #define NFP_TUN_PRE_TUN_IDX_BIT 0x8 + + /** + * struct nfp_tun_pre_run_rule - rule matched before decap + * @flags: options for the rule offset + * @port_idx: index of destination MAC address for the rule + * @vlan_tci: VLAN info associated with MAC + * @host_ctx_id: stats context of rule to update + */ + struct nfp_tun_pre_tun_rule { + __be32 flags; + __be16 port_idx; + __be16 vlan_tci; + __be32 host_ctx_id; + }; + /** * struct nfp_tun_active_tuns - periodic message of active tunnels * @seq: sequence number of the message @@@ -124,11 -142,12 +142,12 @@@ enum nfp_flower_mac_offload_cmd
/** * struct nfp_tun_offloaded_mac - hashtable entry for an offloaded MAC - * @ht_node: Hashtable entry - * @addr: Offloaded MAC address - * @index: Offloaded index for given MAC address - * @ref_count: Number of devs using this MAC address - * @repr_list: List of reprs sharing this MAC address + * @ht_node: Hashtable entry + * @addr: Offloaded MAC address + * @index: Offloaded index for given MAC address + * @ref_count: Number of devs using this MAC address + * @repr_list: List of reprs sharing this MAC address + * @bridge_count: Number of bridge/internal devs with MAC */ struct nfp_tun_offloaded_mac { struct rhash_head ht_node; @@@ -136,6 -155,7 +155,7 @@@ u16 index; int ref_count; struct list_head repr_list; + int bridge_count; };
static const struct rhashtable_params offloaded_macs_params = { @@@ -328,13 -348,13 +348,13 @@@ nfp_tun_neigh_event_handler(struct noti
flow.daddr = *(__be32 *)n->primary_key;
- /* Only concerned with route changes for representors. */ - if (!nfp_netdev_is_nfp_repr(n->dev)) - return NOTIFY_DONE; - app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb); app = app_priv->app;
+ if (!nfp_netdev_is_nfp_repr(n->dev) && + !nfp_flower_internal_port_can_offload(app, n->dev)) + return NOTIFY_DONE; + /* Only concerned with changes to routes already added to NFP. */ if (!nfp_tun_has_route(app, flow.daddr)) return NOTIFY_DONE; @@@ -556,6 -576,8 +576,8 @@@ nfp_tunnel_offloaded_macs_inc_ref_and_l list_del(&repr_priv->mac_list);
list_add_tail(&repr_priv->mac_list, &entry->repr_list); + } else if (nfp_flower_is_supported_bridge(netdev)) { + entry->bridge_count++; }
entry->ref_count++; @@@ -572,20 -594,35 +594,35 @@@ nfp_tunnel_add_shared_mac(struct nfp_ap
entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr); if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) { - nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, netdev, mod); - return 0; + if (entry->bridge_count || + !nfp_flower_is_supported_bridge(netdev)) { + nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, + netdev, mod); + return 0; + } + + /* MAC is global but matches need to go to pre_tun table. */ + nfp_mac_idx = entry->index | NFP_TUN_PRE_TUN_IDX_BIT; }
- /* Assign a global index if non-repr or MAC address is now shared. */ - if (entry || !port) { - ida_idx = ida_simple_get(&priv->tun.mac_off_ids, 0, - NFP_MAX_MAC_INDEX, GFP_KERNEL); - if (ida_idx < 0) - return ida_idx; + if (!nfp_mac_idx) { + /* Assign a global index if non-repr or MAC is now shared. */ + if (entry || !port) { + ida_idx = ida_simple_get(&priv->tun.mac_off_ids, 0, + NFP_MAX_MAC_INDEX, GFP_KERNEL); + if (ida_idx < 0) + return ida_idx;
- nfp_mac_idx = nfp_tunnel_get_global_mac_idx_from_ida(ida_idx); - } else { - nfp_mac_idx = nfp_tunnel_get_mac_idx_from_phy_port_id(port); + nfp_mac_idx = + nfp_tunnel_get_global_mac_idx_from_ida(ida_idx); + + if (nfp_flower_is_supported_bridge(netdev)) + nfp_mac_idx |= NFP_TUN_PRE_TUN_IDX_BIT; + + } else { + nfp_mac_idx = + nfp_tunnel_get_mac_idx_from_phy_port_id(port); + } }
if (!entry) { @@@ -654,6 -691,25 +691,25 @@@ nfp_tunnel_del_shared_mac(struct nfp_ap list_del(&repr_priv->mac_list); }
+ if (nfp_flower_is_supported_bridge(netdev)) { + entry->bridge_count--; + + if (!entry->bridge_count && entry->ref_count) { + u16 nfp_mac_idx; + + nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; + if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, + false)) { + nfp_flower_cmsg_warn(app, "MAC offload index revert failed on %s.\n", + netdev_name(netdev)); + return 0; + } + + entry->index = nfp_mac_idx; + return 0; + } + } + /* If MAC is now used by 1 repr set the offloaded MAC index to port. */ if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) { u16 nfp_mac_idx; @@@ -713,6 -769,9 +769,9 @@@ nfp_tunnel_offload_mac(struct nfp_app * return 0;
repr_priv = repr->app_priv; + if (repr_priv->on_bridge) + return 0; + mac_offloaded = &repr_priv->mac_offloaded; off_mac = &repr_priv->offloaded_mac_addr[0]; port = nfp_repr_get_port_id(netdev); @@@ -828,10 -887,119 +887,119 @@@ int nfp_tunnel_mac_event_handler(struc if (err) nfp_flower_cmsg_warn(app, "Failed to offload MAC change on %s.\n", netdev_name(netdev)); + } else if (event == NETDEV_CHANGEUPPER) { + /* If a repr is attached to a bridge then tunnel packets + * entering the physical port are directed through the bridge + * datapath and cannot be directly detunneled. Therefore, + * associated offloaded MACs and indexes should not be used + * by fw for detunneling. + */ + struct netdev_notifier_changeupper_info *info = ptr; + struct net_device *upper = info->upper_dev; + struct nfp_flower_repr_priv *repr_priv; + struct nfp_repr *repr; + + if (!nfp_netdev_is_nfp_repr(netdev) || + !nfp_flower_is_supported_bridge(upper)) + return NOTIFY_OK; + + repr = netdev_priv(netdev); + if (repr->app != app) + return NOTIFY_OK; + + repr_priv = repr->app_priv; + + if (info->linking) { + if (nfp_tunnel_offload_mac(app, netdev, + NFP_TUNNEL_MAC_OFFLOAD_DEL)) + nfp_flower_cmsg_warn(app, "Failed to delete offloaded MAC on %s.\n", + netdev_name(netdev)); + repr_priv->on_bridge = true; + } else { + repr_priv->on_bridge = false; + + if (!(netdev->flags & IFF_UP)) + return NOTIFY_OK; + + if (nfp_tunnel_offload_mac(app, netdev, + NFP_TUNNEL_MAC_OFFLOAD_ADD)) + nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n", + netdev_name(netdev)); + } } return NOTIFY_OK; }
+ int nfp_flower_xmit_pre_tun_flow(struct nfp_app *app, + struct nfp_fl_payload *flow) + { + struct nfp_flower_priv *app_priv = app->priv; + struct nfp_tun_offloaded_mac *mac_entry; + struct nfp_tun_pre_tun_rule payload; + struct net_device *internal_dev; + int err; + + if (app_priv->pre_tun_rule_cnt == NFP_TUN_PRE_TUN_RULE_LIMIT) + return -ENOSPC; + + memset(&payload, 0, sizeof(struct nfp_tun_pre_tun_rule)); + + internal_dev = flow->pre_tun_rule.dev; + payload.vlan_tci = flow->pre_tun_rule.vlan_tci; + payload.host_ctx_id = flow->meta.host_ctx_id; + + /* Lookup MAC index for the pre-tunnel rule egress device. + * Note that because the device is always an internal port, it will + * have a constant global index so does not need to be tracked. + */ + mac_entry = nfp_tunnel_lookup_offloaded_macs(app, + internal_dev->dev_addr); + if (!mac_entry) + return -ENOENT; + + payload.port_idx = cpu_to_be16(mac_entry->index); + + /* Copy mac id and vlan to flow - dev may not exist at delete time. */ + flow->pre_tun_rule.vlan_tci = payload.vlan_tci; + flow->pre_tun_rule.port_idx = payload.port_idx; + + err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, + sizeof(struct nfp_tun_pre_tun_rule), + (unsigned char *)&payload, GFP_KERNEL); + if (err) + return err; + + app_priv->pre_tun_rule_cnt++; + + return 0; + } + + int nfp_flower_xmit_pre_tun_del_flow(struct nfp_app *app, + struct nfp_fl_payload *flow) + { + struct nfp_flower_priv *app_priv = app->priv; + struct nfp_tun_pre_tun_rule payload; + u32 tmp_flags = 0; + int err; + + memset(&payload, 0, sizeof(struct nfp_tun_pre_tun_rule)); + + tmp_flags |= NFP_TUN_PRE_TUN_RULE_DEL; + payload.flags = cpu_to_be32(tmp_flags); + payload.vlan_tci = flow->pre_tun_rule.vlan_tci; + payload.port_idx = flow->pre_tun_rule.port_idx; + + err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, + sizeof(struct nfp_tun_pre_tun_rule), + (unsigned char *)&payload, GFP_KERNEL); + if (err) + return err; + + app_priv->pre_tun_rule_cnt--; + + return 0; + } + int nfp_tunnel_config_start(struct nfp_app *app) { struct nfp_flower_priv *priv = app->priv; diff --combined drivers/net/ethernet/realtek/r8169_main.c index 492e8623a154,0ef01db1f8b8..74f81fe03810 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@@ -28,6 -28,7 +28,6 @@@ #include <linux/dma-mapping.h> #include <linux/pm_runtime.h> #include <linux/prefetch.h> -#include <linux/pci-aspm.h> #include <linux/ipv6.h> #include <net/ip6_checksum.h>
@@@ -54,13 -55,14 +54,14 @@@ #define FIRMWARE_8168H_2 "rtl_nic/rtl8168h-2.fw" #define FIRMWARE_8107E_1 "rtl_nic/rtl8107e-1.fw" #define FIRMWARE_8107E_2 "rtl_nic/rtl8107e-2.fw" + #define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw"
#define R8169_MSG_DEFAULT \ (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). The RTL chips use a 64 element hash table based on the Ethernet CRC. */ - static const int multicast_filter_limit = 32; + #define MC_FILTER_LIMIT 32
#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ @@@ -134,6 -136,8 +135,8 @@@ enum mac_version RTL_GIGA_MAC_VER_49, RTL_GIGA_MAC_VER_50, RTL_GIGA_MAC_VER_51, + RTL_GIGA_MAC_VER_60, + RTL_GIGA_MAC_VER_61, RTL_GIGA_MAC_NONE };
@@@ -199,6 -203,8 +202,8 @@@ static const struct [RTL_GIGA_MAC_VER_49] = {"RTL8168ep/8111ep" }, [RTL_GIGA_MAC_VER_50] = {"RTL8168ep/8111ep" }, [RTL_GIGA_MAC_VER_51] = {"RTL8168ep/8111ep" }, + [RTL_GIGA_MAC_VER_60] = {"RTL8125" }, + [RTL_GIGA_MAC_VER_61] = {"RTL8125", FIRMWARE_8125A_3}, };
static const struct pci_device_id rtl8169_pci_tbl[] = { @@@ -219,6 -225,8 +224,8 @@@ { PCI_VDEVICE(USR, 0x0116) }, { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024 }, { 0x0001, 0x8168, PCI_ANY_ID, 0x2410 }, + { PCI_VDEVICE(REALTEK, 0x8125) }, + { PCI_VDEVICE(REALTEK, 0x3000) }, {} };
@@@ -270,7 -278,6 +277,6 @@@ enum rtl_registers Config3 = 0x54, Config4 = 0x55, Config5 = 0x56, - MultiIntr = 0x5c, PHYAR = 0x60, PHYstatus = 0x6c, RxMaxSize = 0xda, @@@ -384,6 -391,19 +390,19 @@@ enum rtl8168_registers #define EARLY_TALLY_EN (1 << 16) };
+ enum rtl8125_registers { + IntrMask_8125 = 0x38, + IntrStatus_8125 = 0x3c, + TxPoll_8125 = 0x90, + MAC0_BKP = 0x19e0, + }; + + #define RX_VLAN_INNER_8125 BIT(22) + #define RX_VLAN_OUTER_8125 BIT(23) + #define RX_VLAN_8125 (RX_VLAN_INNER_8125 | RX_VLAN_OUTER_8125) + + #define RX_FETCH_DFLT_8125 (8 << 27) + enum rtl_register_content { /* InterruptStatusBits */ SYSErr = 0x8000, @@@ -538,11 -558,11 +557,11 @@@ enum rtl_tx_desc_bit_1 TD1_GTSENV4 = (1 << 26), /* Giant Send for IPv4 */ TD1_GTSENV6 = (1 << 25), /* Giant Send for IPv6 */ #define GTTCPHO_SHIFT 18 - #define GTTCPHO_MAX 0x7fU + #define GTTCPHO_MAX 0x7f
/* Second doubleword. */ #define TCPHO_SHIFT 18 - #define TCPHO_MAX 0x3ffU + #define TCPHO_MAX 0x3ff #define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */ TD1_IPv6_CS = (1 << 28), /* Calculate IPv6 checksum */ TD1_IPv4_CS = (1 << 29), /* Calculate IPv4 checksum */ @@@ -568,6 -588,11 +587,11 @@@ enum rtl_rx_desc_bit
#define RsvdMask 0x3fffc000
+ #define RTL_GSO_MAX_SIZE_V1 32000 + #define RTL_GSO_MAX_SEGS_V1 24 + #define RTL_GSO_MAX_SIZE_V2 64000 + #define RTL_GSO_MAX_SEGS_V2 64 + struct TxDesc { __le32 opts1; __le32 opts2; @@@ -637,10 -662,10 +661,10 @@@ struct rtl8169_private struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; - void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ + struct page *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ u16 cp_cmd; - u16 irq_mask; + u32 irq_mask; struct clk *clk;
struct { @@@ -690,6 -715,7 +714,7 @@@ MODULE_FIRMWARE(FIRMWARE_8168H_1) MODULE_FIRMWARE(FIRMWARE_8168H_2); MODULE_FIRMWARE(FIRMWARE_8107E_1); MODULE_FIRMWARE(FIRMWARE_8107E_2); + MODULE_FIRMWARE(FIRMWARE_8125A_3);
static inline struct device *tp_to_dev(struct rtl8169_private *tp) { @@@ -722,12 -748,33 +747,33 @@@ static void rtl_tx_performance_tweak(st PCI_EXP_DEVCTL_READRQ, force); }
+ static bool rtl_is_8125(struct rtl8169_private *tp) + { + return tp->mac_version >= RTL_GIGA_MAC_VER_60; + } + static bool rtl_is_8168evl_up(struct rtl8169_private *tp) { return tp->mac_version >= RTL_GIGA_MAC_VER_34 && + tp->mac_version != RTL_GIGA_MAC_VER_39 && + tp->mac_version <= RTL_GIGA_MAC_VER_51; + } + + static bool rtl_supports_eee(struct rtl8169_private *tp) + { + return tp->mac_version >= RTL_GIGA_MAC_VER_34 && + tp->mac_version != RTL_GIGA_MAC_VER_37 && tp->mac_version != RTL_GIGA_MAC_VER_39; }
+ static void rtl_read_mac_from_reg(struct rtl8169_private *tp, u8 *mac, int reg) + { + int i; + + for (i = 0; i < ETH_ALEN; i++) + mac[i] = RTL_R8(tp, reg + i); + } + struct rtl_cond { bool (*check)(struct rtl8169_private *); const char *msg; @@@ -845,6 -892,14 +891,14 @@@ static u16 r8168_mac_ocp_read(struct rt return RTL_R32(tp, OCPDR); }
+ static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask, + u16 set) + { + u16 data = r8168_mac_ocp_read(tp, reg); + + r8168_mac_ocp_write(tp, reg, (data & ~mask) | set); + } + #define OCP_STD_PHY_BASE 0xa400
static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value) @@@ -994,7 -1049,7 +1048,7 @@@ static void rtl_writephy(struct rtl8169 case RTL_GIGA_MAC_VER_31: r8168dp_2_mdio_write(tp, location, val); break; - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: + case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_61: r8168g_mdio_write(tp, location, val); break; default: @@@ -1011,7 -1066,7 +1065,7 @@@ static int rtl_readphy(struct rtl8169_p case RTL_GIGA_MAC_VER_28: case RTL_GIGA_MAC_VER_31: return r8168dp_2_mdio_read(tp, location); - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: + case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_61: return r8168g_mdio_read(tp, location); default: return r8169_mdio_read(tp, location); @@@ -1293,14 -1348,28 +1347,28 @@@ static u8 rtl8168d_efuse_read(struct rt RTL_R32(tp, EFUSEAR) & EFUSEAR_DATA_MASK : ~0; }
- static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) + static u32 rtl_get_events(struct rtl8169_private *tp) + { + if (rtl_is_8125(tp)) + return RTL_R32(tp, IntrStatus_8125); + else + return RTL_R16(tp, IntrStatus); + } + + static void rtl_ack_events(struct rtl8169_private *tp, u32 bits) { - RTL_W16(tp, IntrStatus, bits); + if (rtl_is_8125(tp)) + RTL_W32(tp, IntrStatus_8125, bits); + else + RTL_W16(tp, IntrStatus, bits); }
static void rtl_irq_disable(struct rtl8169_private *tp) { - RTL_W16(tp, IntrMask, 0); + if (rtl_is_8125(tp)) + RTL_W32(tp, IntrMask_8125, 0); + else + RTL_W16(tp, IntrMask, 0); tp->irq_enabled = 0; }
@@@ -1311,13 -1380,16 +1379,16 @@@ static void rtl_irq_enable(struct rtl8169_private *tp) { tp->irq_enabled = 1; - RTL_W16(tp, IntrMask, tp->irq_mask); + if (rtl_is_8125(tp)) + RTL_W32(tp, IntrMask_8125, tp->irq_mask); + else + RTL_W16(tp, IntrMask, tp->irq_mask); }
static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) { rtl_irq_disable(tp); - rtl_ack_events(tp, 0xffff); + rtl_ack_events(tp, 0xffffffff); /* PCI commit */ RTL_R8(tp, ChipCmd); } @@@ -1376,7 -1448,6 +1447,6 @@@ static void rtl8169_get_wol(struct net_
static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) { - unsigned int i, tmp; static const struct { u32 opt; u16 reg; @@@ -1389,20 -1460,25 +1459,25 @@@ { WAKE_ANY, Config5, LanWake }, { WAKE_MAGIC, Config3, MagicPacket } }; + unsigned int i, tmp = ARRAY_SIZE(cfg); u8 options;
rtl_unlock_config_regs(tp);
if (rtl_is_8168evl_up(tp)) { - tmp = ARRAY_SIZE(cfg) - 1; + tmp--; if (wolopts & WAKE_MAGIC) rtl_eri_set_bits(tp, 0x0dc, ERIAR_MASK_0100, MagicPacket_v2); else rtl_eri_clear_bits(tp, 0x0dc, ERIAR_MASK_0100, MagicPacket_v2); - } else { - tmp = ARRAY_SIZE(cfg); + } else if (rtl_is_8125(tp)) { + tmp--; + if (wolopts & WAKE_MAGIC) + r8168_mac_ocp_modify(tp, 0xc0b6, 0, BIT(0)); + else + r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0); }
for (i = 0; i < tmp; i++) { @@@ -1413,18 -1489,22 +1488,22 @@@ }
switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: options = RTL_R8(tp, Config1) & ~PMEnable; if (wolopts) options |= PMEnable; RTL_W8(tp, Config1, options); break; - default: + case RTL_GIGA_MAC_VER_34: + case RTL_GIGA_MAC_VER_37: + case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_51: options = RTL_R8(tp, Config2) & ~PME_SIGNAL; if (wolopts) options |= PME_SIGNAL; RTL_W8(tp, Config2, options); break; + default: + break; }
rtl_lock_config_regs(tp); @@@ -1504,6 -1584,13 +1583,13 @@@ static int rtl8169_set_features(struct else rx_config &= ~(AcceptErr | AcceptRunt);
+ if (rtl_is_8125(tp)) { + if (features & NETIF_F_HW_VLAN_CTAG_RX) + rx_config |= RX_VLAN_8125; + else + rx_config &= ~RX_VLAN_8125; + } + RTL_W32(tp, RxConfig, rx_config);
if (features & NETIF_F_RXCSUM) @@@ -1511,10 -1598,12 +1597,12 @@@ else tp->cp_cmd &= ~RxChkSum;
- if (features & NETIF_F_HW_VLAN_CTAG_RX) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; + if (!rtl_is_8125(tp)) { + if (features & NETIF_F_HW_VLAN_CTAG_RX) + tp->cp_cmd |= RxVlan; + else + tp->cp_cmd &= ~RxVlan; + }
RTL_W16(tp, CPlusCmd, tp->cp_cmd); RTL_R16(tp, CPlusCmd); @@@ -1813,6 -1902,9 +1901,9 @@@ static int rtl_get_coalesce(struct net_ int i; u16 w;
+ if (rtl_is_8125(tp)) + return -EOPNOTSUPP; + memset(ec, 0, sizeof(*ec));
/* get rx/tx scale corresponding to current speed and CPlusCmd[0:1] */ @@@ -1881,6 -1973,9 +1972,9 @@@ static int rtl_set_coalesce(struct net_ u16 w = 0, cp01; int i;
+ if (rtl_is_8125(tp)) + return -EOPNOTSUPP; + scale = rtl_coalesce_choose_scale(dev, max(p[0].usecs, p[1].usecs) * 1000, &cp01); if (IS_ERR(scale)) @@@ -1928,144 -2023,40 +2022,40 @@@ return 0; }
- static int rtl_get_eee_supp(struct rtl8169_private *tp) - { - struct phy_device *phydev = tp->phydev; - int ret; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_38: - ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE); - break; - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: - ret = phy_read_paged(phydev, 0x0a5c, 0x12); - break; - default: - ret = -EPROTONOSUPPORT; - break; - } - - return ret; - } - - static int rtl_get_eee_lpadv(struct rtl8169_private *tp) - { - struct phy_device *phydev = tp->phydev; - int ret; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_38: - ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE); - break; - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: - ret = phy_read_paged(phydev, 0x0a5d, 0x11); - break; - default: - ret = -EPROTONOSUPPORT; - break; - } - - return ret; - } - - static int rtl_get_eee_adv(struct rtl8169_private *tp) - { - struct phy_device *phydev = tp->phydev; - int ret; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_38: - ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV); - break; - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: - ret = phy_read_paged(phydev, 0x0a5d, 0x10); - break; - default: - ret = -EPROTONOSUPPORT; - break; - } - - return ret; - } - - static int rtl_set_eee_adv(struct rtl8169_private *tp, int val) - { - struct phy_device *phydev = tp->phydev; - int ret = 0; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_38: - ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); - break; - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: - phy_write_paged(phydev, 0x0a5d, 0x10, val); - break; - default: - ret = -EPROTONOSUPPORT; - break; - } - - return ret; - } - static int rtl8169_get_eee(struct net_device *dev, struct ethtool_eee *data) { struct rtl8169_private *tp = netdev_priv(dev); struct device *d = tp_to_dev(tp); int ret;
+ if (!rtl_supports_eee(tp)) + return -EOPNOTSUPP; + pm_runtime_get_noresume(d);
if (!pm_runtime_active(d)) { ret = -EOPNOTSUPP; - goto out; + } else { + ret = phy_ethtool_get_eee(tp->phydev, data); }
- /* Get Supported EEE */ - ret = rtl_get_eee_supp(tp); - if (ret < 0) - goto out; - data->supported = mmd_eee_cap_to_ethtool_sup_t(ret); - - /* Get advertisement EEE */ - ret = rtl_get_eee_adv(tp); - if (ret < 0) - goto out; - data->advertised = mmd_eee_adv_to_ethtool_adv_t(ret); - data->eee_enabled = !!data->advertised; - - /* Get LP advertisement EEE */ - ret = rtl_get_eee_lpadv(tp); - if (ret < 0) - goto out; - data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(ret); - data->eee_active = !!(data->advertised & data->lp_advertised); - out: pm_runtime_put_noidle(d); - return ret < 0 ? ret : 0; + + return ret; }
static int rtl8169_set_eee(struct net_device *dev, struct ethtool_eee *data) { struct rtl8169_private *tp = netdev_priv(dev); struct device *d = tp_to_dev(tp); - int old_adv, adv = 0, cap, ret; + int ret; + + if (!rtl_supports_eee(tp)) + return -EOPNOTSUPP;
pm_runtime_get_noresume(d);
- if (!dev->phydev || !pm_runtime_active(d)) { + if (!pm_runtime_active(d)) { ret = -EOPNOTSUPP; goto out; } @@@ -2076,38 -2067,10 +2066,10 @@@ goto out; }
- /* Get Supported EEE */ - ret = rtl_get_eee_supp(tp); - if (ret < 0) - goto out; - cap = ret; - - ret = rtl_get_eee_adv(tp); - if (ret < 0) - goto out; - old_adv = ret; - - if (data->eee_enabled) { - adv = !data->advertised ? cap : - ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap; - /* Mask prohibited EEE modes */ - adv &= ~dev->phydev->eee_broken_modes; - } - - if (old_adv != adv) { - ret = rtl_set_eee_adv(tp, adv); - if (ret < 0) - goto out; - - /* Restart autonegotiation so the new modes get sent to the - * link partner. - */ - ret = phy_restart_aneg(dev->phydev); - } - + ret = phy_ethtool_set_eee(tp->phydev, data); out: pm_runtime_put_noidle(d); - return ret < 0 ? ret : 0; + return ret; }
static const struct ethtool_ops rtl8169_ethtool_ops = { @@@ -2134,10 -2097,11 +2096,11 @@@
static void rtl_enable_eee(struct rtl8169_private *tp) { - int supported = rtl_get_eee_supp(tp); + struct phy_device *phydev = tp->phydev; + int supported = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
if (supported > 0) - rtl_set_eee_adv(tp, supported); + phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, supported); }
static void rtl8169_get_mac_version(struct rtl8169_private *tp) @@@ -2158,6 -2122,10 +2121,10 @@@ u16 val; u16 mac_version; } mac_info[] = { + /* 8125 family. */ + { 0x7cf, 0x608, RTL_GIGA_MAC_VER_60 }, + { 0x7c8, 0x608, RTL_GIGA_MAC_VER_61 }, + /* 8168EP family. */ { 0x7cf, 0x502, RTL_GIGA_MAC_VER_51 }, { 0x7cf, 0x501, RTL_GIGA_MAC_VER_50 }, @@@ -2303,6 -2271,12 +2270,12 @@@ static void rtl8168_config_eee_mac(stru rtl_eri_set_bits(tp, 0x1b0, ERIAR_MASK_1111, 0x0003); }
+ static void rtl8125_config_eee_mac(struct rtl8169_private *tp) + { + r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0)); + r8168_mac_ocp_modify(tp, 0xeb62, 0, BIT(2) | BIT(1)); + } + static void rtl8168f_config_eee_phy(struct rtl8169_private *tp) { struct phy_device *phydev = tp->phydev; @@@ -2323,6 -2297,26 +2296,26 @@@ static void rtl8168g_config_eee_phy(str phy_modify_paged(tp->phydev, 0x0a43, 0x11, 0, BIT(4)); }
+ static void rtl8168h_config_eee_phy(struct rtl8169_private *tp) + { + struct phy_device *phydev = tp->phydev; + + rtl8168g_config_eee_phy(tp); + + phy_modify_paged(phydev, 0xa4a, 0x11, 0x0000, 0x0200); + phy_modify_paged(phydev, 0xa42, 0x14, 0x0000, 0x0080); + } + + static void rtl8125_config_eee_phy(struct rtl8169_private *tp) + { + struct phy_device *phydev = tp->phydev; + + rtl8168h_config_eee_phy(tp); + + phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000); + phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000); + } + static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@@ -3390,7 -3384,7 +3383,7 @@@ static void rtl8168h_1_hw_phy_config(st phy_modify_paged(tp->phydev, 0x0a44, 0x11, BIT(7), 0);
rtl8168g_disable_aldps(tp); - rtl8168g_config_eee_phy(tp); + rtl8168h_config_eee_phy(tp); rtl_enable_eee(tp); }
@@@ -3643,6 -3637,134 +3636,134 @@@ static void rtl8106e_hw_phy_config(stru rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000); }
+ static void rtl8125_1_hw_phy_config(struct rtl8169_private *tp) + { + struct phy_device *phydev = tp->phydev; + + phy_modify_paged(phydev, 0xad4, 0x10, 0x03ff, 0x0084); + phy_modify_paged(phydev, 0xad4, 0x17, 0x0000, 0x0010); + phy_modify_paged(phydev, 0xad1, 0x13, 0x03ff, 0x0006); + phy_modify_paged(phydev, 0xad3, 0x11, 0x003f, 0x0006); + phy_modify_paged(phydev, 0xac0, 0x14, 0x0000, 0x1100); + phy_modify_paged(phydev, 0xac8, 0x15, 0xf000, 0x7000); + phy_modify_paged(phydev, 0xad1, 0x14, 0x0000, 0x0400); + phy_modify_paged(phydev, 0xad1, 0x15, 0x0000, 0x03ff); + phy_modify_paged(phydev, 0xad1, 0x16, 0x0000, 0x03ff); + + phy_write(phydev, 0x1f, 0x0a43); + phy_write(phydev, 0x13, 0x80ea); + phy_modify(phydev, 0x14, 0xff00, 0xc400); + phy_write(phydev, 0x13, 0x80eb); + phy_modify(phydev, 0x14, 0x0700, 0x0300); + phy_write(phydev, 0x13, 0x80f8); + phy_modify(phydev, 0x14, 0xff00, 0x1c00); + phy_write(phydev, 0x13, 0x80f1); + phy_modify(phydev, 0x14, 0xff00, 0x3000); + phy_write(phydev, 0x13, 0x80fe); + phy_modify(phydev, 0x14, 0xff00, 0xa500); + phy_write(phydev, 0x13, 0x8102); + phy_modify(phydev, 0x14, 0xff00, 0x5000); + phy_write(phydev, 0x13, 0x8105); + phy_modify(phydev, 0x14, 0xff00, 0x3300); + phy_write(phydev, 0x13, 0x8100); + phy_modify(phydev, 0x14, 0xff00, 0x7000); + phy_write(phydev, 0x13, 0x8104); + phy_modify(phydev, 0x14, 0xff00, 0xf000); + phy_write(phydev, 0x13, 0x8106); + phy_modify(phydev, 0x14, 0xff00, 0x6500); + phy_write(phydev, 0x13, 0x80dc); + phy_modify(phydev, 0x14, 0xff00, 0xed00); + phy_write(phydev, 0x13, 0x80df); + phy_set_bits(phydev, 0x14, BIT(8)); + phy_write(phydev, 0x13, 0x80e1); + phy_clear_bits(phydev, 0x14, BIT(8)); + phy_write(phydev, 0x1f, 0x0000); + + phy_modify_paged(phydev, 0xbf0, 0x13, 0x003f, 0x0038); + phy_write_paged(phydev, 0xa43, 0x13, 0x819f); + phy_write_paged(phydev, 0xa43, 0x14, 0xd0b6); + + phy_write_paged(phydev, 0xbc3, 0x12, 0x5555); + phy_modify_paged(phydev, 0xbf0, 0x15, 0x0e00, 0x0a00); + phy_modify_paged(phydev, 0xa5c, 0x10, 0x0400, 0x0000); + phy_modify_paged(phydev, 0xa44, 0x11, 0x0000, 0x0800); + + rtl8125_config_eee_phy(tp); + rtl_enable_eee(tp); + } + + static void rtl8125_2_hw_phy_config(struct rtl8169_private *tp) + { + struct phy_device *phydev = tp->phydev; + int i; + + phy_modify_paged(phydev, 0xad4, 0x17, 0x0000, 0x0010); + phy_modify_paged(phydev, 0xad1, 0x13, 0x03ff, 0x03ff); + phy_modify_paged(phydev, 0xad3, 0x11, 0x003f, 0x0006); + phy_modify_paged(phydev, 0xac0, 0x14, 0x1100, 0x0000); + phy_modify_paged(phydev, 0xacc, 0x10, 0x0003, 0x0002); + phy_modify_paged(phydev, 0xad4, 0x10, 0x00e7, 0x0044); + phy_modify_paged(phydev, 0xac1, 0x12, 0x0080, 0x0000); + phy_modify_paged(phydev, 0xac8, 0x10, 0x0300, 0x0000); + phy_modify_paged(phydev, 0xac5, 0x17, 0x0007, 0x0002); + phy_write_paged(phydev, 0xad4, 0x16, 0x00a8); + phy_write_paged(phydev, 0xac5, 0x16, 0x01ff); + phy_modify_paged(phydev, 0xac8, 0x15, 0x00f0, 0x0030); + + phy_write(phydev, 0x1f, 0x0b87); + phy_write(phydev, 0x16, 0x80a2); + phy_write(phydev, 0x17, 0x0153); + phy_write(phydev, 0x16, 0x809c); + phy_write(phydev, 0x17, 0x0153); + phy_write(phydev, 0x1f, 0x0000); + + phy_write(phydev, 0x1f, 0x0a43); + phy_write(phydev, 0x13, 0x81B3); + phy_write(phydev, 0x14, 0x0043); + phy_write(phydev, 0x14, 0x00A7); + phy_write(phydev, 0x14, 0x00D6); + phy_write(phydev, 0x14, 0x00EC); + phy_write(phydev, 0x14, 0x00F6); + phy_write(phydev, 0x14, 0x00FB); + phy_write(phydev, 0x14, 0x00FD); + phy_write(phydev, 0x14, 0x00FF); + phy_write(phydev, 0x14, 0x00BB); + phy_write(phydev, 0x14, 0x0058); + phy_write(phydev, 0x14, 0x0029); + phy_write(phydev, 0x14, 0x0013); + phy_write(phydev, 0x14, 0x0009); + phy_write(phydev, 0x14, 0x0004); + phy_write(phydev, 0x14, 0x0002); + for (i = 0; i < 25; i++) + phy_write(phydev, 0x14, 0x0000); + + phy_write(phydev, 0x13, 0x8257); + phy_write(phydev, 0x14, 0x020F); + + phy_write(phydev, 0x13, 0x80EA); + phy_write(phydev, 0x14, 0x7843); + phy_write(phydev, 0x1f, 0x0000); + + rtl_apply_firmware(tp); + + phy_modify_paged(phydev, 0xd06, 0x14, 0x0000, 0x2000); + + phy_write(phydev, 0x1f, 0x0a43); + phy_write(phydev, 0x13, 0x81a2); + phy_set_bits(phydev, 0x14, BIT(8)); + phy_write(phydev, 0x1f, 0x0000); + + phy_modify_paged(phydev, 0xb54, 0x16, 0xff00, 0xdb00); + phy_modify_paged(phydev, 0xa45, 0x12, 0x0001, 0x0000); + phy_modify_paged(phydev, 0xa5d, 0x12, 0x0000, 0x0020); + phy_modify_paged(phydev, 0xad4, 0x17, 0x0010, 0x0000); + phy_modify_paged(phydev, 0xa86, 0x15, 0x0001, 0x0000); + phy_modify_paged(phydev, 0xa44, 0x11, 0x0000, 0x0800); + + rtl8125_config_eee_phy(tp); + rtl_enable_eee(tp); + } + static void rtl_hw_phy_config(struct net_device *dev) { static const rtl_generic_fct phy_configs[] = { @@@ -3698,6 -3820,8 +3819,8 @@@ [RTL_GIGA_MAC_VER_49] = rtl8168ep_1_hw_phy_config, [RTL_GIGA_MAC_VER_50] = rtl8168ep_2_hw_phy_config, [RTL_GIGA_MAC_VER_51] = rtl8168ep_2_hw_phy_config, + [RTL_GIGA_MAC_VER_60] = rtl8125_1_hw_phy_config, + [RTL_GIGA_MAC_VER_61] = rtl8125_2_hw_phy_config, }; struct rtl8169_private *tp = netdev_priv(dev);
@@@ -3825,6 -3949,8 +3948,8 @@@ static void rtl_pll_power_down(struct r case RTL_GIGA_MAC_VER_48: case RTL_GIGA_MAC_VER_50: case RTL_GIGA_MAC_VER_51: + case RTL_GIGA_MAC_VER_60: + case RTL_GIGA_MAC_VER_61: RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~0x80); break; case RTL_GIGA_MAC_VER_40: @@@ -3854,6 -3980,8 +3979,8 @@@ static void rtl_pll_power_up(struct rtl case RTL_GIGA_MAC_VER_48: case RTL_GIGA_MAC_VER_50: case RTL_GIGA_MAC_VER_51: + case RTL_GIGA_MAC_VER_60: + case RTL_GIGA_MAC_VER_61: RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | 0xc0); break; case RTL_GIGA_MAC_VER_40: @@@ -3886,6 -4014,10 +4013,10 @@@ static void rtl_init_rxcfg(struct rtl81 case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF); break; + case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_61: + RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_VLAN_8125 | + RX_DMA_BURST); + break; default: RTL_W32(tp, RxConfig, RX128_INT_EN | RX_DMA_BURST); break; @@@ -4145,54 -4277,46 +4276,46 @@@ static void rtl8169_set_magic_reg(struc
static void rtl_set_rx_mode(struct net_device *dev) { + u32 rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast; + /* Multicast hash filter */ + u32 mc_filter[2] = { 0xffffffff, 0xffffffff }; struct rtl8169_private *tp = netdev_priv(dev); - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; + u32 tmp;
if (dev->flags & IFF_PROMISC) { /* Unconditionally log net taps. */ netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; + rx_mode |= AcceptAllPhys; + } else if (netdev_mc_count(dev) > MC_FILTER_LIMIT || + dev->flags & IFF_ALLMULTI || + tp->mac_version == RTL_GIGA_MAC_VER_35) { + /* accept all multicasts */ + } else if (netdev_mc_empty(dev)) { + rx_mode &= ~AcceptMulticast; } else { struct netdev_hw_addr *ha;
- rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; + u32 bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; + mc_filter[bit_nr >> 5] |= BIT(bit_nr & 31); + } + + if (tp->mac_version > RTL_GIGA_MAC_VER_06) { + tmp = mc_filter[0]; + mc_filter[0] = swab32(mc_filter[1]); + mc_filter[1] = swab32(tmp); } }
if (dev->features & NETIF_F_RXALL) rx_mode |= (AcceptErr | AcceptRunt);
- tmp = (RTL_R32(tp, RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode; - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - if (tp->mac_version == RTL_GIGA_MAC_VER_35) - mc_filter[1] = mc_filter[0] = 0xffffffff; - RTL_W32(tp, MAR0 + 4, mc_filter[1]); RTL_W32(tp, MAR0 + 0, mc_filter[0]);
- RTL_W32(tp, RxConfig, tmp); + tmp = RTL_R32(tp, RxConfig); + RTL_W32(tp, RxConfig, (tmp & ~RX_CONFIG_ACCEPT_MASK) | rx_mode); }
DECLARE_RTL_COND(rtl_csiar_cond) @@@ -4406,7 -4530,7 +4529,7 @@@ static void rtl_hw_start_8168c_2(struc { static const struct ephy_info e_info_8168c_2[] = { { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } + { 0x03, 0x0400, 0x0020 } };
rtl_set_def_aspm_entry_latency(tp); @@@ -4453,7 -4577,8 +4576,8 @@@ static void rtl_hw_start_8168d_4(struc static const struct ephy_info e_info_8168d_4[] = { { 0x0b, 0x0000, 0x0048 }, { 0x19, 0x0020, 0x0050 }, - { 0x0c, 0x0100, 0x0020 } + { 0x0c, 0x0100, 0x0020 }, + { 0x10, 0x0004, 0x0000 }, };
rtl_set_def_aspm_entry_latency(tp); @@@ -4503,7 -4628,9 +4627,9 @@@ static void rtl_hw_start_8168e_2(struc { static const struct ephy_info e_info_8168e_2[] = { { 0x09, 0x0000, 0x0080 }, - { 0x19, 0x0000, 0x0224 } + { 0x19, 0x0000, 0x0224 }, + { 0x00, 0x0000, 0x0004 }, + { 0x0c, 0x3df0, 0x0200 }, };
rtl_set_def_aspm_entry_latency(tp); @@@ -4565,7 -4692,9 +4691,9 @@@ static void rtl_hw_start_8168f_1(struc { 0x06, 0x00c0, 0x0020 }, { 0x08, 0x0001, 0x0002 }, { 0x09, 0x0000, 0x0080 }, - { 0x19, 0x0000, 0x0224 } + { 0x19, 0x0000, 0x0224 }, + { 0x00, 0x0000, 0x0004 }, + { 0x0c, 0x3df0, 0x0200 }, };
rtl_hw_start_8168f(tp); @@@ -4580,8 -4709,9 +4708,9 @@@ static void rtl_hw_start_8411(struct rt static const struct ephy_info e_info_8168f_1[] = { { 0x06, 0x00c0, 0x0020 }, { 0x0f, 0xffff, 0x5200 }, - { 0x1e, 0x0000, 0x4000 }, - { 0x19, 0x0000, 0x0224 } + { 0x19, 0x0000, 0x0224 }, + { 0x00, 0x0000, 0x0004 }, + { 0x0c, 0x3df0, 0x0200 }, };
rtl_hw_start_8168f(tp); @@@ -4620,8 -4750,8 +4749,8 @@@ static void rtl_hw_start_8168g(struct r static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) { static const struct ephy_info e_info_8168g_1[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x37d0, 0x0820 }, + { 0x00, 0x0008, 0x0000 }, + { 0x0c, 0x3ff0, 0x0820 }, { 0x1e, 0x0000, 0x0001 }, { 0x19, 0x8000, 0x0000 } }; @@@ -4637,10 -4767,15 +4766,15 @@@ static void rtl_hw_start_8168g_2(struct rtl8169_private *tp) { static const struct ephy_info e_info_8168g_2[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x3df0, 0x0200 }, - { 0x19, 0xffff, 0xfc00 }, - { 0x1e, 0xffff, 0x20eb } + { 0x00, 0x0008, 0x0000 }, + { 0x0c, 0x3ff0, 0x0820 }, + { 0x19, 0xffff, 0x7c00 }, + { 0x1e, 0xffff, 0x20eb }, + { 0x0d, 0xffff, 0x1666 }, + { 0x00, 0xffff, 0x10a3 }, + { 0x06, 0xffff, 0xf050 }, + { 0x04, 0x0000, 0x0010 }, + { 0x1d, 0x4000, 0x0000 }, };
rtl_hw_start_8168g(tp); @@@ -4654,11 -4789,16 +4788,16 @@@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp) { static const struct ephy_info e_info_8411_2[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x3df0, 0x0200 }, - { 0x0f, 0xffff, 0x5200 }, - { 0x19, 0x0020, 0x0000 }, - { 0x1e, 0x0000, 0x2000 } + { 0x00, 0x0008, 0x0000 }, + { 0x0c, 0x37d0, 0x0820 }, + { 0x1e, 0x0000, 0x0001 }, + { 0x19, 0x8021, 0x0000 }, + { 0x1e, 0x0000, 0x2000 }, + { 0x0d, 0x0100, 0x0200 }, + { 0x00, 0x0000, 0x0080 }, + { 0x06, 0x0000, 0x0010 }, + { 0x04, 0x0000, 0x0010 }, + { 0x1d, 0x0000, 0x4000 }, };
rtl_hw_start_8168g(tp); @@@ -4808,16 -4948,15 +4947,15 @@@
static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) { - int rg_saw_cnt; - u32 data; static const struct ephy_info e_info_8168h_1[] = { { 0x1e, 0x0800, 0x0001 }, { 0x1d, 0x0000, 0x0800 }, { 0x05, 0xffff, 0x2089 }, { 0x06, 0xffff, 0x5881 }, - { 0x04, 0xffff, 0x154a }, + { 0x04, 0xffff, 0x854a }, { 0x01, 0xffff, 0x068b } }; + int rg_saw_cnt;
/* disable aspm and clock request before access ephy */ rtl_hw_aspm_clkreq_enable(tp, false); @@@ -4862,31 -5001,13 +5000,13 @@@
sw_cnt_1ms_ini = 16000000/rg_saw_cnt; sw_cnt_1ms_ini &= 0x0fff; - data = r8168_mac_ocp_read(tp, 0xd412); - data &= ~0x0fff; - data |= sw_cnt_1ms_ini; - r8168_mac_ocp_write(tp, 0xd412, data); + r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini); }
- data = r8168_mac_ocp_read(tp, 0xe056); - data &= ~0xf0; - data |= 0x70; - r8168_mac_ocp_write(tp, 0xe056, data); - - data = r8168_mac_ocp_read(tp, 0xe052); - data &= ~0x6000; - data |= 0x8008; - r8168_mac_ocp_write(tp, 0xe052, data); - - data = r8168_mac_ocp_read(tp, 0xe0d6); - data &= ~0x01ff; - data |= 0x017f; - r8168_mac_ocp_write(tp, 0xe0d6, data); - - data = r8168_mac_ocp_read(tp, 0xd420); - data &= ~0x0fff; - data |= 0x047f; - r8168_mac_ocp_write(tp, 0xd420, data); + r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070); + r8168_mac_ocp_modify(tp, 0xe052, 0x6000, 0x8008); + r8168_mac_ocp_modify(tp, 0xe0d6, 0x01ff, 0x017f); + r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f);
r8168_mac_ocp_write(tp, 0xe63e, 0x0001); r8168_mac_ocp_write(tp, 0xe63e, 0x0000); @@@ -4968,12 -5089,11 +5088,11 @@@ static void rtl_hw_start_8168ep_2(struc
static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp) { - u32 data; static const struct ephy_info e_info_8168ep_3[] = { - { 0x00, 0xffff, 0x10a3 }, - { 0x19, 0xffff, 0x7c00 }, - { 0x1e, 0xffff, 0x20eb }, - { 0x0d, 0xffff, 0x1666 } + { 0x00, 0x0000, 0x0080 }, + { 0x0d, 0x0100, 0x0200 }, + { 0x19, 0x8021, 0x0000 }, + { 0x1e, 0x0000, 0x2000 }, };
/* disable aspm and clock request before access ephy */ @@@ -4985,18 -5105,9 +5104,9 @@@ RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN); RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
- data = r8168_mac_ocp_read(tp, 0xd3e2); - data &= 0xf000; - data |= 0x0271; - r8168_mac_ocp_write(tp, 0xd3e2, data); - - data = r8168_mac_ocp_read(tp, 0xd3e4); - data &= 0xff00; - r8168_mac_ocp_write(tp, 0xd3e4, data); - - data = r8168_mac_ocp_read(tp, 0xe860); - data |= 0x0080; - r8168_mac_ocp_write(tp, 0xe860, data); + r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x0271); + r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000); + r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
rtl_hw_aspm_clkreq_enable(tp, true); } @@@ -5124,6 -5235,128 +5234,128 @@@ static void rtl_hw_start_8106(struct rt rtl_hw_aspm_clkreq_enable(tp, true); }
+ DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond) + { + return r8168_mac_ocp_read(tp, 0xe00e) & BIT(13); + } + + static void rtl_hw_start_8125_common(struct rtl8169_private *tp) + { + rtl_pcie_state_l2l3_disable(tp); + + RTL_W16(tp, 0x382, 0x221b); + RTL_W8(tp, 0x4500, 0); + RTL_W16(tp, 0x4800, 0); + + /* disable UPS */ + r8168_mac_ocp_modify(tp, 0xd40a, 0x0010, 0x0000); + + RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10); + + r8168_mac_ocp_write(tp, 0xc140, 0xffff); + r8168_mac_ocp_write(tp, 0xc142, 0xffff); + + r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x03a9); + r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000); + r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080); + + /* disable new tx descriptor format */ + r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000); + + r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400); + r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0020); + r8168_mac_ocp_modify(tp, 0xc0b4, 0x0000, 0x000c); + r8168_mac_ocp_modify(tp, 0xeb6a, 0x00ff, 0x0033); + r8168_mac_ocp_modify(tp, 0xeb50, 0x03e0, 0x0040); + r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0030); + r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000); + r8168_mac_ocp_modify(tp, 0xe0c0, 0x4f0f, 0x4403); + r8168_mac_ocp_modify(tp, 0xe052, 0x0080, 0x0067); + r8168_mac_ocp_modify(tp, 0xc0ac, 0x0080, 0x1f00); + r8168_mac_ocp_modify(tp, 0xd430, 0x0fff, 0x047f); + r8168_mac_ocp_modify(tp, 0xe84c, 0x0000, 0x00c0); + r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000); + r8168_mac_ocp_modify(tp, 0xeb54, 0x0000, 0x0001); + udelay(1); + r8168_mac_ocp_modify(tp, 0xeb54, 0x0001, 0x0000); + RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~0x0030); + + r8168_mac_ocp_write(tp, 0xe098, 0xc302); + + rtl_udelay_loop_wait_low(tp, &rtl_mac_ocp_e00e_cond, 1000, 10); + + rtl8125_config_eee_mac(tp); + + RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN); + udelay(10); + } + + static void rtl_hw_start_8125_1(struct rtl8169_private *tp) + { + static const struct ephy_info e_info_8125_1[] = { + { 0x01, 0xffff, 0xa812 }, + { 0x09, 0xffff, 0x520c }, + { 0x04, 0xffff, 0xd000 }, + { 0x0d, 0xffff, 0xf702 }, + { 0x0a, 0xffff, 0x8653 }, + { 0x06, 0xffff, 0x001e }, + { 0x08, 0xffff, 0x3595 }, + { 0x20, 0xffff, 0x9455 }, + { 0x21, 0xffff, 0x99ff }, + { 0x02, 0xffff, 0x6046 }, + { 0x29, 0xffff, 0xfe00 }, + { 0x23, 0xffff, 0xab62 }, + + { 0x41, 0xffff, 0xa80c }, + { 0x49, 0xffff, 0x520c }, + { 0x44, 0xffff, 0xd000 }, + { 0x4d, 0xffff, 0xf702 }, + { 0x4a, 0xffff, 0x8653 }, + { 0x46, 0xffff, 0x001e }, + { 0x48, 0xffff, 0x3595 }, + { 0x60, 0xffff, 0x9455 }, + { 0x61, 0xffff, 0x99ff }, + { 0x42, 0xffff, 0x6046 }, + { 0x69, 0xffff, 0xfe00 }, + { 0x63, 0xffff, 0xab62 }, + }; + + rtl_set_def_aspm_entry_latency(tp); + + /* disable aspm and clock request before access ephy */ + rtl_hw_aspm_clkreq_enable(tp, false); + rtl_ephy_init(tp, e_info_8125_1); + + rtl_hw_start_8125_common(tp); + } + + static void rtl_hw_start_8125_2(struct rtl8169_private *tp) + { + static const struct ephy_info e_info_8125_2[] = { + { 0x04, 0xffff, 0xd000 }, + { 0x0a, 0xffff, 0x8653 }, + { 0x23, 0xffff, 0xab66 }, + { 0x20, 0xffff, 0x9455 }, + { 0x21, 0xffff, 0x99ff }, + { 0x29, 0xffff, 0xfe04 }, + + { 0x44, 0xffff, 0xd000 }, + { 0x4a, 0xffff, 0x8653 }, + { 0x63, 0xffff, 0xab66 }, + { 0x60, 0xffff, 0x9455 }, + { 0x61, 0xffff, 0x99ff }, + { 0x69, 0xffff, 0xfe04 }, + }; + + rtl_set_def_aspm_entry_latency(tp); + + /* disable aspm and clock request before access ephy */ + rtl_hw_aspm_clkreq_enable(tp, false); + rtl_ephy_init(tp, e_info_8125_2); + + rtl_hw_start_8125_common(tp); + } + static void rtl_hw_config(struct rtl8169_private *tp) { static const rtl_generic_fct hw_configs[] = { @@@ -5172,12 -5405,25 +5404,25 @@@ [RTL_GIGA_MAC_VER_49] = rtl_hw_start_8168ep_1, [RTL_GIGA_MAC_VER_50] = rtl_hw_start_8168ep_2, [RTL_GIGA_MAC_VER_51] = rtl_hw_start_8168ep_3, + [RTL_GIGA_MAC_VER_60] = rtl_hw_start_8125_1, + [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125_2, };
if (hw_configs[tp->mac_version]) hw_configs[tp->mac_version](tp); }
+ static void rtl_hw_start_8125(struct rtl8169_private *tp) + { + int i; + + /* disable interrupt coalescing */ + for (i = 0xa00; i < 0xb00; i += 4) + RTL_W32(tp, i, 0); + + rtl_hw_config(tp); + } + static void rtl_hw_start_8168(struct rtl8169_private *tp) { if (tp->mac_version == RTL_GIGA_MAC_VER_13 || @@@ -5191,6 -5437,9 +5436,9 @@@ RTL_W8(tp, MaxTxPacketSize, TxPacketMax);
rtl_hw_config(tp); + + /* disable interrupt coalescing */ + RTL_W16(tp, IntrMitigate, 0x0000); }
static void rtl_hw_start_8169(struct rtl8169_private *tp) @@@ -5214,6 -5463,9 +5462,9 @@@ rtl8169_set_magic_reg(tp, tp->mac_version);
RTL_W32(tp, RxMissed, 0); + + /* disable interrupt coalescing */ + RTL_W16(tp, IntrMitigate, 0x0000); }
static void rtl_hw_start(struct rtl8169_private *tp) @@@ -5225,6 -5477,8 +5476,8 @@@
if (tp->mac_version <= RTL_GIGA_MAC_VER_06) rtl_hw_start_8169(tp); + else if (rtl_is_8125(tp)) + rtl_hw_start_8125(tp); else rtl_hw_start_8168(tp);
@@@ -5232,17 -5486,12 +5485,12 @@@ rtl_set_rx_tx_desc_registers(tp); rtl_lock_config_regs(tp);
- /* disable interrupt coalescing */ - RTL_W16(tp, IntrMitigate, 0x0000); /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(tp, IntrMask); + RTL_R16(tp, CPlusCmd); RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); rtl_init_rxcfg(tp); rtl_set_tx_config_registers(tp); - rtl_set_rx_mode(tp->dev); - /* no early-rx interrupts */ - RTL_W16(tp, MultiIntr, RTL_R16(tp, MultiIntr) & 0xf000); rtl_irq_enable(tp); }
@@@ -5267,17 -5516,6 +5515,6 @@@ static inline void rtl8169_make_unusabl desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); }
- static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, - void **data_buff, struct RxDesc *desc) - { - dma_unmap_single(tp_to_dev(tp), le64_to_cpu(desc->addr), - R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); - - kfree(*data_buff); - *data_buff = NULL; - rtl8169_make_unusable_by_asic(desc); - } - static inline void rtl8169_mark_to_asic(struct RxDesc *desc) { u32 eor = le32_to_cpu(desc->opts1) & RingEnd; @@@ -5288,49 -5526,43 +5525,43 @@@ desc->opts1 = cpu_to_le32(DescOwn | eor | R8169_RX_BUF_SIZE); }
- static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, - struct RxDesc *desc) + static struct page *rtl8169_alloc_rx_data(struct rtl8169_private *tp, + struct RxDesc *desc) { - void *data; - dma_addr_t mapping; struct device *d = tp_to_dev(tp); int node = dev_to_node(d); + dma_addr_t mapping; + struct page *data;
- data = kmalloc_node(R8169_RX_BUF_SIZE, GFP_KERNEL, node); + data = alloc_pages_node(node, GFP_KERNEL, get_order(R8169_RX_BUF_SIZE)); if (!data) return NULL;
- /* Memory should be properly aligned, but better check. */ - if (!IS_ALIGNED((unsigned long)data, 8)) { - netdev_err_once(tp->dev, "RX buffer not 8-byte-aligned\n"); - goto err_out; - } - - mapping = dma_map_single(d, data, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); + mapping = dma_map_page(d, data, 0, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(d, mapping))) { if (net_ratelimit()) netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; + __free_pages(data, get_order(R8169_RX_BUF_SIZE)); + return NULL; }
desc->addr = cpu_to_le64(mapping); rtl8169_mark_to_asic(desc); - return data;
- err_out: - kfree(data); - return NULL; + return data; }
static void rtl8169_rx_clear(struct rtl8169_private *tp) { unsigned int i;
- for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_databuff[i]) { - rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i, - tp->RxDescArray + i); - } + for (i = 0; i < NUM_RX_DESC && tp->Rx_databuff[i]; i++) { + dma_unmap_page(tp_to_dev(tp), + le64_to_cpu(tp->RxDescArray[i].addr), + R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); + __free_pages(tp->Rx_databuff[i], get_order(R8169_RX_BUF_SIZE)); + tp->Rx_databuff[i] = NULL; + rtl8169_make_unusable_by_asic(tp->RxDescArray + i); } }
@@@ -5344,7 -5576,7 +5575,7 @@@ static int rtl8169_rx_fill(struct rtl81 unsigned int i;
for (i = 0; i < NUM_RX_DESC; i++) { - void *data; + struct page *data;
data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i); if (!data) { @@@ -5506,44 -5738,6 +5737,6 @@@ static bool rtl_test_hw_pad_bug(struct return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34; }
- static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); - /* r8169_csum_workaround() - * The hw limites the value the transport offset. When the offset is out of the - * range, calculate the checksum by sw. - */ - static void r8169_csum_workaround(struct rtl8169_private *tp, - struct sk_buff *skb) - { - if (skb_is_gso(skb)) { - netdev_features_t features = tp->dev->features; - struct sk_buff *segs, *nskb; - - features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - segs = skb_gso_segment(skb, features); - if (IS_ERR(segs) || !segs) - goto drop; - - do { - nskb = segs; - segs = segs->next; - nskb->next = NULL; - rtl8169_start_xmit(nskb, tp->dev); - } while (segs); - - dev_consume_skb_any(skb); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (skb_checksum_help(skb) < 0) - goto drop; - - rtl8169_start_xmit(skb, tp->dev); - } else { - drop: - tp->dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - } - } - /* msdn_giant_send_check() * According to the document of microsoft, the TCP Pseudo Header excludes the * packet length for IPv6 TCP large packets. @@@ -5593,13 -5787,6 +5786,6 @@@ static bool rtl8169_tso_csum_v2(struct u32 mss = skb_shinfo(skb)->gso_size;
if (mss) { - if (transport_offset > GTTCPHO_MAX) { - netif_warn(tp, tx_err, tp->dev, - "Invalid transport offset 0x%x for TSO\n", - transport_offset); - return false; - } - switch (vlan_get_protocol(skb)) { case htons(ETH_P_IP): opts[0] |= TD1_GTSENV4; @@@ -5622,16 -5809,6 +5808,6 @@@ } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 ip_protocol;
- if (unlikely(rtl_test_hw_pad_bug(tp, skb))) - return !(skb_checksum_help(skb) || eth_skb_pad(skb)); - - if (transport_offset > TCPHO_MAX) { - netif_warn(tp, tx_err, tp->dev, - "Invalid transport offset 0x%x\n", - transport_offset); - return false; - } - switch (vlan_get_protocol(skb)) { case htons(ETH_P_IP): opts[1] |= TD1_IPv4_CS; @@@ -5685,6 -5862,14 +5861,14 @@@ static bool rtl_chip_supports_csum_v2(s } }
+ static void rtl8169_doorbell(struct rtl8169_private *tp) + { + if (rtl_is_8125(tp)) + RTL_W16(tp, TxPoll_8125, BIT(0)); + else + RTL_W8(tp, TxPoll, NPQ); + } + static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@@ -5694,6 -5879,8 +5878,8 @@@ struct device *d = tp_to_dev(tp); dma_addr_t mapping; u32 opts[2], len; + bool stop_queue; + bool door_bell; int frags;
if (unlikely(!rtl_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) { @@@ -5708,10 -5895,8 +5894,8 @@@ opts[0] = DescOwn;
if (rtl_chip_supports_csum_v2(tp)) { - if (!rtl8169_tso_csum_v2(tp, skb, opts)) { - r8169_csum_workaround(tp, skb); - return NETDEV_TX_OK; - } + if (!rtl8169_tso_csum_v2(tp, skb, opts)) + goto err_dma_0; } else { rtl8169_tso_csum_v1(skb, opts); } @@@ -5739,13 -5924,13 +5923,13 @@@
txd->opts2 = cpu_to_le32(opts[1]);
- netdev_sent_queue(dev, skb->len); - skb_tx_timestamp(skb);
/* Force memory writes to complete before releasing descriptor */ dma_wmb();
+ door_bell = __netdev_sent_queue(dev, skb->len, netdev_xmit_more()); + txd->opts1 = rtl8169_get_txd_opts1(opts[0], len, entry);
/* Force all memory writes to complete before notifying device */ @@@ -5753,14 -5938,20 +5937,20 @@@
tp->cur_tx += frags + 1;
- RTL_W8(tp, TxPoll, NPQ); - - if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) { + stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS); + if (unlikely(stop_queue)) { /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must * not miss a ring update when it notices a stopped queue. */ smp_wmb(); netif_stop_queue(dev); + door_bell = true; + } + + if (door_bell) + rtl8169_doorbell(tp); + + if (unlikely(stop_queue)) { /* Sync with rtl_tx: * - publish queue status and cur_tx ring index (write barrier) * - refresh dirty_tx ring index (read barrier). @@@ -5788,6 -5979,39 +5978,39 @@@ err_stop_0 return NETDEV_TX_BUSY; }
+ static netdev_features_t rtl8169_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) + { + int transport_offset = skb_transport_offset(skb); + struct rtl8169_private *tp = netdev_priv(dev); + + if (skb_is_gso(skb)) { + if (transport_offset > GTTCPHO_MAX && + rtl_chip_supports_csum_v2(tp)) + features &= ~NETIF_F_ALL_TSO; + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->len < ETH_ZLEN) { + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_11: + case RTL_GIGA_MAC_VER_12: + case RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_34: + features &= ~NETIF_F_CSUM_MASK; + break; + default: + break; + } + } + + if (transport_offset > TCPHO_MAX && + rtl_chip_supports_csum_v2(tp)) + features &= ~NETIF_F_CSUM_MASK; + } + + return vlan_features_check(skb, features); + } + static void rtl8169_pcierr_interrupt(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@@ -5849,7 -6073,7 +6072,7 @@@ static void rtl_tx(struct net_device *d
rtl8169_unmap_tx_skb(tp_to_dev(tp), tx_skb, tp->TxDescArray + entry); - if (status & LastFrag) { + if (tx_skb->skb) { pkts_compl++; bytes_compl += tx_skb->skb->len; napi_consume_skb(tx_skb->skb, budget); @@@ -5887,7 -6111,7 +6110,7 @@@ * it is slow enough). -- FR */ if (tp->cur_tx != dirty_tx) - RTL_W8(tp, TxPoll, NPQ); + rtl8169_doorbell(tp); } }
@@@ -5907,24 -6131,6 +6130,6 @@@ static inline void rtl8169_rx_csum(stru skb_checksum_none_assert(skb); }
- static struct sk_buff *rtl8169_try_rx_copy(void *data, - struct rtl8169_private *tp, - int pkt_size, - dma_addr_t addr) - { - struct sk_buff *skb; - struct device *d = tp_to_dev(tp); - - dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); - prefetch(data); - skb = napi_alloc_skb(&tp->napi, pkt_size); - if (skb) - skb_copy_to_linear_data(skb, data, pkt_size); - dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); - - return skb; - } - static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget) { unsigned int cur_rx, rx_left; @@@ -5934,6 -6140,7 +6139,7 @@@
for (rx_left = min(budget, NUM_RX_DESC); rx_left > 0; rx_left--, cur_rx++) { unsigned int entry = cur_rx % NUM_RX_DESC; + const void *rx_buf = page_address(tp->Rx_databuff[entry]); struct RxDesc *desc = tp->RxDescArray + entry; u32 status;
@@@ -5960,17 -6167,13 +6166,13 @@@ goto process_pkt; } } else { + unsigned int pkt_size; struct sk_buff *skb; - dma_addr_t addr; - int pkt_size;
process_pkt: - addr = le64_to_cpu(desc->addr); + pkt_size = status & GENMASK(13, 0); if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - + pkt_size -= ETH_FCS_LEN; /* * The driver does not support incoming fragmented * frames. They are seen as a symptom of over-mtu @@@ -5982,15 -6185,25 +6184,25 @@@ goto release_descriptor; }
- skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], - tp, pkt_size, addr); - if (!skb) { + skb = napi_alloc_skb(&tp->napi, pkt_size); + if (unlikely(!skb)) { dev->stats.rx_dropped++; goto release_descriptor; }
+ dma_sync_single_for_cpu(tp_to_dev(tp), + le64_to_cpu(desc->addr), + pkt_size, DMA_FROM_DEVICE); + prefetch(rx_buf); + skb_copy_to_linear_data(skb, rx_buf, pkt_size); + skb->tail += pkt_size; + skb->len = pkt_size; + + dma_sync_single_for_device(tp_to_dev(tp), + le64_to_cpu(desc->addr), + pkt_size, DMA_FROM_DEVICE); + rtl8169_rx_csum(skb, status); - skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev);
rtl8169_rx_vlan_tag(desc, skb); @@@ -6019,9 -6232,10 +6231,10 @@@ release_descriptor static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) { struct rtl8169_private *tp = dev_instance; - u16 status = RTL_R16(tp, IntrStatus); + u32 status = rtl_get_events(tp);
- if (!tp->irq_enabled || status == 0xffff || !(status & tp->irq_mask)) + if (!tp->irq_enabled || (status & 0xffff) == 0xffff || + !(status & tp->irq_mask)) return IRQ_NONE;
if (unlikely(status & SYSErr)) { @@@ -6331,7 -6545,7 +6544,7 @@@ rtl8169_get_stats64(struct net_device * stats->multicast = dev->stats.multicast;
/* - * Fetch additonal counter values missing in stats collected by driver + * Fetch additional counter values missing in stats collected by driver * from tally counters. */ if (pm_runtime_active(&pdev->dev)) @@@ -6555,6 -6769,7 +6768,7 @@@ static const struct net_device_ops rtl_ .ndo_stop = rtl8169_close, .ndo_get_stats64 = rtl8169_get_stats64, .ndo_start_xmit = rtl8169_start_xmit, + .ndo_features_check = rtl8169_features_check, .ndo_tx_timeout = rtl8169_tx_timeout, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = rtl8169_change_mtu, @@@ -6618,6 -6833,8 +6832,8 @@@ static void rtl_read_mac_address(struc value = rtl_eri_read(tp, 0xe4); mac_addr[4] = (value >> 0) & 0xff; mac_addr[5] = (value >> 8) & 0xff; + } else if (rtl_is_8125(tp)) { + rtl_read_mac_from_reg(tp, mac_addr, MAC0_BKP); } }
@@@ -6691,8 -6908,6 +6907,6 @@@ static int r8169_mdio_register(struct r
static void rtl_hw_init_8168g(struct rtl8169_private *tp) { - u32 data; - tp->ocp_base = OCP_STD_PHY_BASE;
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | RXDV_GATED_EN); @@@ -6707,16 -6922,37 +6921,37 @@@ msleep(1); RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
- data = r8168_mac_ocp_read(tp, 0xe8de); - data &= ~(1 << 14); - r8168_mac_ocp_write(tp, 0xe8de, data); + r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0);
if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) return;
- data = r8168_mac_ocp_read(tp, 0xe8de); - data |= (1 << 15); - r8168_mac_ocp_write(tp, 0xe8de, data); + r8168_mac_ocp_modify(tp, 0xe8de, 0, BIT(15)); + + rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42); + } + + static void rtl_hw_init_8125(struct rtl8169_private *tp) + { + tp->ocp_base = OCP_STD_PHY_BASE; + + RTL_W32(tp, MISC, RTL_R32(tp, MISC) | RXDV_GATED_EN); + + if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42)) + return; + + RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) & ~(CmdTxEnb | CmdRxEnb)); + msleep(1); + RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB); + + r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0); + + if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) + return; + + r8168_mac_ocp_write(tp, 0xc0aa, 0x07d0); + r8168_mac_ocp_write(tp, 0xc0a6, 0x0150); + r8168_mac_ocp_write(tp, 0xc01e, 0x5555);
rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42); } @@@ -6730,6 -6966,9 +6965,9 @@@ static void rtl_hw_initialize(struct rt case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48: rtl_hw_init_8168g(tp); break; + case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_61: + rtl_hw_init_8125(tp); + break; default: break; } @@@ -6793,7 -7032,7 +7031,7 @@@ static void rtl_init_mac_address(struc { struct net_device *dev = tp->dev; u8 *mac_addr = dev->dev_addr; - int rc, i; + int rc;
rc = eth_platform_get_mac_address(tp_to_dev(tp), mac_addr); if (!rc) @@@ -6803,8 -7042,7 +7041,7 @@@ if (is_valid_ether_addr(mac_addr)) goto done;
- for (i = 0; i < ETH_ALEN; i++) - mac_addr[i] = RTL_R8(tp, MAC0 + i); + rtl_read_mac_from_reg(tp, mac_addr, MAC0); if (is_valid_ether_addr(mac_addr)) goto done;
@@@ -6916,11 -7154,9 +7153,9 @@@ static int rtl_init_one(struct pci_dev
netif_napi_add(dev, &tp->napi, rtl8169_poll, NAPI_POLL_WEIGHT);
- /* don't enable SG, IP_CSUM and TSO by default - it might not work - * properly for all devices */ - dev->features |= NETIF_F_RXCSUM | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; - + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; @@@ -6928,8 -7164,10 +7163,10 @@@ NETIF_F_HIGHDMA; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
- tp->cp_cmd |= RxChkSum | RxVlan; - + tp->cp_cmd |= RxChkSum; + /* RTL8125 uses register RxConfig for VLAN offloading config */ + if (!rtl_is_8125(tp)) + tp->cp_cmd |= RxVlan; /* * Pretend we are using VLANs; This bypasses a nasty bug where * Interrupts stop flowing on high load on 8110SCd controllers. @@@ -6938,8 -7176,22 +7175,22 @@@ /* Disallow toggling */ dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
- if (rtl_chip_supports_csum_v2(tp)) + if (rtl_chip_supports_csum_v2(tp)) { dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + dev->features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + dev->gso_max_size = RTL_GSO_MAX_SIZE_V2; + dev->gso_max_segs = RTL_GSO_MAX_SEGS_V2; + } else { + dev->gso_max_size = RTL_GSO_MAX_SIZE_V1; + dev->gso_max_segs = RTL_GSO_MAX_SEGS_V1; + } + + /* RTL8168e-vl has a HW issue with TSO */ + if (tp->mac_version == RTL_GIGA_MAC_VER_34) { + dev->vlan_features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG); + dev->hw_features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG); + dev->features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG); + }
dev->hw_features |= NETIF_F_RXALL; dev->hw_features |= NETIF_F_RXFCS; diff --combined drivers/net/phy/phy.c index 6b0f89369b46,0acd5b49f450..35d29a823af8 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@@ -507,7 -507,7 +507,7 @@@ static int phy_config_aneg(struct phy_d * allowed to call genphy_config_aneg() */ if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0))) - return -EOPNOTSUPP; + return genphy_c45_config_aneg(phydev);
return genphy_config_aneg(phydev); } @@@ -608,38 -608,21 +608,21 @@@ static int phy_poll_aneg_done(struct ph */ int phy_speed_down(struct phy_device *phydev, bool sync) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old); - __ETHTOOL_DECLARE_LINK_MODE_MASK(adv); + __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp); int ret;
if (phydev->autoneg != AUTONEG_ENABLE) return 0;
- linkmode_copy(adv_old, phydev->advertising); - linkmode_copy(adv, phydev->lp_advertising); - linkmode_and(adv, adv, phydev->supported); - - if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, adv) || - linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, adv)) { - linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, - phydev->advertising); - linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, - phydev->advertising); - linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, - phydev->advertising); - linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - phydev->advertising); - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, - adv) || - linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, - adv)) { - linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, - phydev->advertising); - linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - phydev->advertising); - } + linkmode_copy(adv_tmp, phydev->advertising); + + ret = phy_speed_down_core(phydev); + if (ret) + return ret;
- if (linkmode_equal(phydev->advertising, adv_old)) + linkmode_copy(phydev->adv_old, adv_tmp); + + if (linkmode_equal(phydev->advertising, adv_tmp)) return 0;
ret = phy_config_aneg(phydev); @@@ -658,30 -641,19 +641,19 @@@ EXPORT_SYMBOL_GPL(phy_speed_down) */ int phy_speed_up(struct phy_device *phydev) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(all_speeds) = { 0, }; - __ETHTOOL_DECLARE_LINK_MODE_MASK(not_speeds); - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); - __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old); - __ETHTOOL_DECLARE_LINK_MODE_MASK(speeds); - - linkmode_copy(adv_old, phydev->advertising); + __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
if (phydev->autoneg != AUTONEG_ENABLE) return 0;
- linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, all_speeds); - linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, all_speeds); - linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, all_speeds); - linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, all_speeds); - linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, all_speeds); - linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, all_speeds); + if (linkmode_empty(phydev->adv_old)) + return 0;
- linkmode_andnot(not_speeds, adv_old, all_speeds); - linkmode_copy(supported, phydev->supported); - linkmode_and(speeds, supported, all_speeds); - linkmode_or(phydev->advertising, not_speeds, speeds); + linkmode_copy(adv_tmp, phydev->advertising); + linkmode_copy(phydev->advertising, phydev->adv_old); + linkmode_zero(phydev->adv_old);
- if (linkmode_equal(phydev->advertising, adv_old)) + if (linkmode_equal(phydev->advertising, adv_tmp)) return 0;
return phy_config_aneg(phydev); @@@ -939,8 -911,8 +911,8 @@@ void phy_state_machine(struct work_stru if (phydev->link) { phydev->link = 0; phy_link_down(phydev, true); - do_suspend = true; } + do_suspend = true; break; }
diff --combined drivers/net/usb/r8152.c index 04137ac373b0,c6fa0c17c13d..778d27d1fb15 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@@ -22,10 -22,11 +22,11 @@@ #include <linux/mdio.h> #include <linux/usb/cdc.h> #include <linux/suspend.h> + #include <linux/atomic.h> #include <linux/acpi.h>
/* Information for net-next */ - #define NETNEXT_VERSION "09" + #define NETNEXT_VERSION "10"
/* Information for net */ #define NET_VERSION "10" @@@ -583,6 -584,9 +584,9 @@@ enum rtl_register_content #define TX_ALIGN 4 #define RX_ALIGN 8
+ #define RTL8152_RX_MAX_PENDING 4096 + #define RTL8152_RXFG_HEADSZ 256 + #define INTR_LINK 0x0004
#define RTL8152_REQT_READ 0xc0 @@@ -615,7 -619,7 +619,7 @@@ enum rtl8152_flags RTL8152_LINK_CHG, SELECTIVE_SUSPEND, PHY_RESET, - SCHEDULE_NAPI, + SCHEDULE_TASKLET, GREEN_ETHERNET, DELL_TB_RX_AGG_BUG, }; @@@ -694,11 -698,11 +698,11 @@@ struct tx_desc struct r8152;
struct rx_agg { - struct list_head list; + struct list_head list, info_list; struct urb *urb; struct r8152 *context; + struct page *page; void *buffer; - void *head; };
struct tx_agg { @@@ -719,7 -723,7 +723,7 @@@ struct r8152 struct net_device *netdev; struct urb *intr_urb; struct tx_agg tx_info[RTL8152_MAX_TX]; - struct rx_agg rx_info[RTL8152_MAX_RX]; + struct list_head rx_info, rx_used; struct list_head rx_done, tx_free; struct sk_buff_head tx_queue, rx_queue; spinlock_t rx_lock, tx_lock; @@@ -729,6 -733,7 +733,7 @@@ #ifdef CONFIG_PM_SLEEP struct notifier_block pm_notifier; #endif + struct tasklet_struct tx_tl;
struct rtl_ops { void (*init)(struct r8152 *); @@@ -744,13 -749,21 +749,21 @@@ void (*autosuspend_en)(struct r8152 *tp, bool enable); } rtl_ops;
+ atomic_t rx_count; + + bool eee_en; int intr_interval; u32 saved_wolopts; u32 msg_enable; u32 tx_qlen; u32 coalesce; + u32 rx_buf_sz; + u32 rx_copybreak; + u32 rx_pending; + u16 ocp_base; u16 speed; + u16 eee_adv; u8 *intr_buff; u8 version; u8 duplex; @@@ -1394,7 -1407,7 +1407,7 @@@ static void write_bulk_callback(struct return;
if (!skb_queue_empty(&tp->tx_queue)) - napi_schedule(&tp->napi); + tasklet_schedule(&tp->tx_tl); }
static void intr_callback(struct urb *urb) @@@ -1470,18 -1483,72 +1483,72 @@@ static inline void *tx_agg_align(void * return (void *)ALIGN((uintptr_t)data, TX_ALIGN); }
+ static void free_rx_agg(struct r8152 *tp, struct rx_agg *agg) + { + list_del(&agg->info_list); + + usb_free_urb(agg->urb); + put_page(agg->page); + kfree(agg); + + atomic_dec(&tp->rx_count); + } + + static struct rx_agg *alloc_rx_agg(struct r8152 *tp, gfp_t mflags) + { + struct net_device *netdev = tp->netdev; + int node = netdev->dev.parent ? dev_to_node(netdev->dev.parent) : -1; + unsigned int order = get_order(tp->rx_buf_sz); + struct rx_agg *rx_agg; + unsigned long flags; + + rx_agg = kmalloc_node(sizeof(*rx_agg), mflags, node); + if (!rx_agg) + return NULL; + + rx_agg->page = alloc_pages(mflags | __GFP_COMP, order); + if (!rx_agg->page) + goto free_rx; + + rx_agg->buffer = page_address(rx_agg->page); + + rx_agg->urb = usb_alloc_urb(0, mflags); + if (!rx_agg->urb) + goto free_buf; + + rx_agg->context = tp; + + INIT_LIST_HEAD(&rx_agg->list); + INIT_LIST_HEAD(&rx_agg->info_list); + spin_lock_irqsave(&tp->rx_lock, flags); + list_add_tail(&rx_agg->info_list, &tp->rx_info); + spin_unlock_irqrestore(&tp->rx_lock, flags); + + atomic_inc(&tp->rx_count); + + return rx_agg; + + free_buf: + __free_pages(rx_agg->page, order); + free_rx: + kfree(rx_agg); + return NULL; + } + static void free_all_mem(struct r8152 *tp) { + struct rx_agg *agg, *agg_next; + unsigned long flags; int i;
- for (i = 0; i < RTL8152_MAX_RX; i++) { - usb_free_urb(tp->rx_info[i].urb); - tp->rx_info[i].urb = NULL; + spin_lock_irqsave(&tp->rx_lock, flags);
- kfree(tp->rx_info[i].buffer); - tp->rx_info[i].buffer = NULL; - tp->rx_info[i].head = NULL; - } + list_for_each_entry_safe(agg, agg_next, &tp->rx_info, info_list) + free_rx_agg(tp, agg); + + spin_unlock_irqrestore(&tp->rx_lock, flags); + + WARN_ON(atomic_read(&tp->rx_count));
for (i = 0; i < RTL8152_MAX_TX; i++) { usb_free_urb(tp->tx_info[i].urb); @@@ -1505,46 -1572,28 +1572,28 @@@ static int alloc_all_mem(struct r8152 * struct usb_interface *intf = tp->intf; struct usb_host_interface *alt = intf->cur_altsetting; struct usb_host_endpoint *ep_intr = alt->endpoint + 2; - struct urb *urb; int node, i; - u8 *buf;
node = netdev->dev.parent ? dev_to_node(netdev->dev.parent) : -1;
spin_lock_init(&tp->rx_lock); spin_lock_init(&tp->tx_lock); + INIT_LIST_HEAD(&tp->rx_info); INIT_LIST_HEAD(&tp->tx_free); INIT_LIST_HEAD(&tp->rx_done); skb_queue_head_init(&tp->tx_queue); skb_queue_head_init(&tp->rx_queue); + atomic_set(&tp->rx_count, 0);
for (i = 0; i < RTL8152_MAX_RX; i++) { - buf = kmalloc_node(agg_buf_sz, GFP_KERNEL, node); - if (!buf) + if (!alloc_rx_agg(tp, GFP_KERNEL)) goto err1; - - if (buf != rx_agg_align(buf)) { - kfree(buf); - buf = kmalloc_node(agg_buf_sz + RX_ALIGN, GFP_KERNEL, - node); - if (!buf) - goto err1; - } - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - kfree(buf); - goto err1; - } - - INIT_LIST_HEAD(&tp->rx_info[i].list); - tp->rx_info[i].context = tp; - tp->rx_info[i].urb = urb; - tp->rx_info[i].buffer = buf; - tp->rx_info[i].head = rx_agg_align(buf); }
for (i = 0; i < RTL8152_MAX_TX; i++) { + struct urb *urb; + u8 *buf; + buf = kmalloc_node(agg_buf_sz, GFP_KERNEL, node); if (!buf) goto err1; @@@ -1910,6 -1959,46 +1959,46 @@@ return_result return checksum; }
+ static inline bool rx_count_exceed(struct r8152 *tp) + { + return atomic_read(&tp->rx_count) > RTL8152_MAX_RX; + } + + static inline int agg_offset(struct rx_agg *agg, void *addr) + { + return (int)(addr - agg->buffer); + } + + static struct rx_agg *rtl_get_free_rx(struct r8152 *tp, gfp_t mflags) + { + struct rx_agg *agg, *agg_next, *agg_free = NULL; + unsigned long flags; + + spin_lock_irqsave(&tp->rx_lock, flags); + + list_for_each_entry_safe(agg, agg_next, &tp->rx_used, list) { + if (page_count(agg->page) == 1) { + if (!agg_free) { + list_del_init(&agg->list); + agg_free = agg; + continue; + } + if (rx_count_exceed(tp)) { + list_del_init(&agg->list); + free_rx_agg(tp, agg); + } + break; + } + } + + spin_unlock_irqrestore(&tp->rx_lock, flags); + + if (!agg_free && atomic_read(&tp->rx_count) < tp->rx_pending) + agg_free = alloc_rx_agg(tp, mflags); + + return agg_free; + } + static int rx_bottom(struct r8152 *tp, int budget) { unsigned long flags; @@@ -1945,7 -2034,7 +2034,7 @@@
list_for_each_safe(cursor, next, &rx_queue) { struct rx_desc *rx_desc; - struct rx_agg *agg; + struct rx_agg *agg, *agg_free; int len_used = 0; struct urb *urb; u8 *rx_data; @@@ -1957,14 -2046,16 +2046,16 @@@ if (urb->actual_length < ETH_ZLEN) goto submit;
- rx_desc = agg->head; - rx_data = agg->head; + agg_free = rtl_get_free_rx(tp, GFP_ATOMIC); + + rx_desc = agg->buffer; + rx_data = agg->buffer; len_used += sizeof(struct rx_desc);
while (urb->actual_length > len_used) { struct net_device *netdev = tp->netdev; struct net_device_stats *stats = &netdev->stats; - unsigned int pkt_len; + unsigned int pkt_len, rx_frag_head_sz; struct sk_buff *skb;
/* limite the skb numbers for rx_queue */ @@@ -1982,22 -2073,37 +2073,37 @@@ pkt_len -= ETH_FCS_LEN; rx_data += sizeof(struct rx_desc);
- skb = napi_alloc_skb(napi, pkt_len); + if (!agg_free || tp->rx_copybreak > pkt_len) + rx_frag_head_sz = pkt_len; + else + rx_frag_head_sz = tp->rx_copybreak; + + skb = napi_alloc_skb(napi, rx_frag_head_sz); if (!skb) { stats->rx_dropped++; goto find_next_rx; }
skb->ip_summed = r8152_rx_csum(tp, rx_desc); - memcpy(skb->data, rx_data, pkt_len); - skb_put(skb, pkt_len); + memcpy(skb->data, rx_data, rx_frag_head_sz); + skb_put(skb, rx_frag_head_sz); + pkt_len -= rx_frag_head_sz; + rx_data += rx_frag_head_sz; + if (pkt_len) { + skb_add_rx_frag(skb, 0, agg->page, + agg_offset(agg, rx_data), + pkt_len, + SKB_DATA_ALIGN(pkt_len)); + get_page(agg->page); + } + skb->protocol = eth_type_trans(skb, netdev); rtl_rx_vlan_tag(rx_desc, skb); if (work_done < budget) { - napi_gro_receive(napi, skb); work_done++; stats->rx_packets++; - stats->rx_bytes += pkt_len; + stats->rx_bytes += skb->len; + napi_gro_receive(napi, skb); } else { __skb_queue_tail(&tp->rx_queue, skb); } @@@ -2005,10 -2111,24 +2111,24 @@@ find_next_rx: rx_data = rx_agg_align(rx_data + pkt_len + ETH_FCS_LEN); rx_desc = (struct rx_desc *)rx_data; - len_used = (int)(rx_data - (u8 *)agg->head); + len_used = agg_offset(agg, rx_data); len_used += sizeof(struct rx_desc); }
+ WARN_ON(!agg_free && page_count(agg->page) > 1); + + if (agg_free) { + spin_lock_irqsave(&tp->rx_lock, flags); + if (page_count(agg->page) == 1) { + list_add(&agg_free->list, &tp->rx_used); + } else { + list_add_tail(&agg->list, &tp->rx_used); + agg = agg_free; + urb = agg->urb; + } + spin_unlock_irqrestore(&tp->rx_lock, flags); + } + submit: if (!ret) { ret = r8152_submit_rx(tp, agg, GFP_ATOMIC); @@@ -2065,8 -2185,12 +2185,12 @@@ static void tx_bottom(struct r8152 *tp } while (res == 0); }
- static void bottom_half(struct r8152 *tp) + static void bottom_half(unsigned long data) { + struct r8152 *tp; + + tp = (struct r8152 *)data; + if (test_bit(RTL8152_UNPLUG, &tp->flags)) return;
@@@ -2078,7 -2202,7 +2202,7 @@@ if (!netif_carrier_ok(tp->netdev)) return;
- clear_bit(SCHEDULE_NAPI, &tp->flags); + clear_bit(SCHEDULE_TASKLET, &tp->flags);
tx_bottom(tp); } @@@ -2089,16 -2213,12 +2213,12 @@@ static int r8152_poll(struct napi_struc int work_done;
work_done = rx_bottom(tp, budget); - bottom_half(tp);
if (work_done < budget) { if (!napi_complete_done(napi, work_done)) goto out; if (!list_empty(&tp->rx_done)) napi_schedule(napi); - else if (!skb_queue_empty(&tp->tx_queue) && - !list_empty(&tp->tx_free)) - napi_schedule(napi); }
out: @@@ -2116,7 -2236,7 +2236,7 @@@ int r8152_submit_rx(struct r8152 *tp, s return 0;
usb_fill_bulk_urb(agg->urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1), - agg->head, agg_buf_sz, + agg->buffer, tp->rx_buf_sz, (usb_complete_t)read_bulk_callback, agg);
ret = usb_submit_urb(agg->urb, mem_flags); @@@ -2252,11 -2372,11 +2372,11 @@@ static netdev_tx_t rtl8152_start_xmit(s
if (!list_empty(&tp->tx_free)) { if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { - set_bit(SCHEDULE_NAPI, &tp->flags); + set_bit(SCHEDULE_TASKLET, &tp->flags); schedule_delayed_work(&tp->schedule, 0); } else { usb_mark_last_busy(tp->udev); - napi_schedule(&tp->napi); + tasklet_schedule(&tp->tx_tl); } } else if (skb_queue_len(&tp->tx_queue) > tp->tx_qlen) { netif_stop_queue(netdev); @@@ -2333,44 -2453,80 +2453,80 @@@ static void rxdy_gated_en(struct r8152
static int rtl_start_rx(struct r8152 *tp) { - int i, ret = 0; + struct rx_agg *agg, *agg_next; + struct list_head tmp_list; + unsigned long flags; + int ret = 0, i = 0;
- INIT_LIST_HEAD(&tp->rx_done); - for (i = 0; i < RTL8152_MAX_RX; i++) { - INIT_LIST_HEAD(&tp->rx_info[i].list); - ret = r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL); - if (ret) - break; - } + INIT_LIST_HEAD(&tmp_list);
- if (ret && ++i < RTL8152_MAX_RX) { - struct list_head rx_queue; - unsigned long flags; + spin_lock_irqsave(&tp->rx_lock, flags);
- INIT_LIST_HEAD(&rx_queue); + INIT_LIST_HEAD(&tp->rx_done); + INIT_LIST_HEAD(&tp->rx_used);
- do { - struct rx_agg *agg = &tp->rx_info[i++]; - struct urb *urb = agg->urb; + list_splice_init(&tp->rx_info, &tmp_list);
- urb->actual_length = 0; - list_add_tail(&agg->list, &rx_queue); - } while (i < RTL8152_MAX_RX); + spin_unlock_irqrestore(&tp->rx_lock, flags);
- spin_lock_irqsave(&tp->rx_lock, flags); - list_splice_tail(&rx_queue, &tp->rx_done); - spin_unlock_irqrestore(&tp->rx_lock, flags); + list_for_each_entry_safe(agg, agg_next, &tmp_list, info_list) { + INIT_LIST_HEAD(&agg->list); + + /* Only RTL8152_MAX_RX rx_agg need to be submitted. */ + if (++i > RTL8152_MAX_RX) { + spin_lock_irqsave(&tp->rx_lock, flags); + list_add_tail(&agg->list, &tp->rx_used); + spin_unlock_irqrestore(&tp->rx_lock, flags); + } else if (unlikely(ret < 0)) { + spin_lock_irqsave(&tp->rx_lock, flags); + list_add_tail(&agg->list, &tp->rx_done); + spin_unlock_irqrestore(&tp->rx_lock, flags); + } else { + ret = r8152_submit_rx(tp, agg, GFP_KERNEL); + } }
+ spin_lock_irqsave(&tp->rx_lock, flags); + WARN_ON(!list_empty(&tp->rx_info)); + list_splice(&tmp_list, &tp->rx_info); + spin_unlock_irqrestore(&tp->rx_lock, flags); + return ret; }
static int rtl_stop_rx(struct r8152 *tp) { - int i; + struct rx_agg *agg, *agg_next; + struct list_head tmp_list; + unsigned long flags; + + INIT_LIST_HEAD(&tmp_list); + + /* The usb_kill_urb() couldn't be used in atomic. + * Therefore, move the list of rx_info to a tmp one. + * Then, list_for_each_entry_safe could be used without + * spin lock. + */ + + spin_lock_irqsave(&tp->rx_lock, flags); + list_splice_init(&tp->rx_info, &tmp_list); + spin_unlock_irqrestore(&tp->rx_lock, flags); + + list_for_each_entry_safe(agg, agg_next, &tmp_list, info_list) { + /* At least RTL8152_MAX_RX rx_agg have the page_count being + * equal to 1, so the other ones could be freed safely. + */ + if (page_count(agg->page) > 1) + free_rx_agg(tp, agg); + else + usb_kill_urb(agg->urb); + }
- for (i = 0; i < RTL8152_MAX_RX; i++) - usb_kill_urb(tp->rx_info[i].urb); + /* Move back the list of temp to the rx_info */ + spin_lock_irqsave(&tp->rx_lock, flags); + WARN_ON(!list_empty(&tp->rx_info)); + list_splice(&tmp_list, &tp->rx_info); + spin_unlock_irqrestore(&tp->rx_lock, flags);
while (!skb_queue_empty(&tp->rx_queue)) dev_kfree_skb(__skb_dequeue(&tp->rx_queue)); @@@ -2450,7 -2606,7 +2606,7 @@@ static void r8153_set_rx_early_timeout(
static void r8153_set_rx_early_size(struct r8152 *tp) { - u32 ocp_data = agg_buf_sz - rx_reserved_size(tp->netdev->mtu); + u32 ocp_data = tp->rx_buf_sz - rx_reserved_size(tp->netdev->mtu);
switch (tp->version) { case RTL_VER_03: @@@ -3049,10 -3205,76 +3205,76 @@@ static void r8152_eee_en(struct r8152 * ocp_reg_write(tp, OCP_EEE_CONFIG3, config3); }
- static void r8152b_enable_eee(struct r8152 *tp) + static void r8153_eee_en(struct r8152 *tp, bool enable) { - r8152_eee_en(tp, true); - r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, MDIO_EEE_100TX); + u32 ocp_data; + u16 config; + + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR); + config = ocp_reg_read(tp, OCP_EEE_CFG); + + if (enable) { + ocp_data |= EEE_RX_EN | EEE_TX_EN; + config |= EEE10_EN; + } else { + ocp_data &= ~(EEE_RX_EN | EEE_TX_EN); + config &= ~EEE10_EN; + } + + ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data); + ocp_reg_write(tp, OCP_EEE_CFG, config); + } + + static void r8153b_eee_en(struct r8152 *tp, bool enable) + { + r8153_eee_en(tp, enable); + + if (enable) + r8153b_ups_flags_w1w0(tp, UPS_FLAGS_EN_EEE, 0); + else + r8153b_ups_flags_w1w0(tp, 0, UPS_FLAGS_EN_EEE); + } + + static void rtl_eee_enable(struct r8152 *tp, bool enable) + { + switch (tp->version) { + case RTL_VER_01: + case RTL_VER_02: + case RTL_VER_07: + if (enable) { + r8152_eee_en(tp, true); + r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, + tp->eee_adv); + } else { + r8152_eee_en(tp, false); + r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); + } + break; + case RTL_VER_03: + case RTL_VER_04: + case RTL_VER_05: + case RTL_VER_06: + if (enable) { + r8153_eee_en(tp, true); + ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); + } else { + r8153_eee_en(tp, false); + ocp_reg_write(tp, OCP_EEE_ADV, 0); + } + break; + case RTL_VER_08: + case RTL_VER_09: + if (enable) { + r8153b_eee_en(tp, true); + ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); + } else { + r8153b_eee_en(tp, false); + ocp_reg_write(tp, OCP_EEE_ADV, 0); + } + break; + default: + break; + } }
static void r8152b_enable_fc(struct r8152 *tp) @@@ -3073,7 -3295,7 +3295,7 @@@ static void rtl8152_disable(struct r815
static void r8152b_hw_phy_cfg(struct r8152 *tp) { - r8152b_enable_eee(tp); + rtl_eee_enable(tp, tp->eee_en); r8152_aldps_en(tp, true); r8152b_enable_fc(tp);
@@@ -3267,36 -3489,6 +3489,6 @@@ static void r8153b_aldps_en(struct r815 r8153b_ups_flags_w1w0(tp, 0, UPS_FLAGS_EN_ALDPS); }
- static void r8153_eee_en(struct r8152 *tp, bool enable) - { - u32 ocp_data; - u16 config; - - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR); - config = ocp_reg_read(tp, OCP_EEE_CFG); - - if (enable) { - ocp_data |= EEE_RX_EN | EEE_TX_EN; - config |= EEE10_EN; - } else { - ocp_data &= ~(EEE_RX_EN | EEE_TX_EN); - config &= ~EEE10_EN; - } - - ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data); - ocp_reg_write(tp, OCP_EEE_CFG, config); - } - - static void r8153b_eee_en(struct r8152 *tp, bool enable) - { - r8153_eee_en(tp, enable); - - if (enable) - r8153b_ups_flags_w1w0(tp, UPS_FLAGS_EN_EEE, 0); - else - r8153b_ups_flags_w1w0(tp, 0, UPS_FLAGS_EN_EEE); - } - static void r8153b_enable_fc(struct r8152 *tp) { r8152b_enable_fc(tp); @@@ -3312,8 -3504,7 +3504,7 @@@ static void r8153_hw_phy_cfg(struct r81 r8153_aldps_en(tp, false);
/* disable EEE before updating the PHY parameters */ - r8153_eee_en(tp, false); - ocp_reg_write(tp, OCP_EEE_ADV, 0); + rtl_eee_enable(tp, false);
if (tp->version == RTL_VER_03) { data = ocp_reg_read(tp, OCP_EEE_CFG); @@@ -3344,8 -3535,8 +3535,8 @@@ sram_write(tp, SRAM_10M_AMP1, 0x00af); sram_write(tp, SRAM_10M_AMP2, 0x0208);
- r8153_eee_en(tp, true); - ocp_reg_write(tp, OCP_EEE_ADV, MDIO_EEE_1000T | MDIO_EEE_100TX); + if (tp->eee_en) + rtl_eee_enable(tp, true);
r8153_aldps_en(tp, true); r8152b_enable_fc(tp); @@@ -3385,8 -3576,7 +3576,7 @@@ static void r8153b_hw_phy_cfg(struct r8 r8153b_aldps_en(tp, false);
/* disable EEE before updating the PHY parameters */ - r8153b_eee_en(tp, false); - ocp_reg_write(tp, OCP_EEE_ADV, 0); + rtl_eee_enable(tp, false);
r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags));
@@@ -3448,8 -3638,8 +3638,8 @@@
r8153b_ups_flags_w1w0(tp, ups_flags, 0);
- r8153b_eee_en(tp, true); - ocp_reg_write(tp, OCP_EEE_ADV, MDIO_EEE_1000T | MDIO_EEE_100TX); + if (tp->eee_en) + rtl_eee_enable(tp, true);
r8153b_aldps_en(tp, true); r8153b_enable_fc(tp); @@@ -3870,9 -4060,11 +4060,11 @@@ static void set_carrier(struct r8152 *t } else { if (netif_carrier_ok(netdev)) { netif_carrier_off(netdev); + tasklet_disable(&tp->tx_tl); napi_disable(napi); tp->rtl_ops.disable(tp); napi_enable(napi); + tasklet_enable(&tp->tx_tl); netif_info(tp, link, netdev, "carrier off\n"); } } @@@ -3905,10 -4097,10 +4097,10 @@@ static void rtl_work_func_t(struct work if (test_and_clear_bit(RTL8152_SET_RX_MODE, &tp->flags)) _rtl8152_set_rx_mode(tp->netdev);
- /* don't schedule napi before linking */ - if (test_and_clear_bit(SCHEDULE_NAPI, &tp->flags) && + /* don't schedule tasket before linking */ + if (test_and_clear_bit(SCHEDULE_TASKLET, &tp->flags) && netif_carrier_ok(tp->netdev)) - napi_schedule(&tp->napi); + tasklet_schedule(&tp->tx_tl);
mutex_unlock(&tp->control);
@@@ -3994,6 -4186,7 +4186,7 @@@ static int rtl8152_open(struct net_devi goto out_unlock; } napi_enable(&tp->napi); + tasklet_enable(&tp->tx_tl);
mutex_unlock(&tp->control);
@@@ -4021,7 -4214,9 +4214,8 @@@ static int rtl8152_close(struct net_dev #ifdef CONFIG_PM_SLEEP unregister_pm_notifier(&tp->pm_notifier); #endif + tasklet_disable(&tp->tx_tl); - if (!test_bit(RTL8152_UNPLUG, &tp->flags)) - napi_disable(&tp->napi); + napi_disable(&tp->napi); clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); cancel_delayed_work_sync(&tp->schedule); @@@ -4289,6 -4484,7 +4483,7 @@@ static int rtl8152_pre_reset(struct usb return 0;
netif_stop_queue(netdev); + tasklet_disable(&tp->tx_tl); napi_disable(&tp->napi); clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); @@@ -4332,6 -4528,7 +4527,7 @@@ static int rtl8152_post_reset(struct us }
napi_enable(&tp->napi); + tasklet_enable(&tp->tx_tl); netif_wake_queue(netdev); usb_submit_urb(tp->intr_urb, GFP_KERNEL);
@@@ -4485,10 -4682,12 +4681,12 @@@ static int rtl8152_system_suspend(struc
clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); + tasklet_disable(&tp->tx_tl); napi_disable(napi); cancel_delayed_work_sync(&tp->schedule); tp->rtl_ops.down(tp); napi_enable(napi); + tasklet_enable(&tp->tx_tl); }
return 0; @@@ -4731,7 -4930,7 +4929,7 @@@ static void rtl8152_get_strings(struct
static int r8152_get_eee(struct r8152 *tp, struct ethtool_eee *eee) { - u32 ocp_data, lp, adv, supported = 0; + u32 lp, adv, supported = 0; u16 val;
val = r8152_mmd_read(tp, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE); @@@ -4743,13 -4942,10 +4941,10 @@@ val = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE); lp = mmd_eee_adv_to_ethtool_adv_t(val);
- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR); - ocp_data &= EEE_RX_EN | EEE_TX_EN; - - eee->eee_enabled = !!ocp_data; + eee->eee_enabled = tp->eee_en; eee->eee_active = !!(supported & adv & lp); eee->supported = supported; - eee->advertised = adv; + eee->advertised = tp->eee_adv; eee->lp_advertised = lp;
return 0; @@@ -4759,19 -4955,17 +4954,17 @@@ static int r8152_set_eee(struct r8152 * { u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised);
- r8152_eee_en(tp, eee->eee_enabled); + tp->eee_en = eee->eee_enabled; + tp->eee_adv = val;
- if (!eee->eee_enabled) - val = 0; - - r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); + rtl_eee_enable(tp, tp->eee_en);
return 0; }
static int r8153_get_eee(struct r8152 *tp, struct ethtool_eee *eee) { - u32 ocp_data, lp, adv, supported = 0; + u32 lp, adv, supported = 0; u16 val;
val = ocp_reg_read(tp, OCP_EEE_ABLE); @@@ -4783,46 -4977,15 +4976,15 @@@ val = ocp_reg_read(tp, OCP_EEE_LPABLE); lp = mmd_eee_adv_to_ethtool_adv_t(val);
- ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR); - ocp_data &= EEE_RX_EN | EEE_TX_EN; - - eee->eee_enabled = !!ocp_data; + eee->eee_enabled = tp->eee_en; eee->eee_active = !!(supported & adv & lp); eee->supported = supported; - eee->advertised = adv; + eee->advertised = tp->eee_adv; eee->lp_advertised = lp;
return 0; }
- static int r8153_set_eee(struct r8152 *tp, struct ethtool_eee *eee) - { - u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - - r8153_eee_en(tp, eee->eee_enabled); - - if (!eee->eee_enabled) - val = 0; - - ocp_reg_write(tp, OCP_EEE_ADV, val); - - return 0; - } - - static int r8153b_set_eee(struct r8152 *tp, struct ethtool_eee *eee) - { - u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - - r8153b_eee_en(tp, eee->eee_enabled); - - if (!eee->eee_enabled) - val = 0; - - ocp_reg_write(tp, OCP_EEE_ADV, val); - - return 0; - } - static int rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) { @@@ -4956,6 -5119,77 +5118,77 @@@ static int rtl8152_set_coalesce(struct return ret; }
+ static int rtl8152_get_tunable(struct net_device *netdev, + const struct ethtool_tunable *tunable, void *d) + { + struct r8152 *tp = netdev_priv(netdev); + + switch (tunable->id) { + case ETHTOOL_RX_COPYBREAK: + *(u32 *)d = tp->rx_copybreak; + break; + default: + return -EOPNOTSUPP; + } + + return 0; + } + + static int rtl8152_set_tunable(struct net_device *netdev, + const struct ethtool_tunable *tunable, + const void *d) + { + struct r8152 *tp = netdev_priv(netdev); + u32 val; + + switch (tunable->id) { + case ETHTOOL_RX_COPYBREAK: + val = *(u32 *)d; + if (val < ETH_ZLEN) { + netif_err(tp, rx_err, netdev, + "Invalid rx copy break value\n"); + return -EINVAL; + } + + if (tp->rx_copybreak != val) { + napi_disable(&tp->napi); + tp->rx_copybreak = val; + napi_enable(&tp->napi); + } + break; + default: + return -EOPNOTSUPP; + } + + return 0; + } + + static void rtl8152_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) + { + struct r8152 *tp = netdev_priv(netdev); + + ring->rx_max_pending = RTL8152_RX_MAX_PENDING; + ring->rx_pending = tp->rx_pending; + } + + static int rtl8152_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) + { + struct r8152 *tp = netdev_priv(netdev); + + if (ring->rx_pending < (RTL8152_MAX_RX * 2)) + return -EINVAL; + + if (tp->rx_pending != ring->rx_pending) { + napi_disable(&tp->napi); + tp->rx_pending = ring->rx_pending; + napi_enable(&tp->napi); + } + + return 0; + } + static const struct ethtool_ops ops = { .get_drvinfo = rtl8152_get_drvinfo, .get_link = ethtool_op_get_link, @@@ -4973,6 -5207,10 +5206,10 @@@ .set_eee = rtl_ethtool_set_eee, .get_link_ksettings = rtl8152_get_link_ksettings, .set_link_ksettings = rtl8152_set_link_ksettings, + .get_tunable = rtl8152_get_tunable, + .set_tunable = rtl8152_set_tunable, + .get_ringparam = rtl8152_get_ringparam, + .set_ringparam = rtl8152_set_ringparam, };
static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) @@@ -5117,6 -5355,9 +5354,9 @@@ static int rtl_ops_init(struct r8152 *t ops->in_nway = rtl8152_in_nway; ops->hw_phy_cfg = r8152b_hw_phy_cfg; ops->autosuspend_en = rtl_runtime_suspend_enable; + tp->rx_buf_sz = 16 * 1024; + tp->eee_en = true; + tp->eee_adv = MDIO_EEE_100TX; break;
case RTL_VER_03: @@@ -5130,10 -5371,13 +5370,13 @@@ ops->down = rtl8153_down; ops->unload = rtl8153_unload; ops->eee_get = r8153_get_eee; - ops->eee_set = r8153_set_eee; + ops->eee_set = r8152_set_eee; ops->in_nway = rtl8153_in_nway; ops->hw_phy_cfg = r8153_hw_phy_cfg; ops->autosuspend_en = rtl8153_runtime_enable; + tp->rx_buf_sz = 32 * 1024; + tp->eee_en = true; + tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; break;
case RTL_VER_08: @@@ -5145,10 -5389,13 +5388,13 @@@ ops->down = rtl8153b_down; ops->unload = rtl8153b_unload; ops->eee_get = r8153_get_eee; - ops->eee_set = r8153b_set_eee; + ops->eee_set = r8152_set_eee; ops->in_nway = rtl8153_in_nway; ops->hw_phy_cfg = r8153b_hw_phy_cfg; ops->autosuspend_en = rtl8153b_runtime_enable; + tp->rx_buf_sz = 32 * 1024; + tp->eee_en = true; + tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; break;
default: @@@ -5270,6 -5517,8 +5516,8 @@@ static int rtl8152_probe(struct usb_int mutex_init(&tp->control); INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t); + tasklet_init(&tp->tx_tl, bottom_half, (unsigned long)tp); + tasklet_disable(&tp->tx_tl);
netdev->netdev_ops = &rtl8152_netdev_ops; netdev->watchdog_timeo = RTL8152_TX_TIMEOUT; @@@ -5323,6 -5572,9 +5571,9 @@@ tp->speed = tp->mii.supports_gmii ? SPEED_1000 : SPEED_100; tp->duplex = DUPLEX_FULL;
+ tp->rx_copybreak = RTL8152_RXFG_HEADSZ; + tp->rx_pending = 10 * RTL8152_MAX_RX; + intf->needs_remote_wakeup = 1;
tp->rtl_ops.init(tp); @@@ -5352,6 -5604,8 +5603,7 @@@ return 0;
out1: - netif_napi_del(&tp->napi); + tasklet_kill(&tp->tx_tl); usb_set_intfdata(intf, NULL); out: free_netdev(netdev); @@@ -5366,7 -5620,9 +5618,8 @@@ static void rtl8152_disconnect(struct u if (tp) { rtl_set_unplug(tp);
- netif_napi_del(&tp->napi); unregister_netdev(tp->netdev); + tasklet_kill(&tp->tx_tl); cancel_delayed_work_sync(&tp->hw_phy_work); tp->rtl_ops.unload(tp); free_netdev(tp->netdev); diff --combined drivers/pci/Kconfig index a5017b66bd9d,c313de96a357..a304f5ea11b9 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@@ -52,7 -52,7 +52,7 @@@ config PCI_MS If you don't know what to do here, say Y.
config PCI_MSI_IRQ_DOMAIN - def_bool ARC || ARM || ARM64 || X86 + def_bool ARC || ARM || ARM64 || X86 || RISCV depends on PCI_MSI select GENERIC_MSI_IRQ_DOMAIN
@@@ -170,7 -170,7 +170,7 @@@ config PCI_P2PDM
Many PCIe root complexes do not support P2P transactions and it's hard to tell which support it at all, so at this time, - P2P DMA transations must be between devices behind the same root + P2P DMA transactions must be between devices behind the same root port.
If unsure, say N. @@@ -181,7 -181,8 +181,8 @@@ config PCI_LABE
config PCI_HYPERV tristate "Hyper-V PCI Frontend" - depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 + depends on X86_64 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && SYSFS + select PCI_HYPERV_INTERFACE help The PCI device frontend driver allows the kernel to import arbitrary PCI devices from a PCI backend to support PCI driver domains. diff --combined drivers/pci/controller/pci-hyperv.c index 3a56de6b2ec2,9c93ac2215b7..6b8733ba3692 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@@ -365,6 -365,39 +365,39 @@@ struct pci_delete_interrupt struct tran_int_desc int_desc; } __packed;
+ /* + * Note: the VM must pass a valid block id, wslot and bytes_requested. + */ + struct pci_read_block { + struct pci_message message_type; + u32 block_id; + union win_slot_encoding wslot; + u32 bytes_requested; + } __packed; + + struct pci_read_block_response { + struct vmpacket_descriptor hdr; + u32 status; + u8 bytes[HV_CONFIG_BLOCK_SIZE_MAX]; + } __packed; + + /* + * Note: the VM must pass a valid block id, wslot and byte_count. + */ + struct pci_write_block { + struct pci_message message_type; + u32 block_id; + union win_slot_encoding wslot; + u32 byte_count; + u8 bytes[HV_CONFIG_BLOCK_SIZE_MAX]; + } __packed; + + struct pci_dev_inval_block { + struct pci_incoming_message incoming; + union win_slot_encoding wslot; + u64 block_mask; + } __packed; + struct pci_dev_incoming { struct pci_incoming_message incoming; union win_slot_encoding wslot; @@@ -499,6 -532,9 +532,9 @@@ struct hv_pci_dev struct hv_pcibus_device *hbus; struct work_struct wrk;
+ void (*block_invalidate)(void *context, u64 block_mask); + void *invalidate_context; + /* * What would be observed if one wrote 0xFFFFFFFF to a BAR and then * read it back, for each of the BAR offsets within config space. @@@ -817,6 -853,253 +853,253 @@@ static struct pci_ops hv_pcifront_ops .write = hv_pcifront_write_config, };
+ /* + * Paravirtual backchannel + * + * Hyper-V SR-IOV provides a backchannel mechanism in software for + * communication between a VF driver and a PF driver. These + * "configuration blocks" are similar in concept to PCI configuration space, + * but instead of doing reads and writes in 32-bit chunks through a very slow + * path, packets of up to 128 bytes can be sent or received asynchronously. + * + * Nearly every SR-IOV device contains just such a communications channel in + * hardware, so using this one in software is usually optional. Using the + * software channel, however, allows driver implementers to leverage software + * tools that fuzz the communications channel looking for vulnerabilities. + * + * The usage model for these packets puts the responsibility for reading or + * writing on the VF driver. The VF driver sends a read or a write packet, + * indicating which "block" is being referred to by number. + * + * If the PF driver wishes to initiate communication, it can "invalidate" one or + * more of the first 64 blocks. This invalidation is delivered via a callback + * supplied by the VF driver by this driver. + * + * No protocol is implied, except that supplied by the PF and VF drivers. + */ + + struct hv_read_config_compl { + struct hv_pci_compl comp_pkt; + void *buf; + unsigned int len; + unsigned int bytes_returned; + }; + + /** + * hv_pci_read_config_compl() - Invoked when a response packet + * for a read config block operation arrives. + * @context: Identifies the read config operation + * @resp: The response packet itself + * @resp_packet_size: Size in bytes of the response packet + */ + static void hv_pci_read_config_compl(void *context, struct pci_response *resp, + int resp_packet_size) + { + struct hv_read_config_compl *comp = context; + struct pci_read_block_response *read_resp = + (struct pci_read_block_response *)resp; + unsigned int data_len, hdr_len; + + hdr_len = offsetof(struct pci_read_block_response, bytes); + if (resp_packet_size < hdr_len) { + comp->comp_pkt.completion_status = -1; + goto out; + } + + data_len = resp_packet_size - hdr_len; + if (data_len > 0 && read_resp->status == 0) { + comp->bytes_returned = min(comp->len, data_len); + memcpy(comp->buf, read_resp->bytes, comp->bytes_returned); + } else { + comp->bytes_returned = 0; + } + + comp->comp_pkt.completion_status = read_resp->status; + out: + complete(&comp->comp_pkt.host_event); + } + + /** + * hv_read_config_block() - Sends a read config block request to + * the back-end driver running in the Hyper-V parent partition. + * @pdev: The PCI driver's representation for this device. + * @buf: Buffer into which the config block will be copied. + * @len: Size in bytes of buf. + * @block_id: Identifies the config block which has been requested. + * @bytes_returned: Size which came back from the back-end driver. + * + * Return: 0 on success, -errno on failure + */ + int hv_read_config_block(struct pci_dev *pdev, void *buf, unsigned int len, + unsigned int block_id, unsigned int *bytes_returned) + { + struct hv_pcibus_device *hbus = + container_of(pdev->bus->sysdata, struct hv_pcibus_device, + sysdata); + struct { + struct pci_packet pkt; + char buf[sizeof(struct pci_read_block)]; + } pkt; + struct hv_read_config_compl comp_pkt; + struct pci_read_block *read_blk; + int ret; + + if (len == 0 || len > HV_CONFIG_BLOCK_SIZE_MAX) + return -EINVAL; + + init_completion(&comp_pkt.comp_pkt.host_event); + comp_pkt.buf = buf; + comp_pkt.len = len; + + memset(&pkt, 0, sizeof(pkt)); + pkt.pkt.completion_func = hv_pci_read_config_compl; + pkt.pkt.compl_ctxt = &comp_pkt; + read_blk = (struct pci_read_block *)&pkt.pkt.message; + read_blk->message_type.type = PCI_READ_BLOCK; + read_blk->wslot.slot = devfn_to_wslot(pdev->devfn); + read_blk->block_id = block_id; + read_blk->bytes_requested = len; + + ret = vmbus_sendpacket(hbus->hdev->channel, read_blk, + sizeof(*read_blk), (unsigned long)&pkt.pkt, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (ret) + return ret; + + ret = wait_for_response(hbus->hdev, &comp_pkt.comp_pkt.host_event); + if (ret) + return ret; + + if (comp_pkt.comp_pkt.completion_status != 0 || + comp_pkt.bytes_returned == 0) { + dev_err(&hbus->hdev->device, + "Read Config Block failed: 0x%x, bytes_returned=%d\n", + comp_pkt.comp_pkt.completion_status, + comp_pkt.bytes_returned); + return -EIO; + } + + *bytes_returned = comp_pkt.bytes_returned; + return 0; + } + + /** + * hv_pci_write_config_compl() - Invoked when a response packet for a write + * config block operation arrives. + * @context: Identifies the write config operation + * @resp: The response packet itself + * @resp_packet_size: Size in bytes of the response packet + */ + static void hv_pci_write_config_compl(void *context, struct pci_response *resp, + int resp_packet_size) + { + struct hv_pci_compl *comp_pkt = context; + + comp_pkt->completion_status = resp->status; + complete(&comp_pkt->host_event); + } + + /** + * hv_write_config_block() - Sends a write config block request to the + * back-end driver running in the Hyper-V parent partition. + * @pdev: The PCI driver's representation for this device. + * @buf: Buffer from which the config block will be copied. + * @len: Size in bytes of buf. + * @block_id: Identifies the config block which is being written. + * + * Return: 0 on success, -errno on failure + */ + int hv_write_config_block(struct pci_dev *pdev, void *buf, unsigned int len, + unsigned int block_id) + { + struct hv_pcibus_device *hbus = + container_of(pdev->bus->sysdata, struct hv_pcibus_device, + sysdata); + struct { + struct pci_packet pkt; + char buf[sizeof(struct pci_write_block)]; + u32 reserved; + } pkt; + struct hv_pci_compl comp_pkt; + struct pci_write_block *write_blk; + u32 pkt_size; + int ret; + + if (len == 0 || len > HV_CONFIG_BLOCK_SIZE_MAX) + return -EINVAL; + + init_completion(&comp_pkt.host_event); + + memset(&pkt, 0, sizeof(pkt)); + pkt.pkt.completion_func = hv_pci_write_config_compl; + pkt.pkt.compl_ctxt = &comp_pkt; + write_blk = (struct pci_write_block *)&pkt.pkt.message; + write_blk->message_type.type = PCI_WRITE_BLOCK; + write_blk->wslot.slot = devfn_to_wslot(pdev->devfn); + write_blk->block_id = block_id; + write_blk->byte_count = len; + memcpy(write_blk->bytes, buf, len); + pkt_size = offsetof(struct pci_write_block, bytes) + len; + /* + * This quirk is required on some hosts shipped around 2018, because + * these hosts don't check the pkt_size correctly (new hosts have been + * fixed since early 2019). The quirk is also safe on very old hosts + * and new hosts, because, on them, what really matters is the length + * specified in write_blk->byte_count. + */ + pkt_size += sizeof(pkt.reserved); + + ret = vmbus_sendpacket(hbus->hdev->channel, write_blk, pkt_size, + (unsigned long)&pkt.pkt, VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (ret) + return ret; + + ret = wait_for_response(hbus->hdev, &comp_pkt.host_event); + if (ret) + return ret; + + if (comp_pkt.completion_status != 0) { + dev_err(&hbus->hdev->device, + "Write Config Block failed: 0x%x\n", + comp_pkt.completion_status); + return -EIO; + } + + return 0; + } + + /** + * hv_register_block_invalidate() - Invoked when a config block invalidation + * arrives from the back-end driver. + * @pdev: The PCI driver's representation for this device. + * @context: Identifies the device. + * @block_invalidate: Identifies all of the blocks being invalidated. + * + * Return: 0 on success, -errno on failure + */ + int hv_register_block_invalidate(struct pci_dev *pdev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)) + { + struct hv_pcibus_device *hbus = + container_of(pdev->bus->sysdata, struct hv_pcibus_device, + sysdata); + struct hv_pci_dev *hpdev; + + hpdev = get_pcichild_wslot(hbus, devfn_to_wslot(pdev->devfn)); + if (!hpdev) + return -ENODEV; + + hpdev->block_invalidate = block_invalidate; + hpdev->invalidate_context = context; + + put_pcichild(hpdev); + return 0; + + } + /* Interrupt management hooks */ static void hv_int_desc_free(struct hv_pci_dev *hpdev, struct tran_int_desc *int_desc) @@@ -1968,6 -2251,7 +2251,7 @@@ static void hv_pci_onchannelcallback(vo struct pci_response *response; struct pci_incoming_message *new_message; struct pci_bus_relations *bus_rel; + struct pci_dev_inval_block *inval; struct pci_dev_incoming *dev_message; struct hv_pci_dev *hpdev;
@@@ -2045,6 -2329,21 +2329,21 @@@ } break;
+ case PCI_INVALIDATE_BLOCK: + + inval = (struct pci_dev_inval_block *)buffer; + hpdev = get_pcichild_wslot(hbus, + inval->wslot.slot); + if (hpdev) { + if (hpdev->block_invalidate) { + hpdev->block_invalidate( + hpdev->invalidate_context, + inval->block_mask); + } + put_pcichild(hpdev); + } + break; + default: dev_warn(&hbus->hdev->device, "Unimplemented protocol message %x\n", @@@ -2510,48 -2809,6 +2809,48 @@@ static void put_hvpcibus(struct hv_pcib complete(&hbus->remove_event); }
+#define HVPCI_DOM_MAP_SIZE (64 * 1024) +static DECLARE_BITMAP(hvpci_dom_map, HVPCI_DOM_MAP_SIZE); + +/* + * PCI domain number 0 is used by emulated devices on Gen1 VMs, so define 0 + * as invalid for passthrough PCI devices of this driver. + */ +#define HVPCI_DOM_INVALID 0 + +/** + * hv_get_dom_num() - Get a valid PCI domain number + * Check if the PCI domain number is in use, and return another number if + * it is in use. + * + * @dom: Requested domain number + * + * return: domain number on success, HVPCI_DOM_INVALID on failure + */ +static u16 hv_get_dom_num(u16 dom) +{ + unsigned int i; + + if (test_and_set_bit(dom, hvpci_dom_map) == 0) + return dom; + + for_each_clear_bit(i, hvpci_dom_map, HVPCI_DOM_MAP_SIZE) { + if (test_and_set_bit(i, hvpci_dom_map) == 0) + return i; + } + + return HVPCI_DOM_INVALID; +} + +/** + * hv_put_dom_num() - Mark the PCI domain number as free + * @dom: Domain number to be freed + */ +static void hv_put_dom_num(u16 dom) +{ + clear_bit(dom, hvpci_dom_map); +} + /** * hv_pci_probe() - New VMBus channel probe, for a root PCI bus * @hdev: VMBus's tracking struct for this root PCI bus @@@ -2563,7 -2820,6 +2862,7 @@@ static int hv_pci_probe(struct hv_devic const struct hv_vmbus_device_id *dev_id) { struct hv_pcibus_device *hbus; + u16 dom_req, dom; int ret;
/* @@@ -2578,34 -2834,19 +2877,34 @@@ hbus->state = hv_pcibus_init;
/* - * The PCI bus "domain" is what is called "segment" in ACPI and - * other specs. Pull it from the instance ID, to get something - * unique. Bytes 8 and 9 are what is used in Windows guests, so - * do the same thing for consistency. Note that, since this code - * only runs in a Hyper-V VM, Hyper-V can (and does) guarantee - * that (1) the only domain in use for something that looks like - * a physical PCI bus (which is actually emulated by the - * hypervisor) is domain 0 and (2) there will be no overlap - * between domains derived from these instance IDs in the same - * VM. + * The PCI bus "domain" is what is called "segment" in ACPI and other + * specs. Pull it from the instance ID, to get something usually + * unique. In rare cases of collision, we will find out another number + * not in use. + * + * Note that, since this code only runs in a Hyper-V VM, Hyper-V + * together with this guest driver can guarantee that (1) The only + * domain used by Gen1 VMs for something that looks like a physical + * PCI bus (which is actually emulated by the hypervisor) is domain 0. + * (2) There will be no overlap between domains (after fixing possible + * collisions) in the same VM. */ - hbus->sysdata.domain = hdev->dev_instance.b[9] | - hdev->dev_instance.b[8] << 8; + dom_req = hdev->dev_instance.b[5] << 8 | hdev->dev_instance.b[4]; + dom = hv_get_dom_num(dom_req); + + if (dom == HVPCI_DOM_INVALID) { + dev_err(&hdev->device, + "Unable to use dom# 0x%hx or other numbers", dom_req); + ret = -EINVAL; + goto free_bus; + } + + if (dom != dom_req) + dev_info(&hdev->device, + "PCI dom# 0x%hx has collision, using 0x%hx", + dom_req, dom); + + hbus->sysdata.domain = dom;
hbus->hdev = hdev; refcount_set(&hbus->remove_lock, 1); @@@ -2620,7 -2861,7 +2919,7 @@@ hbus->sysdata.domain); if (!hbus->wq) { ret = -ENOMEM; - goto free_bus; + goto free_dom; }
ret = vmbus_open(hdev->channel, pci_ring_size, pci_ring_size, NULL, 0, @@@ -2697,8 -2938,6 +2996,8 @@@ close vmbus_close(hdev->channel); destroy_wq: destroy_workqueue(hbus->wq); +free_dom: + hv_put_dom_num(hbus->sysdata.domain); free_bus: free_page((unsigned long)hbus); return ret; @@@ -2761,8 -3000,8 +3060,8 @@@ static int hv_pci_remove(struct hv_devi /* Remove the bus from PCI's point of view. */ pci_lock_rescan_remove(); pci_stop_root_bus(hbus->pci_bus); - pci_remove_root_bus(hbus->pci_bus); hv_pci_remove_slots(hbus); + pci_remove_root_bus(hbus->pci_bus); pci_unlock_rescan_remove(); hbus->state = hv_pcibus_removed; } @@@ -2780,9 -3019,6 +3079,9 @@@ put_hvpcibus(hbus); wait_for_completion(&hbus->remove_event); destroy_workqueue(hbus->wq); + + hv_put_dom_num(hbus->sysdata.domain); + free_page((unsigned long)hbus); return 0; } @@@ -2806,13 -3042,19 +3105,22 @@@ static struct hv_driver hv_pci_drv = static void __exit exit_hv_pci_drv(void) { vmbus_driver_unregister(&hv_pci_drv); + + hvpci_block_ops.read_block = NULL; + hvpci_block_ops.write_block = NULL; + hvpci_block_ops.reg_blk_invalidate = NULL; }
static int __init init_hv_pci_drv(void) { + /* Set the invalid domain number's bit, so it will not be used */ + set_bit(HVPCI_DOM_INVALID, hvpci_dom_map); + + /* Initialize PCI block r/w interface */ + hvpci_block_ops.read_block = hv_read_config_block; + hvpci_block_ops.write_block = hv_write_config_block; + hvpci_block_ops.reg_blk_invalidate = hv_register_block_invalidate; + return vmbus_driver_register(&hv_pci_drv); }
diff --combined include/Kbuild index fc2aa4e20658,af498acb7cd2..ac284c7aa05b --- a/include/Kbuild +++ b/include/Kbuild @@@ -386,31 -386,6 +386,6 @@@ header-test- += linux/mvebu-pmsu. header-test- += linux/mxm-wmi.h header-test- += linux/n_r3964.h header-test- += linux/ndctl.h - header-test- += linux/netfilter/ipset/ip_set.h - header-test- += linux/netfilter/ipset/ip_set_bitmap.h - header-test- += linux/netfilter/ipset/ip_set_comment.h - header-test- += linux/netfilter/ipset/ip_set_counter.h - header-test- += linux/netfilter/ipset/ip_set_getport.h - header-test- += linux/netfilter/ipset/ip_set_hash.h - header-test- += linux/netfilter/ipset/ip_set_list.h - header-test- += linux/netfilter/ipset/ip_set_skbinfo.h - header-test- += linux/netfilter/ipset/ip_set_timeout.h - header-test- += linux/netfilter/nf_conntrack_amanda.h - header-test- += linux/netfilter/nf_conntrack_ftp.h - header-test- += linux/netfilter/nf_conntrack_h323.h - header-test- += linux/netfilter/nf_conntrack_h323_asn1.h - header-test- += linux/netfilter/nf_conntrack_irc.h - header-test- += linux/netfilter/nf_conntrack_pptp.h - header-test- += linux/netfilter/nf_conntrack_proto_gre.h - header-test- += linux/netfilter/nf_conntrack_sip.h - header-test- += linux/netfilter/nf_conntrack_snmp.h - header-test- += linux/netfilter/nf_conntrack_tftp.h - header-test- += linux/netfilter/x_tables.h - header-test- += linux/netfilter_arp/arp_tables.h - header-test- += linux/netfilter_bridge/ebtables.h - header-test- += linux/netfilter_ipv4/ip4_tables.h - header-test- += linux/netfilter_ipv4/ip_tables.h - header-test- += linux/netfilter_ipv6/ip6_tables.h header-test- += linux/nfs.h header-test- += linux/nfs_fs_i.h header-test- += linux/nfs_fs_sb.h @@@ -874,43 -849,6 +849,6 @@@ header-test- += net/mpls_iptunnel. header-test- += net/mrp.h header-test- += net/ncsi.h header-test- += net/netevent.h - header-test- += net/netfilter/br_netfilter.h - header-test- += net/netfilter/ipv4/nf_dup_ipv4.h - header-test- += net/netfilter/ipv6/nf_defrag_ipv6.h - header-test- += net/netfilter/ipv6/nf_dup_ipv6.h - header-test- += net/netfilter/nf_conntrack.h - header-test- += net/netfilter/nf_conntrack_acct.h - header-test- += net/netfilter/nf_conntrack_bridge.h - header-test- += net/netfilter/nf_conntrack_core.h - header-test- += net/netfilter/nf_conntrack_count.h - header-test- += net/netfilter/nf_conntrack_ecache.h - header-test- += net/netfilter/nf_conntrack_expect.h - header-test- += net/netfilter/nf_conntrack_extend.h - header-test- += net/netfilter/nf_conntrack_helper.h - header-test- += net/netfilter/nf_conntrack_l4proto.h - header-test- += net/netfilter/nf_conntrack_labels.h - header-test- += net/netfilter/nf_conntrack_seqadj.h - header-test- += net/netfilter/nf_conntrack_synproxy.h - header-test- += net/netfilter/nf_conntrack_timeout.h - header-test- += net/netfilter/nf_conntrack_timestamp.h - header-test- += net/netfilter/nf_conntrack_tuple.h - header-test- += net/netfilter/nf_dup_netdev.h - header-test- += net/netfilter/nf_flow_table.h - header-test- += net/netfilter/nf_nat.h - header-test- += net/netfilter/nf_nat_helper.h - header-test- += net/netfilter/nf_nat_masquerade.h - header-test- += net/netfilter/nf_nat_redirect.h - header-test- += net/netfilter/nf_queue.h - header-test- += net/netfilter/nf_reject.h - header-test- += net/netfilter/nf_synproxy.h - header-test-$(CONFIG_NF_TABLES) += net/netfilter/nf_tables.h - header-test-$(CONFIG_NF_TABLES) += net/netfilter/nf_tables_core.h - header-test-$(CONFIG_NF_TABLES) += net/netfilter/nf_tables_ipv4.h - header-test- += net/netfilter/nf_tables_ipv6.h - header-test-$(CONFIG_NF_TABLES) += net/netfilter/nf_tables_offload.h - header-test- += net/netfilter/nft_fib.h - header-test- += net/netfilter/nft_meta.h - header-test- += net/netfilter/nft_reject.h header-test- += net/netns/can.h header-test- += net/netns/generic.h header-test- += net/netns/ieee802154_6lowpan.h @@@ -945,6 -883,12 +883,6 @@@ header-test- += net/xdp. header-test- += net/xdp_priv.h header-test- += pcmcia/cistpl.h header-test- += pcmcia/ds.h -header-test- += rdma/ib.h -header-test- += rdma/iw_portmap.h -header-test- += rdma/opa_port_info.h -header-test- += rdma/rdmavt_cq.h -header-test- += rdma/restrack.h -header-test- += rdma/signature.h header-test- += rdma/tid_rdma_defs.h header-test- += scsi/fc/fc_encaps.h header-test- += scsi/fc/fc_fc2.h @@@ -1134,18 -1078,6 +1072,6 @@@ header-test- += uapi/linux/kvm_para. header-test- += uapi/linux/lightnvm.h header-test- += uapi/linux/mic_common.h header-test- += uapi/linux/mman.h - header-test- += uapi/linux/netfilter/ipset/ip_set_bitmap.h - header-test- += uapi/linux/netfilter/ipset/ip_set_hash.h - header-test- += uapi/linux/netfilter/ipset/ip_set_list.h - header-test- += uapi/linux/netfilter/nf_synproxy.h - header-test- += uapi/linux/netfilter/xt_policy.h - header-test- += uapi/linux/netfilter/xt_set.h - header-test- += uapi/linux/netfilter_arp/arp_tables.h - header-test- += uapi/linux/netfilter_arp/arpt_mangle.h - header-test- += uapi/linux/netfilter_ipv4/ip_tables.h - header-test- += uapi/linux/netfilter_ipv4/ipt_LOG.h - header-test- += uapi/linux/netfilter_ipv6/ip6_tables.h - header-test- += uapi/linux/netfilter_ipv6/ip6t_LOG.h header-test- += uapi/linux/nilfs2_ondisk.h header-test- += uapi/linux/patchkey.h header-test- += uapi/linux/ptrace.h diff --combined include/linux/phy.h index 2fb9c8ffaf10,d26779f1fb6b..a7ecbe0e55aa --- a/include/linux/phy.h +++ b/include/linux/phy.h @@@ -403,6 -403,8 +403,8 @@@ struct phy_device __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising); + /* used with phy_speed_down */ + __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
/* Energy efficient ethernet modes which should be prohibited */ u32 eee_broken_modes; @@@ -665,6 -667,7 +667,7 @@@ size_t phy_speeds(unsigned int *speeds unsigned long *mask); void of_set_phy_supported(struct phy_device *phydev); void of_set_phy_eee_broken(struct phy_device *phydev); + int phy_speed_down_core(struct phy_device *phydev);
/** * phy_is_started - Convenience function to check whether PHY is started @@@ -984,6 -987,8 +987,8 @@@ int phy_select_page(struct phy_device * int phy_restore_page(struct phy_device *phydev, int oldpage, int ret); int phy_read_paged(struct phy_device *phydev, int page, u32 regnum); int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val); + int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum, + u16 mask, u16 set); int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum, u16 mask, u16 set);
@@@ -1064,12 -1069,11 +1069,11 @@@ void phy_attached_print(struct phy_devi void phy_attached_info(struct phy_device *phydev);
/* Clause 22 PHY */ - int genphy_config_init(struct phy_device *phydev); int genphy_read_abilities(struct phy_device *phydev); int genphy_setup_forced(struct phy_device *phydev); int genphy_restart_aneg(struct phy_device *phydev); int genphy_config_eee_advert(struct phy_device *phydev); - int genphy_config_aneg(struct phy_device *phydev); + int __genphy_config_aneg(struct phy_device *phydev, bool changed); int genphy_aneg_done(struct phy_device *phydev); int genphy_update_link(struct phy_device *phydev); int genphy_read_status(struct phy_device *phydev); @@@ -1077,6 -1081,12 +1081,12 @@@ int genphy_suspend(struct phy_device *p int genphy_resume(struct phy_device *phydev); int genphy_loopback(struct phy_device *phydev, bool enable); int genphy_soft_reset(struct phy_device *phydev); + + static inline int genphy_config_aneg(struct phy_device *phydev) + { + return __genphy_config_aneg(phydev, false); + } + static inline int genphy_no_soft_reset(struct phy_device *phydev) { return 0; @@@ -1107,7 -1117,6 +1117,7 @@@ int genphy_c45_an_disable_aneg(struct p int genphy_c45_read_mdix(struct phy_device *phydev); int genphy_c45_pma_read_abilities(struct phy_device *phydev); int genphy_c45_read_status(struct phy_device *phydev); +int genphy_c45_config_aneg(struct phy_device *phydev);
/* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev); diff --combined net/batman-adv/bat_v_ogm.c index bc06e3cdfa84,319249f0f85f..dc4f7430cb5a --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c @@@ -17,12 -17,14 +17,14 @@@ #include <linux/kernel.h> #include <linux/kref.h> #include <linux/list.h> + #include <linux/lockdep.h> #include <linux/netdevice.h> #include <linux/random.h> #include <linux/rculist.h> #include <linux/rcupdate.h> #include <linux/skbuff.h> #include <linux/slab.h> + #include <linux/spinlock.h> #include <linux/stddef.h> #include <linux/string.h> #include <linux/types.h> @@@ -77,6 -79,20 +79,20 @@@ struct batadv_orig_node *batadv_v_ogm_o }
/** + * batadv_v_ogm_start_queue_timer() - restart the OGM aggregation timer + * @hard_iface: the interface to use to send the OGM + */ + static void batadv_v_ogm_start_queue_timer(struct batadv_hard_iface *hard_iface) + { + unsigned int msecs = BATADV_MAX_AGGREGATION_MS * 1000; + + /* msecs * [0.9, 1.1] */ + msecs += prandom_u32() % (msecs / 5) - (msecs / 10); + queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.aggr_wq, + msecs_to_jiffies(msecs / 1000)); + } + + /** * batadv_v_ogm_start_timer() - restart the OGM sending timer * @bat_priv: the bat priv with all the soft interface information */ @@@ -116,6 -132,130 +132,130 @@@ static void batadv_v_ogm_send_to_if(str }
/** + * batadv_v_ogm_len() - OGMv2 packet length + * @skb: the OGM to check + * + * Return: Length of the given OGMv2 packet, including tvlv length, excluding + * ethernet header length. + */ + static unsigned int batadv_v_ogm_len(struct sk_buff *skb) + { + struct batadv_ogm2_packet *ogm_packet; + + ogm_packet = (struct batadv_ogm2_packet *)skb->data; + return BATADV_OGM2_HLEN + ntohs(ogm_packet->tvlv_len); + } + + /** + * batadv_v_ogm_queue_left() - check if given OGM still fits aggregation queue + * @skb: the OGM to check + * @hard_iface: the interface to use to send the OGM + * + * Caller needs to hold the hard_iface->bat_v.aggr_list_lock. + * + * Return: True, if the given OGMv2 packet still fits, false otherwise. + */ + static bool batadv_v_ogm_queue_left(struct sk_buff *skb, + struct batadv_hard_iface *hard_iface) + { + unsigned int max = min_t(unsigned int, hard_iface->net_dev->mtu, + BATADV_MAX_AGGREGATION_BYTES); + unsigned int ogm_len = batadv_v_ogm_len(skb); + + lockdep_assert_held(&hard_iface->bat_v.aggr_list_lock); + + return hard_iface->bat_v.aggr_len + ogm_len <= max; + } + + /** + * batadv_v_ogm_aggr_list_free - free all elements in an aggregation queue + * @hard_iface: the interface holding the aggregation queue + * + * Empties the OGMv2 aggregation queue and frees all the skbs it contained. + * + * Caller needs to hold the hard_iface->bat_v.aggr_list_lock. + */ + static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface) + { + struct sk_buff *skb; + + lockdep_assert_held(&hard_iface->bat_v.aggr_list_lock); + + while ((skb = skb_dequeue(&hard_iface->bat_v.aggr_list))) + kfree_skb(skb); + + hard_iface->bat_v.aggr_len = 0; + } + + /** + * batadv_v_ogm_aggr_send() - flush & send aggregation queue + * @hard_iface: the interface with the aggregation queue to flush + * + * Aggregates all OGMv2 packets currently in the aggregation queue into a + * single OGMv2 packet and transmits this aggregate. + * + * The aggregation queue is empty after this call. + * + * Caller needs to hold the hard_iface->bat_v.aggr_list_lock. + */ + static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface) + { + unsigned int aggr_len = hard_iface->bat_v.aggr_len; + struct sk_buff *skb_aggr; + unsigned int ogm_len; + struct sk_buff *skb; + + lockdep_assert_held(&hard_iface->bat_v.aggr_list_lock); + + if (!aggr_len) + return; + + skb_aggr = dev_alloc_skb(aggr_len + ETH_HLEN + NET_IP_ALIGN); + if (!skb_aggr) { + batadv_v_ogm_aggr_list_free(hard_iface); + return; + } + + skb_reserve(skb_aggr, ETH_HLEN + NET_IP_ALIGN); + skb_reset_network_header(skb_aggr); + + while ((skb = skb_dequeue(&hard_iface->bat_v.aggr_list))) { + hard_iface->bat_v.aggr_len -= batadv_v_ogm_len(skb); + + ogm_len = batadv_v_ogm_len(skb); + skb_put_data(skb_aggr, skb->data, ogm_len); + + consume_skb(skb); + } + + batadv_v_ogm_send_to_if(skb_aggr, hard_iface); + } + + /** + * batadv_v_ogm_queue_on_if() - queue a batman ogm on a given interface + * @skb: the OGM to queue + * @hard_iface: the interface to queue the OGM on + */ + static void batadv_v_ogm_queue_on_if(struct sk_buff *skb, + struct batadv_hard_iface *hard_iface) + { + struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + + if (!atomic_read(&bat_priv->aggregated_ogms)) { + batadv_v_ogm_send_to_if(skb, hard_iface); + return; + } + + spin_lock_bh(&hard_iface->bat_v.aggr_list_lock); + if (!batadv_v_ogm_queue_left(skb, hard_iface)) + batadv_v_ogm_aggr_send(hard_iface); + + hard_iface->bat_v.aggr_len += batadv_v_ogm_len(skb); + skb_queue_tail(&hard_iface->bat_v.aggr_list, skb); + spin_unlock_bh(&hard_iface->bat_v.aggr_list_lock); + } + + /** * batadv_v_ogm_send() - periodic worker broadcasting the own OGM * @work: work queue item */ @@@ -210,7 -350,7 +350,7 @@@ static void batadv_v_ogm_send(struct wo break; }
- batadv_v_ogm_send_to_if(skb_tmp, hard_iface); + batadv_v_ogm_queue_on_if(skb_tmp, hard_iface); batadv_hardif_put(hard_iface); } rcu_read_unlock(); @@@ -224,6 -364,27 +364,27 @@@ out }
/** + * batadv_v_ogm_aggr_work() - OGM queue periodic task per interface + * @work: work queue item + * + * Emits aggregated OGM message in regular intervals. + */ + void batadv_v_ogm_aggr_work(struct work_struct *work) + { + struct batadv_hard_iface_bat_v *batv; + struct batadv_hard_iface *hard_iface; + + batv = container_of(work, struct batadv_hard_iface_bat_v, aggr_wq.work); + hard_iface = container_of(batv, struct batadv_hard_iface, bat_v); + + spin_lock_bh(&hard_iface->bat_v.aggr_list_lock); + batadv_v_ogm_aggr_send(hard_iface); + spin_unlock_bh(&hard_iface->bat_v.aggr_list_lock); + + batadv_v_ogm_start_queue_timer(hard_iface); + } + + /** * batadv_v_ogm_iface_enable() - prepare an interface for B.A.T.M.A.N. V * @hard_iface: the interface to prepare * @@@ -235,12 -396,26 +396,26 @@@ int batadv_v_ogm_iface_enable(struct ba { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+ batadv_v_ogm_start_queue_timer(hard_iface); batadv_v_ogm_start_timer(bat_priv);
return 0; }
/** + * batadv_v_ogm_iface_disable() - release OGM interface private resources + * @hard_iface: interface for which the resources have to be released + */ + void batadv_v_ogm_iface_disable(struct batadv_hard_iface *hard_iface) + { + cancel_delayed_work_sync(&hard_iface->bat_v.aggr_wq); + + spin_lock_bh(&hard_iface->bat_v.aggr_list_lock); + batadv_v_ogm_aggr_list_free(hard_iface); + spin_unlock_bh(&hard_iface->bat_v.aggr_list_lock); + } + + /** * batadv_v_ogm_primary_iface_set() - set a new primary interface * @primary_iface: the new primary interface */ @@@ -382,7 -557,7 +557,7 @@@ static void batadv_v_ogm_forward(struc if_outgoing->net_dev->name, ntohl(ogm_forward->throughput), ogm_forward->ttl, if_incoming->net_dev->name);
- batadv_v_ogm_send_to_if(skb, if_outgoing); + batadv_v_ogm_queue_on_if(skb, if_outgoing);
out: if (orig_ifinfo) @@@ -631,23 -806,17 +806,23 @@@ batadv_v_ogm_process_per_outif(struct b * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated * @buff_pos: current position in the skb * @packet_len: total length of the skb - * @tvlv_len: tvlv length of the previously considered OGM + * @ogm2_packet: potential OGM2 in buffer * * Return: true if there is enough space for another OGM, false otherwise. */ -static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len, - __be16 tvlv_len) +static bool +batadv_v_ogm_aggr_packet(int buff_pos, int packet_len, + const struct batadv_ogm2_packet *ogm2_packet) { int next_buff_pos = 0;
- next_buff_pos += buff_pos + BATADV_OGM2_HLEN; - next_buff_pos += ntohs(tvlv_len); + /* check if there is enough space for the header */ + next_buff_pos += buff_pos + sizeof(*ogm2_packet); + if (next_buff_pos > packet_len) + return false; + + /* check if there is enough space for the optional TVLV */ + next_buff_pos += ntohs(ogm2_packet->tvlv_len);
return (next_buff_pos <= packet_len) && (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); @@@ -824,7 -993,7 +999,7 @@@ int batadv_v_ogm_packet_recv(struct sk_ ogm_packet = (struct batadv_ogm2_packet *)skb->data;
while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb), - ogm_packet->tvlv_len)) { + ogm_packet)) { batadv_v_ogm_process(skb, ogm_offset, if_incoming);
ogm_offset += BATADV_OGM2_HLEN; diff --combined net/dsa/tag_8021q.c index 67a1bc635a7b,e44e6275b0a1..9c1cc2482b68 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@@ -28,7 -28,6 +28,7 @@@ * * RSV - VID[9]: * To be used for further expansion of SWITCH_ID or for other purposes. + * Must be transmitted as zero and ignored on receive. * * SWITCH_ID - VID[8:6]: * Index of switch within DSA tree. Must be between 0 and @@@ -36,7 -35,6 +36,7 @@@ * * RSV - VID[5:4]: * To be used for further expansion of PORT or for other purposes. + * Must be transmitted as zero and ignored on receive. * * PORT - VID[3:0]: * Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1. @@@ -93,6 -91,79 +93,79 @@@ int dsa_8021q_rx_source_port(u16 vid } EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port);
+ static int dsa_8021q_restore_pvid(struct dsa_switch *ds, int port) + { + struct bridge_vlan_info vinfo; + struct net_device *slave; + u16 pvid; + int err; + + if (!dsa_is_user_port(ds, port)) + return 0; + + slave = ds->ports[port].slave; + + err = br_vlan_get_pvid(slave, &pvid); + if (err < 0) + /* There is no pvid on the bridge for this port, which is + * perfectly valid. Nothing to restore, bye-bye! + */ + return 0; + + err = br_vlan_get_info(slave, pvid, &vinfo); + if (err < 0) { + dev_err(ds->dev, "Couldn't determine PVID attributes\n"); + return err; + } + + return dsa_port_vid_add(&ds->ports[port], pvid, vinfo.flags); + } + + /* If @enabled is true, installs @vid with @flags into the switch port's HW + * filter. + * If @enabled is false, deletes @vid (ignores @flags) from the port. Had the + * user explicitly configured this @vid through the bridge core, then the @vid + * is installed again, but this time with the flags from the bridge layer. + */ + static int dsa_8021q_vid_apply(struct dsa_switch *ds, int port, u16 vid, + u16 flags, bool enabled) + { + struct dsa_port *dp = &ds->ports[port]; + struct bridge_vlan_info vinfo; + int err; + + if (enabled) + return dsa_port_vid_add(dp, vid, flags); + + err = dsa_port_vid_del(dp, vid); + if (err < 0) + return err; + + /* Nothing to restore from the bridge for a non-user port. + * The CPU port VLANs are restored implicitly with the user ports, + * similar to how the bridge does in dsa_slave_vlan_add and + * dsa_slave_vlan_del. + */ + if (!dsa_is_user_port(ds, port)) + return 0; + + err = br_vlan_get_info(dp->slave, vid, &vinfo); + /* Couldn't determine bridge attributes for this vid, + * it means the bridge had not configured it. + */ + if (err < 0) + return 0; + + /* Restore the VID from the bridge */ + err = dsa_port_vid_add(dp, vid, vinfo.flags); + if (err < 0) + return err; + + vinfo.flags &= ~BRIDGE_VLAN_INFO_PVID; + + return dsa_port_vid_add(dp->cpu_dp, vid, vinfo.flags); + } + /* RX VLAN tagging (left) and TX VLAN tagging (right) setup shown for a single * front-panel switch port (here swp0). * @@@ -148,8 -219,6 +221,6 @@@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled) { int upstream = dsa_upstream_port(ds, port); - struct dsa_port *dp = &ds->ports[port]; - struct dsa_port *upstream_dp = &ds->ports[upstream]; u16 rx_vid = dsa_8021q_rx_vid(ds, port); u16 tx_vid = dsa_8021q_tx_vid(ds, port); int i, err; @@@ -166,7 -235,6 +237,6 @@@ * restrictions, so there are no concerns about leaking traffic. */ for (i = 0; i < ds->num_ports; i++) { - struct dsa_port *other_dp = &ds->ports[i]; u16 flags;
if (i == upstream) @@@ -179,10 -247,7 +249,7 @@@ /* The RX VID is a regular VLAN on all others */ flags = BRIDGE_VLAN_INFO_UNTAGGED;
- if (enabled) - err = dsa_port_vid_add(other_dp, rx_vid, flags); - else - err = dsa_port_vid_del(other_dp, rx_vid); + err = dsa_8021q_vid_apply(ds, i, rx_vid, flags, enabled); if (err) { dev_err(ds->dev, "Failed to apply RX VID %d to port %d: %d\n", rx_vid, port, err); @@@ -193,10 -258,7 +260,7 @@@ /* CPU port needs to see this port's RX VID * as tagged egress. */ - if (enabled) - err = dsa_port_vid_add(upstream_dp, rx_vid, 0); - else - err = dsa_port_vid_del(upstream_dp, rx_vid); + err = dsa_8021q_vid_apply(ds, upstream, rx_vid, 0, enabled); if (err) { dev_err(ds->dev, "Failed to apply RX VID %d to port %d: %d\n", rx_vid, port, err); @@@ -204,26 -266,24 +268,24 @@@ }
/* Finally apply the TX VID on this port and on the CPU port */ - if (enabled) - err = dsa_port_vid_add(dp, tx_vid, BRIDGE_VLAN_INFO_UNTAGGED); - else - err = dsa_port_vid_del(dp, tx_vid); + err = dsa_8021q_vid_apply(ds, port, tx_vid, BRIDGE_VLAN_INFO_UNTAGGED, + enabled); if (err) { dev_err(ds->dev, "Failed to apply TX VID %d on port %d: %d\n", tx_vid, port, err); return err; } - if (enabled) - err = dsa_port_vid_add(upstream_dp, tx_vid, 0); - else - err = dsa_port_vid_del(upstream_dp, tx_vid); + err = dsa_8021q_vid_apply(ds, upstream, tx_vid, 0, enabled); if (err) { dev_err(ds->dev, "Failed to apply TX VID %d on port %d: %d\n", tx_vid, upstream, err); return err; }
- return 0; + if (!enabled) + err = dsa_8021q_restore_pvid(ds, port); + + return err; } EXPORT_SYMBOL_GPL(dsa_port_setup_8021q_tagging);
diff --combined net/ipv4/tcp.c index 61082065b26a,051ef10374f6..94df48bcecc2 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@@ -935,22 -935,6 +935,22 @@@ static int tcp_send_mss(struct sock *sk return mss_now; }
+/* In some cases, both sendpage() and sendmsg() could have added + * an skb to the write queue, but failed adding payload on it. + * We need to remove it to consume less memory, but more + * importantly be able to generate EPOLLOUT for Edge Trigger epoll() + * users. + */ +static void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb) +{ + if (skb && !skb->len) { + tcp_unlink_write_queue(skb, sk); + if (tcp_write_queue_empty(sk)) + tcp_chrono_stop(sk, TCP_CHRONO_BUSY); + sk_wmem_free_skb(sk, skb); + } +} + ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, size_t size, int flags) { @@@ -1080,7 -1064,6 +1080,7 @@@ out return copied;
do_error: + tcp_remove_empty_skb(sk, tcp_write_queue_tail(sk)); if (copied) goto out; out_err: @@@ -1182,7 -1165,7 +1182,7 @@@ int tcp_sendmsg_locked(struct sock *sk struct sockcm_cookie sockc; int flags, err, copied = 0; int mss_now = 0, size_goal, copied_syn = 0; - bool process_backlog = false; + int process_backlog = 0; bool zc = false; long timeo;
@@@ -1274,9 -1257,10 +1274,10 @@@ new_segment if (!sk_stream_memory_free(sk)) goto wait_for_sndbuf;
- if (process_backlog && sk_flush_backlog(sk)) { - process_backlog = false; - goto restart; + if (unlikely(process_backlog >= 16)) { + process_backlog = 0; + if (sk_flush_backlog(sk)) + goto restart; } first_skb = tcp_rtx_and_write_queues_empty(sk); skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation, @@@ -1284,7 -1268,7 +1285,7 @@@ if (!skb) goto wait_for_memory;
- process_backlog = true; + process_backlog++; skb->ip_summed = CHECKSUM_PARTIAL;
skb_entail(sk, skb); @@@ -1405,11 -1389,18 +1406,11 @@@ out_nopush sock_zerocopy_put(uarg); return copied + copied_syn;
+do_error: + skb = tcp_write_queue_tail(sk); do_fault: - if (!skb->len) { - tcp_unlink_write_queue(skb, sk); - /* It is the one place in all of TCP, except connection - * reset, where we can be unlinking the send_head. - */ - if (tcp_write_queue_empty(sk)) - tcp_chrono_stop(sk, TCP_CHRONO_BUSY); - sk_wmem_free_skb(sk, skb); - } + tcp_remove_empty_skb(sk, skb);
-do_error: if (copied + copied_syn) goto out; out_err: @@@ -1789,19 -1780,21 +1790,21 @@@ static int tcp_zerocopy_receive(struct break; frags = skb_shinfo(skb)->frags; while (offset) { - if (frags->size > offset) + if (skb_frag_size(frags) > offset) goto out; - offset -= frags->size; + offset -= skb_frag_size(frags); frags++; } } - if (frags->size != PAGE_SIZE || frags->page_offset) { + if (skb_frag_size(frags) != PAGE_SIZE || skb_frag_off(frags)) { int remaining = zc->recv_skip_hint; + int size = skb_frag_size(frags);
- while (remaining && (frags->size != PAGE_SIZE || - frags->page_offset)) { - remaining -= frags->size; + while (remaining && (size != PAGE_SIZE || + skb_frag_off(frags))) { + remaining -= size; frags++; + size = skb_frag_size(frags); } zc->recv_skip_hint -= remaining; break; @@@ -3794,8 -3787,8 +3797,8 @@@ int tcp_md5_hash_skb_data(struct tcp_md return 1;
for (i = 0; i < shi->nr_frags; ++i) { - const struct skb_frag_struct *f = &shi->frags[i]; - unsigned int offset = f->page_offset; + const skb_frag_t *f = &shi->frags[i]; + unsigned int offset = skb_frag_off(f); struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT);
sg_set_page(&sg, page, skb_frag_size(f), diff --combined net/ipv4/tcp_output.c index 8a645f304e6c,5c46bc4c7e8d..42abc9bd687a --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@@ -1403,7 -1403,7 +1403,7 @@@ static int __pskb_trim_head(struct sk_b } else { shinfo->frags[k] = shinfo->frags[i]; if (eat) { - shinfo->frags[k].page_offset += eat; + skb_frag_off_add(&shinfo->frags[k], eat); skb_frag_size_sub(&shinfo->frags[k], eat); eat = 0; } @@@ -2053,7 -2053,7 +2053,7 @@@ static bool tcp_can_coalesce_send_queue if (len <= skb->len) break;
- if (unlikely(TCP_SKB_CB(skb)->eor)) + if (unlikely(TCP_SKB_CB(skb)->eor) || tcp_has_tx_tstamp(skb)) return false;
len -= skb->len; @@@ -2170,7 -2170,6 +2170,7 @@@ static int tcp_mtu_probe(struct sock *s * we need to propagate it to the new skb. */ TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor; + tcp_skb_collapse_tstamp(nskb, skb); tcp_unlink_write_queue(skb, sk); sk_wmem_free_skb(sk, skb); } else { diff --combined net/netfilter/nf_conntrack_ftp.c index 8d96738b7dfd,c57d2348c505..9eca90414bb7 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@@ -162,7 -162,7 +162,7 @@@ static int try_rfc959(const char *data if (length == 0) return 0;
- cmd->u3.ip = htonl((array[0] << 24) | (array[1] << 16) | + cmd->u3.ip = htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]); cmd->u.tcp.port = htons((array[4] << 8) | array[5]); return length; @@@ -322,7 -322,7 +322,7 @@@ static int find_pattern(const char *dat i++; }
- pr_debug("Skipped up to `%c'!\n", skip); + pr_debug("Skipped up to 0x%hhx delimiter!\n", skip);
*numoff = i; *numlen = getnum(data + i, dlen - i, cmd, term, numoff); diff --combined net/netfilter/nf_conntrack_standalone.c index 0006503d2da9,d97f4ea47cf3..88d4127df863 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@@ -511,8 -511,6 +511,6 @@@ static void nf_conntrack_standalone_fin /* Log invalid packets of a given protocol */ static int log_invalid_proto_min __read_mostly; static int log_invalid_proto_max __read_mostly = 255; - static int zero; - static int one = 1;
/* size the user *wants to set */ static unsigned int nf_conntrack_htable_size_user __read_mostly; @@@ -629,8 -627,8 +627,8 @@@ static struct ctl_table nf_ct_sysctl_ta .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, [NF_SYSCTL_CT_LOG_INVALID] = { .procname = "nf_conntrack_log_invalid", @@@ -654,8 -652,8 +652,8 @@@ .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, [NF_SYSCTL_CT_HELPER] = { .procname = "nf_conntrack_helper", @@@ -663,8 -661,8 +661,8 @@@ .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, #ifdef CONFIG_NF_CONNTRACK_EVENTS [NF_SYSCTL_CT_EVENTS] = { @@@ -673,8 -671,8 +671,8 @@@ .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, #endif #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP @@@ -684,8 -682,8 +682,8 @@@ .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, #endif [NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC] = { @@@ -759,16 -757,16 +757,16 @@@ .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, [NF_SYSCTL_CT_PROTO_TCP_LIBERAL] = { .procname = "nf_conntrack_tcp_be_liberal", .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, [NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS] = { .procname = "nf_conntrack_tcp_max_retrans", @@@ -904,8 -902,8 +902,8 @@@ .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, }, #endif #ifdef CONFIG_NF_CT_PROTO_GRE @@@ -1037,14 -1035,9 +1035,14 @@@ static int nf_conntrack_standalone_init table[NF_SYSCTL_CT_COUNT].data = &net->ct.count; table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum; table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid; + table[NF_SYSCTL_CT_ACCT].data = &net->ct.sysctl_acct; + table[NF_SYSCTL_CT_HELPER].data = &net->ct.sysctl_auto_assign_helper; #ifdef CONFIG_NF_CONNTRACK_EVENTS table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events; #endif +#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP + table[NF_SYSCTL_CT_TIMESTAMP].data = &net->ct.sysctl_tstamp; +#endif table[NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC].data = &nf_generic_pernet(net)->timeout; table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP].data = &nf_icmp_pernet(net)->timeout; table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6].data = &nf_icmpv6_pernet(net)->timeout; diff --combined net/rds/recv.c index a42ba7fa06d5,7e451c82595b..c8404971d5ab --- a/net/rds/recv.c +++ b/net/rds/recv.c @@@ -1,5 -1,5 +1,5 @@@ /* - * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@@ -47,8 -47,8 +47,8 @@@ void rds_inc_init(struct rds_incoming * INIT_LIST_HEAD(&inc->i_item); inc->i_conn = conn; inc->i_saddr = *saddr; - inc->i_rdma_cookie = 0; - inc->i_rx_tstamp = ktime_set(0, 0); + inc->i_usercopy.rdma_cookie = 0; + inc->i_usercopy.rx_tstamp = ktime_set(0, 0);
memset(inc->i_rx_lat_trace, 0, sizeof(inc->i_rx_lat_trace)); } @@@ -62,8 -62,8 +62,8 @@@ void rds_inc_path_init(struct rds_incom inc->i_conn = cp->cp_conn; inc->i_conn_path = cp; inc->i_saddr = *saddr; - inc->i_rdma_cookie = 0; - inc->i_rx_tstamp = ktime_set(0, 0); + inc->i_usercopy.rdma_cookie = 0; + inc->i_usercopy.rx_tstamp = ktime_set(0, 0); } EXPORT_SYMBOL_GPL(rds_inc_path_init);
@@@ -186,7 -186,7 +186,7 @@@ static void rds_recv_incoming_exthdrs(s case RDS_EXTHDR_RDMA_DEST: /* We ignore the size for now. We could stash it * somewhere and use it for error checking. */ - inc->i_rdma_cookie = rds_rdma_make_cookie( + inc->i_usercopy.rdma_cookie = rds_rdma_make_cookie( be32_to_cpu(buffer.rdma_dest.h_rdma_rkey), be32_to_cpu(buffer.rdma_dest.h_rdma_offset));
@@@ -380,7 -380,7 +380,7 @@@ void rds_recv_incoming(struct rds_conne be32_to_cpu(inc->i_hdr.h_len), inc->i_hdr.h_dport); if (sock_flag(sk, SOCK_RCVTSTAMP)) - inc->i_rx_tstamp = ktime_get_real(); + inc->i_usercopy.rx_tstamp = ktime_get_real(); rds_inc_addref(inc); inc->i_rx_lat_trace[RDS_MSG_RX_END] = local_clock(); list_add_tail(&inc->i_item, &rs->rs_recv_queue); @@@ -540,16 -540,18 +540,18 @@@ static int rds_cmsg_recv(struct rds_inc { int ret = 0;
- if (inc->i_rdma_cookie) { + if (inc->i_usercopy.rdma_cookie) { ret = put_cmsg(msg, SOL_RDS, RDS_CMSG_RDMA_DEST, - sizeof(inc->i_rdma_cookie), &inc->i_rdma_cookie); + sizeof(inc->i_usercopy.rdma_cookie), + &inc->i_usercopy.rdma_cookie); if (ret) goto out; }
- if ((inc->i_rx_tstamp != 0) && + if ((inc->i_usercopy.rx_tstamp != 0) && sock_flag(rds_rs_to_sk(rs), SOCK_RCVTSTAMP)) { - struct __kernel_old_timeval tv = ns_to_kernel_old_timeval(inc->i_rx_tstamp); + struct __kernel_old_timeval tv = + ns_to_kernel_old_timeval(inc->i_usercopy.rx_tstamp);
if (!sock_flag(rds_rs_to_sk(rs), SOCK_TSTAMP_NEW)) { ret = put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD, @@@ -811,7 -813,6 +813,7 @@@ void rds6_inc_info_copy(struct rds_inco
minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence); minfo6.len = be32_to_cpu(inc->i_hdr.h_len); + minfo6.tos = inc->i_conn->c_tos;
if (flip) { minfo6.laddr = *daddr; @@@ -825,8 -826,6 +827,8 @@@ minfo6.fport = inc->i_hdr.h_dport; }
+ minfo6.flags = 0; + rds_info_copy(iter, &minfo6, sizeof(minfo6)); } #endif diff --combined net/rxrpc/ar-internal.h index 8051dfdcf26d,fa5b030acaa8..1091bf35a199 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@@ -185,17 -185,11 +185,17 @@@ struct rxrpc_host_header * - max 48 bytes (struct sk_buff::cb) */ struct rxrpc_skb_priv { - union { - u8 nr_jumbo; /* Number of jumbo subpackets */ - }; + atomic_t nr_ring_pins; /* Number of rxtx ring pins */ + u8 nr_subpackets; /* Number of subpackets */ + u8 rx_flags; /* Received packet flags */ +#define RXRPC_SKB_INCL_LAST 0x01 /* - Includes last packet */ +#define RXRPC_SKB_TX_BUFFER 0x02 /* - Is transmit buffer */ union { int remain; /* amount of space remaining for next write */ + + /* List of requested ACKs on subpackets */ + unsigned long rx_req_ack[(RXRPC_MAX_NR_JUMBO + BITS_PER_LONG - 1) / + BITS_PER_LONG]; };
struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */ @@@ -232,6 -226,9 +232,9 @@@ struct rxrpc_security int (*verify_packet)(struct rxrpc_call *, struct sk_buff *, unsigned int, unsigned int, rxrpc_seq_t, u16);
+ /* Free crypto request on a call */ + void (*free_call_crypto)(struct rxrpc_call *); + /* Locate the data in a received packet that has been verified. */ void (*locate_data)(struct rxrpc_call *, struct sk_buff *, unsigned int *, unsigned int *); @@@ -564,6 -561,7 +567,7 @@@ struct rxrpc_call unsigned long expect_term_by; /* When we expect call termination by */ u32 next_rx_timo; /* Timeout for next Rx packet (jif) */ u32 next_req_timo; /* Timeout for next Rx request packet (jif) */ + struct skcipher_request *cipher_req; /* Packet cipher request buffer */ struct timer_list timer; /* Combined event timer */ struct work_struct processor; /* Event processor */ rxrpc_notify_rx_t notify_rx; /* kernel service Rx notification function */ @@@ -619,7 -617,8 +623,7 @@@ #define RXRPC_TX_ANNO_LAST 0x04 #define RXRPC_TX_ANNO_RESENT 0x08
-#define RXRPC_RX_ANNO_JUMBO 0x3f /* Jumbo subpacket number + 1 if not zero */ -#define RXRPC_RX_ANNO_JLAST 0x40 /* Set if last element of a jumbo packet */ +#define RXRPC_RX_ANNO_SUBPACKET 0x3f /* Subpacket number in jumbogram */ #define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */ rxrpc_seq_t tx_hard_ack; /* Dead slot in buffer; the first transmitted but * not hard-ACK'd packet follows this. @@@ -910,7 -909,6 +914,7 @@@ void rxrpc_disconnect_client_call(struc void rxrpc_put_client_conn(struct rxrpc_connection *); void rxrpc_discard_expired_client_conns(struct work_struct *); void rxrpc_destroy_all_client_connections(struct rxrpc_net *); +void rxrpc_clean_up_local_conns(struct rxrpc_local *);
/* * conn_event.c @@@ -1111,7 -1109,6 +1115,7 @@@ void rxrpc_kernel_data_consumed(struct void rxrpc_packet_destructor(struct sk_buff *); void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace); void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace); +void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace); void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace); void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace); void rxrpc_purge_queue(struct sk_buff_head *); diff --combined net/rxrpc/call_object.c index 014548c259ce,60cbc81dc461..32d8dc677142 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@@ -422,19 -422,6 +422,19 @@@ void rxrpc_get_call(struct rxrpc_call * }
/* + * Clean up the RxTx skb ring. + */ +static void rxrpc_cleanup_ring(struct rxrpc_call *call) +{ + int i; + + for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { + rxrpc_free_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned); + call->rxtx_buffer[i] = NULL; + } +} + +/* * Detach a call from its owning socket. */ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) @@@ -442,6 -429,7 +442,6 @@@ const void *here = __builtin_return_address(0); struct rxrpc_connection *conn = call->conn; bool put = false; - int i;
_enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
@@@ -488,10 -476,18 +488,12 @@@
_debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn);
- if (conn) + if (conn) { rxrpc_disconnect_call(call); + conn->security->free_call_crypto(call); + }
- for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { - rxrpc_free_skb(call->rxtx_buffer[i], - (call->tx_phase ? rxrpc_skb_tx_cleaned : - rxrpc_skb_rx_cleaned)); - call->rxtx_buffer[i] = NULL; - } - + rxrpc_cleanup_ring(call); _leave(""); }
@@@ -574,6 -570,8 +576,6 @@@ static void rxrpc_rcu_destroy_call(stru */ void rxrpc_cleanup_call(struct rxrpc_call *call) { - int i; - _net("DESTROY CALL %d", call->debug_id);
memset(&call->sock_node, 0xcd, sizeof(call->sock_node)); @@@ -584,8 -582,13 +586,8 @@@ ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); ASSERTCMP(call->conn, ==, NULL);
- /* Clean up the Rx/Tx buffer */ - for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) - rxrpc_free_skb(call->rxtx_buffer[i], - (call->tx_phase ? rxrpc_skb_tx_cleaned : - rxrpc_skb_rx_cleaned)); - - rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned); + rxrpc_cleanup_ring(call); + rxrpc_free_skb(call->tx_pending, rxrpc_skb_cleaned);
call_rcu(&call->rcu, rxrpc_rcu_destroy_call); } diff --combined net/rxrpc/rxkad.c index c60c520fde7c,dbb109da1835..8d8aa3c230b5 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@@ -43,6 -43,7 +43,7 @@@ struct rxkad_level2_hdr * packets */ static struct crypto_sync_skcipher *rxkad_ci; + static struct skcipher_request *rxkad_ci_req; static DEFINE_MUTEX(rxkad_ci_mutex);
/* @@@ -99,8 -100,8 +100,8 @@@ error */ static int rxkad_prime_packet_security(struct rxrpc_connection *conn) { + struct skcipher_request *req; struct rxrpc_key_token *token; - SYNC_SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); struct scatterlist sg; struct rxrpc_crypt iv; __be32 *tmpbuf; @@@ -115,6 -116,12 +116,12 @@@ if (!tmpbuf) return -ENOMEM;
+ req = skcipher_request_alloc(&conn->cipher->base, GFP_NOFS); + if (!req) { + kfree(tmpbuf); + return -ENOMEM; + } + token = conn->params.key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv));
@@@ -128,7 -135,7 +135,7 @@@ skcipher_request_set_callback(req, 0, NULL, NULL); skcipher_request_set_crypt(req, &sg, &sg, tmpsize, iv.x); crypto_skcipher_encrypt(req); - skcipher_request_zero(req); + skcipher_request_free(req);
memcpy(&conn->csum_iv, tmpbuf + 2, sizeof(conn->csum_iv)); kfree(tmpbuf); @@@ -137,6 -144,35 +144,35 @@@ }
/* + * Allocate and prepare the crypto request on a call. For any particular call, + * this is called serially for the packets, so no lock should be necessary. + */ + static struct skcipher_request *rxkad_get_call_crypto(struct rxrpc_call *call) + { + struct crypto_skcipher *tfm = &call->conn->cipher->base; + struct skcipher_request *cipher_req = call->cipher_req; + + if (!cipher_req) { + cipher_req = skcipher_request_alloc(tfm, GFP_NOFS); + if (!cipher_req) + return NULL; + call->cipher_req = cipher_req; + } + + return cipher_req; + } + + /* + * Clean up the crypto on a call. + */ + static void rxkad_free_call_crypto(struct rxrpc_call *call) + { + if (call->cipher_req) + skcipher_request_free(call->cipher_req); + call->cipher_req = NULL; + } + + /* * partially encrypt a packet (level 1 security) */ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, @@@ -187,8 -223,10 +223,8 @@@ static int rxkad_secure_packet_encrypt( struct rxrpc_skb_priv *sp; struct rxrpc_crypt iv; struct scatterlist sg[16]; - struct sk_buff *trailer; unsigned int len; u16 check; - int nsg; int err;
sp = rxrpc_skb(skb); @@@ -212,14 -250,15 +248,14 @@@ crypto_skcipher_encrypt(req);
/* we want to encrypt the skbuff in-place */ - nsg = skb_cow_data(skb, 0, &trailer); - err = -ENOMEM; - if (nsg < 0 || nsg > 16) + err = -EMSGSIZE; + if (skb_shinfo(skb)->nr_frags > 16) goto out;
len = data_size + call->conn->size_align - 1; len &= ~(call->conn->size_align - 1);
- sg_init_table(sg, nsg); + sg_init_table(sg, ARRAY_SIZE(sg)); err = skb_to_sgvec(skb, sg, 0, len); if (unlikely(err < 0)) goto out; @@@ -243,7 -282,7 +279,7 @@@ static int rxkad_secure_packet(struct r void *sechdr) { struct rxrpc_skb_priv *sp; - SYNC_SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); + struct skcipher_request *req; struct rxrpc_crypt iv; struct scatterlist sg; u32 x, y; @@@ -262,6 -301,10 +298,10 @@@ if (ret < 0) return ret;
+ req = rxkad_get_call_crypto(call); + if (!req) + return -ENOMEM; + /* continue encrypting from where we left off */ memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
@@@ -316,10 -359,11 +356,10 @@@ static int rxkad_verify_packet_1(struc struct rxkad_level1_hdr sechdr; struct rxrpc_crypt iv; struct scatterlist sg[16]; - struct sk_buff *trailer; bool aborted; u32 data_size, buf; u16 check; - int nsg, ret; + int ret;
_enter("");
@@@ -332,7 -376,11 +372,7 @@@ /* Decrypt the skbuff in-place. TODO: We really want to decrypt * directly into the target buffer. */ - nsg = skb_cow_data(skb, 0, &trailer); - if (nsg < 0 || nsg > 16) - goto nomem; - - sg_init_table(sg, nsg); + sg_init_table(sg, ARRAY_SIZE(sg)); ret = skb_to_sgvec(skb, sg, offset, 8); if (unlikely(ret < 0)) return ret; @@@ -380,6 -428,10 +420,6 @@@ protocol_error if (aborted) rxrpc_send_abort_packet(call); return -EPROTO; - -nomem: - _leave(" = -ENOMEM"); - return -ENOMEM; }
/* @@@ -394,6 -446,7 +434,6 @@@ static int rxkad_verify_packet_2(struc struct rxkad_level2_hdr sechdr; struct rxrpc_crypt iv; struct scatterlist _sg[4], *sg; - struct sk_buff *trailer; bool aborted; u32 data_size, buf; u16 check; @@@ -410,11 -463,12 +450,11 @@@ /* Decrypt the skbuff in-place. TODO: We really want to decrypt * directly into the target buffer. */ - nsg = skb_cow_data(skb, 0, &trailer); - if (nsg < 0) - goto nomem; - sg = _sg; - if (unlikely(nsg > 4)) { + nsg = skb_shinfo(skb)->nr_frags; + if (nsg <= 4) { + nsg = 4; + } else { sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO); if (!sg) goto nomem; @@@ -488,7 -542,7 +528,7 @@@ static int rxkad_verify_packet(struct r unsigned int offset, unsigned int len, rxrpc_seq_t seq, u16 expected_cksum) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); + struct skcipher_request *req; struct rxrpc_crypt iv; struct scatterlist sg; bool aborted; @@@ -501,6 -555,10 +541,10 @@@ if (!call->conn->cipher) return 0;
+ req = rxkad_get_call_crypto(call); + if (!req) + return -ENOMEM; + /* continue encrypting from where we left off */ memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
@@@ -733,14 -791,18 +777,18 @@@ static void rxkad_calc_response_checksu /* * encrypt the response packet */ - static void rxkad_encrypt_response(struct rxrpc_connection *conn, - struct rxkad_response *resp, - const struct rxkad_key *s2) + static int rxkad_encrypt_response(struct rxrpc_connection *conn, + struct rxkad_response *resp, + const struct rxkad_key *s2) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); + struct skcipher_request *req; struct rxrpc_crypt iv; struct scatterlist sg[1];
+ req = skcipher_request_alloc(&conn->cipher->base, GFP_NOFS); + if (!req) + return -ENOMEM; + /* continue encrypting from where we left off */ memcpy(&iv, s2->session_key, sizeof(iv));
@@@ -750,7 -812,8 +798,8 @@@ skcipher_request_set_callback(req, 0, NULL, NULL); skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); crypto_skcipher_encrypt(req); - skcipher_request_zero(req); + skcipher_request_free(req); + return 0; }
/* @@@ -825,8 -888,9 +874,9 @@@ static int rxkad_respond_to_challenge(s
/* calculate the response checksum and then do the encryption */ rxkad_calc_response_checksum(resp); - rxkad_encrypt_response(conn, resp, token->kad); - ret = rxkad_send_response(conn, &sp->hdr, resp, token->kad); + ret = rxkad_encrypt_response(conn, resp, token->kad); + if (ret == 0) + ret = rxkad_send_response(conn, &sp->hdr, resp, token->kad); kfree(resp); return ret;
@@@ -1003,18 -1067,16 +1053,16 @@@ static void rxkad_decrypt_response(stru struct rxkad_response *resp, const struct rxrpc_crypt *session_key) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, rxkad_ci); + struct skcipher_request *req = rxkad_ci_req; struct scatterlist sg[1]; struct rxrpc_crypt iv;
_enter(",,%08x%08x", ntohl(session_key->n[0]), ntohl(session_key->n[1]));
- ASSERT(rxkad_ci != NULL); - mutex_lock(&rxkad_ci_mutex); if (crypto_sync_skcipher_setkey(rxkad_ci, session_key->x, - sizeof(*session_key)) < 0) + sizeof(*session_key)) < 0) BUG();
memcpy(&iv, session_key, sizeof(iv)); @@@ -1208,10 -1270,26 +1256,26 @@@ static void rxkad_clear(struct rxrpc_co */ static int rxkad_init(void) { + struct crypto_sync_skcipher *tfm; + struct skcipher_request *req; + /* pin the cipher we need so that the crypto layer doesn't invoke * keventd to go get it */ - rxkad_ci = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0); - return PTR_ERR_OR_ZERO(rxkad_ci); + tfm = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + req = skcipher_request_alloc(&tfm->base, GFP_KERNEL); + if (!req) + goto nomem_tfm; + + rxkad_ci_req = req; + rxkad_ci = tfm; + return 0; + + nomem_tfm: + crypto_free_sync_skcipher(tfm); + return -ENOMEM; }
/* @@@ -1219,8 -1297,8 +1283,8 @@@ */ static void rxkad_exit(void) { - if (rxkad_ci) - crypto_free_sync_skcipher(rxkad_ci); + crypto_free_sync_skcipher(rxkad_ci); + skcipher_request_free(rxkad_ci_req); }
/* @@@ -1235,6 -1313,7 +1299,7 @@@ const struct rxrpc_security rxkad = .prime_packet_security = rxkad_prime_packet_security, .secure_packet = rxkad_secure_packet, .verify_packet = rxkad_verify_packet, + .free_call_crypto = rxkad_free_call_crypto, .locate_data = rxkad_locate_data, .issue_challenge = rxkad_issue_challenge, .respond_to_challenge = rxkad_respond_to_challenge, diff --combined net/sched/act_vlan.c index 287a30bf8930,216b75709875..08aaf719a70f --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c @@@ -301,6 -301,19 +301,19 @@@ static int tcf_vlan_walker(struct net * return tcf_generic_walker(tn, skb, cb, type, ops, extack); }
+ static void tcf_vlan_stats_update(struct tc_action *a, u64 bytes, u32 packets, + u64 lastuse, bool hw) + { + struct tcf_vlan *v = to_vlan(a); + struct tcf_t *tm = &v->tcf_tm; + + _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats), bytes, packets); + if (hw) + _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats_hw), + bytes, packets); + tm->lastuse = max_t(u64, tm->lastuse, lastuse); + } + static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index) { struct tc_action_net *tn = net_generic(net, vlan_net_id); @@@ -325,6 -338,7 +338,7 @@@ static struct tc_action_ops act_vlan_op .init = tcf_vlan_init, .cleanup = tcf_vlan_cleanup, .walk = tcf_vlan_walker, + .stats_update = tcf_vlan_stats_update, .get_fill_size = tcf_vlan_get_fill_size, .lookup = tcf_vlan_search, .size = sizeof(struct tcf_vlan), @@@ -334,7 -348,7 +348,7 @@@ static __net_init int vlan_init_net(str { struct tc_action_net *tn = net_generic(net, vlan_net_id);
- return tc_action_net_init(tn, &act_vlan_ops); + return tc_action_net_init(net, tn, &act_vlan_ops); }
static void __net_exit vlan_exit_net(struct list_head *net_list) diff --combined net/sched/sch_taprio.c index 8d8bc2ec5cd6,540bde009ea5..84b863e2bdbd --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@@ -477,6 -477,11 +477,6 @@@ static struct sk_buff *taprio_dequeue(s u32 gate_mask; int i;
- if (atomic64_read(&q->picos_per_byte) == -1) { - WARN_ONCE(1, "taprio: dequeue() called with unknown picos per byte."); - return NULL; - } - rcu_read_lock(); entry = rcu_dereference(q->current_entry); /* if there's no entry, it means that the schedule didn't @@@ -672,10 -677,6 +672,6 @@@ static const struct nla_policy entry_po [TCA_TAPRIO_SCHED_ENTRY_INTERVAL] = { .type = NLA_U32 }, };
- static const struct nla_policy entry_list_policy[TCA_TAPRIO_SCHED_MAX + 1] = { - [TCA_TAPRIO_SCHED_ENTRY] = { .type = NLA_NESTED }, - }; - static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = { [TCA_TAPRIO_ATTR_PRIOMAP] = { .len = sizeof(struct tc_mqprio_qopt) @@@ -953,20 -954,12 +949,20 @@@ static void taprio_set_picos_per_byte(s struct taprio_sched *q) { struct ethtool_link_ksettings ecmd; - int picos_per_byte = -1; + int speed = SPEED_10; + int picos_per_byte; + int err;
- if (!__ethtool_get_link_ksettings(dev, &ecmd) && - ecmd.base.speed != SPEED_UNKNOWN) - picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8, - ecmd.base.speed * 1000 * 1000); + err = __ethtool_get_link_ksettings(dev, &ecmd); + if (err < 0) + goto skip; + + if (ecmd.base.speed != SPEED_UNKNOWN) + speed = ecmd.base.speed; + +skip: + picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8, + speed * 1000 * 1000);
atomic64_set(&q->picos_per_byte, picos_per_byte); netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n", @@@ -1252,10 -1245,6 +1248,10 @@@ static int taprio_init(struct Qdisc *sc */ q->clockid = -1;
+ spin_lock(&taprio_list_lock); + list_add(&q->taprio_list, &taprio_list); + spin_unlock(&taprio_list_lock); + if (sch->parent != TC_H_ROOT) return -EOPNOTSUPP;
@@@ -1273,6 -1262,10 +1269,6 @@@ if (!opt) return -EINVAL;
- spin_lock(&taprio_list_lock); - list_add(&q->taprio_list, &taprio_list); - spin_unlock(&taprio_list_lock); - for (i = 0; i < dev->num_tx_queues; i++) { struct netdev_queue *dev_queue; struct Qdisc *qdisc; diff --combined scripts/link-vmlinux.sh index 2438a9faf3f1,c31193340108..f7edb75f9806 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@@ -56,11 -56,10 +56,11 @@@ modpost_link( }
# Link of vmlinux - # ${1} - optional extra .o files - # ${2} - output file + # ${1} - output file + # ${@:2} - optional extra .o files vmlinux_link() { - info LD ${2} ++ info LD ${1} local lds="${objtree}/${KBUILD_LDS}" local objects
@@@ -71,9 -70,9 +71,9 @@@ --start-group \ ${KBUILD_VMLINUX_LIBS} \ --end-group \ - ${1}" + ${@:2}"
- ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ + ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${1} \ -T ${lds} ${objects} else objects="-Wl,--whole-archive \ @@@ -82,9 -81,9 +82,9 @@@ -Wl,--start-group \ ${KBUILD_VMLINUX_LIBS} \ -Wl,--end-group \ - ${1}" + ${@:2}"
- ${CC} ${CFLAGS_vmlinux} -o ${2} \ + ${CC} ${CFLAGS_vmlinux} -o ${1} \ -Wl,-T,${lds} \ ${objects} \ -lutil -lrt -lpthread @@@ -93,23 -92,34 +93,34 @@@ }
# generate .BTF typeinfo from DWARF debuginfo + # ${1} - vmlinux image + # ${2} - file to dump raw BTF data into gen_btf() { - local pahole_ver; + local pahole_ver + local bin_arch
if ! [ -x "$(command -v ${PAHOLE})" ]; then info "BTF" "${1}: pahole (${PAHOLE}) is not available" - return 0 + return 1 fi
pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+).([0-9]+)/\1\2/') if [ "${pahole_ver}" -lt "113" ]; then info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" - return 0 + return 1 fi
- info "BTF" ${1} + info "BTF" ${2} + vmlinux_link ${1} LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} + + # dump .BTF section into raw binary file to link with final vmlinux + bin_arch=$(${OBJDUMP} -f ${1} | grep architecture | \ + cut -d, -f1 | cut -d' ' -f2) + ${OBJCOPY} --dump-section .BTF=.btf.vmlinux.bin ${1} 2>/dev/null + ${OBJCOPY} -I binary -O ${CONFIG_OUTPUT_FORMAT} -B ${bin_arch} \ + --rename-section .data=.BTF .btf.vmlinux.bin ${2} }
# Create ${2} .o file with all symbols from the ${1} object file @@@ -139,18 -149,6 +150,18 @@@ kallsyms( ${CC} ${aflags} -c -o ${2} ${afile} }
+# Perform one step in kallsyms generation, including temporary linking of +# vmlinux. +kallsyms_step() +{ + kallsymso_prev=${kallsymso} + kallsymso=.tmp_kallsyms${1}.o + kallsyms_vmlinux=.tmp_vmlinux${1} + - vmlinux_link "${kallsymso_prev}" ${kallsyms_vmlinux} ++ vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o} + kallsyms ${kallsyms_vmlinux} ${kallsymso} +} + # Create map file with all symbols from ${1} # See mksymap for additional details mksysmap() @@@ -166,6 -164,7 +177,7 @@@ sortextable( # Delete output files in case of error cleanup() { + rm -f .btf.* rm -f .tmp_System.map rm -f .tmp_kallsyms* rm -f .tmp_vmlinux* @@@ -228,8 -227,14 +240,15 @@@ ${MAKE} -f "${srctree}/scripts/Makefile info MODINFO modules.builtin.modinfo ${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
+ btf_vmlinux_bin_o="" + if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then + if gen_btf .tmp_vmlinux.btf .btf.vmlinux.bin.o ; then + btf_vmlinux_bin_o=.btf.vmlinux.bin.o + fi + fi + kallsymso="" +kallsymso_prev="" kallsyms_vmlinux="" if [ -n "${CONFIG_KALLSYMS}" ]; then
@@@ -256,23 -261,32 +275,19 @@@ # a) Verify that the System.map from vmlinux matches the map from # ${kallsymso}.
- kallsymso=.tmp_kallsyms2.o - kallsyms_vmlinux=.tmp_vmlinux2 - - # step 1 - vmlinux_link .tmp_vmlinux1 ${btf_vmlinux_bin_o} - kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o - - # step 2 - vmlinux_link .tmp_vmlinux2 .tmp_kallsyms1.o ${btf_vmlinux_bin_o} - kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o + kallsyms_step 1 + kallsyms_step 2
# step 3 - size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms1.o) - size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms2.o) + size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev}) + size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then - kallsymso=.tmp_kallsyms3.o - kallsyms_vmlinux=.tmp_vmlinux3 - - vmlinux_link .tmp_vmlinux3 .tmp_kallsyms2.o ${btf_vmlinux_bin_o} - kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o + kallsyms_step 3 fi fi
- vmlinux_link "${kallsymso}" vmlinux - - if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then - gen_btf vmlinux - fi -info LD vmlinux + vmlinux_link vmlinux "${kallsymso}" "${btf_vmlinux_bin_o}"
if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then info SORTEX vmlinux