The following commit has been merged in the master branch: commit fdb5a5c43615cffca383fc1711e01c28b47f8c55 Merge: c36b0adfdd8d50829bdcd616de17cb6def53a348 ae1804de93f6f1626906567ae7deec8e0111259d Author: Stephen Rothwell sfr@canb.auug.org.au Date: Thu May 7 11:55:07 2020 +1000
Merge remote-tracking branch 'net-next/master'
# Conflicts: # drivers/net/ipa/ipa_endpoint.c # include/net/mptcp.h
diff --combined Documentation/admin-guide/kernel-parameters.txt index 554240da88c7,398c34804bb8..d2d2dd5a9ad0 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@@ -356,7 -356,7 +356,7 @@@ shot down by NMI
autoconf= [IPV6] - See Documentation/networking/ipv6.txt. + See Documentation/networking/ipv6.rst.
show_lapic= [APIC,X86] Advanced Programmable Interrupt Controller Limit apic dumping. The parameter defines the maximal @@@ -458,7 -458,7 +458,7 @@@ bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards) bttv.radio= Most important insmod options are available as kernel args too. - bttv.pll= See Documentation/media/v4l-drivers/bttv.rst + bttv.pll= See Documentation/admin-guide/media/bttv.rst bttv.tuner=
bulk_remove=off [PPC] This parameter disables the use of the pSeries @@@ -638,7 -638,7 +638,7 @@@
See Documentation/admin-guide/serial-console.rst for more information. See - Documentation/networking/netconsole.txt for an + Documentation/networking/netconsole.rst for an alternative.
uart[8250],io,<addr>[,options] @@@ -831,7 -831,7 +831,7 @@@
decnet.addr= [HW,NET] Format: <area>[,<node>] - See also Documentation/networking/decnet.txt. + See also Documentation/networking/decnet.rst.
default_hugepagesz= [same as hugepagesz=] The size of the default @@@ -872,7 -872,7 +872,7 @@@ miss to occur.
disable= [IPV6] - See Documentation/networking/ipv6.txt. + See Documentation/networking/ipv6.rst.
hardened_usercopy= [KNL] Under CONFIG_HARDENED_USERCOPY, whether @@@ -912,7 -912,7 +912,7 @@@ to workaround buggy firmware.
disable_ipv6= [IPV6] - See Documentation/networking/ipv6.txt. + See Documentation/networking/ipv6.rst.
disable_mtrr_cleanup [X86] The kernel tries to adjust MTRR layout from continuous @@@ -2705,7 -2705,7 +2705,7 @@@ See Documentation/admin-guide/pm/sleep-states.rst.
meye.*= [HW] Set MotionEye Camera parameters - See Documentation/media/v4l-drivers/meye.rst. + See Documentation/admin-guide/media/meye.rst.
mfgpt_irq= [IA-32] Specify the IRQ to use for the Multi-Function General Purpose Timers on AMD Geode @@@ -3669,8 -3669,6 +3669,8 @@@ may put more devices in an IOMMU group. force_floating [S390] Force usage of floating interrupts. nomio [S390] Do not use MIO instructions. + norid [S390] ignore the RID field and force use of + one PCI domain per PCI function
pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power Management. @@@ -4912,7 -4910,7 +4912,7 @@@ Set the number of tcp_metrics_hash slots. Default value is 8192 or 16384 depending on total ram pages. This is used to specify the TCP metrics - cache size. See Documentation/networking/ip-sysctl.txt + cache size. See Documentation/networking/ip-sysctl.rst "tcp_no_metrics_save" section for more details.
tdfx= [HW,DRM] @@@ -5189,7 -5187,8 +5189,7 @@@
usbcore.old_scheme_first= [USB] Start with the old device initialization - scheme, applies only to low and full-speed devices - (default 0 = off). + scheme (default 0 = off).
usbcore.usbfs_memory_mb= [USB] Memory limit (in MB) for buffers allocated by diff --combined MAINTAINERS index c2aae6ffeb14,db7a6d462dff..5d4f0097b28a --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -147,7 -147,7 +147,7 @@@ Maintainers Lis M: Steffen Klassert klassert@kernel.org L: netdev@vger.kernel.org S: Odd Fixes - F: Documentation/networking/device_drivers/3com/vortex.txt + F: Documentation/networking/device_drivers/3com/vortex.rst F: drivers/net/ethernet/3com/3c59x.c
3CR990 NETWORK DRIVER @@@ -193,7 -193,7 +193,7 @@@ W: https://wireless.wiki.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git F: Documentation/driver-api/80211/cfg80211.rst - F: Documentation/networking/regulatory.txt + F: Documentation/networking/regulatory.rst F: include/linux/ieee80211.h F: include/net/cfg80211.h F: include/net/ieee80211_radiotap.h @@@ -570,7 -570,7 +570,7 @@@ F: Documentation/devicetree/bindings/ii F: drivers/input/misc/adxl34x.c
ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER -M: Stefan Popa stefan.popa@analog.com +M: Michael Hennerich michael.hennerich@analog.com S: Supported W: http://ez.analog.com/community/linux-device-drivers F: Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml @@@ -815,7 -815,7 +815,7 @@@ R: Saeed Bishara <saeedb@amazon.com R: Zorik Machulsky zorik@amazon.com L: netdev@vger.kernel.org S: Supported - F: Documentation/networking/device_drivers/amazon/ena.txt + F: Documentation/networking/device_drivers/amazon/ena.rst F: drivers/net/ethernet/amazon/
AMAZON RDMA EFA DRIVER @@@ -922,7 -922,7 +922,7 @@@ F: arch/arm64/boot/dts/amd/amd-seattle- F: drivers/net/ethernet/amd/xgbe/
ANALOG DEVICES INC AD5686 DRIVER -M: Stefan Popa stefan.popa@analog.com +M: Michael Hennerich Michael.Hennerich@analog.com L: linux-pm@vger.kernel.org S: Supported W: http://ez.analog.com/community/linux-device-drivers @@@ -930,7 -930,7 +930,7 @@@ F: drivers/iio/dac/ad5686 F: drivers/iio/dac/ad5696*
ANALOG DEVICES INC AD5758 DRIVER -M: Stefan Popa stefan.popa@analog.com +M: Michael Hennerich Michael.Hennerich@analog.com L: linux-iio@vger.kernel.org S: Supported W: http://ez.analog.com/community/linux-device-drivers @@@ -946,7 -946,7 +946,7 @@@ F: Documentation/devicetree/bindings/ii F: drivers/iio/adc/ad7091r5.c
ANALOG DEVICES INC AD7124 DRIVER -M: Stefan Popa stefan.popa@analog.com +M: Michael Hennerich Michael.Hennerich@analog.com L: linux-iio@vger.kernel.org S: Supported W: http://ez.analog.com/community/linux-device-drivers @@@ -970,7 -970,7 +970,7 @@@ F: Documentation/devicetree/bindings/ii F: drivers/iio/adc/ad7292.c
ANALOG DEVICES INC AD7606 DRIVER -M: Stefan Popa stefan.popa@analog.com +M: Michael Hennerich Michael.Hennerich@analog.com M: Beniamin Bia beniamin.bia@analog.com L: linux-iio@vger.kernel.org S: Supported @@@ -979,7 -979,7 +979,7 @@@ F: Documentation/devicetree/bindings/ii F: drivers/iio/adc/ad7606.c
ANALOG DEVICES INC AD7768-1 DRIVER -M: Stefan Popa stefan.popa@analog.com +M: Michael Hennerich Michael.Hennerich@analog.com L: linux-iio@vger.kernel.org S: Supported W: http://ez.analog.com/community/linux-device-drivers @@@ -1040,7 -1040,7 +1040,7 @@@ F: Documentation/devicetree/bindings/hw F: drivers/hwmon/adm1177.c
ANALOG DEVICES INC ADP5061 DRIVER -M: Stefan Popa stefan.popa@analog.com +M: Michael Hennerich Michael.Hennerich@analog.com L: linux-pm@vger.kernel.org S: Supported W: http://ez.analog.com/community/linux-device-drivers @@@ -1109,6 -1109,7 +1109,6 @@@ F: drivers/iio/amplifiers/hmc425a. ANALOG DEVICES INC IIO DRIVERS M: Lars-Peter Clausen lars@metafoo.de M: Michael Hennerich Michael.Hennerich@analog.com -M: Stefan Popa stefan.popa@analog.com S: Supported W: http://wiki.analog.com/ W: http://ez.analog.com/community/linux-device-drivers @@@ -1274,7 -1275,7 +1274,7 @@@ L: netdev@vger.kernel.or S: Supported W: https://www.marvell.com/ Q: http://patchwork.ozlabs.org/project/netdev/list/ - F: Documentation/networking/device_drivers/aquantia/atlantic.txt + F: Documentation/networking/device_drivers/aquantia/atlantic.rst F: drivers/net/ethernet/aquantia/atlantic/
AQUANTIA ETHERNET DRIVER PTP SUBSYSTEM @@@ -2272,8 -2273,6 +2272,8 @@@ L: linux-arm-kernel@lists.infradead.or L: linux-realtek-soc@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/arm/realtek.yaml +F: arch/arm/boot/dts/rtd* +F: arch/arm/mach-realtek/ F: arch/arm64/boot/dts/realtek/
ARM/RENESAS ARM64 ARCHITECTURE @@@ -3193,7 -3192,7 +3193,7 @@@ Q: https://patchwork.ozlabs.org/project T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git F: Documentation/bpf/ - F: Documentation/networking/filter.txt + F: Documentation/networking/filter.rst F: arch/*/net/* F: include/linux/bpf* F: include/linux/filter.h @@@ -3659,7 -3658,7 +3659,7 @@@ L: linux-btrfs@vger.kernel.or S: Maintained W: http://btrfs.wiki.kernel.org/ Q: http://patchwork.kernel.org/project/linux-btrfs/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git F: Documentation/filesystems/btrfs.rst F: fs/btrfs/ F: include/linux/btrfs* @@@ -3671,7 -3670,7 +3671,7 @@@ L: linux-media@vger.kernel.or S: Odd fixes W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/bttv* +F: Documentation/driver-api/media/drivers/bttv* F: drivers/media/pci/bt8xx/bttv*
BUS FREQUENCY DRIVER FOR SAMSUNG EXYNOS @@@ -3732,7 -3731,7 +3732,7 @@@ CACHEFILES: FS-CACHE BACKEND FOR CACHIN M: David Howells dhowells@redhat.com L: linux-cachefs@redhat.com (moderated for non-subscribers) S: Supported -F: Documentation/filesystems/caching/cachefiles.txt +F: Documentation/filesystems/caching/cachefiles.rst F: fs/cachefiles/
CADENCE MIPI-CSI2 BRIDGES @@@ -3762,7 -3761,7 +3762,7 @@@ M: Jonathan Corbet <corbet@lwn.net L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/cafe_ccic* +F: Documentation/admin-guide/media/cafe_ccic* F: drivers/media/platform/marvell-ccic/
CAIF NETWORK LAYER @@@ -3906,8 -3905,8 +3906,8 @@@ W: http://linuxtv.or T: git git://linuxtv.org/media_tree.git F: Documentation/ABI/testing/debugfs-cec-error-inj F: Documentation/devicetree/bindings/media/cec.txt -F: Documentation/media/kapi/cec-core.rst -F: Documentation/media/uapi/cec +F: Documentation/driver-api/media/cec-core.rst +F: Documentation/userspace-api/media/cec F: drivers/media/cec/ F: drivers/media/rc/keymaps/rc-cec.c F: include/media/cec-notifier.h @@@ -3938,9 -3937,11 +3938,9 @@@ F: arch/powerpc/platforms/cell CEPH COMMON CODE (LIBCEPH) M: Ilya Dryomov idryomov@gmail.com M: Jeff Layton jlayton@kernel.org -M: Sage Weil sage@redhat.com L: ceph-devel@vger.kernel.org S: Supported W: http://ceph.com/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git T: git git://github.com/ceph/ceph-client.git F: include/linux/ceph/ F: include/linux/crush/ @@@ -3948,10 -3949,12 +3948,10 @@@ F: net/ceph
CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH) M: Jeff Layton jlayton@kernel.org -M: Sage Weil sage@redhat.com M: Ilya Dryomov idryomov@gmail.com L: ceph-devel@vger.kernel.org S: Supported W: http://ceph.com/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git T: git git://github.com/ceph/ceph-client.git F: Documentation/filesystems/ceph.rst F: fs/ceph/ @@@ -4200,7 -4203,7 +4200,7 @@@ M: coda@cs.cmu.ed L: codalist@coda.cs.cmu.edu S: Maintained W: http://www.coda.cs.cmu.edu/ -F: Documentation/filesystems/coda.txt +F: Documentation/filesystems/coda.rst F: fs/coda/ F: include/linux/coda*.h F: include/uapi/linux/coda*.h @@@ -4539,7 -4542,7 +4539,7 @@@ L: linux-media@vger.kernel.or S: Odd fixes W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/cx88* +F: Documentation/driver-api/media/drivers/cx88* F: drivers/media/pci/cx88/
CXD2820R MEDIA DRIVER @@@ -4691,7 -4694,7 +4691,7 @@@ F: net/ax25/sysctl_net_ax25. DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER L: netdev@vger.kernel.org S: Orphan - F: Documentation/networking/device_drivers/dec/dmfe.txt + F: Documentation/networking/device_drivers/dec/dmfe.rst F: drivers/net/ethernet/dec/tulip/dmfe.c
DC390/AM53C974 SCSI driver @@@ -4725,7 -4728,7 +4725,7 @@@ DECnet NETWORK LAYE L: linux-decnet-user@lists.sourceforge.net S: Orphan W: http://linux-decnet.sourceforge.net - F: Documentation/networking/decnet.txt + F: Documentation/networking/decnet.rst F: net/decnet/
DECSTATION PLATFORM SUPPORT @@@ -4993,7 -4996,7 +4993,7 @@@ M: Jan Kara <jack@suse.cz R: Amir Goldstein amir73il@gmail.com L: linux-fsdevel@vger.kernel.org S: Maintained -F: Documentation/filesystems/dnotify.txt +F: Documentation/filesystems/dnotify.rst F: fs/notify/dnotify/ F: include/linux/dnotify.h
@@@ -5007,7 -5010,7 +5007,7 @@@ W: http://www.win.tue.nl/~aeb/partition DISKQUOTA M: Jan Kara jack@suse.com S: Maintained -F: Documentation/filesystems/quota.txt +F: Documentation/filesystems/quota.rst F: fs/quota/ F: include/linux/quota*.h F: include/uapi/linux/quota*.h @@@ -5122,14 -5125,12 +5122,14 @@@ F: scripts/documentation-file-ref-chec F: scripts/kernel-doc F: scripts/sphinx-pre-install X: Documentation/ABI/ +X: Documentation/admin-guide/media/ X: Documentation/devicetree/ +X: Documentation/driver-api/media/ X: Documentation/firmware-guide/acpi/ X: Documentation/i2c/ -X: Documentation/media/ X: Documentation/power/ X: Documentation/spi/ +X: Documentation/userspace-api/media/
DOCUMENTATION SCRIPTS M: Mauro Carvalho Chehab mchehab@kernel.org @@@ -6236,7 -6237,7 +6236,7 @@@ L: linux-media@vger.kernel.or S: Maintained W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/em28xx* +F: Documentation/admin-guide/media/em28xx* F: drivers/media/usb/em28xx/
EMBEDDED LINUX @@@ -7119,10 -7120,9 +7119,10 @@@ F: include/uapi/asm-generic
GENERIC PHY FRAMEWORK M: Kishon Vijay Abraham I kishon@ti.com +M: Vinod Koul vkoul@kernel.org L: linux-kernel@vger.kernel.org S: Supported -T: git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git F: Documentation/devicetree/bindings/phy/ F: drivers/phy/ F: include/linux/phy/ @@@ -7459,7 -7459,7 +7459,7 @@@ L: linux-media@vger.kernel.or L: linux-rockchip@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/media/nxp,imx8mq-vpu.yaml -F: Documentation/devicetree/bindings/media/rockchip-vpu.txt +F: Documentation/devicetree/bindings/media/rockchip-vpu.yaml F: drivers/staging/media/hantro/
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER @@@ -7747,6 -7747,11 +7747,6 @@@ L: platform-driver-x86@vger.kernel.or S: Orphan F: drivers/platform/x86/tc1100-wmi.c
-HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series -M: Jaroslav Kysela perex@perex.cz -S: Obsolete -F: drivers/staging/hp/hp100.* - HPET: High Precision Event Timers driver M: Clemens Ladisch clemens@ladisch.de S: Maintained @@@ -7810,7 -7815,7 +7810,7 @@@ HUAWEI ETHERNET DRIVE M: Aviad Krawczyk aviad.krawczyk@huawei.com L: netdev@vger.kernel.org S: Supported - F: Documentation/networking/hinic.txt + F: Documentation/networking/hinic.rst F: drivers/net/ethernet/huawei/hinic/
HUGETLB FILESYSTEM @@@ -7862,7 -7867,7 +7862,7 @@@ S: Supporte T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git F: Documentation/ABI/stable/sysfs-bus-vmbus F: Documentation/ABI/testing/debugfs-hyperv - F: Documentation/networking/device_drivers/microsoft/netvsc.txt + F: Documentation/networking/device_drivers/microsoft/netvsc.rst F: arch/x86/hyperv F: arch/x86/include/asm/hyperv-tlfs.h F: arch/x86/include/asm/mshyperv.h @@@ -7945,7 -7950,7 +7945,7 @@@ F: Documentation/i2c/busses/i2c-parport F: drivers/i2c/busses/i2c-parport.c
I2C SUBSYSTEM -M: Wolfram Sang wsa@the-dreams.de +M: Wolfram Sang wsa@kernel.org L: linux-i2c@vger.kernel.org S: Maintained W: https://i2c.wiki.kernel.org/ @@@ -8641,18 -8646,16 +8641,18 @@@ M: Bingbu Cao <bingbu.cao@intel.com R: Tian Shu Qiu tian.shu.qiu@intel.com L: linux-media@vger.kernel.org S: Maintained -F: Documentation/media/uapi/v4l/pixfmt-srggb10-ipu3.rst +F: Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst F: drivers/media/pci/intel/ipu3/
INTEL IPU3 CSI-2 IMGU DRIVER M: Sakari Ailus sakari.ailus@linux.intel.com +R: Bingbu Cao bingbu.cao@intel.com +R: Tian Shu Qiu tian.shu.qiu@intel.com L: linux-media@vger.kernel.org S: Maintained -F: Documentation/media/uapi/v4l/pixfmt-meta-intel-ipu3.rst -F: Documentation/media/v4l-drivers/ipu3.rst -F: Documentation/media/v4l-drivers/ipu3_rcb.svg +F: Documentation/admin-guide/media/ipu3.rst +F: Documentation/admin-guide/media/ipu3_rcb.svg +F: Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst F: drivers/staging/media/ipu3/
INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT @@@ -8739,8 -8742,8 +8739,8 @@@ INTEL PRO/WIRELESS 2100, 2200BG, 2915AB M: Stanislav Yakovlev stas.yakovlev@gmail.com L: linux-wireless@vger.kernel.org S: Maintained - F: Documentation/networking/device_drivers/intel/ipw2100.txt - F: Documentation/networking/device_drivers/intel/ipw2200.txt + F: Documentation/networking/device_drivers/intel/ipw2100.rst + F: Documentation/networking/device_drivers/intel/ipw2200.rst F: drivers/net/wireless/intel/ipw2x00/
INTEL PSTATE DRIVER @@@ -8931,7 -8934,7 +8931,7 @@@ L: lvs-devel@vger.kernel.or S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs-next.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git - F: Documentation/networking/ipvs-sysctl.txt + F: Documentation/networking/ipvs-sysctl.rst F: include/net/ip_vs.h F: include/uapi/linux/ip_vs.h F: net/netfilter/ipvs/ @@@ -9076,7 -9079,7 +9076,7 @@@ L: linux-media@vger.kernel.or S: Maintained W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/ivtv* +F: Documentation/admin-guide/media/ivtv* F: drivers/media/pci/ivtv/ F: include/uapi/linux/ivtv*
@@@ -9512,7 -9515,7 +9512,7 @@@ F: drivers/soc/lanti LAPB module L: linux-x25@vger.kernel.org S: Orphan - F: Documentation/networking/lapb-module.txt + F: Documentation/networking/lapb-module.rst F: include/*/lapb.h F: net/lapb/
@@@ -10076,7 -10079,7 +10076,7 @@@ S: Maintaine W: https://wireless.wiki.kernel.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git - F: Documentation/networking/mac80211-injection.txt + F: Documentation/networking/mac80211-injection.rst F: Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst F: drivers/net/wireless/mac80211_hwsim.[ch] F: include/net/mac80211.h @@@ -10257,7 -10260,7 +10257,7 @@@ L: linux-media@vger.kernel.or S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/max2175.txt -F: Documentation/media/v4l-drivers/max2175.rst +F: Documentation/userspace-api/media/drivers/max2175.rst F: drivers/media/i2c/max2175* F: include/uapi/linux/max2175.h
@@@ -10457,8 -10460,8 +10457,8 @@@ M: Philipp Zabel <p.zabel@pengutronix.d L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git +F: Documentation/admin-guide/media/imx.rst F: Documentation/devicetree/bindings/media/imx.txt -F: Documentation/media/v4l-drivers/imx.rst F: drivers/staging/media/imx/ F: include/linux/imx-media.h F: include/media/imx.h @@@ -10468,9 -10471,9 +10468,9 @@@ M: Rui Miguel Silva <rmfrfs@gmail.com L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git +F: Documentation/admin-guide/media/imx7.rst F: Documentation/devicetree/bindings/media/imx7-csi.txt F: Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt -F: Documentation/media/v4l-drivers/imx7.rst F: drivers/staging/media/imx/imx7-media-csi.c F: drivers/staging/media/imx/imx7-mipi-csis.c
@@@ -10616,10 -10619,8 +10616,10 @@@ S: Maintaine W: https://linuxtv.org Q: http://patchwork.kernel.org/project/linux-media/list/ T: git git://linuxtv.org/media_tree.git +F: Documentation/admin-guide/media/ F: Documentation/devicetree/bindings/media/ -F: Documentation/media/ +F: Documentation/driver-api/media/ +F: Documentation/userspace-api/media/ F: drivers/media/ F: drivers/staging/media/ F: include/linux/platform_data/media/ @@@ -11012,12 -11013,10 +11012,12 @@@ F: drivers/mtd/nand/raw/meson_
MESON VIDEO DECODER DRIVER FOR AMLOGIC SOCS M: Maxime Jourdan mjourdan@baylibre.com +M: Neil Armstrong narmstrong@baylibre.com L: linux-media@vger.kernel.org L: linux-amlogic@lists.infradead.org S: Supported T: git git://linuxtv.org/media_tree.git +F: Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml F: drivers/staging/media/meson/vdec/
METHODE UDPU SUPPORT @@@ -11398,7 -11397,7 +11398,7 @@@ F: drivers/regulator/mpq7920. MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER S: Orphan W: http://popies.net/meye/ -F: Documentation/media/v4l-drivers/meye* +F: Documentation/userspace-api/media/drivers/meye* F: drivers/media/pci/meye/ F: include/uapi/linux/meye.h
@@@ -11657,8 -11656,8 +11657,8 @@@ NETERION 10GbE DRIVERS (s2io/vxge M: Jon Mason jdmason@kudzu.us L: netdev@vger.kernel.org S: Supported - F: Documentation/networking/device_drivers/neterion/s2io.txt - F: Documentation/networking/device_drivers/neterion/vxge.txt + F: Documentation/networking/device_drivers/neterion/s2io.rst + F: Documentation/networking/device_drivers/neterion/vxge.rst F: drivers/net/ethernet/neterion/
NETFILTER @@@ -13263,7 -13262,7 +13263,7 @@@ F: drivers/input/joystick/pxrc. PHONET PROTOCOL M: Remi Denis-Courmont courmisch@gmail.com S: Supported - F: Documentation/networking/phonet.txt + F: Documentation/networking/phonet.rst F: include/linux/phonet.h F: include/net/phonet/ F: include/uapi/linux/phonet.h @@@ -13710,8 -13709,8 +13710,8 @@@ M: Hans Verkuil <hverkuil@xs4all.nl L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/media/cec-drivers/pulse8-cec.rst -F: drivers/media/usb/pulse8-cec/* +F: Documentation/admin-guide/media/pulse8-cec.rst +F: drivers/media/cec/usb/pulse8/
PVRUSB2 VIDEO4LINUX DRIVER M: Mike Isely isely@pobox.com @@@ -13720,7 -13719,7 +13720,7 @@@ L: linux-media@vger.kernel.or S: Maintained W: http://www.isely.net/pvrusb2/ T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/pvrusb2* +F: Documentation/driver-api/media/drivers/pvrusb2* F: drivers/media/usb/pvrusb2/
PWC WEBCAM DRIVER @@@ -13967,8 -13966,8 +13967,8 @@@ QUALCOMM CAMERA SUBSYSTEM DRIVE M: Todor Tomov todor.too@gmail.com L: linux-media@vger.kernel.org S: Maintained +F: Documentation/admin-guide/media/qcom_camss.rst F: Documentation/devicetree/bindings/media/qcom,camss.txt -F: Documentation/media/v4l-drivers/qcom_camss.rst F: drivers/media/platform/qcom/camss/
QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER @@@ -14032,7 -14031,7 +14032,7 @@@ M: Subash Abhinov Kasiviswanathan <suba M: Sean Tranchetti stranche@codeaurora.org L: netdev@vger.kernel.org S: Maintained - F: Documentation/networking/device_drivers/qualcomm/rmnet.txt + F: Documentation/networking/device_drivers/qualcomm/rmnet.rst F: drivers/net/ethernet/qualcomm/rmnet/ F: include/linux/if_rmnet.h
@@@ -14104,10 -14103,12 +14104,10 @@@ F: drivers/media/radio/radio-tea5777.
RADOS BLOCK DEVICE (RBD) M: Ilya Dryomov idryomov@gmail.com -M: Sage Weil sage@redhat.com R: Dongsheng Yang dongsheng.yang@easystack.cn L: ceph-devel@vger.kernel.org S: Supported W: http://ceph.com/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git T: git git://github.com/ceph/ceph-client.git F: Documentation/ABI/testing/sysfs-bus-rbd F: drivers/block/rbd.c @@@ -14124,7 -14125,7 +14124,7 @@@ M: Hans Verkuil <hverkuil@xs4all.nl L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: drivers/media/usb/rainshadow-cec/* +F: drivers/media/cec/usb/rainshadow/
RALINK MIPS ARCHITECTURE M: John Crispin john@phrozen.org @@@ -14218,7 -14219,7 +14218,7 @@@ L: linux-rdma@vger.kernel.or L: rds-devel@oss.oracle.com (moderated for non-subscribers) S: Supported W: https://oss.oracle.com/projects/rds/ - F: Documentation/networking/rds.txt + F: Documentation/networking/rds.rst F: net/rds/
RDT - RESOURCE ALLOCATION @@@ -14477,19 -14478,10 +14477,19 @@@ ROCKCHIP RASTER 2D GRAPHIC ACCELERATIO M: Jacob Chen jacob-chen@iotwrt.com M: Ezequiel Garcia ezequiel@collabora.com L: linux-media@vger.kernel.org +L: linux-rockchip@lists.infradead.org S: Maintained -F: Documentation/devicetree/bindings/media/rockchip-rga.txt +F: Documentation/devicetree/bindings/media/rockchip-rga.yaml F: drivers/media/platform/rockchip/rga/
+ROCKCHIP VIDEO DECODER DRIVER +M: Ezequiel Garcia ezequiel@collabora.com +L: linux-media@vger.kernel.org +L: linux-rockchip@lists.infradead.org +S: Maintained +F: Documentation/devicetree/bindings/media/rockchip,vdec.yaml +F: drivers/staging/media/rkvdec/ + ROCKER DRIVER M: Jiri Pirko jiri@resnulli.us L: netdev@vger.kernel.org @@@ -14601,7 -14593,7 +14601,7 @@@ M: David Howells <dhowells@redhat.com L: linux-afs@lists.infradead.org S: Supported W: https://www.infradead.org/~dhowells/kafs/ - F: Documentation/networking/rxrpc.txt + F: Documentation/networking/rxrpc.rst F: include/keys/rxrpc-type.h F: include/net/af_rxrpc.h F: include/trace/events/rxrpc.h @@@ -14677,7 -14669,6 +14677,7 @@@ S: Supporte W: http://www.ibm.com/developerworks/linux/linux390/ F: arch/s390/pci/ F: drivers/pci/hotplug/s390_pci_hpc.c +F: Documentation/s390/pci.rst
S390 VFIO AP DRIVER M: Tony Krowiak akrowiak@linux.ibm.com @@@ -14737,7 -14728,7 +14737,7 @@@ L: linux-media@vger.kernel.or S: Odd fixes W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/saa7134* +F: Documentation/driver-api/media/drivers/saa7134* F: drivers/media/pci/saa7134/
SAA7146 VIDEO4LINUX-2 DRIVER @@@ -15008,7 -14999,7 +15008,7 @@@ M: Marcelo Ricardo Leitner <marcelo.lei L: linux-sctp@vger.kernel.org S: Maintained W: http://lksctp.sourceforge.net - F: Documentation/networking/sctp.txt + F: Documentation/networking/sctp.rst F: include/linux/sctp.h F: include/net/sctp/ F: include/uapi/linux/sctp.h @@@ -15883,7 -15874,7 +15883,7 @@@ SPIDERNET NETWORK DRIVER for CEL M: Ishizaki Kou kou.ishizaki@toshiba.co.jp L: netdev@vger.kernel.org S: Supported - F: Documentation/networking/device_drivers/toshiba/spider_net.txt + F: Documentation/networking/device_drivers/toshiba/spider_net.rst F: drivers/net/ethernet/toshiba/spider_net*
SPMI SUBSYSTEM @@@ -15900,7 -15891,7 +15900,7 @@@ M: Jeremy Kerr <jk@ozlabs.org L: linuxppc-dev@lists.ozlabs.org S: Supported W: http://www.ibm.com/developerworks/power/cell/ -F: Documentation/filesystems/spufs.txt +F: Documentation/filesystems/spufs/spufs.rst F: arch/powerpc/platforms/cell/spufs/
SQUASHFS FILE SYSTEM @@@ -16980,7 -16971,7 +16980,7 @@@ M: Samuel Chessman <chessman@tux.org L: tlan-devel@lists.sourceforge.net (subscribers-only) S: Maintained W: http://sourceforge.net/projects/tlan/ - F: Documentation/networking/device_drivers/ti/tlan.txt + F: Documentation/networking/device_drivers/ti/tlan.rst F: drivers/net/ethernet/ti/tlan.*
TM6000 VIDEO4LINUX DRIVER @@@ -16989,7 -16980,7 +16989,7 @@@ L: linux-media@vger.kernel.or S: Odd fixes W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/tm6000* +F: Documentation/admin-guide/media/tm6000* F: drivers/media/usb/tm6000/
TMIO/SDHI MMC DRIVER @@@ -17170,7 -17161,7 +17170,7 @@@ TUN/TAP drive M: Maxim Krasnyansky maxk@qti.qualcomm.com S: Maintained W: http://vtun.sourceforge.net/tun - F: Documentation/networking/tuntap.txt + F: Documentation/networking/tuntap.rst F: arch/um/os-Linux/drivers/
TURBOCHANNEL SUBSYSTEM @@@ -17670,7 -17661,7 +17670,7 @@@ L: linux-media@vger.kernel.or S: Maintained W: http://royale.zerezo.com/zr364xx/ T: git git://linuxtv.org/media_tree.git -F: Documentation/media/v4l-drivers/zr364xx* +F: Documentation/admin-guide/media/zr364xx* F: drivers/media/usb/zr364xx/
USER-MODE LINUX (UML) @@@ -17819,7 -17810,7 +17819,7 @@@ L: linux-media@vger.kernel.or S: Maintained W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: drivers/media/platform/vicodec/* +F: drivers/media/test-drivers/vicodec/*
VIDEO I2C POLLING DRIVER M: Matt Ranostay matt.ranostay@konsulko.com @@@ -17850,7 -17841,7 +17850,7 @@@ L: linux-media@vger.kernel.or S: Maintained W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: drivers/media/platform/vimc/* +F: drivers/media/test-drivers/vimc/*
VIRT LIB M: Alex Williamson alex.williamson@redhat.com @@@ -18017,7 -18008,7 +18017,7 @@@ L: linux-media@vger.kernel.or S: Maintained W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -F: drivers/media/platform/vivid/* +F: drivers/media/test-drivers/vivid/*
VLYNQ BUS M: Florian Fainelli f.fainelli@gmail.com @@@ -18115,7 -18106,7 +18115,7 @@@ M: David Ahern <dsahern@kernel.org M: Shrijeet Mukherjee shrijeet@gmail.com L: netdev@vger.kernel.org S: Maintained - F: Documentation/networking/vrf.txt + F: Documentation/networking/vrf.rst F: drivers/net/vrf.c
VSPRINTF @@@ -18551,8 -18542,8 +18551,8 @@@ W: http://xfs.org T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git F: Documentation/ABI/testing/sysfs-fs-xfs F: Documentation/admin-guide/xfs.rst -F: Documentation/filesystems/xfs-delayed-logging-design.txt -F: Documentation/filesystems/xfs-self-describing-metadata.txt +F: Documentation/filesystems/xfs-delayed-logging-design.rst +F: Documentation/filesystems/xfs-self-describing-metadata.rst F: fs/xfs/ F: include/uapi/linux/dqblk_xfs.h F: include/uapi/linux/fsmap.h @@@ -18653,7 -18644,7 +18653,7 @@@ L: linux-hams@vger.kernel.or S: Maintained W: http://yaina.de/jreuter/ W: http://www.qsl.net/dl1bke/ - F: Documentation/networking/z8530drv.txt + F: Documentation/networking/z8530drv.rst F: drivers/net/hamradio/*scc.c F: drivers/net/hamradio/z8530.h
diff --combined arch/arm/boot/dts/qcom-ipq4019.dtsi index c6956015dedc,b9839f86e703..74d8e2c8e4b3 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@@ -166,7 -166,6 +166,7 @@@ <1 4 0xf08>, <1 1 0xf08>; clock-frequency = <48000000>; + always-on; };
soc { @@@ -577,5 -576,33 +577,33 @@@ "legacy"; status = "disabled"; }; + + mdio: mdio@90000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "qcom,ipq4019-mdio"; + reg = <0x90000 0x64>; + status = "disabled"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; + + ethphy2: ethernet-phy@2 { + reg = <2>; + }; + + ethphy3: ethernet-phy@3 { + reg = <3>; + }; + + ethphy4: ethernet-phy@4 { + reg = <4>; + }; + }; }; }; diff --combined arch/arm64/boot/dts/ti/k3-am65-main.dtsi index dfc06ecdb47b,0d533d52fcda..61815228e230 --- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi @@@ -287,17 -287,6 +287,17 @@@ mux-reg-masks = <0x4080 0x3>, /* SERDES0 lane select */ <0x4090 0x3>; /* SERDES1 lane select */ }; + + dss_oldi_io_ctrl: dss_oldi_io_ctrl@41E0 { + compatible = "syscon"; + reg = <0x0000041E0 0x14>; + }; + + ehrpwm_tbclk: syscon@4140 { + compatible = "ti,am654-ehrpwm-tbclk", "syscon"; + reg = <0x4140 0x18>; + #clock-cells = <1>; + }; };
dwc3_0: dwc3@4000000 { @@@ -581,6 -570,28 +581,28 @@@ <0x5>; /* RX_CHAN */ ti,sci-rm-range-rflow = <0x6>; /* GP RFLOW */ }; + + cpts@310d0000 { + compatible = "ti,am65-cpts"; + reg = <0x0 0x310d0000 0x0 0x400>; + reg-names = "cpts"; + clocks = <&main_cpts_mux>; + clock-names = "cpts"; + interrupts-extended = <&intr_main_navss 163 0>; + interrupt-names = "cpts"; + ti,cpts-periodic-outputs = <6>; + ti,cpts-ext-ts-inputs = <8>; + + main_cpts_mux: refclk-mux { + #clock-cells = <0>; + clocks = <&k3_clks 118 5>, <&k3_clks 118 11>, + <&k3_clks 118 6>, <&k3_clks 118 3>, + <&k3_clks 118 8>, <&k3_clks 118 14>, + <&k3_clks 120 3>, <&k3_clks 121 3>; + assigned-clocks = <&main_cpts_mux>; + assigned-clock-parents = <&k3_clks 118 5>; + }; + }; };
main_gpio0: main_gpio0@600000 { @@@ -757,97 -768,4 +779,97 @@@ }; }; }; + + dss: dss@04a00000 { + compatible = "ti,am65x-dss"; + reg = <0x0 0x04a00000 0x0 0x1000>, /* common */ + <0x0 0x04a02000 0x0 0x1000>, /* vidl1 */ + <0x0 0x04a06000 0x0 0x1000>, /* vid */ + <0x0 0x04a07000 0x0 0x1000>, /* ovr1 */ + <0x0 0x04a08000 0x0 0x1000>, /* ovr2 */ + <0x0 0x04a0a000 0x0 0x1000>, /* vp1 */ + <0x0 0x04a0b000 0x0 0x1000>; /* vp2 */ + reg-names = "common", "vidl1", "vid", + "ovr1", "ovr2", "vp1", "vp2"; + + ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>; + + power-domains = <&k3_pds 67 TI_SCI_PD_EXCLUSIVE>; + + clocks = <&k3_clks 67 1>, + <&k3_clks 216 1>, + <&k3_clks 67 2>; + clock-names = "fck", "vp1", "vp2"; + + /* + * Set vp2 clk (DPI_1_IN_CLK) mux to PLL4 via + * DIV1. See "Figure 12-3365. DSS Integration" + * in AM65x TRM for details. + */ + assigned-clocks = <&k3_clks 67 2>; + assigned-clock-parents = <&k3_clks 67 5>; + + interrupts = <GIC_SPI 166 IRQ_TYPE_EDGE_RISING>; + + status = "disabled"; + + dss_ports: ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + ehrpwm0: pwm@3000000 { + compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm"; + #pwm-cells = <3>; + reg = <0x0 0x3000000 0x0 0x100>; + power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>; + clocks = <&ehrpwm_tbclk 0>, <&k3_clks 40 0>; + clock-names = "tbclk", "fck"; + }; + + ehrpwm1: pwm@3010000 { + compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm"; + #pwm-cells = <3>; + reg = <0x0 0x3010000 0x0 0x100>; + power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>; + clocks = <&ehrpwm_tbclk 1>, <&k3_clks 41 0>; + clock-names = "tbclk", "fck"; + }; + + ehrpwm2: pwm@3020000 { + compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm"; + #pwm-cells = <3>; + reg = <0x0 0x3020000 0x0 0x100>; + power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>; + clocks = <&ehrpwm_tbclk 2>, <&k3_clks 42 0>; + clock-names = "tbclk", "fck"; + }; + + ehrpwm3: pwm@3030000 { + compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm"; + #pwm-cells = <3>; + reg = <0x0 0x3030000 0x0 0x100>; + power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>; + clocks = <&ehrpwm_tbclk 3>, <&k3_clks 43 0>; + clock-names = "tbclk", "fck"; + }; + + ehrpwm4: pwm@3040000 { + compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm"; + #pwm-cells = <3>; + reg = <0x0 0x3040000 0x0 0x100>; + power-domains = <&k3_pds 44 TI_SCI_PD_EXCLUSIVE>; + clocks = <&ehrpwm_tbclk 4>, <&k3_clks 44 0>; + clock-names = "tbclk", "fck"; + }; + + ehrpwm5: pwm@3050000 { + compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm"; + #pwm-cells = <3>; + reg = <0x0 0x3050000 0x0 0x100>; + power-domains = <&k3_pds 45 TI_SCI_PD_EXCLUSIVE>; + clocks = <&ehrpwm_tbclk 5>, <&k3_clks 45 0>; + clock-names = "tbclk", "fck"; + }; }; diff --combined arch/arm64/boot/dts/ti/k3-j721e-main.dtsi index 21c362042ecf,844a5b50cf09..1a800917a924 --- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi @@@ -254,6 -254,18 +254,18 @@@ <0x0c>; /* RX_UHCHAN */ ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */ }; + + cpts@310d0000 { + compatible = "ti,j721e-cpts"; + reg = <0x0 0x310d0000 0x0 0x400>; + reg-names = "cpts"; + clocks = <&k3_clks 201 1>; + clock-names = "cpts"; + interrupts-extended = <&main_navss_intr 201 0>; + interrupt-names = "cpts"; + ti,cpts-periodic-outputs = <6>; + ti,cpts-ext-ts-inputs = <8>; + }; };
main_pmx0: pinmux@11c000 { @@@ -736,63 -748,6 +748,63 @@@ }; };
+ dss: dss@04a00000 { + compatible = "ti,j721e-dss"; + reg = + <0x00 0x04a00000 0x00 0x10000>, /* common_m */ + <0x00 0x04a10000 0x00 0x10000>, /* common_s0*/ + <0x00 0x04b00000 0x00 0x10000>, /* common_s1*/ + <0x00 0x04b10000 0x00 0x10000>, /* common_s2*/ + + <0x00 0x04a20000 0x00 0x10000>, /* vidl1 */ + <0x00 0x04a30000 0x00 0x10000>, /* vidl2 */ + <0x00 0x04a50000 0x00 0x10000>, /* vid1 */ + <0x00 0x04a60000 0x00 0x10000>, /* vid2 */ + + <0x00 0x04a70000 0x00 0x10000>, /* ovr1 */ + <0x00 0x04a90000 0x00 0x10000>, /* ovr2 */ + <0x00 0x04ab0000 0x00 0x10000>, /* ovr3 */ + <0x00 0x04ad0000 0x00 0x10000>, /* ovr4 */ + + <0x00 0x04a80000 0x00 0x10000>, /* vp1 */ + <0x00 0x04aa0000 0x00 0x10000>, /* vp2 */ + <0x00 0x04ac0000 0x00 0x10000>, /* vp3 */ + <0x00 0x04ae0000 0x00 0x10000>, /* vp4 */ + <0x00 0x04af0000 0x00 0x10000>; /* wb */ + + reg-names = "common_m", "common_s0", + "common_s1", "common_s2", + "vidl1", "vidl2","vid1","vid2", + "ovr1", "ovr2", "ovr3", "ovr4", + "vp1", "vp2", "vp3", "vp4", + "wb"; + + clocks = <&k3_clks 152 0>, + <&k3_clks 152 1>, + <&k3_clks 152 4>, + <&k3_clks 152 9>, + <&k3_clks 152 13>; + clock-names = "fck", "vp1", "vp2", "vp3", "vp4"; + + power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>; + + interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "common_m", + "common_s0", + "common_s1", + "common_s2"; + + status = "disabled"; + + dss_ports: ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + mcasp0: mcasp@2b00000 { compatible = "ti,am33xx-mcasp-audio"; reg = <0x0 0x02b00000 0x0 0x2000>, diff --combined drivers/crypto/chelsio/chcr_crypto.h index 1cc522a07aac,b3fdbdc25acb..31e427e273f8 --- a/drivers/crypto/chelsio/chcr_crypto.h +++ b/drivers/crypto/chelsio/chcr_crypto.h @@@ -223,7 -223,7 +223,7 @@@ struct chcr_authenc_ctx
struct __aead_ctx { struct chcr_gcm_ctx gcm[0]; - struct chcr_authenc_ctx authenc[0]; + struct chcr_authenc_ctx authenc[]; };
struct chcr_aead_ctx { @@@ -235,7 -235,7 +235,7 @@@ u8 nonce[4]; u16 hmac_ctrl; u16 mayverify; - struct __aead_ctx ctx[0]; + struct __aead_ctx ctx[]; };
struct hmac_ctx { @@@ -247,7 -247,7 +247,7 @@@ struct __crypto_ctx { struct hmac_ctx hmacctx[0]; struct ablk_ctx ablkctx[0]; - struct chcr_aead_ctx aeadctx[0]; + struct chcr_aead_ctx aeadctx[]; };
struct chcr_context { @@@ -257,7 -257,7 +257,7 @@@ unsigned int ntxq; unsigned int nrxq; struct completion cbc_aes_aio_done; - struct __crypto_ctx crypto_ctx[0]; + struct __crypto_ctx crypto_ctx[]; };
struct chcr_hctx_per_wr { @@@ -302,6 -302,7 +302,7 @@@ struct chcr_skcipher_req_ctx unsigned int op; u16 imm; u8 iv[CHCR_MAX_CRYPTO_IV_LEN]; + u8 init_iv[CHCR_MAX_CRYPTO_IV_LEN]; u16 txqidx; u16 rxqidx; }; diff --combined drivers/net/bonding/bond_main.c index 39b1ad7edbb4,baa93191dfdd..82338615e8e9 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@@ -3923,15 -3923,16 +3923,15 @@@ unwind }
/** - * bond_xmit_slave_id - transmit skb through slave with slave_id + * bond_get_slave_by_id - get xmit slave with slave_id * @bond: bonding device that is transmitting - * @skb: buffer to transmit * @slave_id: slave id up to slave_cnt-1 through which to transmit * - * This function tries to transmit through slave with slave_id but in case + * This function tries to get slave with slave_id but in case * it fails, it tries to find the first available slave for transmission. - * The skb is consumed in all cases, thus the function is void. */ -static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id) +static struct slave *bond_get_slave_by_id(struct bonding *bond, + int slave_id) { struct list_head *iter; struct slave *slave; @@@ -3940,8 -3941,10 +3940,8 @@@ /* Here we start from the slave with slave_id */ bond_for_each_slave_rcu(bond, slave, iter) { if (--i < 0) { - if (bond_slave_can_tx(slave)) { - bond_dev_queue_xmit(bond, skb, slave->dev); - return; - } + if (bond_slave_can_tx(slave)) + return slave; } }
@@@ -3950,11 -3953,13 +3950,11 @@@ bond_for_each_slave_rcu(bond, slave, iter) { if (--i < 0) break; - if (bond_slave_can_tx(slave)) { - bond_dev_queue_xmit(bond, skb, slave->dev); - return; - } + if (bond_slave_can_tx(slave)) + return slave; } - /* no slave that can tx has been found */ - bond_tx_drop(bond->dev, skb); + + return NULL; }
/** @@@ -3990,9 -3995,10 +3990,9 @@@ static u32 bond_rr_gen_slave_id(struct return slave_id; }
-static netdev_tx_t bond_xmit_roundrobin(struct sk_buff *skb, - struct net_device *bond_dev) +static struct slave *bond_xmit_roundrobin_slave_get(struct bonding *bond, + struct sk_buff *skb) { - struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; int slave_cnt; u32 slave_id; @@@ -4014,40 -4020,24 +4014,40 @@@ if (iph->protocol == IPPROTO_IGMP) { slave = rcu_dereference(bond->curr_active_slave); if (slave) - bond_dev_queue_xmit(bond, skb, slave->dev); - else - bond_xmit_slave_id(bond, skb, 0); - return NETDEV_TX_OK; + return slave; + return bond_get_slave_by_id(bond, 0); } }
non_igmp: slave_cnt = READ_ONCE(bond->slave_cnt); if (likely(slave_cnt)) { - slave_id = bond_rr_gen_slave_id(bond); - bond_xmit_slave_id(bond, skb, slave_id % slave_cnt); - } else { - bond_tx_drop(bond_dev, skb); + slave_id = bond_rr_gen_slave_id(bond) % slave_cnt; + return bond_get_slave_by_id(bond, slave_id); } + return NULL; +} + +static netdev_tx_t bond_xmit_roundrobin(struct sk_buff *skb, + struct net_device *bond_dev) +{ + struct bonding *bond = netdev_priv(bond_dev); + struct slave *slave; + + slave = bond_xmit_roundrobin_slave_get(bond, skb); + if (slave) + bond_dev_queue_xmit(bond, skb, slave->dev); + else + bond_tx_drop(bond_dev, skb); return NETDEV_TX_OK; }
+static struct slave *bond_xmit_activebackup_slave_get(struct bonding *bond, + struct sk_buff *skb) +{ + return rcu_dereference(bond->curr_active_slave); +} + /* In active-backup mode, we know that bond->curr_active_slave is always valid if * the bond has a usable interface. */ @@@ -4057,7 -4047,7 +4057,7 @@@ static netdev_tx_t bond_xmit_activeback struct bonding *bond = netdev_priv(bond_dev); struct slave *slave;
- slave = rcu_dereference(bond->curr_active_slave); + slave = bond_xmit_activebackup_slave_get(bond, skb); if (slave) bond_dev_queue_xmit(bond, skb, slave->dev); else @@@ -4097,61 -4087,6 +4097,61 @@@ err bond_slave_arr_work_rearm(bond, 1); }
+static void bond_skip_slave(struct bond_up_slave *slaves, + struct slave *skipslave) +{ + int idx; + + /* Rare situation where caller has asked to skip a specific + * slave but allocation failed (most likely!). BTW this is + * only possible when the call is initiated from + * __bond_release_one(). In this situation; overwrite the + * skipslave entry in the array with the last entry from the + * array to avoid a situation where the xmit path may choose + * this to-be-skipped slave to send a packet out. + */ + for (idx = 0; slaves && idx < slaves->count; idx++) { + if (skipslave == slaves->arr[idx]) { + slaves->arr[idx] = + slaves->arr[slaves->count - 1]; + slaves->count--; + break; + } + } +} + +static void bond_set_slave_arr(struct bonding *bond, + struct bond_up_slave *usable_slaves, + struct bond_up_slave *all_slaves) +{ + struct bond_up_slave *usable, *all; + + usable = rtnl_dereference(bond->usable_slaves); + rcu_assign_pointer(bond->usable_slaves, usable_slaves); + kfree_rcu(usable, rcu); + + all = rtnl_dereference(bond->all_slaves); + rcu_assign_pointer(bond->all_slaves, all_slaves); + kfree_rcu(all, rcu); +} + +static void bond_reset_slave_arr(struct bonding *bond) +{ + struct bond_up_slave *usable, *all; + + usable = rtnl_dereference(bond->usable_slaves); + if (usable) { + RCU_INIT_POINTER(bond->usable_slaves, NULL); + kfree_rcu(usable, rcu); + } + + all = rtnl_dereference(bond->all_slaves); + if (all) { + RCU_INIT_POINTER(bond->all_slaves, NULL); + kfree_rcu(all, rcu); + } +} + /* Build the usable slaves array in control path for modes that use xmit-hash * to determine the slave interface - * (a) BOND_MODE_8023AD @@@ -4162,9 -4097,9 +4162,9 @@@ */ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave) { + struct bond_up_slave *usable_slaves = NULL, *all_slaves = NULL; struct slave *slave; struct list_head *iter; - struct bond_up_slave *new_arr, *old_arr; int agg_id = 0; int ret = 0;
@@@ -4172,12 -4107,11 +4172,12 @@@ WARN_ON(lockdep_is_held(&bond->mode_lock)); #endif
- new_arr = kzalloc(offsetof(struct bond_up_slave, arr[bond->slave_cnt]), - GFP_KERNEL); - if (!new_arr) { + usable_slaves = kzalloc(struct_size(usable_slaves, arr, + bond->slave_cnt), GFP_KERNEL); + all_slaves = kzalloc(struct_size(all_slaves, arr, + bond->slave_cnt), GFP_KERNEL); + if (!usable_slaves || !all_slaves) { ret = -ENOMEM; - pr_err("Failed to build slave-array.\n"); goto out; } if (BOND_MODE(bond) == BOND_MODE_8023AD) { @@@ -4185,19 -4119,20 +4185,19 @@@
if (bond_3ad_get_active_agg_info(bond, &ad_info)) { pr_debug("bond_3ad_get_active_agg_info failed\n"); - kfree_rcu(new_arr, rcu); /* No active aggragator means it's not safe to use * the previous array. */ - old_arr = rtnl_dereference(bond->slave_arr); - if (old_arr) { - RCU_INIT_POINTER(bond->slave_arr, NULL); - kfree_rcu(old_arr, rcu); - } + bond_reset_slave_arr(bond); goto out; } agg_id = ad_info.aggregator_id; } bond_for_each_slave(bond, slave, iter) { + if (skipslave == slave) + continue; + + all_slaves->arr[all_slaves->count++] = slave; if (BOND_MODE(bond) == BOND_MODE_8023AD) { struct aggregator *agg;
@@@ -4207,45 -4142,44 +4207,45 @@@ } if (!bond_slave_can_tx(slave)) continue; - if (skipslave == slave) - continue;
slave_dbg(bond->dev, slave->dev, "Adding slave to tx hash array[%d]\n", - new_arr->count); + usable_slaves->count);
- new_arr->arr[new_arr->count++] = slave; + usable_slaves->arr[usable_slaves->count++] = slave; }
- old_arr = rtnl_dereference(bond->slave_arr); - rcu_assign_pointer(bond->slave_arr, new_arr); - if (old_arr) - kfree_rcu(old_arr, rcu); + bond_set_slave_arr(bond, usable_slaves, all_slaves); + return ret; out: if (ret != 0 && skipslave) { - int idx; - - /* Rare situation where caller has asked to skip a specific - * slave but allocation failed (most likely!). BTW this is - * only possible when the call is initiated from - * __bond_release_one(). In this situation; overwrite the - * skipslave entry in the array with the last entry from the - * array to avoid a situation where the xmit path may choose - * this to-be-skipped slave to send a packet out. - */ - old_arr = rtnl_dereference(bond->slave_arr); - for (idx = 0; old_arr != NULL && idx < old_arr->count; idx++) { - if (skipslave == old_arr->arr[idx]) { - old_arr->arr[idx] = - old_arr->arr[old_arr->count-1]; - old_arr->count--; - break; - } - } + bond_skip_slave(rtnl_dereference(bond->all_slaves), + skipslave); + bond_skip_slave(rtnl_dereference(bond->usable_slaves), + skipslave); } + kfree_rcu(all_slaves, rcu); + kfree_rcu(usable_slaves, rcu); + return ret; }
+static struct slave *bond_xmit_3ad_xor_slave_get(struct bonding *bond, + struct sk_buff *skb, + struct bond_up_slave *slaves) +{ + struct slave *slave; + unsigned int count; + u32 hash; + + hash = bond_xmit_hash(bond, skb); + count = slaves ? READ_ONCE(slaves->count) : 0; + if (unlikely(!count)) + return NULL; + + slave = slaves->arr[hash % count]; + return slave; +} + /* Use this Xmit function for 3AD as well as XOR modes. The current * usable slave array is formed in the control path. The xmit function * just calculates hash and sends the packet out. @@@ -4254,15 -4188,18 +4254,15 @@@ static netdev_tx_t bond_3ad_xor_xmit(st struct net_device *dev) { struct bonding *bond = netdev_priv(dev); - struct slave *slave; struct bond_up_slave *slaves; - unsigned int count; + struct slave *slave;
- slaves = rcu_dereference(bond->slave_arr); - count = slaves ? READ_ONCE(slaves->count) : 0; - if (likely(count)) { - slave = slaves->arr[bond_xmit_hash(bond, skb) % count]; + slaves = rcu_dereference(bond->usable_slaves); + slave = bond_xmit_3ad_xor_slave_get(bond, skb, slaves); + if (likely(slave)) bond_dev_queue_xmit(bond, skb, slave->dev); - } else { + else bond_tx_drop(dev, skb); - }
return NETDEV_TX_OK; } @@@ -4347,48 -4284,6 +4347,48 @@@ static u16 bond_select_queue(struct net return txq; }
+static struct net_device *bond_xmit_get_slave(struct net_device *master_dev, + struct sk_buff *skb, + bool all_slaves) +{ + struct bonding *bond = netdev_priv(master_dev); + struct bond_up_slave *slaves; + struct slave *slave = NULL; + + switch (BOND_MODE(bond)) { + case BOND_MODE_ROUNDROBIN: + slave = bond_xmit_roundrobin_slave_get(bond, skb); + break; + case BOND_MODE_ACTIVEBACKUP: + slave = bond_xmit_activebackup_slave_get(bond, skb); + break; + case BOND_MODE_8023AD: + case BOND_MODE_XOR: + if (all_slaves) + slaves = rcu_dereference(bond->all_slaves); + else + slaves = rcu_dereference(bond->usable_slaves); + slave = bond_xmit_3ad_xor_slave_get(bond, skb, slaves); + break; + case BOND_MODE_BROADCAST: + break; + case BOND_MODE_ALB: + slave = bond_xmit_alb_slave_get(bond, skb); + break; + case BOND_MODE_TLB: + slave = bond_xmit_tlb_slave_get(bond, skb); + break; + default: + /* Should never happen, mode already checked */ + WARN_ONCE(true, "Unknown bonding mode"); + break; + } + + if (slave) + return slave->dev; + return NULL; +} + static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct bonding *bond = netdev_priv(dev); @@@ -4510,7 -4405,6 +4510,7 @@@ static const struct net_device_ops bond .ndo_del_slave = bond_release, .ndo_fix_features = bond_fix_features, .ndo_features_check = passthru_features_check, + .ndo_get_xmit_slave = bond_xmit_get_slave, };
static const struct device_type bond_type = { @@@ -4578,9 -4472,9 +4578,9 @@@ void bond_setup(struct net_device *bond static void bond_uninit(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); + struct bond_up_slave *usable, *all; struct list_head *iter; struct slave *slave; - struct bond_up_slave *arr;
bond_netpoll_cleanup(bond_dev);
@@@ -4589,21 -4483,14 +4589,20 @@@ __bond_release_one(bond_dev, slave->dev, true, true); netdev_info(bond_dev, "Released all slaves\n");
- arr = rtnl_dereference(bond->slave_arr); - if (arr) { - RCU_INIT_POINTER(bond->slave_arr, NULL); - kfree_rcu(arr, rcu); + usable = rtnl_dereference(bond->usable_slaves); + if (usable) { + RCU_INIT_POINTER(bond->usable_slaves, NULL); + kfree_rcu(usable, rcu); + } + + all = rtnl_dereference(bond->all_slaves); + if (all) { + RCU_INIT_POINTER(bond->all_slaves, NULL); + kfree_rcu(all, rcu); }
list_del(&bond->bond_list);
- lockdep_unregister_key(&bond->stats_lock_key); bond_debug_unregister(bond); }
@@@ -5008,8 -4895,7 +5007,7 @@@ static int bond_init(struct net_device return -ENOMEM;
spin_lock_init(&bond->stats_lock); - lockdep_register_key(&bond->stats_lock_key); - lockdep_set_class(&bond->stats_lock, &bond->stats_lock_key); + netdev_lockdep_set_classes(bond_dev);
list_add_tail(&bond->bond_list, &bn->dev_list);
diff --combined drivers/net/ethernet/amazon/ena/ena_netdev.h index 9e1860d81908,bd278c4721c6..7df67bf09b93 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@@ -69,7 -69,7 +69,7 @@@ * 16kB. */ #if PAGE_SIZE > SZ_16K -#define ENA_PAGE_SIZE SZ_16K +#define ENA_PAGE_SIZE (_AC(SZ_16K, UL)) #else #define ENA_PAGE_SIZE PAGE_SIZE #endif @@@ -248,6 -248,7 +248,7 @@@ struct ena_stats_tx u64 bad_req_id; u64 llq_buffer_copy; u64 missed_tx; + u64 unmask_interrupt; };
struct ena_stats_rx { @@@ -333,6 -334,7 +334,7 @@@ struct ena_stats_dev u64 interface_down; u64 admin_q_pause; u64 rx_drops; + u64 tx_drops; };
enum ena_flags_t { diff --combined drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index 8a70ffe1d326,ce46cdbc69e6..d10fff8a8c71 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@@ -16,6 -16,7 +16,7 @@@ #include "aq_pci_func.h" #include "hw_atl/hw_atl_a0.h" #include "hw_atl/hw_atl_b0.h" + #include "hw_atl2/hw_atl2.h" #include "aq_filters.h" #include "aq_drvinfo.h" #include "aq_macsec.h" @@@ -41,6 -42,13 +42,13 @@@ static const struct pci_device_id aq_pc { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111S), }, { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112S), },
+ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113DEV), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113CS), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC114CS), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113C), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC115C), }, + {} };
@@@ -57,7 -65,7 +65,7 @@@ static const struct aq_board_revision_ { AQ_DEVICE_ID_D108, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc108, }, { AQ_DEVICE_ID_D109, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc109, },
- { AQ_DEVICE_ID_AQC100, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, }, + { AQ_DEVICE_ID_AQC100, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100, }, { AQ_DEVICE_ID_AQC107, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, }, { AQ_DEVICE_ID_AQC108, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108, }, { AQ_DEVICE_ID_AQC109, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109, }, @@@ -70,6 -78,13 +78,13 @@@ { AQ_DEVICE_ID_AQC109S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109s, }, { AQ_DEVICE_ID_AQC111S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111s, }, { AQ_DEVICE_ID_AQC112S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112s, }, + + { AQ_DEVICE_ID_AQC113DEV, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, + { AQ_DEVICE_ID_AQC113, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, + { AQ_DEVICE_ID_AQC113CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, + { AQ_DEVICE_ID_AQC114CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, + { AQ_DEVICE_ID_AQC113C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, + { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, };
MODULE_DEVICE_TABLE(pci, aq_pci_tbl); @@@ -104,10 -119,8 +119,8 @@@ int aq_pci_func_init(struct pci_dev *pd int err;
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); - if (!err) { + if (!err) err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); - - } if (err) { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (!err) @@@ -237,6 -250,15 +250,15 @@@ static int aq_pci_probe(struct pci_dev goto err_ioremap; } self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self); + if (self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len) { + int len = self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len; + + self->aq_hw->priv = kzalloc(len, GFP_KERNEL); + if (!self->aq_hw->priv) { + err = -ENOMEM; + goto err_free_aq_hw; + } + }
for (bar = 0; bar < 4; ++bar) { if (IORESOURCE_MEM & pci_resource_flags(pdev, bar)) { @@@ -245,19 -267,19 +267,19 @@@ mmio_pa = pci_resource_start(pdev, bar); if (mmio_pa == 0U) { err = -EIO; - goto err_free_aq_hw; + goto err_free_aq_hw_priv; }
reg_sz = pci_resource_len(pdev, bar); if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) { err = -EIO; - goto err_free_aq_hw; + goto err_free_aq_hw_priv; }
self->aq_hw->mmio = ioremap(mmio_pa, reg_sz); if (!self->aq_hw->mmio) { err = -EIO; - goto err_free_aq_hw; + goto err_free_aq_hw_priv; } break; } @@@ -265,7 -287,7 +287,7 @@@
if (bar == 4) { err = -EIO; - goto err_free_aq_hw; + goto err_free_aq_hw_priv; }
numvecs = min((u8)AQ_CFG_VECS_DEF, @@@ -305,6 -327,8 +327,8 @@@ err_register aq_pci_free_irq_vectors(self); err_hwinit: iounmap(self->aq_hw->mmio); + err_free_aq_hw_priv: + kfree(self->aq_hw->priv); err_free_aq_hw: kfree(self->aq_hw); err_ioremap: @@@ -332,6 -356,7 +356,7 @@@ static void aq_pci_remove(struct pci_de aq_nic_free_vectors(self); aq_pci_free_irq_vectors(self); iounmap(self->aq_hw->mmio); + kfree(self->aq_hw->priv); kfree(self->aq_hw); pci_release_regions(pdev); free_netdev(self->ndev); diff --combined drivers/net/ethernet/broadcom/bnxt/bnxt.c index d1a83716d934,4bbfea147d98..f86b6217f829 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@@ -1766,7 -1766,7 +1766,7 @@@ static int bnxt_rx_pkt(struct bnxt *bp
rc = -EIO; if (rx_err & RX_CMPL_ERRORS_BUFFER_ERROR_MASK) { - bnapi->cp_ring.rx_buf_errors++; + bnapi->cp_ring.sw_stats.rx.rx_buf_errors++; if (!(bp->flags & BNXT_FLAG_CHIP_P5)) { netdev_warn(bp->dev, "RX buffer error %x\n", rx_err); @@@ -1849,7 -1849,7 +1849,7 @@@ } else { if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS) { if (dev->features & NETIF_F_RXCSUM) - bnapi->cp_ring.rx_l4_csum_errors++; + bnapi->cp_ring.sw_stats.rx.rx_l4_csum_errors++; } }
@@@ -5045,8 -5045,7 +5045,7 @@@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp req.dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id); req.lb_rule = cpu_to_le16(0xffff); vnic_mru: - req.mru = cpu_to_le16(bp->dev->mtu + ETH_HLEN + ETH_FCS_LEN + - VLAN_HLEN); + req.mru = cpu_to_le16(bp->dev->mtu + ETH_HLEN + VLAN_HLEN);
req.vnic_id = cpu_to_le16(vnic->fw_vnic_id); #ifdef CONFIG_BNXT_SRIOV @@@ -5356,9 -5355,9 +5355,9 @@@ static void bnxt_set_db(struct bnxt *bp { if (bp->flags & BNXT_FLAG_CHIP_P5) { if (BNXT_PF(bp)) - db->doorbell = bp->bar1 + 0x10000; + db->doorbell = bp->bar1 + DB_PF_OFFSET_P5; else - db->doorbell = bp->bar1 + 0x4000; + db->doorbell = bp->bar1 + DB_VF_OFFSET_P5; switch (ring_type) { case HWRM_RING_ALLOC_TX: db->db_key64 = DBR_PATH_L2 | DBR_TYPE_SQ; @@@ -6365,6 -6364,7 +6364,7 @@@ static int bnxt_hwrm_func_qcfg(struct b { struct hwrm_func_qcfg_input req = {0}; struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr; + u32 min_db_offset = 0; u16 flags; int rc;
@@@ -6413,6 -6413,21 +6413,21 @@@ if (!bp->max_mtu) bp->max_mtu = BNXT_MAX_MTU;
+ if (bp->db_size) + goto func_qcfg_exit; + + if (bp->flags & BNXT_FLAG_CHIP_P5) { + if (BNXT_PF(bp)) + min_db_offset = DB_PF_OFFSET_P5; + else + min_db_offset = DB_VF_OFFSET_P5; + } + bp->db_size = PAGE_ALIGN(le16_to_cpu(resp->l2_doorbell_bar_size_kb) * + 1024); + if (!bp->db_size || bp->db_size > pci_resource_len(bp->pdev, 2) || + bp->db_size <= min_db_offset) + bp->db_size = pci_resource_len(bp->pdev, 2); + func_qcfg_exit: mutex_unlock(&bp->hwrm_cmd_lock); return rc; @@@ -6434,23 -6449,13 +6449,13 @@@ static int bnxt_hwrm_func_backing_store if (!rc) { struct bnxt_ctx_pg_info *ctx_pg; struct bnxt_ctx_mem_info *ctx; - int i; + int i, tqm_rings;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { rc = -ENOMEM; goto ctx_err; } - ctx_pg = kzalloc(sizeof(*ctx_pg) * (bp->max_q + 1), GFP_KERNEL); - if (!ctx_pg) { - kfree(ctx); - rc = -ENOMEM; - goto ctx_err; - } - for (i = 0; i < bp->max_q + 1; i++, ctx_pg++) - ctx->tqm_mem[i] = ctx_pg; - - bp->ctx = ctx; ctx->qp_max_entries = le32_to_cpu(resp->qp_max_entries); ctx->qp_min_qp1_entries = le16_to_cpu(resp->qp_min_qp1_entries); ctx->qp_max_l2_entries = le16_to_cpu(resp->qp_max_l2_entries); @@@ -6483,6 -6488,20 +6488,20 @@@ ctx->tim_entry_size = le16_to_cpu(resp->tim_entry_size); ctx->tim_max_entries = le32_to_cpu(resp->tim_max_entries); ctx->ctx_kind_initializer = resp->ctx_kind_initializer; + ctx->tqm_fp_rings_count = resp->tqm_fp_rings_count; + if (!ctx->tqm_fp_rings_count) + ctx->tqm_fp_rings_count = bp->max_q; + + tqm_rings = ctx->tqm_fp_rings_count + 1; + ctx_pg = kcalloc(tqm_rings, sizeof(*ctx_pg), GFP_KERNEL); + if (!ctx_pg) { + kfree(ctx); + rc = -ENOMEM; + goto ctx_err; + } + for (i = 0; i < tqm_rings; i++, ctx_pg++) + ctx->tqm_mem[i] = ctx_pg; + bp->ctx = ctx; } else { rc = 0; } @@@ -6642,7 -6661,7 +6661,7 @@@ static int bnxt_alloc_ctx_pg_tbls(struc int rc;
if (!mem_size) - return 0; + return -EINVAL;
ctx_pg->nr_pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE); if (ctx_pg->nr_pages > MAX_CTX_TOTAL_PAGES) { @@@ -6735,7 -6754,7 +6754,7 @@@ static void bnxt_free_ctx_mem(struct bn return;
if (ctx->tqm_mem[0]) { - for (i = 0; i < bp->max_q + 1; i++) + for (i = 0; i < ctx->tqm_fp_rings_count + 1; i++) bnxt_free_ctx_pg_tbls(bp, ctx->tqm_mem[i]); kfree(ctx->tqm_mem[0]); ctx->tqm_mem[0] = NULL; @@@ -6756,6 -6775,7 +6775,7 @@@ static int bnxt_alloc_ctx_mem(struct bn struct bnxt_ctx_pg_info *ctx_pg; struct bnxt_ctx_mem_info *ctx; u32 mem_size, ena, entries; + u32 entries_sp, min; u32 num_mr, num_ah; u32 extra_srqs = 0; u32 extra_qps = 0; @@@ -6845,14 -6865,17 +6865,17 @@@ ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_TIM;
skip_rdma: - entries = ctx->qp_max_l2_entries + extra_qps; + min = ctx->tqm_min_entries_per_ring; + entries_sp = ctx->vnic_max_vnic_entries + ctx->qp_max_l2_entries + + 2 * (extra_qps + ctx->qp_min_qp1_entries) + min; + entries_sp = roundup(entries_sp, ctx->tqm_entries_multiple); + entries = ctx->qp_max_l2_entries + extra_qps + ctx->qp_min_qp1_entries; entries = roundup(entries, ctx->tqm_entries_multiple); - entries = clamp_t(u32, entries, ctx->tqm_min_entries_per_ring, - ctx->tqm_max_entries_per_ring); - for (i = 0; i < bp->max_q + 1; i++) { + entries = clamp_t(u32, entries, min, ctx->tqm_max_entries_per_ring); + for (i = 0; i < ctx->tqm_fp_rings_count + 1; i++) { ctx_pg = ctx->tqm_mem[i]; - ctx_pg->entries = entries; - mem_size = ctx->tqm_entry_size * entries; + ctx_pg->entries = i ? entries : entries_sp; + mem_size = ctx->tqm_entry_size * ctx_pg->entries; rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, false); if (rc) return rc; @@@ -9780,7 -9803,6 +9803,7 @@@ static netdev_features_t bnxt_fix_featu netdev_features_t features) { struct bnxt *bp = netdev_priv(dev); + netdev_features_t vlan_features;
if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp)) features &= ~NETIF_F_NTUPLE; @@@ -9797,14 -9819,12 +9820,14 @@@ /* Both CTAG and STAG VLAN accelaration on the RX side have to be * turned on or off together. */ - if ((features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) != - (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) { + vlan_features = features & (NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_STAG_RX); + if (vlan_features != (NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_STAG_RX)) { if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) features &= ~(NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX); - else + else if (vlan_features) features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX; } @@@ -10265,7 -10285,7 +10288,7 @@@ static void bnxt_chk_missed_irq(struct bnxt_dbg_hwrm_ring_info_get(bp, DBG_RING_INFO_GET_REQ_RING_TYPE_L2_CMPL, fw_ring_id, &val[0], &val[1]); - cpr->missed_irqs++; + cpr->sw_stats.cmn.missed_irqs++; } } } @@@ -10894,6 -10914,9 +10917,9 @@@ static int bnxt_init_board(struct pci_d bp->dev = dev; bp->pdev = pdev;
+ /* Doorbell BAR bp->bar1 is mapped after bnxt_fw_init_one_p2() + * determines the BAR size. + */ bp->bar0 = pci_ioremap_bar(pdev, 0); if (!bp->bar0) { dev_err(&pdev->dev, "Cannot map device registers, aborting\n"); @@@ -10901,13 -10924,6 +10927,6 @@@ goto init_err_release; }
- bp->bar1 = pci_ioremap_bar(pdev, 2); - if (!bp->bar1) { - dev_err(&pdev->dev, "Cannot map doorbell registers, aborting\n"); - rc = -ENOMEM; - goto init_err_release; - } - bp->bar2 = pci_ioremap_bar(pdev, 4); if (!bp->bar2) { dev_err(&pdev->dev, "Cannot map bar4 registers, aborting\n"); @@@ -11829,6 -11845,16 +11848,16 @@@ static int bnxt_pcie_dsn_get(struct bnx return 0; }
+ static int bnxt_map_db_bar(struct bnxt *bp) + { + if (!bp->db_size) + return -ENODEV; + bp->bar1 = pci_iomap(bp->pdev, 2, bp->db_size); + if (!bp->bar1) + return -ENOMEM; + return 0; + } + static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; @@@ -11889,6 -11915,13 +11918,13 @@@ if (rc) goto init_err_pci_clean;
+ rc = bnxt_map_db_bar(bp); + if (rc) { + dev_err(&pdev->dev, "Cannot map doorbell BAR rc = %d, aborting\n", + rc); + goto init_err_pci_clean; + } + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE | @@@ -12215,15 -12248,12 +12251,15 @@@ static pci_ers_result_t bnxt_io_slot_re bnxt_ulp_start(bp, err); }
- if (result != PCI_ERS_RESULT_RECOVERED && netif_running(netdev)) - dev_close(netdev); + if (result != PCI_ERS_RESULT_RECOVERED) { + if (netif_running(netdev)) + dev_close(netdev); + pci_disable_device(pdev); + }
rtnl_unlock();
- return PCI_ERS_RESULT_RECOVERED; + return result; }
/** diff --combined drivers/net/ethernet/broadcom/bnxt/bnxt.h index f6a3250ef1c5,c15517ff7ff6..c04ac4a36005 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@@ -537,6 -537,9 +537,9 @@@ struct nqe_cn #define DBR_TYPE_NQ_ARM (0xbULL << 60) #define DBR_TYPE_NULL (0xfULL << 60)
+ #define DB_PF_OFFSET_P5 0x10000 + #define DB_VF_OFFSET_P5 0x4000 + #define INVALID_HW_RING_ID ((u16)-1)
/* The hardware supports certain page sizes. Use the supported page sizes @@@ -907,6 -910,20 +910,20 @@@ struct bnxt_rx_ring_info struct page_pool *page_pool; };
+ struct bnxt_rx_sw_stats { + u64 rx_l4_csum_errors; + u64 rx_buf_errors; + }; + + struct bnxt_cmn_sw_stats { + u64 missed_irqs; + }; + + struct bnxt_sw_stats { + struct bnxt_rx_sw_stats rx; + struct bnxt_cmn_sw_stats cmn; + }; + struct bnxt_cp_ring_info { struct bnxt_napi *bnapi; u32 cp_raw_cons; @@@ -934,9 -951,8 +951,8 @@@ struct ctx_hw_stats *hw_stats; dma_addr_t hw_stats_map; u32 hw_stats_ctx_id; - u64 rx_l4_csum_errors; - u64 rx_buf_errors; - u64 missed_irqs; + + struct bnxt_sw_stats sw_stats;
struct bnxt_ring_struct cp_ring_struct;
@@@ -1066,6 -1082,7 +1082,6 @@@ struct bnxt_vf_info #define BNXT_VF_LINK_FORCED 0x4 #define BNXT_VF_LINK_UP 0x8 #define BNXT_VF_TRUST 0x10 - u32 func_flags; /* func cfg flags */ u32 min_tx_rate; u32 max_tx_rate; void *hwrm_cmd_req_addr; @@@ -1356,6 -1373,7 +1372,7 @@@ struct bnxt_ctx_mem_info u16 mrav_num_entries_units; u8 tqm_entries_multiple; u8 ctx_kind_initializer; + u8 tqm_fp_rings_count;
u32 flags; #define BNXT_CTX_FLAG_INITED 0x01 @@@ -1815,6 -1833,7 +1832,7 @@@ struct bnxt /* ensure atomic 64-bit doorbell writes on 32-bit systems. */ spinlock_t db_lock; #endif + int db_size;
#define BNXT_NTP_FLTR_MAX_FLTR 4096 #define BNXT_NTP_FLTR_HASH_SIZE 512 diff --combined drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index cea2f9958a1d,c883e8884faf..3a9a51f7063a --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@@ -85,10 -85,11 +85,10 @@@ int bnxt_set_vf_spoofchk(struct net_dev if (old_setting == setting) return 0;
- func_flags = vf->func_flags; if (setting) - func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE; + func_flags = FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE; else - func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE; + func_flags = FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE; /*TODO: if the driver supports VLAN filter on guest VLAN, * the spoof check should also include vlan anti-spoofing */ @@@ -97,6 -98,7 +97,6 @@@ req.flags = cpu_to_le32(func_flags); rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); if (!rc) { - vf->func_flags = func_flags; if (setting) vf->flags |= BNXT_VF_SPOOFCHK; else @@@ -226,6 -228,7 +226,6 @@@ int bnxt_set_vf_mac(struct net_device * memcpy(vf->mac_addr, mac, ETH_ALEN); bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); req.fid = cpu_to_le16(vf->fw_fid); - req.flags = cpu_to_le32(vf->func_flags); req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR); memcpy(req.dflt_mac_addr, mac, ETH_ALEN); return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); @@@ -263,6 -266,7 +263,6 @@@ int bnxt_set_vf_vlan(struct net_device
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); req.fid = cpu_to_le16(vf->fw_fid); - req.flags = cpu_to_le32(vf->func_flags); req.dflt_vlan = cpu_to_le16(vlan_tag); req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN); rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); @@@ -301,6 -305,7 +301,6 @@@ int bnxt_set_vf_bw(struct net_device *d return 0; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); req.fid = cpu_to_le16(vf->fw_fid); - req.flags = cpu_to_le32(vf->func_flags); req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW); req.max_bw = cpu_to_le32(max_tx_rate); req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_MIN_BW); @@@ -472,6 -477,7 +472,6 @@@ static void __bnxt_set_vf_params(struc vf = &bp->pf.vf[vf_id]; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); req.fid = cpu_to_le16(vf->fw_fid); - req.flags = cpu_to_le32(vf->func_flags);
if (is_valid_ether_addr(vf->mac_addr)) { req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR); @@@ -645,7 -651,7 +645,7 @@@ static int bnxt_hwrm_func_cfg(struct bn FUNC_CFG_REQ_ENABLES_NUM_VNICS | FUNC_CFG_REQ_ENABLES_NUM_HW_RING_GRPS);
- mtu = bp->dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; + mtu = bp->dev->mtu + ETH_HLEN + VLAN_HLEN; req.mru = cpu_to_le16(mtu); req.mtu = cpu_to_le16(mtu);
diff --combined drivers/net/ethernet/intel/e1000e/netdev.c index 2730b1c7dddb,e0b074820b47..53e53164188f --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@@ -6404,6 -6404,31 +6404,31 @@@ static void e1000e_s0ix_entry_flow(stru mac_data |= BIT(3); ew32(CTRL_EXT, mac_data);
+ /* Disable disconnected cable conditioning for Power Gating */ + mac_data = er32(DPGFR); + mac_data |= BIT(2); + ew32(DPGFR, mac_data); + + /* Don't wake from dynamic Power Gating with clock request */ + mac_data = er32(FEXTNVM12); + mac_data |= BIT(12); + ew32(FEXTNVM12, mac_data); + + /* Ungate PGCB clock */ + mac_data = er32(FEXTNVM9); + mac_data |= BIT(28); + ew32(FEXTNVM9, mac_data); + + /* Enable K1 off to enable mPHY Power Gating */ + mac_data = er32(FEXTNVM6); + mac_data |= BIT(31); + ew32(FEXTNVM12, mac_data); + + /* Enable mPHY power gating for any link and speed */ + mac_data = er32(FEXTNVM8); + mac_data |= BIT(9); + ew32(FEXTNVM8, mac_data); + /* Enable the Dynamic Clock Gating in the DMA and MAC */ mac_data = er32(CTRL_EXT); mac_data |= E1000_CTRL_EXT_DMA_DYN_CLK_EN; @@@ -6433,6 -6458,35 +6458,35 @@@ static void e1000e_s0ix_exit_flow(struc mac_data |= BIT(0); ew32(FEXTNVM7, mac_data);
+ /* Disable mPHY power gating for any link and speed */ + mac_data = er32(FEXTNVM8); + mac_data &= ~BIT(9); + ew32(FEXTNVM8, mac_data); + + /* Disable K1 off */ + mac_data = er32(FEXTNVM6); + mac_data &= ~BIT(31); + ew32(FEXTNVM12, mac_data); + + /* Disable Ungate PGCB clock */ + mac_data = er32(FEXTNVM9); + mac_data &= ~BIT(28); + ew32(FEXTNVM9, mac_data); + + /* Cancel not waking from dynamic + * Power Gating with clock request + */ + mac_data = er32(FEXTNVM12); + mac_data &= ~BIT(12); + ew32(FEXTNVM12, mac_data); + + /* Cancel disable disconnected cable conditioning + * for Power Gating + */ + mac_data = er32(DPGFR); + mac_data &= ~BIT(2); + ew32(DPGFR, mac_data); + /* Disable Dynamic Power Gating */ mac_data = er32(CTRL_EXT); mac_data &= 0xFFFFFFF7; @@@ -7549,7 -7603,7 +7603,7 @@@ static int e1000_probe(struct pci_dev *
e1000_print_device_info(adapter);
- dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP); + dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
if (pci_dev_run_wake(pdev) && hw->mac.type < e1000_pch_cnp) pm_runtime_put_noidle(&pdev->dev); diff --combined drivers/net/ethernet/intel/igc/igc_main.c index 59fc0097438f,9d5f8287c704..927fc95c5684 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@@ -9,11 -9,13 +9,13 @@@ #include <linux/udp.h> #include <linux/ip.h> #include <linux/pm_runtime.h> + #include <net/pkt_sched.h>
#include <net/ipv6.h>
#include "igc.h" #include "igc_hw.h" + #include "igc_tsn.h"
#define DRV_VERSION "0.0.1-k" #define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" @@@ -45,6 -47,9 +47,9 @@@ static const struct pci_device_id igc_p { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_I), board_base }, { PCI_VDEVICE(INTEL, IGC_DEV_ID_I220_V), board_base }, { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_K), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_K2), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_LMVP), board_base }, + { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_IT), board_base }, { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_BLANK_NVM), board_base }, /* required last entry */ {0, } @@@ -106,6 -111,9 +111,9 @@@ void igc_reset(struct igc_adapter *adap /* Re-enable PTP, where applicable. */ igc_ptp_reset(adapter);
+ /* Re-enable TSN offloading, where applicable. */ + igc_tsn_offload_apply(adapter); + igc_get_phy_info(hw); }
@@@ -757,48 -765,74 +765,74 @@@ static void igc_setup_tctl(struct igc_a }
/** - * igc_rar_set_index - Sync RAL[index] and RAH[index] registers with MAC table - * @adapter: address of board private structure - * @index: Index of the RAR entry which need to be synced with MAC table + * igc_set_mac_filter_hw() - Set MAC address filter in hardware + * @adapter: Pointer to adapter where the filter should be set + * @index: Filter index + * @addr: Destination MAC address + * @queue: If non-negative, queue assignment feature is enabled and frames + * matching the filter are enqueued onto 'queue'. Otherwise, queue + * assignment is disabled. */ - static void igc_rar_set_index(struct igc_adapter *adapter, u32 index) + static void igc_set_mac_filter_hw(struct igc_adapter *adapter, int index, + const u8 *addr, int queue) { - u8 *addr = adapter->mac_table[index].addr; + struct net_device *dev = adapter->netdev; struct igc_hw *hw = &adapter->hw; - u32 rar_low, rar_high; + u32 ral, rah;
- /* HW expects these to be in network order when they are plugged - * into the registers which are little endian. In order to guarantee - * that ordering we need to do an leXX_to_cpup here in order to be - * ready for the byteswap that occurs with writel - */ - rar_low = le32_to_cpup((__le32 *)(addr)); - rar_high = le16_to_cpup((__le16 *)(addr + 4)); + if (WARN_ON(index >= hw->mac.rar_entry_count)) + return;
- /* Indicate to hardware the Address is Valid. */ - if (adapter->mac_table[index].state & IGC_MAC_STATE_IN_USE) { - if (is_valid_ether_addr(addr)) - rar_high |= IGC_RAH_AV; + ral = le32_to_cpup((__le32 *)(addr)); + rah = le16_to_cpup((__le16 *)(addr + 4));
- rar_high |= IGC_RAH_POOL_1 << - adapter->mac_table[index].queue; + if (queue >= 0) { + rah &= ~IGC_RAH_QSEL_MASK; + rah |= (queue << IGC_RAH_QSEL_SHIFT); + rah |= IGC_RAH_QSEL_ENABLE; }
- wr32(IGC_RAL(index), rar_low); - wrfl(); - wr32(IGC_RAH(index), rar_high); - wrfl(); + rah |= IGC_RAH_AV; + + wr32(IGC_RAL(index), ral); + wr32(IGC_RAH(index), rah); + + netdev_dbg(dev, "MAC address filter set in HW: index %d", index); + } + + /** + * igc_clear_mac_filter_hw() - Clear MAC address filter in hardware + * @adapter: Pointer to adapter where the filter should be cleared + * @index: Filter index + */ + static void igc_clear_mac_filter_hw(struct igc_adapter *adapter, int index) + { + struct net_device *dev = adapter->netdev; + struct igc_hw *hw = &adapter->hw; + + if (WARN_ON(index >= hw->mac.rar_entry_count)) + return; + + wr32(IGC_RAL(index), 0); + wr32(IGC_RAH(index), 0); + + netdev_dbg(dev, "MAC address filter cleared in HW: index %d", index); }
/* Set default MAC address for the PF in the first RAR entry */ static void igc_set_default_mac_filter(struct igc_adapter *adapter) { struct igc_mac_addr *mac_table = &adapter->mac_table[0]; + struct net_device *dev = adapter->netdev; + u8 *addr = adapter->hw.mac.addr;
- ether_addr_copy(mac_table->addr, adapter->hw.mac.addr); + netdev_dbg(dev, "Set default MAC address filter: address %pM", addr); + + ether_addr_copy(mac_table->addr, addr); mac_table->state = IGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE; + mac_table->queue = -1;
- igc_rar_set_index(adapter, 0); + igc_set_mac_filter_hw(adapter, 0, addr, mac_table->queue); }
/** @@@ -864,6 -898,23 +898,23 @@@ static int igc_write_mc_addr_list(struc return netdev_mc_count(netdev); }
+ static __le32 igc_tx_launchtime(struct igc_adapter *adapter, ktime_t txtime) + { + ktime_t cycle_time = adapter->cycle_time; + ktime_t base_time = adapter->base_time; + u32 launchtime; + + /* FIXME: when using ETF together with taprio, we may have a + * case where 'delta' is larger than the cycle_time, this may + * cause problems if we don't read the current value of + * IGC_BASET, as the value writen into the launchtime + * descriptor field may be misinterpreted. + */ + div_s64_rem(ktime_sub_ns(txtime, base_time), cycle_time, &launchtime); + + return cpu_to_le32(launchtime); + } + static void igc_tx_ctxtdesc(struct igc_ring *tx_ring, struct igc_tx_buffer *first, u32 vlan_macip_lens, u32 type_tucmd, @@@ -871,7 -922,6 +922,6 @@@ { struct igc_adv_tx_context_desc *context_desc; u16 i = tx_ring->next_to_use; - struct timespec64 ts;
context_desc = IGC_TX_CTXTDESC(tx_ring, i);
@@@ -893,9 -943,12 +943,12 @@@ * should have been handled by the upper layers. */ if (tx_ring->launchtime_enable) { - ts = ktime_to_timespec64(first->skb->tstamp); + struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); + ktime_t txtime = first->skb->tstamp; + first->skb->tstamp = ktime_set(0, 0); - context_desc->launch_time = cpu_to_le32(ts.tv_nsec / 32); + context_desc->launch_time = igc_tx_launchtime(adapter, + txtime); } else { context_desc->launch_time = 0; } @@@ -2133,129 -2186,148 +2186,148 @@@ static void igc_nfc_filter_restore(stru spin_unlock(&adapter->nfc_lock); }
- /* If the filter to be added and an already existing filter express - * the same address and address type, it should be possible to only - * override the other configurations, for example the queue to steer - * traffic. - */ - static bool igc_mac_entry_can_be_used(const struct igc_mac_addr *entry, - const u8 *addr, const u8 flags) + static int igc_find_mac_filter(struct igc_adapter *adapter, const u8 *addr, + u8 flags) { - if (!(entry->state & IGC_MAC_STATE_IN_USE)) - return true; + int max_entries = adapter->hw.mac.rar_entry_count; + struct igc_mac_addr *entry; + int i;
- if ((entry->state & IGC_MAC_STATE_SRC_ADDR) != - (flags & IGC_MAC_STATE_SRC_ADDR)) - return false; + for (i = 0; i < max_entries; i++) { + entry = &adapter->mac_table[i];
- if (!ether_addr_equal(addr, entry->addr)) - return false; + if (!(entry->state & IGC_MAC_STATE_IN_USE)) + continue; + if (!ether_addr_equal(addr, entry->addr)) + continue; + if ((entry->state & IGC_MAC_STATE_SRC_ADDR) != + (flags & IGC_MAC_STATE_SRC_ADDR)) + continue;
- return true; + return i; + } + + return -1; }
- /* Add a MAC filter for 'addr' directing matching traffic to 'queue', - * 'flags' is used to indicate what kind of match is made, match is by - * default for the destination address, if matching by source address - * is desired the flag IGC_MAC_STATE_SRC_ADDR can be used. - */ - static int igc_add_mac_filter(struct igc_adapter *adapter, - const u8 *addr, const u8 queue) + static int igc_get_avail_mac_filter_slot(struct igc_adapter *adapter) { - struct igc_hw *hw = &adapter->hw; - int rar_entries = hw->mac.rar_entry_count; + int max_entries = adapter->hw.mac.rar_entry_count; + struct igc_mac_addr *entry; int i;
- if (is_zero_ether_addr(addr)) + for (i = 0; i < max_entries; i++) { + entry = &adapter->mac_table[i]; + + if (!(entry->state & IGC_MAC_STATE_IN_USE)) + return i; + } + + return -1; + } + + /** + * igc_add_mac_filter() - Add MAC address filter + * @adapter: Pointer to adapter where the filter should be added + * @addr: MAC address + * @queue: If non-negative, queue assignment feature is enabled and frames + * matching the filter are enqueued onto 'queue'. Otherwise, queue + * assignment is disabled. + * @flags: Set IGC_MAC_STATE_SRC_ADDR bit to indicate @address is a source + * address + * + * Return: 0 in case of success, negative errno code otherwise. + */ + int igc_add_mac_filter(struct igc_adapter *adapter, const u8 *addr, + const s8 queue, const u8 flags) + { + struct net_device *dev = adapter->netdev; + int index; + + if (!is_valid_ether_addr(addr)) return -EINVAL; + if (flags & IGC_MAC_STATE_SRC_ADDR) + return -ENOTSUPP;
- /* Search for the first empty entry in the MAC table. - * Do not touch entries at the end of the table reserved for the VF MAC - * addresses. - */ - for (i = 0; i < rar_entries; i++) { - if (!igc_mac_entry_can_be_used(&adapter->mac_table[i], - addr, 0)) - continue; + index = igc_find_mac_filter(adapter, addr, flags); + if (index >= 0) + goto update_queue_assignment;
- ether_addr_copy(adapter->mac_table[i].addr, addr); - adapter->mac_table[i].queue = queue; - adapter->mac_table[i].state |= IGC_MAC_STATE_IN_USE; + index = igc_get_avail_mac_filter_slot(adapter); + if (index < 0) + return -ENOSPC;
- igc_rar_set_index(adapter, i); - return i; - } + netdev_dbg(dev, "Add MAC address filter: index %d address %pM queue %d", + index, addr, queue); + + ether_addr_copy(adapter->mac_table[index].addr, addr); + adapter->mac_table[index].state |= IGC_MAC_STATE_IN_USE | flags; + update_queue_assignment: + adapter->mac_table[index].queue = queue;
- return -ENOSPC; + igc_set_mac_filter_hw(adapter, index, addr, queue); + return 0; }
- /* Remove a MAC filter for 'addr' directing matching traffic to - * 'queue', 'flags' is used to indicate what kind of match need to be - * removed, match is by default for the destination address, if - * matching by source address is to be removed the flag - * IGC_MAC_STATE_SRC_ADDR can be used. + /** + * igc_del_mac_filter() - Delete MAC address filter + * @adapter: Pointer to adapter where the filter should be deleted from + * @addr: MAC address + * @flags: Set IGC_MAC_STATE_SRC_ADDR bit to indicate @address is a source + * address + * + * Return: 0 in case of success, negative errno code otherwise. */ - static int igc_del_mac_filter(struct igc_adapter *adapter, - const u8 *addr, const u8 queue) + int igc_del_mac_filter(struct igc_adapter *adapter, const u8 *addr, + const u8 flags) { - struct igc_hw *hw = &adapter->hw; - int rar_entries = hw->mac.rar_entry_count; - int i; + struct net_device *dev = adapter->netdev; + struct igc_mac_addr *entry; + int index;
- if (is_zero_ether_addr(addr)) + if (!is_valid_ether_addr(addr)) return -EINVAL;
- /* Search for matching entry in the MAC table based on given address - * and queue. Do not touch entries at the end of the table reserved - * for the VF MAC addresses. - */ - for (i = 0; i < rar_entries; i++) { - if (!(adapter->mac_table[i].state & IGC_MAC_STATE_IN_USE)) - continue; - if (adapter->mac_table[i].state != 0) - continue; - if (adapter->mac_table[i].queue != queue) - continue; - if (!ether_addr_equal(adapter->mac_table[i].addr, addr)) - continue; + index = igc_find_mac_filter(adapter, addr, flags); + if (index < 0) + return -ENOENT;
- /* When a filter for the default address is "deleted", - * we return it to its initial configuration + entry = &adapter->mac_table[index]; + + if (entry->state & IGC_MAC_STATE_DEFAULT) { + /* If this is the default filter, we don't actually delete it. + * We just reset to its default value i.e. disable queue + * assignment. */ - if (adapter->mac_table[i].state & IGC_MAC_STATE_DEFAULT) { - adapter->mac_table[i].state = - IGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE; - adapter->mac_table[i].queue = 0; - } else { - adapter->mac_table[i].state = 0; - adapter->mac_table[i].queue = 0; - memset(adapter->mac_table[i].addr, 0, ETH_ALEN); - } + netdev_dbg(dev, "Disable default MAC filter queue assignment");
- igc_rar_set_index(adapter, i); - return 0; + entry->queue = -1; + igc_set_mac_filter_hw(adapter, 0, addr, entry->queue); + } else { + netdev_dbg(dev, "Delete MAC address filter: index %d address %pM", + index, addr); + + entry->state = 0; + entry->queue = -1; + memset(entry->addr, 0, ETH_ALEN); + igc_clear_mac_filter_hw(adapter, index); }
- return -ENOENT; + return 0; }
static int igc_uc_sync(struct net_device *netdev, const unsigned char *addr) { struct igc_adapter *adapter = netdev_priv(netdev); - int ret;
- ret = igc_add_mac_filter(adapter, addr, adapter->num_rx_queues); - - return min_t(int, ret, 0); + return igc_add_mac_filter(adapter, addr, -1, 0); }
static int igc_uc_unsync(struct net_device *netdev, const unsigned char *addr) { struct igc_adapter *adapter = netdev_priv(netdev);
- igc_del_mac_filter(adapter, addr, adapter->num_rx_queues); - - return 0; + return igc_del_mac_filter(adapter, addr, 0); }
/** @@@ -2325,7 -2397,9 +2397,9 @@@ static void igc_configure(struct igc_ad igc_setup_mrqc(adapter); igc_setup_rctl(adapter);
+ igc_set_default_mac_filter(adapter); igc_nfc_filter_restore(adapter); + igc_configure_tx(adapter); igc_configure_rx(adapter);
@@@ -3458,9 -3532,6 +3532,6 @@@ static void igc_nfc_filter_exit(struct hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) igc_erase_filter(adapter, rule);
- hlist_for_each_entry(rule, &adapter->cls_flower_list, nfc_node) - igc_erase_filter(adapter, rule); - spin_unlock(&adapter->nfc_lock); }
@@@ -3689,106 -3760,6 +3760,6 @@@ igc_features_check(struct sk_buff *skb return features; }
- /* Add a MAC filter for 'addr' directing matching traffic to 'queue', - * 'flags' is used to indicate what kind of match is made, match is by - * default for the destination address, if matching by source address - * is desired the flag IGC_MAC_STATE_SRC_ADDR can be used. - */ - static int igc_add_mac_filter_flags(struct igc_adapter *adapter, - const u8 *addr, const u8 queue, - const u8 flags) - { - struct igc_hw *hw = &adapter->hw; - int rar_entries = hw->mac.rar_entry_count; - int i; - - if (is_zero_ether_addr(addr)) - return -EINVAL; - - /* Search for the first empty entry in the MAC table. - * Do not touch entries at the end of the table reserved for the VF MAC - * addresses. - */ - for (i = 0; i < rar_entries; i++) { - if (!igc_mac_entry_can_be_used(&adapter->mac_table[i], - addr, flags)) - continue; - - ether_addr_copy(adapter->mac_table[i].addr, addr); - adapter->mac_table[i].queue = queue; - adapter->mac_table[i].state |= IGC_MAC_STATE_IN_USE | flags; - - igc_rar_set_index(adapter, i); - return i; - } - - return -ENOSPC; - } - - int igc_add_mac_steering_filter(struct igc_adapter *adapter, - const u8 *addr, u8 queue, u8 flags) - { - return igc_add_mac_filter_flags(adapter, addr, queue, - IGC_MAC_STATE_QUEUE_STEERING | flags); - } - - /* Remove a MAC filter for 'addr' directing matching traffic to - * 'queue', 'flags' is used to indicate what kind of match need to be - * removed, match is by default for the destination address, if - * matching by source address is to be removed the flag - * IGC_MAC_STATE_SRC_ADDR can be used. - */ - static int igc_del_mac_filter_flags(struct igc_adapter *adapter, - const u8 *addr, const u8 queue, - const u8 flags) - { - struct igc_hw *hw = &adapter->hw; - int rar_entries = hw->mac.rar_entry_count; - int i; - - if (is_zero_ether_addr(addr)) - return -EINVAL; - - /* Search for matching entry in the MAC table based on given address - * and queue. Do not touch entries at the end of the table reserved - * for the VF MAC addresses. - */ - for (i = 0; i < rar_entries; i++) { - if (!(adapter->mac_table[i].state & IGC_MAC_STATE_IN_USE)) - continue; - if ((adapter->mac_table[i].state & flags) != flags) - continue; - if (adapter->mac_table[i].queue != queue) - continue; - if (!ether_addr_equal(adapter->mac_table[i].addr, addr)) - continue; - - /* When a filter for the default address is "deleted", - * we return it to its initial configuration - */ - if (adapter->mac_table[i].state & IGC_MAC_STATE_DEFAULT) { - adapter->mac_table[i].state = - IGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE; - } else { - adapter->mac_table[i].state = 0; - adapter->mac_table[i].queue = 0; - memset(adapter->mac_table[i].addr, 0, ETH_ALEN); - } - - igc_rar_set_index(adapter, i); - return 0; - } - - return -ENOENT; - } - - int igc_del_mac_steering_filter(struct igc_adapter *adapter, - const u8 *addr, u8 queue, u8 flags) - { - return igc_del_mac_filter_flags(adapter, addr, queue, - IGC_MAC_STATE_QUEUE_STEERING | flags); - } - static void igc_tsync_interrupt(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; @@@ -4009,7 -3980,6 +3980,6 @@@ static void igc_watchdog_task(struct wo struct igc_hw *hw = &adapter->hw; struct igc_phy_info *phy = &hw->phy; u16 phy_data, retry_count = 20; - u32 connsw; u32 link; int i;
@@@ -4022,14 -3992,6 +3992,6 @@@ link = false; }
- /* Force link down if we have fiber to swap to */ - if (adapter->flags & IGC_FLAG_MAS_ENABLE) { - if (hw->phy.media_type == igc_media_type_copper) { - connsw = rd32(IGC_CONNSW); - if (!(connsw & IGC_CONNSW_AUTOSENSE_EN)) - link = 0; - } - } if (link) { /* Cancel scheduled suspend requests. */ pm_runtime_resume(netdev->dev.parent); @@@ -4491,6 -4453,158 +4453,158 @@@ static int igc_ioctl(struct net_device } }
+ static int igc_save_launchtime_params(struct igc_adapter *adapter, int queue, + bool enable) + { + struct igc_ring *ring; + int i; + + if (queue < 0 || queue >= adapter->num_tx_queues) + return -EINVAL; + + ring = adapter->tx_ring[queue]; + ring->launchtime_enable = enable; + + if (adapter->base_time) + return 0; + + adapter->cycle_time = NSEC_PER_SEC; + + for (i = 0; i < adapter->num_tx_queues; i++) { + ring = adapter->tx_ring[i]; + ring->start_time = 0; + ring->end_time = NSEC_PER_SEC; + } + + return 0; + } + + static bool validate_schedule(const struct tc_taprio_qopt_offload *qopt) + { + int queue_uses[IGC_MAX_TX_QUEUES] = { }; + size_t n; + + if (qopt->cycle_time_extension) + return false; + + for (n = 0; n < qopt->num_entries; n++) { + const struct tc_taprio_sched_entry *e; + int i; + + e = &qopt->entries[n]; + + /* i225 only supports "global" frame preemption + * settings. + */ + if (e->command != TC_TAPRIO_CMD_SET_GATES) + return false; + + for (i = 0; i < IGC_MAX_TX_QUEUES; i++) { + if (e->gate_mask & BIT(i)) + queue_uses[i]++; + + if (queue_uses[i] > 1) + return false; + } + } + + return true; + } + + static int igc_tsn_enable_launchtime(struct igc_adapter *adapter, + struct tc_etf_qopt_offload *qopt) + { + struct igc_hw *hw = &adapter->hw; + int err; + + if (hw->mac.type != igc_i225) + return -EOPNOTSUPP; + + err = igc_save_launchtime_params(adapter, qopt->queue, qopt->enable); + if (err) + return err; + + return igc_tsn_offload_apply(adapter); + } + + static int igc_save_qbv_schedule(struct igc_adapter *adapter, + struct tc_taprio_qopt_offload *qopt) + { + u32 start_time = 0, end_time = 0; + size_t n; + + if (!qopt->enable) { + adapter->base_time = 0; + return 0; + } + + if (adapter->base_time) + return -EALREADY; + + if (!validate_schedule(qopt)) + return -EINVAL; + + adapter->cycle_time = qopt->cycle_time; + adapter->base_time = qopt->base_time; + + /* FIXME: be a little smarter about cases when the gate for a + * queue stays open for more than one entry. + */ + for (n = 0; n < qopt->num_entries; n++) { + struct tc_taprio_sched_entry *e = &qopt->entries[n]; + int i; + + end_time += e->interval; + + for (i = 0; i < IGC_MAX_TX_QUEUES; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + + if (!(e->gate_mask & BIT(i))) + continue; + + ring->start_time = start_time; + ring->end_time = end_time; + } + + start_time += e->interval; + } + + return 0; + } + + static int igc_tsn_enable_qbv_scheduling(struct igc_adapter *adapter, + struct tc_taprio_qopt_offload *qopt) + { + struct igc_hw *hw = &adapter->hw; + int err; + + if (hw->mac.type != igc_i225) + return -EOPNOTSUPP; + + err = igc_save_qbv_schedule(adapter, qopt); + if (err) + return err; + + return igc_tsn_offload_apply(adapter); + } + + static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data) + { + struct igc_adapter *adapter = netdev_priv(dev); + + switch (type) { + case TC_SETUP_QDISC_TAPRIO: + return igc_tsn_enable_qbv_scheduling(adapter, type_data); + + case TC_SETUP_QDISC_ETF: + return igc_tsn_enable_launchtime(adapter, type_data); + + default: + return -EOPNOTSUPP; + } + } + static const struct net_device_ops igc_netdev_ops = { .ndo_open = igc_open, .ndo_stop = igc_close, @@@ -4503,6 -4617,7 +4617,7 @@@ .ndo_set_features = igc_set_features, .ndo_features_check = igc_features_check, .ndo_do_ioctl = igc_ioctl, + .ndo_setup_tc = igc_setup_tc, };
/* PCIe configuration access */ @@@ -4726,6 -4841,17 +4841,17 @@@ static int igc_probe(struct pci_dev *pd netdev->features |= NETIF_F_RXCSUM; netdev->features |= NETIF_F_HW_CSUM; netdev->features |= NETIF_F_SCTP_CRC; + netdev->features |= NETIF_F_HW_TC; + + #define IGC_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \ + NETIF_F_GSO_GRE_CSUM | \ + NETIF_F_GSO_IPXIP4 | \ + NETIF_F_GSO_IPXIP6 | \ + NETIF_F_GSO_UDP_TUNNEL | \ + NETIF_F_GSO_UDP_TUNNEL_CSUM) + + netdev->gso_partial_features = IGC_GSO_PARTIAL_FEATURES; + netdev->features |= NETIF_F_GSO_PARTIAL | IGC_GSO_PARTIAL_FEATURES;
/* setup the private structure */ err = igc_sw_init(adapter); @@@ -4825,7 -4951,7 +4951,7 @@@ pcie_print_link_status(pdev); netdev_info(netdev, "MAC: %pM\n", netdev->dev_addr);
- dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP); + dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
pm_runtime_put_noidle(&pdev->dev);
diff --combined drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index f372e94948fd,2de54d865dc8..1eac7a53d56f --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@@ -1773,14 -1773,19 +1773,14 @@@ static void mlx5e_cleanup_rep_rx(struc
static int mlx5e_init_ul_rep_rx(struct mlx5e_priv *priv) { - int err = mlx5e_init_rep_rx(priv); - - if (err) - return err; - mlx5e_create_q_counters(priv); - return 0; + return mlx5e_init_rep_rx(priv); }
static void mlx5e_cleanup_ul_rep_rx(struct mlx5e_priv *priv) { - mlx5e_destroy_q_counters(priv); mlx5e_cleanup_rep_rx(priv); + mlx5e_destroy_q_counters(priv); }
static int mlx5e_init_uplink_rep_tx(struct mlx5e_rep_priv *rpriv) @@@ -2051,26 -2056,22 +2051,22 @@@ static int register_devlink_port(struc return 0;
mlx5e_rep_get_port_parent_id(rpriv->netdev, &ppid); + dl_port_index = vport_to_devlink_port_index(dev, rep->vport); pfnum = PCI_FUNC(dev->pdev->devfn);
- if (rep->vport == MLX5_VPORT_UPLINK) { + if (rep->vport == MLX5_VPORT_UPLINK) devlink_port_attrs_set(&rpriv->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, pfnum, false, 0, &ppid.id[0], ppid.id_len); - dl_port_index = vport_to_devlink_port_index(dev, rep->vport); - } else if (rep->vport == MLX5_VPORT_PF) { + else if (rep->vport == MLX5_VPORT_PF) devlink_port_attrs_pci_pf_set(&rpriv->dl_port, &ppid.id[0], ppid.id_len, pfnum); - dl_port_index = rep->vport; - } else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch, - rpriv->rep->vport)) { + else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch, rpriv->rep->vport)) devlink_port_attrs_pci_vf_set(&rpriv->dl_port, &ppid.id[0], ppid.id_len, pfnum, rep->vport - 1); - dl_port_index = vport_to_devlink_port_index(dev, rep->vport); - }
return devlink_port_register(devlink, &rpriv->dl_port, dl_port_index); } diff --combined drivers/net/ethernet/moxa/moxart_ether.c index f70bb81e1ed6,1b25cc42f442..49fd843c4c8a --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@@ -331,14 -331,15 +331,15 @@@ static irqreturn_t moxart_mac_interrupt return IRQ_HANDLED; }
- static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) + static netdev_tx_t moxart_mac_start_xmit(struct sk_buff *skb, + struct net_device *ndev) { struct moxart_mac_priv_t *priv = netdev_priv(ndev); void *desc; unsigned int len; unsigned int tx_head; u32 txdes1; - int ret = NETDEV_TX_BUSY; + netdev_tx_t ret = NETDEV_TX_BUSY;
spin_lock_irq(&priv->txlock);
@@@ -564,7 -565,7 +565,7 @@@ static int moxart_remove(struct platfor struct net_device *ndev = platform_get_drvdata(pdev);
unregister_netdev(ndev); - free_irq(ndev->irq, ndev); + devm_free_irq(&pdev->dev, ndev->irq, ndev); moxart_mac_free_memory(ndev); free_netdev(ndev);
diff --combined drivers/net/ethernet/smsc/Kconfig index 64ca1b36b91e,4d2d91ec8b41..4fcc5858a750 --- a/drivers/net/ethernet/smsc/Kconfig +++ b/drivers/net/ethernet/smsc/Kconfig @@@ -28,7 -28,7 +28,7 @@@ config SMC919 option if you have a DELL laptop with the docking station, or another SMC9192/9194 based chipset. Say Y if you want it compiled into the kernel, and read the file - file:Documentation/networking/device_drivers/smsc/smc9.txt. + file:Documentation/networking/device_drivers/smsc/smc9.rst.
To compile this driver as a module, choose M here. The module will be called smc9194. @@@ -37,13 -37,14 +37,13 @@@ config SMC91 tristate "SMC 91C9x/91C1xxx support" select CRC32 select MII - depends on !OF || GPIOLIB depends on ARM || ARM64 || ATARI_ETHERNAT || COLDFIRE || \ MIPS || NIOS2 || SUPERH || XTENSA || H8300 ---help--- This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it compiled into the kernel, and read the file - file:Documentation/networking/device_drivers/smsc/smc9.txt. + file:Documentation/networking/device_drivers/smsc/smc9.rst.
This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). diff --combined drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a999d6b33a64,90bddca1ddd8..8f08393f25dd --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@@ -3543,15 -3543,6 +3543,6 @@@ static void stmmac_rx_vlan(struct net_d } }
- - static inline int stmmac_rx_threshold_count(struct stmmac_rx_queue *rx_q) - { - if (rx_q->rx_zeroc_thresh < STMMAC_RX_THRESH) - return 0; - - return 1; - } - /** * stmmac_rx_refill - refill used skb preallocated buffers * @priv: driver private structure @@@ -4060,7 -4051,7 +4051,7 @@@ static int stmmac_set_features(struct n /** * stmmac_interrupt - main ISR * @irq: interrupt number. - * @dev_id: to pass the net device pointer. + * @dev_id: to pass the net device pointer (must be valid). * Description: this is the main driver interrupt service routine. * It can call: * o DMA service routine (to manage incoming frame reception and transmission @@@ -4084,6 -4075,11 +4075,6 @@@ static irqreturn_t stmmac_interrupt(in if (priv->irq_wake) pm_wakeup_event(priv->device, 0);
- if (unlikely(!dev)) { - netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__); - return IRQ_NONE; - } - /* Check if adapter is up */ if (test_bit(STMMAC_DOWN, &priv->state)) return IRQ_HANDLED; diff --combined drivers/net/ethernet/ti/Kconfig index 8e348780efb6,519f5a8c5810..988e907e3322 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@@ -90,8 -90,9 +90,8 @@@ config TI_CPT config TI_CPTS_MOD tristate depends on TI_CPTS + depends on PTP_1588_CLOCK default y if TI_CPSW=y || TI_KEYSTONE_NETCP=y || TI_CPSW_SWITCHDEV=y - select NET_PTP_CLASSIFY - imply PTP_1588_CLOCK default m
config TI_K3_AM65_CPSW_NUSS @@@ -99,6 -100,7 +99,7 @@@ depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER select TI_DAVINCI_MDIO imply PHY_TI_GMII_SEL + depends on TI_K3_AM65_CPTS || !TI_K3_AM65_CPTS help This driver supports TI K3 AM654/J721E CPSW2G Ethernet SubSystem. The two-port Gigabit Ethernet MAC (MCU_CPSW0) subsystem provides @@@ -109,6 -111,19 +110,19 @@@ To compile this driver as a module, choose M here: the module will be called ti-am65-cpsw-nuss.
+ config TI_K3_AM65_CPTS + tristate "TI K3 AM65x CPTS" + depends on ARCH_K3 && OF + depends on PTP_1588_CLOCK + help + Say y here to support the TI K3 AM65x CPTS with 1588 features such as + PTP hardware clock for each CPTS device and network packets + timestamping where applicable. + Depending on integration CPTS blocks enable compliance with + the IEEE 1588-2008 standard for a precision clock synchronization + protocol, Ethernet Enhanced Scheduled Traffic Operations (CPTS_ESTFn) + and PCIe Subsystem Precision Time Measurement (PTM). + config TI_KEYSTONE_NETCP tristate "TI Keystone NETCP Core Support" select TI_DAVINCI_MDIO @@@ -137,7 -152,7 +151,7 @@@ config TLA
Devices currently supported by this driver are Compaq Netelligent, Compaq NetFlex and Olicom cards. Please read the file - file:Documentation/networking/device_drivers/ti/tlan.txt + file:Documentation/networking/device_drivers/ti/tlan.rst for more details.
To compile this driver as a module, choose M here. The module diff --combined drivers/net/hyperv/netvsc_drv.c index ebcfbae05690,c0b647a4c893..5de57fc3ec60 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@@ -707,8 -707,7 +707,8 @@@ no_memory goto drop; }
-static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *ndev) +static netdev_tx_t netvsc_start_xmit(struct sk_buff *skb, + struct net_device *ndev) { return netvsc_xmit(skb, ndev, false); } @@@ -2457,6 -2456,8 +2457,8 @@@ static int netvsc_probe(struct hv_devic NETIF_F_HW_VLAN_CTAG_RX; net->vlan_features = net->features;
+ netdev_lockdep_set_classes(net); + /* MTU range: 68 - 1500 or 65521 */ net->min_mtu = NETVSC_MTU_MIN; if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) diff --combined drivers/net/ipa/gsi.c index b671bea0aa7c,8ccbbb920c11..66570609c845 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@@ -415,13 -415,14 +415,14 @@@ static void gsi_evt_ring_de_alloc_comma evt_ring->state); }
- /* Return the hardware's notion of the current state of a channel */ - static enum gsi_channel_state - gsi_channel_state(struct gsi *gsi, u32 channel_id) + /* Fetch the current state of a channel from hardware */ + static enum gsi_channel_state gsi_channel_state(struct gsi_channel *channel) { + u32 channel_id = gsi_channel_id(channel); + void *virt = channel->gsi->virt; u32 val;
- val = ioread32(gsi->virt + GSI_CH_C_CNTXT_0_OFFSET(channel_id)); + val = ioread32(virt + GSI_CH_C_CNTXT_0_OFFSET(channel_id));
return u32_get_bits(val, CHSTATE_FMASK); } @@@ -432,16 -433,18 +433,18 @@@ gsi_channel_command(struct gsi_channel { struct completion *completion = &channel->completion; u32 channel_id = gsi_channel_id(channel); + struct gsi *gsi = channel->gsi; u32 val;
val = u32_encode_bits(channel_id, CH_CHID_FMASK); val |= u32_encode_bits(opcode, CH_OPCODE_FMASK);
- if (gsi_command(channel->gsi, GSI_CH_CMD_OFFSET, val, completion)) + if (gsi_command(gsi, GSI_CH_CMD_OFFSET, val, completion)) return 0; /* Success! */
- dev_err(channel->gsi->dev, "GSI command %u to channel %u timed out " - "(state is %u)\n", opcode, channel_id, channel->state); + dev_err(gsi->dev, + "GSI command %u to channel %u timed out (state is %u)\n", + opcode, channel_id, gsi_channel_state(channel));
return -ETIMEDOUT; } @@@ -450,18 -453,21 +453,21 @@@ static int gsi_channel_alloc_command(struct gsi *gsi, u32 channel_id) { struct gsi_channel *channel = &gsi->channel[channel_id]; + enum gsi_channel_state state; int ret;
/* Get initial channel state */ - channel->state = gsi_channel_state(gsi, channel_id); - - if (channel->state != GSI_CHANNEL_STATE_NOT_ALLOCATED) + state = gsi_channel_state(channel); + if (state != GSI_CHANNEL_STATE_NOT_ALLOCATED) return -EINVAL;
ret = gsi_channel_command(channel, GSI_CH_ALLOCATE); - if (!ret && channel->state != GSI_CHANNEL_STATE_ALLOCATED) { + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (!ret && state != GSI_CHANNEL_STATE_ALLOCATED) { dev_err(gsi->dev, "bad channel state (%u) after alloc\n", - channel->state); + state); ret = -EIO; }
@@@ -471,18 -477,21 +477,21 @@@ /* Start an ALLOCATED channel */ static int gsi_channel_start_command(struct gsi_channel *channel) { - enum gsi_channel_state state = channel->state; + enum gsi_channel_state state; int ret;
+ state = gsi_channel_state(channel); if (state != GSI_CHANNEL_STATE_ALLOCATED && state != GSI_CHANNEL_STATE_STOPPED) return -EINVAL;
ret = gsi_channel_command(channel, GSI_CH_START); - if (!ret && channel->state != GSI_CHANNEL_STATE_STARTED) { + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (!ret && state != GSI_CHANNEL_STATE_STARTED) { dev_err(channel->gsi->dev, - "bad channel state (%u) after start\n", - channel->state); + "bad channel state (%u) after start\n", state); ret = -EIO; }
@@@ -492,23 -501,27 +501,27 @@@ /* Stop a GSI channel in STARTED state */ static int gsi_channel_stop_command(struct gsi_channel *channel) { - enum gsi_channel_state state = channel->state; + enum gsi_channel_state state; int ret;
+ state = gsi_channel_state(channel); if (state != GSI_CHANNEL_STATE_STARTED && state != GSI_CHANNEL_STATE_STOP_IN_PROC) return -EINVAL;
ret = gsi_channel_command(channel, GSI_CH_STOP); - if (ret || channel->state == GSI_CHANNEL_STATE_STOPPED) + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (ret || state == GSI_CHANNEL_STATE_STOPPED) return ret;
/* We may have to try again if stop is in progress */ - if (channel->state == GSI_CHANNEL_STATE_STOP_IN_PROC) + if (state == GSI_CHANNEL_STATE_STOP_IN_PROC) return -EAGAIN;
- dev_err(channel->gsi->dev, "bad channel state (%u) after stop\n", - channel->state); + dev_err(channel->gsi->dev, + "bad channel state (%u) after stop\n", state);
return -EIO; } @@@ -516,41 -529,49 +529,49 @@@ /* Reset a GSI channel in ALLOCATED or ERROR state. */ static void gsi_channel_reset_command(struct gsi_channel *channel) { + enum gsi_channel_state state; int ret;
msleep(1); /* A short delay is required before a RESET command */
- if (channel->state != GSI_CHANNEL_STATE_STOPPED && - channel->state != GSI_CHANNEL_STATE_ERROR) { + state = gsi_channel_state(channel); + if (state != GSI_CHANNEL_STATE_STOPPED && + state != GSI_CHANNEL_STATE_ERROR) { dev_err(channel->gsi->dev, - "bad channel state (%u) before reset\n", - channel->state); + "bad channel state (%u) before reset\n", state); return; }
ret = gsi_channel_command(channel, GSI_CH_RESET); - if (!ret && channel->state != GSI_CHANNEL_STATE_ALLOCATED) + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (!ret && state != GSI_CHANNEL_STATE_ALLOCATED) dev_err(channel->gsi->dev, - "bad channel state (%u) after reset\n", - channel->state); + "bad channel state (%u) after reset\n", state); }
/* Deallocate an ALLOCATED GSI channel */ static void gsi_channel_de_alloc_command(struct gsi *gsi, u32 channel_id) { struct gsi_channel *channel = &gsi->channel[channel_id]; + enum gsi_channel_state state; int ret;
- if (channel->state != GSI_CHANNEL_STATE_ALLOCATED) { - dev_err(gsi->dev, "bad channel state (%u) before dealloc\n", - channel->state); + state = gsi_channel_state(channel); + if (state != GSI_CHANNEL_STATE_ALLOCATED) { + dev_err(gsi->dev, + "bad channel state (%u) before dealloc\n", state); return; }
ret = gsi_channel_command(channel, GSI_CH_DE_ALLOC); - if (!ret && channel->state != GSI_CHANNEL_STATE_NOT_ALLOCATED) - dev_err(gsi->dev, "bad channel state (%u) after dealloc\n", - channel->state); + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (!ret && state != GSI_CHANNEL_STATE_NOT_ALLOCATED) + dev_err(gsi->dev, + "bad channel state (%u) after dealloc\n", state); }
/* Ring an event ring doorbell, reporting the last entry processed by the AP. @@@ -777,6 -798,7 +798,7 @@@ int gsi_channel_start(struct gsi *gsi, int gsi_channel_stop(struct gsi *gsi, u32 channel_id) { struct gsi_channel *channel = &gsi->channel[channel_id]; + enum gsi_channel_state state; u32 retries; int ret;
@@@ -786,7 -808,8 +808,8 @@@ * STOP command timed out. We won't stop a channel if stopping it * was successful previously (so we still want the freeze above). */ - if (channel->state == GSI_CHANNEL_STATE_STOPPED) + state = gsi_channel_state(channel); + if (state == GSI_CHANNEL_STATE_STOPPED) return 0;
/* RX channels might require a little time to enter STOPPED state */ @@@ -811,18 -834,18 +834,18 @@@ }
/* Reset and reconfigure a channel (possibly leaving doorbell disabled) */ - void gsi_channel_reset(struct gsi *gsi, u32 channel_id, bool db_enable) + void gsi_channel_reset(struct gsi *gsi, u32 channel_id, bool legacy) { struct gsi_channel *channel = &gsi->channel[channel_id];
mutex_lock(&gsi->mutex);
- /* Due to a hardware quirk we need to reset RX channels twice. */ gsi_channel_reset_command(channel); - if (!channel->toward_ipa) + /* Due to a hardware quirk we may need to reset RX channels twice. */ + if (legacy && !channel->toward_ipa) gsi_channel_reset_command(channel);
- gsi_channel_program(channel, db_enable); + gsi_channel_program(channel, legacy); gsi_channel_trans_cancel_pending(channel);
mutex_unlock(&gsi->mutex); @@@ -940,7 -963,6 +963,6 @@@ static void gsi_isr_chan_ctrl(struct gs channel_mask ^= BIT(channel_id);
channel = &gsi->channel[channel_id]; - channel->state = gsi_channel_state(gsi, channel_id);
complete(&channel->completion); } @@@ -1041,7 -1063,6 +1063,7 @@@ static void gsi_isr_gp_int1(struct gsi
complete(&gsi->completion); } + /* Inter-EE interrupt handler */ static void gsi_isr_glob_ee(struct gsi *gsi) { @@@ -1434,7 -1455,7 +1456,7 @@@ static void gsi_evt_ring_teardown(struc
/* Setup function for a single channel */ static int gsi_channel_setup_one(struct gsi *gsi, u32 channel_id, - bool db_enable) + bool legacy) { struct gsi_channel *channel = &gsi->channel[channel_id]; u32 evt_ring_id = channel->evt_ring_id; @@@ -1453,7 -1474,7 +1475,7 @@@ if (ret) goto err_evt_ring_de_alloc;
- gsi_channel_program(channel, db_enable); + gsi_channel_program(channel, legacy);
if (channel->toward_ipa) netif_tx_napi_add(&gsi->dummy_dev, &channel->napi, @@@ -1494,12 -1515,6 +1516,12 @@@ static int gsi_generic_command(struct g struct completion *completion = &gsi->completion; u32 val;
+ /* First zero the result code field */ + val = ioread32(gsi->virt + GSI_CNTXT_SCRATCH_0_OFFSET); + val &= ~GENERIC_EE_RESULT_FMASK; + iowrite32(val, gsi->virt + GSI_CNTXT_SCRATCH_0_OFFSET); + + /* Now issue the command */ val = u32_encode_bits(opcode, GENERIC_OPCODE_FMASK); val |= u32_encode_bits(channel_id, GENERIC_CHID_FMASK); val |= u32_encode_bits(GSI_EE_MODEM, GENERIC_EE_FMASK); @@@ -1530,7 -1545,7 +1552,7 @@@ static void gsi_modem_channel_halt(stru }
/* Setup function for channels */ - static int gsi_channel_setup(struct gsi *gsi, bool db_enable) + static int gsi_channel_setup(struct gsi *gsi, bool legacy) { u32 channel_id = 0; u32 mask; @@@ -1542,7 -1557,7 +1564,7 @@@ mutex_lock(&gsi->mutex);
do { - ret = gsi_channel_setup_one(gsi, channel_id, db_enable); + ret = gsi_channel_setup_one(gsi, channel_id, legacy); if (ret) goto err_unwind; } while (++channel_id < gsi->channel_count); @@@ -1628,7 -1643,7 +1650,7 @@@ static void gsi_channel_teardown(struc }
/* Setup function for GSI. GSI firmware must be loaded and initialized */ - int gsi_setup(struct gsi *gsi, bool db_enable) + int gsi_setup(struct gsi *gsi, bool legacy) { u32 val;
@@@ -1671,7 -1686,7 +1693,7 @@@ /* Writing 1 indicates IRQ interrupts; 0 would be MSI */ iowrite32(1, gsi->virt + GSI_CNTXT_INTSET_OFFSET);
- return gsi_channel_setup(gsi, db_enable); + return gsi_channel_setup(gsi, legacy); }
/* Inverse of gsi_setup() */ @@@ -1805,9 -1820,9 +1827,9 @@@ static int gsi_channel_init_one(struct
/* Worst case we need an event for every outstanding TRE */ if (data->channel.tre_count > data->channel.event_count) { - dev_warn(gsi->dev, "channel %u limited to %u TREs\n", - data->channel_id, data->channel.tre_count); tre_count = data->channel.event_count; + dev_warn(gsi->dev, "channel %u limited to %u TREs\n", + data->channel_id, tre_count); } else { tre_count = data->channel.tre_count; } diff --combined drivers/net/macsec.c index d0d31cb99180,ea3f25cc79ef..20b53e255f68 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@@ -1305,8 -1305,7 +1305,8 @@@ static struct crypto_aead *macsec_alloc struct crypto_aead *tfm; int ret;
- tfm = crypto_alloc_aead("gcm(aes)", 0, 0); + /* Pick a sync gcm(aes) cipher to ensure order is preserved. */ + tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) return tfm; @@@ -2641,12 -2640,11 +2641,12 @@@ static int macsec_upd_offload(struct sk if (ret) goto rollback;
- rtnl_unlock(); /* Force features update, since they are different for SW MACSec and * HW offloading cases. */ netdev_update_features(dev); + + rtnl_unlock(); return 0;
rollback: @@@ -4049,6 -4047,8 +4049,8 @@@ static int macsec_newlink(struct net *n if (err < 0) return err;
+ netdev_lockdep_set_classes(dev); + err = netdev_upper_dev_link(real_dev, dev, extack); if (err < 0) goto unregister; diff --combined drivers/net/phy/marvell10g.c index 1f1a01c98e44,8352c09004c7..d4c2e62b2439 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@@ -66,9 -66,6 +66,9 @@@ enum MV_PCS_CSSR1_SPD2_2500 = 0x0004, MV_PCS_CSSR1_SPD2_10000 = 0x0000,
+ /* Temperature read register (88E2110 only) */ + MV_PCS_TEMP = 0x8042, + /* These registers appear at 0x800X and 0xa00X - the 0xa00X control * registers appear to set themselves to the 0x800X when AN is * restarted, but status registers appear readable from either. @@@ -80,7 -77,6 +80,7 @@@ MV_V2_PORT_CTRL = 0xf001, MV_V2_PORT_CTRL_SWRST = BIT(15), MV_V2_PORT_CTRL_PWRDOWN = BIT(11), + /* Temperature control/read registers (88X3310 only) */ MV_V2_TEMP_CTRL = 0xf08a, MV_V2_TEMP_CTRL_MASK = 0xc000, MV_V2_TEMP_CTRL_SAMPLE = 0x0000, @@@ -108,24 -104,6 +108,24 @@@ static umode_t mv3310_hwmon_is_visible( return 0; }
+static int mv3310_hwmon_read_temp_reg(struct phy_device *phydev) +{ + return phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP); +} + +static int mv2110_hwmon_read_temp_reg(struct phy_device *phydev) +{ + return phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_TEMP); +} + +static int mv10g_hwmon_read_temp_reg(struct phy_device *phydev) +{ + if (phydev->drv->phy_id == MARVELL_PHY_ID_88X3310) + return mv3310_hwmon_read_temp_reg(phydev); + else /* MARVELL_PHY_ID_88E2110 */ + return mv2110_hwmon_read_temp_reg(phydev); +} + static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *value) { @@@ -138,7 -116,7 +138,7 @@@ }
if (type == hwmon_temp && attr == hwmon_temp_input) { - temp = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP); + temp = mv10g_hwmon_read_temp_reg(phydev); if (temp < 0) return temp;
@@@ -191,9 -169,6 +191,9 @@@ static int mv3310_hwmon_config(struct p u16 val; int ret;
+ if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310) + return 0; + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP, MV_V2_TEMP_UNKNOWN); if (ret < 0) @@@ -753,7 -728,6 +753,6 @@@ static struct phy_driver mv3310_drivers .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "mv88x3310", .get_features = mv3310_get_features, - .soft_reset = genphy_no_soft_reset, .config_init = mv3310_config_init, .probe = mv3310_probe, .suspend = mv3310_suspend, @@@ -771,7 -745,6 +770,6 @@@ .probe = mv3310_probe, .suspend = mv3310_suspend, .resume = mv3310_resume, - .soft_reset = genphy_no_soft_reset, .config_init = mv3310_config_init, .config_aneg = mv3310_config_aneg, .aneg_done = mv3310_aneg_done, diff --combined drivers/s390/net/qeth_core_main.c index 569966bdc513,c0ab6e7bc129..db8e069be3a0 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@@ -26,6 -26,7 +26,7 @@@ #include <linux/if_vlan.h> #include <linux/netdevice.h> #include <linux/netdev_features.h> + #include <linux/rcutree.h> #include <linux/skbuff.h> #include <linux/vmalloc.h>
@@@ -60,6 -61,7 +61,7 @@@ EXPORT_SYMBOL_GPL(qeth_core_header_cach static struct kmem_cache *qeth_qdio_outbuf_cache;
static struct device *qeth_core_root_dev; + static struct dentry *qeth_debugfs_root; static struct lock_class_key qdio_out_skb_queue_key;
static void qeth_issue_next_read_cb(struct qeth_card *card, @@@ -623,6 -625,257 +625,257 @@@ void qeth_notify_cmd(struct qeth_cmd_bu } EXPORT_SYMBOL_GPL(qeth_notify_cmd);
+ static void qeth_flush_local_addrs4(struct qeth_card *card) + { + struct qeth_local_addr *addr; + struct hlist_node *tmp; + unsigned int i; + + spin_lock_irq(&card->local_addrs4_lock); + hash_for_each_safe(card->local_addrs4, i, tmp, addr, hnode) { + hash_del_rcu(&addr->hnode); + kfree_rcu(addr, rcu); + } + spin_unlock_irq(&card->local_addrs4_lock); + } + + static void qeth_flush_local_addrs6(struct qeth_card *card) + { + struct qeth_local_addr *addr; + struct hlist_node *tmp; + unsigned int i; + + spin_lock_irq(&card->local_addrs6_lock); + hash_for_each_safe(card->local_addrs6, i, tmp, addr, hnode) { + hash_del_rcu(&addr->hnode); + kfree_rcu(addr, rcu); + } + spin_unlock_irq(&card->local_addrs6_lock); + } + + void qeth_flush_local_addrs(struct qeth_card *card) + { + qeth_flush_local_addrs4(card); + qeth_flush_local_addrs6(card); + } + EXPORT_SYMBOL_GPL(qeth_flush_local_addrs); + + static void qeth_add_local_addrs4(struct qeth_card *card, + struct qeth_ipacmd_local_addrs4 *cmd) + { + unsigned int i; + + if (cmd->addr_length != + sizeof_field(struct qeth_ipacmd_local_addr4, addr)) { + dev_err_ratelimited(&card->gdev->dev, + "Dropped IPv4 ADD LOCAL ADDR event with bad length %u\n", + cmd->addr_length); + return; + } + + spin_lock(&card->local_addrs4_lock); + for (i = 0; i < cmd->count; i++) { + unsigned int key = ipv4_addr_hash(cmd->addrs[i].addr); + struct qeth_local_addr *addr; + bool duplicate = false; + + hash_for_each_possible(card->local_addrs4, addr, hnode, key) { + if (addr->addr.s6_addr32[3] == cmd->addrs[i].addr) { + duplicate = true; + break; + } + } + + if (duplicate) + continue; + + addr = kmalloc(sizeof(*addr), GFP_ATOMIC); + if (!addr) { + dev_err(&card->gdev->dev, + "Failed to allocate local addr object. Traffic to %pI4 might suffer.\n", + &cmd->addrs[i].addr); + continue; + } + + ipv6_addr_set(&addr->addr, 0, 0, 0, cmd->addrs[i].addr); + hash_add_rcu(card->local_addrs4, &addr->hnode, key); + } + spin_unlock(&card->local_addrs4_lock); + } + + static void qeth_add_local_addrs6(struct qeth_card *card, + struct qeth_ipacmd_local_addrs6 *cmd) + { + unsigned int i; + + if (cmd->addr_length != + sizeof_field(struct qeth_ipacmd_local_addr6, addr)) { + dev_err_ratelimited(&card->gdev->dev, + "Dropped IPv6 ADD LOCAL ADDR event with bad length %u\n", + cmd->addr_length); + return; + } + + spin_lock(&card->local_addrs6_lock); + for (i = 0; i < cmd->count; i++) { + u32 key = ipv6_addr_hash(&cmd->addrs[i].addr); + struct qeth_local_addr *addr; + bool duplicate = false; + + hash_for_each_possible(card->local_addrs6, addr, hnode, key) { + if (ipv6_addr_equal(&addr->addr, &cmd->addrs[i].addr)) { + duplicate = true; + break; + } + } + + if (duplicate) + continue; + + addr = kmalloc(sizeof(*addr), GFP_ATOMIC); + if (!addr) { + dev_err(&card->gdev->dev, + "Failed to allocate local addr object. Traffic to %pI6c might suffer.\n", + &cmd->addrs[i].addr); + continue; + } + + addr->addr = cmd->addrs[i].addr; + hash_add_rcu(card->local_addrs6, &addr->hnode, key); + } + spin_unlock(&card->local_addrs6_lock); + } + + static void qeth_del_local_addrs4(struct qeth_card *card, + struct qeth_ipacmd_local_addrs4 *cmd) + { + unsigned int i; + + if (cmd->addr_length != + sizeof_field(struct qeth_ipacmd_local_addr4, addr)) { + dev_err_ratelimited(&card->gdev->dev, + "Dropped IPv4 DEL LOCAL ADDR event with bad length %u\n", + cmd->addr_length); + return; + } + + spin_lock(&card->local_addrs4_lock); + for (i = 0; i < cmd->count; i++) { + struct qeth_ipacmd_local_addr4 *addr = &cmd->addrs[i]; + unsigned int key = ipv4_addr_hash(addr->addr); + struct qeth_local_addr *tmp; + + hash_for_each_possible(card->local_addrs4, tmp, hnode, key) { + if (tmp->addr.s6_addr32[3] == addr->addr) { + hash_del_rcu(&tmp->hnode); + kfree_rcu(tmp, rcu); + break; + } + } + } + spin_unlock(&card->local_addrs4_lock); + } + + static void qeth_del_local_addrs6(struct qeth_card *card, + struct qeth_ipacmd_local_addrs6 *cmd) + { + unsigned int i; + + if (cmd->addr_length != + sizeof_field(struct qeth_ipacmd_local_addr6, addr)) { + dev_err_ratelimited(&card->gdev->dev, + "Dropped IPv6 DEL LOCAL ADDR event with bad length %u\n", + cmd->addr_length); + return; + } + + spin_lock(&card->local_addrs6_lock); + for (i = 0; i < cmd->count; i++) { + struct qeth_ipacmd_local_addr6 *addr = &cmd->addrs[i]; + u32 key = ipv6_addr_hash(&addr->addr); + struct qeth_local_addr *tmp; + + hash_for_each_possible(card->local_addrs6, tmp, hnode, key) { + if (ipv6_addr_equal(&tmp->addr, &addr->addr)) { + hash_del_rcu(&tmp->hnode); + kfree_rcu(tmp, rcu); + break; + } + } + } + spin_unlock(&card->local_addrs6_lock); + } + + static bool qeth_next_hop_is_local_v4(struct qeth_card *card, + struct sk_buff *skb) + { + struct qeth_local_addr *tmp; + bool is_local = false; + unsigned int key; + __be32 next_hop; + + if (hash_empty(card->local_addrs4)) + return false; + + rcu_read_lock(); + next_hop = qeth_next_hop_v4_rcu(skb, qeth_dst_check_rcu(skb, 4)); + key = ipv4_addr_hash(next_hop); + + hash_for_each_possible_rcu(card->local_addrs4, tmp, hnode, key) { + if (tmp->addr.s6_addr32[3] == next_hop) { + is_local = true; + break; + } + } + rcu_read_unlock(); + + return is_local; + } + + static bool qeth_next_hop_is_local_v6(struct qeth_card *card, + struct sk_buff *skb) + { + struct qeth_local_addr *tmp; + struct in6_addr *next_hop; + bool is_local = false; + u32 key; + + if (hash_empty(card->local_addrs6)) + return false; + + rcu_read_lock(); + next_hop = qeth_next_hop_v6_rcu(skb, qeth_dst_check_rcu(skb, 6)); + key = ipv6_addr_hash(next_hop); + + hash_for_each_possible_rcu(card->local_addrs6, tmp, hnode, key) { + if (ipv6_addr_equal(&tmp->addr, next_hop)) { + is_local = true; + break; + } + } + rcu_read_unlock(); + + return is_local; + } + + static int qeth_debugfs_local_addr_show(struct seq_file *m, void *v) + { + struct qeth_card *card = m->private; + struct qeth_local_addr *tmp; + unsigned int i; + + rcu_read_lock(); + hash_for_each_rcu(card->local_addrs4, i, tmp, hnode) + seq_printf(m, "%pI4\n", &tmp->addr.s6_addr32[3]); + hash_for_each_rcu(card->local_addrs6, i, tmp, hnode) + seq_printf(m, "%pI6c\n", &tmp->addr); + rcu_read_unlock(); + + return 0; + } + + DEFINE_SHOW_ATTRIBUTE(qeth_debugfs_local_addr); + static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc, struct qeth_card *card) { @@@ -686,9 -939,19 +939,19 @@@ static struct qeth_ipa_cmd *qeth_check_ case IPA_CMD_MODCCID: return cmd; case IPA_CMD_REGISTER_LOCAL_ADDR: + if (cmd->hdr.prot_version == QETH_PROT_IPV4) + qeth_add_local_addrs4(card, &cmd->data.local_addrs4); + else if (cmd->hdr.prot_version == QETH_PROT_IPV6) + qeth_add_local_addrs6(card, &cmd->data.local_addrs6); + QETH_CARD_TEXT(card, 3, "irla"); return NULL; case IPA_CMD_UNREGISTER_LOCAL_ADDR: + if (cmd->hdr.prot_version == QETH_PROT_IPV4) + qeth_del_local_addrs4(card, &cmd->data.local_addrs4); + else if (cmd->hdr.prot_version == QETH_PROT_IPV6) + qeth_del_local_addrs6(card, &cmd->data.local_addrs6); + QETH_CARD_TEXT(card, 3, "urla"); return NULL; default: @@@ -868,16 -1131,18 +1131,18 @@@ static int qeth_set_thread_start_bit(st unsigned long thread) { unsigned long flags; + int rc = 0;
spin_lock_irqsave(&card->thread_mask_lock, flags); - if (!(card->thread_allowed_mask & thread) || - (card->thread_start_mask & thread)) { - spin_unlock_irqrestore(&card->thread_mask_lock, flags); - return -EPERM; - } - card->thread_start_mask |= thread; + if (!(card->thread_allowed_mask & thread)) + rc = -EPERM; + else if (card->thread_start_mask & thread) + rc = -EBUSY; + else + card->thread_start_mask |= thread; spin_unlock_irqrestore(&card->thread_mask_lock, flags); - return 0; + + return rc; }
static void qeth_clear_thread_start_bit(struct qeth_card *card, @@@ -930,11 -1195,17 +1195,17 @@@ static int qeth_do_run_thread(struct qe return rc; }
- void qeth_schedule_recovery(struct qeth_card *card) + int qeth_schedule_recovery(struct qeth_card *card) { + int rc; + QETH_CARD_TEXT(card, 2, "startrec"); - if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0) + + rc = qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD); + if (!rc) schedule_work(&card->kernel_thread_starter); + + return rc; }
static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev, @@@ -1376,6 -1647,10 +1647,10 @@@ static void qeth_setup_card(struct qeth qeth_init_qdio_info(card); INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work); INIT_WORK(&card->close_dev_work, qeth_close_dev_handler); + hash_init(card->local_addrs4); + hash_init(card->local_addrs6); + spin_lock_init(&card->local_addrs4_lock); + spin_lock_init(&card->local_addrs6_lock); }
static void qeth_core_sl_print(struct seq_file *m, struct service_level *slr) @@@ -1412,6 -1687,11 +1687,11 @@@ static struct qeth_card *qeth_alloc_car if (!card->read_cmd) goto out_read_cmd;
+ card->debugfs = debugfs_create_dir(dev_name(&gdev->dev), + qeth_debugfs_root); + debugfs_create_file("local_addrs", 0400, card->debugfs, card, + &qeth_debugfs_local_addr_fops); + card->qeth_service_level.seq_print = qeth_core_sl_print; register_service_level(&card->qeth_service_level); return card; @@@ -3345,11 -3625,11 +3625,11 @@@ static int qeth_switch_to_nonpacking_if static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, int count) { + struct qeth_qdio_out_buffer *buf = queue->bufs[index]; + unsigned int qdio_flags = QDIO_FLAG_SYNC_OUTPUT; struct qeth_card *card = queue->card; - struct qeth_qdio_out_buffer *buf; int rc; int i; - unsigned int qdio_flags;
for (i = index; i < index + count; ++i) { unsigned int bidx = QDIO_BUFNR(i); @@@ -3366,9 -3646,10 +3646,10 @@@ if (IS_IQD(card)) { skb_queue_walk(&buf->skb_list, skb) skb_tx_timestamp(skb); - continue; } + }
+ if (!IS_IQD(card)) { if (!queue->do_pack) { if ((atomic_read(&queue->used_buffers) >= (QETH_HIGH_WATERMARK_PACK - @@@ -3393,12 -3674,12 +3674,12 @@@ buf->buffer->element[0].sflags |= SBAL_SFLAGS0_PCI_REQ; } } + + if (atomic_read(&queue->set_pci_flags_count)) + qdio_flags |= QDIO_FLAG_PCI_OUT; }
QETH_TXQ_STAT_INC(queue, doorbell); - qdio_flags = QDIO_FLAG_SYNC_OUTPUT; - if (atomic_read(&queue->set_pci_flags_count)) - qdio_flags |= QDIO_FLAG_PCI_OUT; rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags, queue->queue_no, index, count);
@@@ -3809,15 -4090,47 +4090,47 @@@ static bool qeth_iqd_may_bulk(struct qe qeth_l3_iqd_same_vlan(&prev_hdr->hdr.l3, &curr_hdr->hdr.l3); }
- static unsigned int __qeth_fill_buffer(struct sk_buff *skb, - struct qeth_qdio_out_buffer *buf, - bool is_first_elem, unsigned int offset) + /** + * qeth_fill_buffer() - map skb into an output buffer + * @buf: buffer to transport the skb + * @skb: skb to map into the buffer + * @hdr: qeth_hdr for this skb. Either at skb->data, or allocated + * from qeth_core_header_cache. + * @offset: when mapping the skb, start at skb->data + offset + * @hd_len: if > 0, build a dedicated header element of this size + */ + static unsigned int qeth_fill_buffer(struct qeth_qdio_out_buffer *buf, + struct sk_buff *skb, struct qeth_hdr *hdr, + unsigned int offset, unsigned int hd_len) { struct qdio_buffer *buffer = buf->buffer; int element = buf->next_element_to_fill; int length = skb_headlen(skb) - offset; char *data = skb->data + offset; unsigned int elem_length, cnt; + bool is_first_elem = true; + + __skb_queue_tail(&buf->skb_list, skb); + + /* build dedicated element for HW Header */ + if (hd_len) { + is_first_elem = false; + + buffer->element[element].addr = virt_to_phys(hdr); + buffer->element[element].length = hd_len; + buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG; + + /* HW header is allocated from cache: */ + if ((void *)hdr != skb->data) + buf->is_header[element] = 1; + /* HW header was pushed and is contiguous with linear part: */ + else if (length > 0 && !PAGE_ALIGNED(data) && + (data == (char *)hdr + hd_len)) + buffer->element[element].eflags |= + SBAL_EFLAGS_CONTIGUOUS; + + element++; + }
/* map linear part into buffer element(s) */ while (length > 0) { @@@ -3871,40 -4184,6 +4184,6 @@@ return element; }
- /** - * qeth_fill_buffer() - map skb into an output buffer - * @buf: buffer to transport the skb - * @skb: skb to map into the buffer - * @hdr: qeth_hdr for this skb. Either at skb->data, or allocated - * from qeth_core_header_cache. - * @offset: when mapping the skb, start at skb->data + offset - * @hd_len: if > 0, build a dedicated header element of this size - */ - static unsigned int qeth_fill_buffer(struct qeth_qdio_out_buffer *buf, - struct sk_buff *skb, struct qeth_hdr *hdr, - unsigned int offset, unsigned int hd_len) - { - struct qdio_buffer *buffer = buf->buffer; - bool is_first_elem = true; - - __skb_queue_tail(&buf->skb_list, skb); - - /* build dedicated header element */ - if (hd_len) { - int element = buf->next_element_to_fill; - is_first_elem = false; - - buffer->element[element].addr = virt_to_phys(hdr); - buffer->element[element].length = hd_len; - buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG; - /* remember to free cache-allocated qeth_hdr: */ - buf->is_header[element] = ((void *)hdr != skb->data); - buf->next_element_to_fill++; - } - - return __qeth_fill_buffer(skb, buf, is_first_elem, offset); - } - static int __qeth_xmit(struct qeth_card *card, struct qeth_qdio_out_q *queue, struct sk_buff *skb, unsigned int elements, struct qeth_hdr *hdr, unsigned int offset, @@@ -4889,9 -5168,11 +5168,11 @@@ out_free_nothing static void qeth_core_free_card(struct qeth_card *card) { QETH_CARD_TEXT(card, 2, "freecrd"); + + unregister_service_level(&card->qeth_service_level); + debugfs_remove_recursive(card->debugfs); qeth_put_cmd(card->read_cmd); destroy_workqueue(card->event_wq); - unregister_service_level(&card->qeth_service_level); dev_set_drvdata(&card->gdev->dev, NULL); kfree(card); } @@@ -6300,7 -6581,7 +6581,7 @@@ static int qeth_set_csum_off(struct qet }
static int qeth_set_csum_on(struct qeth_card *card, enum qeth_ipa_funcs cstype, - enum qeth_prot_versions prot) + enum qeth_prot_versions prot, u8 *lp2lp) { u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP; struct qeth_cmd_buffer *iob; @@@ -6352,18 -6633,17 +6633,17 @@@
dev_info(&card->gdev->dev, "HW Checksumming (%sbound IPv%d) enabled\n", cstype == IPA_INBOUND_CHECKSUM ? "in" : "out", prot); - if (!qeth_ipa_caps_enabled(&caps, QETH_IPA_CHECKSUM_LP2LP) && - cstype == IPA_OUTBOUND_CHECKSUM) - dev_warn(&card->gdev->dev, - "Hardware checksumming is performed only if %s and its peer use different OSA Express 3 ports\n", - QETH_CARD_IFNAME(card)); + + if (lp2lp) + *lp2lp = qeth_ipa_caps_enabled(&caps, QETH_IPA_CHECKSUM_LP2LP); + return 0; }
static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype, - enum qeth_prot_versions prot) + enum qeth_prot_versions prot, u8 *lp2lp) { - return on ? qeth_set_csum_on(card, cstype, prot) : + return on ? qeth_set_csum_on(card, cstype, prot, lp2lp) : qeth_set_csum_off(card, cstype, prot); }
@@@ -6451,13 -6731,13 +6731,13 @@@ static int qeth_set_ipa_rx_csum(struct
if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) rc_ipv4 = qeth_set_ipa_csum(card, on, IPA_INBOUND_CHECKSUM, - QETH_PROT_IPV4); + QETH_PROT_IPV4, NULL); if (!qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6)) /* no/one Offload Assist available, so the rc is trivial */ return rc_ipv4;
rc_ipv6 = qeth_set_ipa_csum(card, on, IPA_INBOUND_CHECKSUM, - QETH_PROT_IPV6); + QETH_PROT_IPV6, NULL);
if (on) /* enable: success if any Assist is active */ @@@ -6493,6 -6773,24 +6773,24 @@@ void qeth_enable_hw_features(struct net } EXPORT_SYMBOL_GPL(qeth_enable_hw_features);
+ static void qeth_check_restricted_features(struct qeth_card *card, + netdev_features_t changed, + netdev_features_t actual) + { + netdev_features_t ipv6_features = NETIF_F_TSO6; + netdev_features_t ipv4_features = NETIF_F_TSO; + + if (!card->info.has_lp2lp_cso_v6) + ipv6_features |= NETIF_F_IPV6_CSUM; + if (!card->info.has_lp2lp_cso_v4) + ipv4_features |= NETIF_F_IP_CSUM; + + if ((changed & ipv6_features) && !(actual & ipv6_features)) + qeth_flush_local_addrs6(card); + if ((changed & ipv4_features) && !(actual & ipv4_features)) + qeth_flush_local_addrs4(card); + } + int qeth_set_features(struct net_device *dev, netdev_features_t features) { struct qeth_card *card = dev->ml_priv; @@@ -6504,13 -6802,15 +6802,15 @@@
if ((changed & NETIF_F_IP_CSUM)) { rc = qeth_set_ipa_csum(card, features & NETIF_F_IP_CSUM, - IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4); + IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4, + &card->info.has_lp2lp_cso_v4); if (rc) changed ^= NETIF_F_IP_CSUM; } if (changed & NETIF_F_IPV6_CSUM) { rc = qeth_set_ipa_csum(card, features & NETIF_F_IPV6_CSUM, - IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6); + IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6, + &card->info.has_lp2lp_cso_v6); if (rc) changed ^= NETIF_F_IPV6_CSUM; } @@@ -6532,6 -6832,9 +6832,9 @@@ changed ^= NETIF_F_TSO6; }
+ qeth_check_restricted_features(card, dev->features ^ features, + dev->features ^ changed); + /* everything changed successfully? */ if ((dev->features ^ features) == changed) return 0; @@@ -6568,6 -6871,34 +6871,34 @@@ netdev_features_t qeth_features_check(s struct net_device *dev, netdev_features_t features) { + /* Traffic with local next-hop is not eligible for some offloads: */ + if (skb->ip_summed == CHECKSUM_PARTIAL) { + struct qeth_card *card = dev->ml_priv; + netdev_features_t restricted = 0; + + if (skb_is_gso(skb) && !netif_needs_gso(skb, features)) + restricted |= NETIF_F_ALL_TSO; + + switch (vlan_get_protocol(skb)) { + case htons(ETH_P_IP): + if (!card->info.has_lp2lp_cso_v4) + restricted |= NETIF_F_IP_CSUM; + + if (restricted && qeth_next_hop_is_local_v4(card, skb)) + features &= ~restricted; + break; + case htons(ETH_P_IPV6): + if (!card->info.has_lp2lp_cso_v6) + restricted |= NETIF_F_IPV6_CSUM; + + if (restricted && qeth_next_hop_is_local_v6(card, skb)) + features &= ~restricted; + break; + default: + break; + } + } + /* GSO segmentation builds skbs with * a (small) linear part for the headers, and * page frags for the data. @@@ -6717,17 -7048,17 +7048,17 @@@ int qeth_stop(struct net_device *dev unsigned int i;
/* Quiesce the NAPI instances: */ - qeth_for_each_output_queue(card, queue, i) { + qeth_for_each_output_queue(card, queue, i) napi_disable(&queue->napi); - del_timer_sync(&queue->timer); - }
/* Stop .ndo_start_xmit, might still access queue->napi. */ netif_tx_disable(dev);
- /* Queues may get re-allocated, so remove the NAPIs here. */ - qeth_for_each_output_queue(card, queue, i) + qeth_for_each_output_queue(card, queue, i) { + del_timer_sync(&queue->timer); + /* Queues may get re-allocated, so remove the NAPIs. */ netif_napi_del(&queue->napi); + } } else { netif_tx_disable(dev); } @@@ -6745,6 -7076,8 +7076,8 @@@ static int __init qeth_core_init(void
pr_info("loading core functions\n");
+ qeth_debugfs_root = debugfs_create_dir("qeth", NULL); + rc = qeth_register_dbf_views(); if (rc) goto dbf_err; @@@ -6786,6 -7119,7 +7119,7 @@@ slab_err register_err: qeth_unregister_dbf_views(); dbf_err: + debugfs_remove_recursive(qeth_debugfs_root); pr_err("Initializing the qeth device driver failed\n"); return rc; } @@@ -6799,6 -7133,7 +7133,7 @@@ static void __exit qeth_core_exit(void kmem_cache_destroy(qeth_core_header_cache); root_device_unregister(qeth_core_root_dev); qeth_unregister_dbf_views(); + debugfs_remove_recursive(qeth_debugfs_root); pr_info("core functions removed\n"); }
diff --combined include/linux/netdevice.h index 26bc0f11b7ad,7725efd6e48a..6a8f8daef09d --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@@ -288,6 -288,7 +288,7 @@@ enum netdev_state_t __LINK_STATE_NOCARRIER, __LINK_STATE_LINKWATCH_PENDING, __LINK_STATE_DORMANT, + __LINK_STATE_TESTING, };
@@@ -328,6 -329,7 +329,7 @@@ struct napi_struct
unsigned long state; int weight; + int defer_hard_irqs_count; unsigned long gro_bitmask; int (*poll)(struct napi_struct *, int); #ifdef CONFIG_NETPOLL @@@ -1146,12 -1148,6 +1148,12 @@@ struct netdev_net_notifier * int (*ndo_del_slave)(struct net_device *dev, struct net_device *slave_dev); * Called to release previously enslaved netdev. * + * struct net_device *(*ndo_get_xmit_slave)(struct net_device *dev, + * struct sk_buff *skb, + * bool all_slaves); + * Get the xmit slave of master device. If all_slaves is true, function + * assume all the slaves can transmit. + * * Feature/offload setting functions. * netdev_features_t (*ndo_fix_features)(struct net_device *dev, * netdev_features_t features); @@@ -1395,9 -1391,6 +1397,9 @@@ struct net_device_ops struct netlink_ext_ack *extack); int (*ndo_del_slave)(struct net_device *dev, struct net_device *slave_dev); + struct net_device* (*ndo_get_xmit_slave)(struct net_device *dev, + struct sk_buff *skb, + bool all_slaves); netdev_features_t (*ndo_fix_features)(struct net_device *dev, netdev_features_t features); int (*ndo_set_features)(struct net_device *dev, @@@ -1812,13 -1805,11 +1814,11 @@@ enum netdev_priv_flags * @phydev: Physical device may attach itself * for hardware timestamping * @sfp_bus: attached &struct sfp_bus structure. - * @qdisc_tx_busylock_key: lockdep class annotating Qdisc->busylock - * spinlock - * @qdisc_running_key: lockdep class annotating Qdisc->running seqcount - * @qdisc_xmit_lock_key: lockdep class annotating - * netdev_queue->_xmit_lock spinlock + * * @addr_list_lock_key: lockdep class annotating * net_device->addr_list_lock spinlock + * @qdisc_tx_busylock: lockdep class annotating Qdisc->busylock spinlock + * @qdisc_running_key: lockdep class annotating Qdisc->running seqcount * * @proto_down: protocol port state information can be sent to the * switch driver and used to set the phys state of the @@@ -2003,6 -1994,7 +2003,7 @@@ struct net_device
struct bpf_prog __rcu *xdp_prog; unsigned long gro_flush_timeout; + int napi_defer_hard_irqs; rx_handler_func_t __rcu *rx_handler; void __rcu *rx_handler_data;
@@@ -2118,10 -2110,9 +2119,9 @@@ #endif struct phy_device *phydev; struct sfp_bus *sfp_bus; - struct lock_class_key qdisc_tx_busylock_key; - struct lock_class_key qdisc_running_key; - struct lock_class_key qdisc_xmit_lock_key; struct lock_class_key addr_list_lock_key; + struct lock_class_key *qdisc_tx_busylock; + struct lock_class_key *qdisc_running_key; bool proto_down; unsigned wol_enabled:1;
@@@ -2206,6 -2197,20 +2206,20 @@@ static inline void netdev_for_each_tx_q f(dev, &dev->_tx[i], arg); }
+ #define netdev_lockdep_set_classes(dev) \ + { \ + static struct lock_class_key qdisc_tx_busylock_key; \ + static struct lock_class_key qdisc_running_key; \ + static struct lock_class_key qdisc_xmit_lock_key; \ + unsigned int i; \ + \ + (dev)->qdisc_tx_busylock = &qdisc_tx_busylock_key; \ + (dev)->qdisc_running_key = &qdisc_running_key; \ + for (i = 0; i < (dev)->num_tx_queues; i++) \ + lockdep_set_class(&(dev)->_tx[i]._xmit_lock, \ + &qdisc_xmit_lock_key); \ + } + u16 netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev); struct netdev_queue *netdev_core_pick_tx(struct net_device *dev, @@@ -2740,9 -2745,6 +2754,9 @@@ void netdev_freemem(struct net_device * void synchronize_net(void); int init_dummy_netdev(struct net_device *dev);
+struct net_device *netdev_get_xmit_slave(struct net_device *dev, + struct sk_buff *skb, + bool all_slaves); struct net_device *dev_get_by_index(struct net *net, int ifindex); struct net_device *__dev_get_by_index(struct net *net, int ifindex); struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); @@@ -3919,6 -3921,46 +3933,46 @@@ static inline bool netif_dormant(const }
+ /** + * netif_testing_on - mark device as under test. + * @dev: network device + * + * Mark device as under test (as per RFC2863). + * + * The testing state indicates that some test(s) must be performed on + * the interface. After completion, of the test, the interface state + * will change to up, dormant, or down, as appropriate. + */ + static inline void netif_testing_on(struct net_device *dev) + { + if (!test_and_set_bit(__LINK_STATE_TESTING, &dev->state)) + linkwatch_fire_event(dev); + } + + /** + * netif_testing_off - set device as not under test. + * @dev: network device + * + * Device is not in testing state. + */ + static inline void netif_testing_off(struct net_device *dev) + { + if (test_and_clear_bit(__LINK_STATE_TESTING, &dev->state)) + linkwatch_fire_event(dev); + } + + /** + * netif_testing - test if device is under test + * @dev: network device + * + * Check if device is under test + */ + static inline bool netif_testing(const struct net_device *dev) + { + return test_bit(__LINK_STATE_TESTING, &dev->state); + } + + /** * netif_oper_up - test if device is operational * @dev: network device diff --combined include/linux/tcp.h index 4f8159e90ce1,2c6f87e9f0cf..e60db06ec28d --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@@ -78,6 -78,47 +78,6 @@@ struct tcp_sack_block #define TCP_SACK_SEEN (1 << 0) /*1 = peer is SACK capable, */ #define TCP_DSACK_SEEN (1 << 2) /*1 = DSACK was received from peer*/
-#if IS_ENABLED(CONFIG_MPTCP) -struct mptcp_options_received { - u64 sndr_key; - u64 rcvr_key; - u64 data_ack; - u64 data_seq; - u32 subflow_seq; - u16 data_len; - u16 mp_capable : 1, - mp_join : 1, - dss : 1, - add_addr : 1, - rm_addr : 1, - family : 4, - echo : 1, - backup : 1; - u32 token; - u32 nonce; - u64 thmac; - u8 hmac[20]; - u8 join_id; - u8 use_map:1, - dsn64:1, - data_fin:1, - use_ack:1, - ack64:1, - mpc_map:1, - __unused:2; - u8 addr_id; - u8 rm_id; - union { - struct in_addr addr; -#if IS_ENABLED(CONFIG_MPTCP_IPV6) - struct in6_addr addr6; -#endif - }; - u64 ahmac; - u16 port; -}; -#endif - struct tcp_options_received { /* PAWS/RTTM data */ int ts_recent_stamp;/* Time we stored ts_recent (for aging) */ @@@ -95,6 -136,9 +95,6 @@@ u8 num_sacks; /* Number of SACK blocks */ u16 user_mss; /* mss requested by user in ioctl */ u16 mss_clamp; /* Maximal mss, negotiated at connection setup */ -#if IS_ENABLED(CONFIG_MPTCP) - struct mptcp_options_received mptcp; -#endif };
static inline void tcp_clear_options(struct tcp_options_received *rx_opt) @@@ -104,6 -148,13 +104,6 @@@ #if IS_ENABLED(CONFIG_SMC) rx_opt->smc_ok = 0; #endif -#if IS_ENABLED(CONFIG_MPTCP) - rx_opt->mptcp.mp_capable = 0; - rx_opt->mptcp.mp_join = 0; - rx_opt->mptcp.add_addr = 0; - rx_opt->mptcp.rm_addr = 0; - rx_opt->mptcp.dss = 0; -#endif }
/* This is the max number of SACKS that we'll generate and process. It's safe @@@ -217,6 -268,7 +217,7 @@@ struct tcp_sock } rack; u16 advmss; /* Advertised MSS */ u8 compressed_ack; + u8 dup_ack_counter; u32 chrono_start; /* Start time in jiffies of a TCP chrono */ u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */ u8 chrono_type:2, /* current chronograph type */ diff --combined include/net/bluetooth/mgmt.h index e104329e227f,65dd6fd1fff3..3303d4bc00cf --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@@ -70,14 -70,14 +70,14 @@@ struct mgmt_rp_read_version struct mgmt_rp_read_commands { __le16 num_commands; __le16 num_events; - __le16 opcodes[0]; + __le16 opcodes[]; } __packed;
#define MGMT_OP_READ_INDEX_LIST 0x0003 #define MGMT_READ_INDEX_LIST_SIZE 0 struct mgmt_rp_read_index_list { __le16 num_controllers; - __le16 index[0]; + __le16 index[]; } __packed;
/* Reserve one extra byte for names in management messages so that they @@@ -183,7 -183,7 +183,7 @@@ struct mgmt_link_key_info struct mgmt_cp_load_link_keys { __u8 debug_keys; __le16 key_count; - struct mgmt_link_key_info keys[0]; + struct mgmt_link_key_info keys[]; } __packed; #define MGMT_LOAD_LINK_KEYS_SIZE 3
@@@ -206,7 -206,7 +206,7 @@@ struct mgmt_ltk_info #define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0013 struct mgmt_cp_load_long_term_keys { __le16 key_count; - struct mgmt_ltk_info keys[0]; + struct mgmt_ltk_info keys[]; } __packed; #define MGMT_LOAD_LONG_TERM_KEYS_SIZE 2
@@@ -223,7 -223,7 +223,7 @@@ struct mgmt_rp_disconnect #define MGMT_GET_CONNECTIONS_SIZE 0 struct mgmt_rp_get_connections { __le16 conn_count; - struct mgmt_addr_info addr[0]; + struct mgmt_addr_info addr[]; } __packed;
#define MGMT_OP_PIN_CODE_REPLY 0x0016 @@@ -413,7 -413,7 +413,7 @@@ struct mgmt_irk_info #define MGMT_OP_LOAD_IRKS 0x0030 struct mgmt_cp_load_irks { __le16 irk_count; - struct mgmt_irk_info irks[0]; + struct mgmt_irk_info irks[]; } __packed; #define MGMT_LOAD_IRKS_SIZE 2
@@@ -465,7 -465,7 +465,7 @@@ struct mgmt_conn_param #define MGMT_OP_LOAD_CONN_PARAM 0x0035 struct mgmt_cp_load_conn_param { __le16 param_count; - struct mgmt_conn_param params[0]; + struct mgmt_conn_param params[]; } __packed; #define MGMT_LOAD_CONN_PARAM_SIZE 2
@@@ -473,7 -473,7 +473,7 @@@ #define MGMT_READ_UNCONF_INDEX_LIST_SIZE 0 struct mgmt_rp_read_unconf_index_list { __le16 num_controllers; - __le16 index[0]; + __le16 index[]; } __packed;
#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001 @@@ -504,7 -504,7 +504,7 @@@ struct mgmt_cp_start_service_discovery __u8 type; __s8 rssi; __le16 uuid_count; - __u8 uuids[0][16]; + __u8 uuids[][16]; } __packed; #define MGMT_START_SERVICE_DISCOVERY_SIZE 4
@@@ -516,7 -516,7 +516,7 @@@ struct mgmt_cp_read_local_oob_ext_data struct mgmt_rp_read_local_oob_ext_data { __u8 type; __le16 eir_len; - __u8 eir[0]; + __u8 eir[]; } __packed;
#define MGMT_OP_READ_EXT_INDEX_LIST 0x003C @@@ -527,7 -527,7 +527,7 @@@ struct mgmt_rp_read_ext_index_list __le16 index; __u8 type; __u8 bus; - } entry[0]; + } entry[]; } __packed;
#define MGMT_OP_READ_ADV_FEATURES 0x0003D @@@ -538,7 -538,7 +538,7 @@@ struct mgmt_rp_read_adv_features __u8 max_scan_rsp_len; __u8 max_instances; __u8 num_instances; - __u8 instance[0]; + __u8 instance[]; } __packed;
#define MGMT_OP_ADD_ADVERTISING 0x003E @@@ -549,7 -549,7 +549,7 @@@ struct mgmt_cp_add_advertising __le16 timeout; __u8 adv_data_len; __u8 scan_rsp_len; - __u8 data[0]; + __u8 data[]; } __packed; #define MGMT_ADD_ADVERTISING_SIZE 11 struct mgmt_rp_add_advertising { @@@ -603,7 -603,7 +603,7 @@@ struct mgmt_rp_read_ext_info __le32 supported_settings; __le32 current_settings; __le16 eir_len; - __u8 eir[0]; + __u8 eir[]; } __packed;
#define MGMT_OP_SET_APPEARANCE 0x0043 @@@ -668,17 -668,24 +668,24 @@@ struct mgmt_blocked_key_info
struct mgmt_cp_set_blocked_keys { __le16 key_count; - struct mgmt_blocked_key_info keys[0]; + struct mgmt_blocked_key_info keys[]; } __packed; #define MGMT_OP_SET_BLOCKED_KEYS_SIZE 2
#define MGMT_OP_SET_WIDEBAND_SPEECH 0x0047
+ #define MGMT_OP_READ_SECURITY_INFO 0x0048 + #define MGMT_READ_SECURITY_INFO_SIZE 0 + struct mgmt_rp_read_security_info { + __le16 sec_len; + __u8 sec[0]; + } __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; __u8 status; - __u8 data[0]; + __u8 data[]; } __packed;
#define MGMT_EV_CMD_STATUS 0x0002 @@@ -726,7 -733,7 +733,7 @@@ struct mgmt_ev_device_connected struct mgmt_addr_info addr; __le32 flags; __le16 eir_len; - __u8 eir[0]; + __u8 eir[]; } __packed;
#define MGMT_DEV_DISCONN_UNKNOWN 0x00 @@@ -781,7 -788,7 +788,7 @@@ struct mgmt_ev_device_found __s8 rssi; __le32 flags; __le16 eir_len; - __u8 eir[0]; + __u8 eir[]; } __packed;
#define MGMT_EV_DISCOVERING 0x0013 @@@ -876,7 -883,7 +883,7 @@@ struct mgmt_ev_ext_index struct mgmt_ev_local_oob_data_updated { __u8 type; __le16 eir_len; - __u8 eir[0]; + __u8 eir[]; } __packed;
#define MGMT_EV_ADVERTISING_ADDED 0x0023 @@@ -892,7 -899,7 +899,7 @@@ struct mgmt_ev_advertising_removed #define MGMT_EV_EXT_INFO_CHANGED 0x0025 struct mgmt_ev_ext_info_changed { __le16 eir_len; - __u8 eir[0]; + __u8 eir[]; } __packed;
#define MGMT_EV_PHY_CONFIGURATION_CHANGED 0x0026 diff --combined include/net/bonding.h index b5e49bedbc9f,0b696da5c115..be312551431d --- a/include/net/bonding.h +++ b/include/net/bonding.h @@@ -200,8 -200,7 +200,8 @@@ struct bonding struct slave __rcu *curr_active_slave; struct slave __rcu *current_arp_slave; struct slave __rcu *primary_slave; - struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */ + struct bond_up_slave __rcu *usable_slaves; + struct bond_up_slave __rcu *all_slaves; bool force_primary; s32 slave_cnt; /* never change this value outside the attach/detach wrappers */ int (*recv_probe)(const struct sk_buff *, struct bonding *, @@@ -238,7 -237,6 +238,6 @@@ struct dentry *debug_dir; #endif /* CONFIG_DEBUG_FS */ struct rtnl_link_stats64 bond_stats; - struct lock_class_key stats_lock_key; };
#define bond_slave_get_rcu(dev) \ diff --combined include/net/cfg80211.h index 5eb776f0069d,46ac80423b28..18fef01c48f1 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@@ -2029,7 -2029,7 +2029,7 @@@ struct cfg80211_scan_request bool no_cck;
/* keep last */ - struct ieee80211_channel *channels[0]; + struct ieee80211_channel *channels[]; };
static inline void get_random_mask_addr(u8 *buf, const u8 *addr, const u8 *mask) @@@ -2175,7 -2175,7 +2175,7 @@@ struct cfg80211_sched_scan_request struct list_head list;
/* keep last */ - struct ieee80211_channel *channels[0]; + struct ieee80211_channel *channels[]; };
/** @@@ -2297,7 -2297,7 +2297,7 @@@ struct cfg80211_bss u8 bssid_index; u8 max_bssid_indicator;
- u8 priv[0] __aligned(sizeof(void *)); + u8 priv[] __aligned(sizeof(void *)); };
/** @@@ -4829,7 -4829,7 +4829,7 @@@ struct wiphy
u8 max_data_retry_count;
- char priv[0] __aligned(NETDEV_ALIGN); + char priv[] __aligned(NETDEV_ALIGN); };
static inline struct net *wiphy_net(struct wiphy *wiphy) @@@ -5211,7 -5211,7 +5211,7 @@@ u32 ieee80211_mandatory_rates(struct ie * Radiotap parsing functions -- for controlled injection support * * Implemented in net/wireless/radiotap.c - * Documentation in Documentation/networking/radiotap-headers.txt + * Documentation in Documentation/networking/radiotap-headers.rst */
struct radiotap_align_size { diff --combined include/net/if_inet6.h index 514dd6e423b1,212eb278bda6..8bf5906073bc --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@@ -78,7 -78,7 +78,7 @@@ struct inet6_ifaddr struct ip6_sf_socklist { unsigned int sl_max; unsigned int sl_count; - struct in6_addr sl_addr[0]; + struct in6_addr sl_addr[]; };
#define IP6_SFLSIZE(count) (sizeof(struct ip6_sf_socklist) + \ @@@ -190,7 -190,6 +190,6 @@@ struct inet6_dev int dead;
u32 desync_factor; - u8 rndid[8]; struct list_head tempaddr_list;
struct in6_addr token; diff --combined include/net/mptcp.h index 3bce2019e4da,5288fba56e55..91c0e9224586 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@@ -68,8 -68,13 +68,10 @@@ static inline bool rsk_is_mptcp(const s return tcp_rsk(req)->is_mptcp; }
+ void mptcp_space(const struct sock *ssk, int *space, int *full_space); + -void mptcp_parse_option(const struct sk_buff *skb, const unsigned char *ptr, - int opsize, struct tcp_options_received *opt_rx); bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, unsigned int *size, struct mptcp_out_options *opts); -void mptcp_rcv_synsent(struct sock *sk); bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, struct mptcp_out_options *opts); bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, @@@ -194,6 -199,7 +196,7 @@@ static inline bool mptcp_sk_is_subflow( return false; }
+ static inline void mptcp_space(const struct sock *ssk, int *s, int *fs) { } static inline void mptcp_seq_show(struct seq_file *seq) { } #endif /* CONFIG_MPTCP */
diff --combined include/net/sch_generic.h index 8428aa614265,1862bf5a105b..ab87a8b86a32 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@@ -407,7 -407,6 +407,7 @@@ struct tcf_block struct mutex lock; struct list_head chain_list; u32 index; /* block index for shared blocks */ + u32 classid; /* which class this block belongs to */ refcount_t refcnt; struct net *net; struct Qdisc *q; @@@ -711,11 -710,6 +711,6 @@@ static inline void qdisc_reset_all_tx_g } }
- static inline void qdisc_reset_all_tx(struct net_device *dev) - { - qdisc_reset_all_tx_gt(dev, 0); - } - /* Are all TX queues of the device empty? */ static inline bool qdisc_all_tx_empty(const struct net_device *dev) { diff --combined include/uapi/linux/bpf.h index f9b7fdd951e4,b3643e27e264..101b0c8a3784 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@@ -73,7 -73,7 +73,7 @@@ struct bpf_insn /* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ struct bpf_lpm_trie_key { __u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */ - __u8 data[]; /* Arbitrary size */ + __u8 data[0]; /* Arbitrary size */ };
struct bpf_cgroup_storage_key { @@@ -113,6 -113,9 +113,9 @@@ enum bpf_cmd BPF_MAP_DELETE_BATCH, BPF_LINK_CREATE, BPF_LINK_UPDATE, + BPF_LINK_GET_FD_BY_ID, + BPF_LINK_GET_NEXT_ID, + BPF_ENABLE_STATS, };
enum bpf_map_type { @@@ -220,6 -223,15 +223,15 @@@ enum bpf_attach_type
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
+ enum bpf_link_type { + BPF_LINK_TYPE_UNSPEC = 0, + BPF_LINK_TYPE_RAW_TRACEPOINT = 1, + BPF_LINK_TYPE_TRACING = 2, + BPF_LINK_TYPE_CGROUP = 3, + + MAX_BPF_LINK_TYPE, + }; + /* cgroup-bpf attach flags used in BPF_PROG_ATTACH command * * NONE(default): No further bpf programs allowed in the subtree. @@@ -379,6 -391,12 +391,12 @@@ enum */ #define BPF_F_QUERY_EFFECTIVE (1U << 0)
+ /* type for BPF_ENABLE_STATS */ + enum bpf_stats_type { + /* enabled run_time_ns and run_cnt */ + BPF_STATS_RUN_TIME = 0, + }; + enum bpf_stack_build_id_status { /* user space need an empty entry to identify end of a trace */ BPF_STACK_BUILD_ID_EMPTY = 0, @@@ -523,6 -541,7 +541,7 @@@ union bpf_attr __u32 prog_id; __u32 map_id; __u32 btf_id; + __u32 link_id; }; __u32 next_id; __u32 open_flags; @@@ -589,6 -608,10 +608,10 @@@ __u32 old_prog_fd; } link_update;
+ struct { /* struct used by BPF_ENABLE_STATS command */ + __u32 type; + } enable_stats; + } __attribute__((aligned(8)));
/* The description below is an attempt at providing documentation to eBPF @@@ -652,6 -675,8 +675,8 @@@ * u64 bpf_ktime_get_ns(void) * Description * Return the time elapsed since system boot, in nanoseconds. + * Does not include time the system was suspended. + * See: clock_gettime(CLOCK_MONOTONIC) * Return * Current *ktime*. * @@@ -1562,7 -1587,7 +1587,7 @@@ * Return * 0 * - * int bpf_setsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, void *optval, int optlen) + * int bpf_setsockopt(void *bpf_socket, int level, int optname, void *optval, int optlen) * Description * Emulate a call to **setsockopt()** on the socket associated to * *bpf_socket*, which must be a full socket. The *level* at @@@ -1570,6 -1595,11 +1595,11 @@@ * must be specified, see **setsockopt(2)** for more information. * The option value of length *optlen* is pointed by *optval*. * + * *bpf_socket* should be one of the following: + * * **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**. + * * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT** + * and **BPF_CGROUP_INET6_CONNECT**. + * * This helper actually implements a subset of **setsockopt()**. * It supports the following *level*\ s: * @@@ -1764,7 -1794,7 +1794,7 @@@ * Return * 0 on success, or a negative error in case of failure. * - * int bpf_getsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, void *optval, int optlen) + * int bpf_getsockopt(void *bpf_socket, int level, int optname, void *optval, int optlen) * Description * Emulate a call to **getsockopt()** on the socket associated to * *bpf_socket*, which must be a full socket. The *level* at @@@ -1773,6 -1803,11 +1803,11 @@@ * The retrieved value is stored in the structure pointed by * *opval* and of length *optlen*. * + * *bpf_socket* should be one of the following: + * * **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**. + * * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT** + * and **BPF_CGROUP_INET6_CONNECT**. + * * This helper actually implements a subset of **getsockopt()**. * It supports the following *level*\ s: * @@@ -3025,6 -3060,14 +3060,14 @@@ * * **-EOPNOTSUPP** Unsupported operation, for example a * call from outside of TC ingress. * * **-ESOCKTNOSUPPORT** Socket type not supported (reuseport). + * + * u64 bpf_ktime_get_boot_ns(void) + * Description + * Return the time elapsed since system boot, in nanoseconds. + * Does include the time the system was suspended. + * See: clock_gettime(CLOCK_BOOTTIME) + * Return + * Current *ktime*. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@@ -3151,7 -3194,8 +3194,8 @@@ FN(xdp_output), \ FN(get_netns_cookie), \ FN(get_current_ancestor_cgroup_id), \ - FN(sk_assign), + FN(sk_assign), \ + FN(ktime_get_boot_ns),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call @@@ -3598,6 -3642,25 +3642,25 @@@ struct bpf_btf_info __u32 id; } __attribute__((aligned(8)));
+ struct bpf_link_info { + __u32 type; + __u32 id; + __u32 prog_id; + union { + struct { + __aligned_u64 tp_name; /* in/out: tp_name buffer ptr */ + __u32 tp_name_len; /* in/out: tp_name buffer len */ + } raw_tracepoint; + struct { + __u32 attach_type; + } tracing; + struct { + __u64 cgroup_id; + __u32 attach_type; + } cgroup; + }; + } __attribute__((aligned(8))); + /* User bpf_sock_addr struct to access socket fields and sockaddr struct passed * by user and intended to be used by socket (e.g. to bind to, depends on * attach attach type). diff --combined include/uapi/linux/ethtool_netlink.h index 1711e57f7848,bf1d310e20bc..0d0162d79f4c --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@@ -2,7 -2,7 +2,7 @@@ /* * include/uapi/linux/ethtool_netlink.h - netlink interface for ethtool * - * See Documentation/networking/ethtool-netlink.txt in kernel source tree for + * See Documentation/networking/ethtool-netlink.rst in kernel source tree for * doucumentation of the interface. */
@@@ -216,6 -216,8 +216,8 @@@ enum ETHTOOL_A_LINKMODES_PEER, /* bitset */ ETHTOOL_A_LINKMODES_SPEED, /* u32 */ ETHTOOL_A_LINKMODES_DUPLEX, /* u8 */ + ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, /* u8 */ + ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, /* u8 */
/* add new constants above here */ __ETHTOOL_A_LINKMODES_CNT, diff --combined kernel/bpf/syscall.c index 2843bbba9ca1,bb1ab7da6103..6f100d852242 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@@ -42,6 -42,8 +42,8 @@@ static DEFINE_IDR(prog_idr) static DEFINE_SPINLOCK(prog_idr_lock); static DEFINE_IDR(map_idr); static DEFINE_SPINLOCK(map_idr_lock); + static DEFINE_IDR(link_idr); + static DEFINE_SPINLOCK(link_idr_lock);
int sysctl_unprivileged_bpf_disabled __read_mostly;
@@@ -49,9 -51,11 +51,11 @@@ static const struct bpf_map_ops * cons #define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) #define BPF_MAP_TYPE(_id, _ops) \ [_id] = &_ops, + #define BPF_LINK_TYPE(_id, _name) #include <linux/bpf_types.h> #undef BPF_PROG_TYPE #undef BPF_MAP_TYPE + #undef BPF_LINK_TYPE };
/* @@@ -1485,10 -1489,8 +1489,10 @@@ static int map_lookup_and_delete_elem(u if (err) goto free_value;
- if (copy_to_user(uvalue, value, value_size) != 0) + if (copy_to_user(uvalue, value, value_size) != 0) { + err = -EFAULT; goto free_value; + }
err = 0;
@@@ -1548,9 -1550,11 +1552,11 @@@ static const struct bpf_prog_ops * cons #define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \ [_id] = & _name ## _prog_ops, #define BPF_MAP_TYPE(_id, _ops) + #define BPF_LINK_TYPE(_id, _name) #include <linux/bpf_types.h> #undef BPF_PROG_TYPE #undef BPF_MAP_TYPE + #undef BPF_LINK_TYPE };
static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog) @@@ -2183,25 -2187,39 +2189,39 @@@ static int bpf_obj_get(const union bpf_ attr->file_flags); }
- void bpf_link_init(struct bpf_link *link, const struct bpf_link_ops *ops, - struct bpf_prog *prog) + void bpf_link_init(struct bpf_link *link, enum bpf_link_type type, + const struct bpf_link_ops *ops, struct bpf_prog *prog) { atomic64_set(&link->refcnt, 1); + link->type = type; + link->id = 0; link->ops = ops; link->prog = prog; }
+ static void bpf_link_free_id(int id) + { + if (!id) + return; + + spin_lock_bh(&link_idr_lock); + idr_remove(&link_idr, id); + spin_unlock_bh(&link_idr_lock); + } + /* Clean up bpf_link and corresponding anon_inode file and FD. After * anon_inode is created, bpf_link can't be just kfree()'d due to deferred - * anon_inode's release() call. This helper manages marking bpf_link as - * defunct, releases anon_inode file and puts reserved FD. + * anon_inode's release() call. This helper marksbpf_link as + * defunct, releases anon_inode file and puts reserved FD. bpf_prog's refcnt + * is not decremented, it's the responsibility of a calling code that failed + * to complete bpf_link initialization. */ - void bpf_link_cleanup(struct bpf_link *link, struct file *link_file, - int link_fd) + void bpf_link_cleanup(struct bpf_link_primer *primer) { - link->prog = NULL; - fput(link_file); - put_unused_fd(link_fd); + primer->link->prog = NULL; + bpf_link_free_id(primer->id); + fput(primer->file); + put_unused_fd(primer->fd); }
void bpf_link_inc(struct bpf_link *link) @@@ -2212,6 -2230,7 +2232,7 @@@ /* bpf_link_free is guaranteed to be called from process context */ static void bpf_link_free(struct bpf_link *link) { + bpf_link_free_id(link->id); if (link->prog) { /* detach BPF program, clean up used resources */ link->ops->release(link); @@@ -2253,35 -2272,35 +2274,35 @@@ static int bpf_link_release(struct inod }
#ifdef CONFIG_PROC_FS - static const struct bpf_link_ops bpf_raw_tp_lops; - static const struct bpf_link_ops bpf_tracing_link_lops; + #define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) + #define BPF_MAP_TYPE(_id, _ops) + #define BPF_LINK_TYPE(_id, _name) [_id] = #_name, + static const char *bpf_link_type_strs[] = { + [BPF_LINK_TYPE_UNSPEC] = "<invalid>", + #include <linux/bpf_types.h> + }; + #undef BPF_PROG_TYPE + #undef BPF_MAP_TYPE + #undef BPF_LINK_TYPE
static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp) { const struct bpf_link *link = filp->private_data; const struct bpf_prog *prog = link->prog; char prog_tag[sizeof(prog->tag) * 2 + 1] = { }; - const char *link_type; - - if (link->ops == &bpf_raw_tp_lops) - link_type = "raw_tracepoint"; - else if (link->ops == &bpf_tracing_link_lops) - link_type = "tracing"; - #ifdef CONFIG_CGROUP_BPF - else if (link->ops == &bpf_cgroup_link_lops) - link_type = "cgroup"; - #endif - else - link_type = "unknown";
bin2hex(prog_tag, prog->tag, sizeof(prog->tag)); seq_printf(m, "link_type:\t%s\n" + "link_id:\t%u\n" "prog_tag:\t%s\n" "prog_id:\t%u\n", - link_type, + bpf_link_type_strs[link->type], + link->id, prog_tag, prog->aux->id); + if (link->ops->show_fdinfo) + link->ops->show_fdinfo(link, m); } #endif
@@@ -2294,36 -2313,77 +2315,77 @@@ static const struct file_operations bpf .write = bpf_dummy_write, };
- int bpf_link_new_fd(struct bpf_link *link) + static int bpf_link_alloc_id(struct bpf_link *link) { - return anon_inode_getfd("bpf-link", &bpf_link_fops, link, O_CLOEXEC); - } + int id;
- /* Similar to bpf_link_new_fd, create anon_inode for given bpf_link, but - * instead of immediately installing fd in fdtable, just reserve it and - * return. Caller then need to either install it with fd_install(fd, file) or - * release with put_unused_fd(fd). - * This is useful for cases when bpf_link attachment/detachment are - * complicated and expensive operations and should be delayed until all the fd - * reservation and anon_inode creation succeeds. + idr_preload(GFP_KERNEL); + spin_lock_bh(&link_idr_lock); + id = idr_alloc_cyclic(&link_idr, link, 1, INT_MAX, GFP_ATOMIC); + spin_unlock_bh(&link_idr_lock); + idr_preload_end(); + + return id; + } + + /* Prepare bpf_link to be exposed to user-space by allocating anon_inode file, + * reserving unused FD and allocating ID from link_idr. This is to be paired + * with bpf_link_settle() to install FD and ID and expose bpf_link to + * user-space, if bpf_link is successfully attached. If not, bpf_link and + * pre-allocated resources are to be freed with bpf_cleanup() call. All the + * transient state is passed around in struct bpf_link_primer. + * This is preferred way to create and initialize bpf_link, especially when + * there are complicated and expensive operations inbetween creating bpf_link + * itself and attaching it to BPF hook. By using bpf_link_prime() and + * bpf_link_settle() kernel code using bpf_link doesn't have to perform + * expensive (and potentially failing) roll back operations in a rare case + * that file, FD, or ID can't be allocated. */ - struct file *bpf_link_new_file(struct bpf_link *link, int *reserved_fd) + int bpf_link_prime(struct bpf_link *link, struct bpf_link_primer *primer) { struct file *file; - int fd; + int fd, id;
fd = get_unused_fd_flags(O_CLOEXEC); if (fd < 0) - return ERR_PTR(fd); + return fd; + + + id = bpf_link_alloc_id(link); + if (id < 0) { + put_unused_fd(fd); + return id; + }
file = anon_inode_getfile("bpf_link", &bpf_link_fops, link, O_CLOEXEC); if (IS_ERR(file)) { + bpf_link_free_id(id); put_unused_fd(fd); - return file; + return PTR_ERR(file); }
- *reserved_fd = fd; - return file; + primer->link = link; + primer->file = file; + primer->fd = fd; + primer->id = id; + return 0; + } + + int bpf_link_settle(struct bpf_link_primer *primer) + { + /* make bpf_link fetchable by ID */ + spin_lock_bh(&link_idr_lock); + primer->link->id = primer->id; + spin_unlock_bh(&link_idr_lock); + /* make bpf_link fetchable by FD */ + fd_install(primer->fd, primer->file); + /* pass through installed FD */ + return primer->fd; + } + + int bpf_link_new_fd(struct bpf_link *link) + { + return anon_inode_getfd("bpf-link", &bpf_link_fops, link, O_CLOEXEC); }
struct bpf_link *bpf_link_get_from_fd(u32 ufd) @@@ -2347,6 -2407,7 +2409,7 @@@
struct bpf_tracing_link { struct bpf_link link; + enum bpf_attach_type attach_type; };
static void bpf_tracing_link_release(struct bpf_link *link) @@@ -2362,16 -2423,40 +2425,40 @@@ static void bpf_tracing_link_dealloc(st kfree(tr_link); }
+ static void bpf_tracing_link_show_fdinfo(const struct bpf_link *link, + struct seq_file *seq) + { + struct bpf_tracing_link *tr_link = + container_of(link, struct bpf_tracing_link, link); + + seq_printf(seq, + "attach_type:\t%d\n", + tr_link->attach_type); + } + + static int bpf_tracing_link_fill_link_info(const struct bpf_link *link, + struct bpf_link_info *info) + { + struct bpf_tracing_link *tr_link = + container_of(link, struct bpf_tracing_link, link); + + info->tracing.attach_type = tr_link->attach_type; + + return 0; + } + static const struct bpf_link_ops bpf_tracing_link_lops = { .release = bpf_tracing_link_release, .dealloc = bpf_tracing_link_dealloc, + .show_fdinfo = bpf_tracing_link_show_fdinfo, + .fill_link_info = bpf_tracing_link_fill_link_info, };
static int bpf_tracing_prog_attach(struct bpf_prog *prog) { + struct bpf_link_primer link_primer; struct bpf_tracing_link *link; - struct file *link_file; - int link_fd, err; + int err;
switch (prog->type) { case BPF_PROG_TYPE_TRACING: @@@ -2404,24 -2489,23 +2491,23 @@@ err = -ENOMEM; goto out_put_prog; } - bpf_link_init(&link->link, &bpf_tracing_link_lops, prog); + bpf_link_init(&link->link, BPF_LINK_TYPE_TRACING, + &bpf_tracing_link_lops, prog); + link->attach_type = prog->expected_attach_type;
- link_file = bpf_link_new_file(&link->link, &link_fd); - if (IS_ERR(link_file)) { + err = bpf_link_prime(&link->link, &link_primer); + if (err) { kfree(link); - err = PTR_ERR(link_file); goto out_put_prog; }
err = bpf_trampoline_link_prog(prog); if (err) { - bpf_link_cleanup(&link->link, link_file, link_fd); + bpf_link_cleanup(&link_primer); goto out_put_prog; }
- fd_install(link_fd, link_file); - return link_fd; - + return bpf_link_settle(&link_primer); out_put_prog: bpf_prog_put(prog); return err; @@@ -2449,22 -2533,69 +2535,69 @@@ static void bpf_raw_tp_link_dealloc(str kfree(raw_tp); }
- static const struct bpf_link_ops bpf_raw_tp_lops = { + static void bpf_raw_tp_link_show_fdinfo(const struct bpf_link *link, + struct seq_file *seq) + { + struct bpf_raw_tp_link *raw_tp_link = + container_of(link, struct bpf_raw_tp_link, link); + + seq_printf(seq, + "tp_name:\t%s\n", + raw_tp_link->btp->tp->name); + } + + static int bpf_raw_tp_link_fill_link_info(const struct bpf_link *link, + struct bpf_link_info *info) + { + struct bpf_raw_tp_link *raw_tp_link = + container_of(link, struct bpf_raw_tp_link, link); + char __user *ubuf = u64_to_user_ptr(info->raw_tracepoint.tp_name); + const char *tp_name = raw_tp_link->btp->tp->name; + u32 ulen = info->raw_tracepoint.tp_name_len; + size_t tp_len = strlen(tp_name); + + if (ulen && !ubuf) + return -EINVAL; + + info->raw_tracepoint.tp_name_len = tp_len + 1; + + if (!ubuf) + return 0; + + if (ulen >= tp_len + 1) { + if (copy_to_user(ubuf, tp_name, tp_len + 1)) + return -EFAULT; + } else { + char zero = '\0'; + + if (copy_to_user(ubuf, tp_name, ulen - 1)) + return -EFAULT; + if (put_user(zero, ubuf + ulen - 1)) + return -EFAULT; + return -ENOSPC; + } + + return 0; + } + + static const struct bpf_link_ops bpf_raw_tp_link_lops = { .release = bpf_raw_tp_link_release, .dealloc = bpf_raw_tp_link_dealloc, + .show_fdinfo = bpf_raw_tp_link_show_fdinfo, + .fill_link_info = bpf_raw_tp_link_fill_link_info, };
#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
static int bpf_raw_tracepoint_open(const union bpf_attr *attr) { + struct bpf_link_primer link_primer; struct bpf_raw_tp_link *link; struct bpf_raw_event_map *btp; - struct file *link_file; struct bpf_prog *prog; const char *tp_name; char buf[128]; - int link_fd, err; + int err;
if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN)) return -EINVAL; @@@ -2517,24 -2648,23 +2650,23 @@@ err = -ENOMEM; goto out_put_btp; } - bpf_link_init(&link->link, &bpf_raw_tp_lops, prog); + bpf_link_init(&link->link, BPF_LINK_TYPE_RAW_TRACEPOINT, + &bpf_raw_tp_link_lops, prog); link->btp = btp;
- link_file = bpf_link_new_file(&link->link, &link_fd); - if (IS_ERR(link_file)) { + err = bpf_link_prime(&link->link, &link_primer); + if (err) { kfree(link); - err = PTR_ERR(link_file); goto out_put_btp; }
err = bpf_probe_register(link->btp, prog); if (err) { - bpf_link_cleanup(&link->link, link_file, link_fd); + bpf_link_cleanup(&link_primer); goto out_put_btp; }
- fd_install(link_fd, link_file); - return link_fd; + return bpf_link_settle(&link_primer);
out_put_btp: bpf_put_raw_tracepoint(btp); @@@ -3315,6 -3445,42 +3447,42 @@@ static int bpf_btf_get_info_by_fd(struc return btf_get_info_by_fd(btf, attr, uattr); }
+ static int bpf_link_get_info_by_fd(struct bpf_link *link, + const union bpf_attr *attr, + union bpf_attr __user *uattr) + { + struct bpf_link_info __user *uinfo = u64_to_user_ptr(attr->info.info); + struct bpf_link_info info; + u32 info_len = attr->info.info_len; + int err; + + err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len); + if (err) + return err; + info_len = min_t(u32, sizeof(info), info_len); + + memset(&info, 0, sizeof(info)); + if (copy_from_user(&info, uinfo, info_len)) + return -EFAULT; + + info.type = link->type; + info.id = link->id; + info.prog_id = link->prog->aux->id; + + if (link->ops->fill_link_info) { + err = link->ops->fill_link_info(link, &info); + if (err) + return err; + } + + if (copy_to_user(uinfo, &info, info_len) || + put_user(info_len, &uattr->info.info_len)) + return -EFAULT; + + return 0; + } + + #define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info
static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, @@@ -3339,6 -3505,9 +3507,9 @@@ uattr); else if (f.file->f_op == &btf_fops) err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr); + else if (f.file->f_op == &bpf_link_fops) + err = bpf_link_get_info_by_fd(f.file->private_data, + attr, uattr); else err = -EINVAL;
@@@ -3466,7 -3635,7 +3637,7 @@@ static int bpf_task_fd_query(const unio if (file->f_op == &bpf_link_fops) { struct bpf_link *link = file->private_data;
- if (link->ops == &bpf_raw_tp_lops) { + if (link->ops == &bpf_raw_tp_link_lops) { struct bpf_raw_tp_link *raw_tp = container_of(link, struct bpf_raw_tp_link, link); struct bpf_raw_event_map *btp = raw_tp->btp; @@@ -3647,13 -3816,10 +3818,10 @@@ static int link_update(union bpf_attr * goto out_put_progs; }
- #ifdef CONFIG_CGROUP_BPF - if (link->ops == &bpf_cgroup_link_lops) { - ret = cgroup_bpf_replace(link, old_prog, new_prog); - goto out_put_progs; - } - #endif - ret = -EINVAL; + if (link->ops->update_prog) + ret = link->ops->update_prog(link, new_prog, old_prog); + else + ret = EINVAL;
out_put_progs: if (old_prog) @@@ -3665,6 -3831,102 +3833,102 @@@ out_put_link return ret; }
+ static int bpf_link_inc_not_zero(struct bpf_link *link) + { + return atomic64_fetch_add_unless(&link->refcnt, 1, 0) ? 0 : -ENOENT; + } + + #define BPF_LINK_GET_FD_BY_ID_LAST_FIELD link_id + + static int bpf_link_get_fd_by_id(const union bpf_attr *attr) + { + struct bpf_link *link; + u32 id = attr->link_id; + int fd, err; + + if (CHECK_ATTR(BPF_LINK_GET_FD_BY_ID)) + return -EINVAL; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + spin_lock_bh(&link_idr_lock); + link = idr_find(&link_idr, id); + /* before link is "settled", ID is 0, pretend it doesn't exist yet */ + if (link) { + if (link->id) + err = bpf_link_inc_not_zero(link); + else + err = -EAGAIN; + } else { + err = -ENOENT; + } + spin_unlock_bh(&link_idr_lock); + + if (err) + return err; + + fd = bpf_link_new_fd(link); + if (fd < 0) + bpf_link_put(link); + + return fd; + } + + DEFINE_MUTEX(bpf_stats_enabled_mutex); + + static int bpf_stats_release(struct inode *inode, struct file *file) + { + mutex_lock(&bpf_stats_enabled_mutex); + static_key_slow_dec(&bpf_stats_enabled_key.key); + mutex_unlock(&bpf_stats_enabled_mutex); + return 0; + } + + static const struct file_operations bpf_stats_fops = { + .release = bpf_stats_release, + }; + + static int bpf_enable_runtime_stats(void) + { + int fd; + + mutex_lock(&bpf_stats_enabled_mutex); + + /* Set a very high limit to avoid overflow */ + if (static_key_count(&bpf_stats_enabled_key.key) > INT_MAX / 2) { + mutex_unlock(&bpf_stats_enabled_mutex); + return -EBUSY; + } + + fd = anon_inode_getfd("bpf-stats", &bpf_stats_fops, NULL, O_CLOEXEC); + if (fd >= 0) + static_key_slow_inc(&bpf_stats_enabled_key.key); + + mutex_unlock(&bpf_stats_enabled_mutex); + return fd; + } + + #define BPF_ENABLE_STATS_LAST_FIELD enable_stats.type + + static int bpf_enable_stats(union bpf_attr *attr) + { + + if (CHECK_ATTR(BPF_ENABLE_STATS)) + return -EINVAL; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + switch (attr->enable_stats.type) { + case BPF_STATS_RUN_TIME: + return bpf_enable_runtime_stats(); + default: + break; + } + return -EINVAL; + } + SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) { union bpf_attr attr; @@@ -3782,6 -4044,16 +4046,16 @@@ case BPF_LINK_UPDATE: err = link_update(&attr); break; + case BPF_LINK_GET_FD_BY_ID: + err = bpf_link_get_fd_by_id(&attr); + break; + case BPF_LINK_GET_NEXT_ID: + err = bpf_obj_get_next_id(&attr, uattr, + &link_idr, &link_idr_lock); + break; + case BPF_ENABLE_STATS: + err = bpf_enable_stats(&attr); + break; default: err = -EINVAL; break; diff --combined net/batman-adv/bat_v_ogm.c index 80b87b1f4e3a,0959d32be65c..18028b9f95f0 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c @@@ -88,7 -88,7 +88,7 @@@ static void batadv_v_ogm_start_queue_ti unsigned int msecs = BATADV_MAX_AGGREGATION_MS * 1000;
/* msecs * [0.9, 1.1] */ - msecs += prandom_u32() % (msecs / 5) - (msecs / 10); + msecs += prandom_u32_max(msecs / 5) - (msecs / 10); queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.aggr_wq, msecs_to_jiffies(msecs / 1000)); } @@@ -107,7 -107,7 +107,7 @@@ static void batadv_v_ogm_start_timer(st return;
msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER; - msecs += prandom_u32() % (2 * BATADV_JITTER); + msecs += prandom_u32_max(2 * BATADV_JITTER); queue_delayed_work(batadv_event_workqueue, &bat_priv->bat_v.ogm_wq, msecs_to_jiffies(msecs)); } @@@ -893,7 -893,7 +893,7 @@@ static void batadv_v_ogm_process(const
orig_node = batadv_v_ogm_orig_get(bat_priv, ogm_packet->orig); if (!orig_node) - return; + goto out;
neigh_node = batadv_neigh_node_get_or_create(orig_node, if_incoming, ethhdr->h_source); diff --combined net/bridge/br_netlink.c index a0f5dbee8f9c,a774e19c41bb..240e260e3461 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@@ -151,6 -151,7 +151,7 @@@ static inline size_t br_port_info_size( + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MULTICAST_ROUTER */ #endif + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_GROUP_FWD_MASK */ + + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MRP_RING_OPEN */ + 0; }
@@@ -213,6 -214,8 +214,8 @@@ static int br_port_fill_attrs(struct sk nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) || nla_put_u8(skb, IFLA_BRPORT_NEIGH_SUPPRESS, !!(p->flags & BR_NEIGH_SUPPRESS)) || + nla_put_u8(skb, IFLA_BRPORT_MRP_RING_OPEN, !!(p->flags & + BR_MRP_LOST_CONT)) || nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED))) return -EMSGSIZE;
@@@ -612,7 -615,6 +615,7 @@@ int br_process_vlan_info(struct net_bri v - 1, rtm_cmd); v_change_start = 0; } + cond_resched(); } /* v_change_start is set only if the last/whole range changed */ if (v_change_start) @@@ -670,6 -672,11 +673,11 @@@ static int br_afspec(struct net_bridge if (err) return err; break; + case IFLA_BRIDGE_MRP: + err = br_mrp_parse(br, p, attr, cmd, extack); + if (err) + return err; + break; } }
@@@ -1102,7 -1109,9 +1110,9 @@@ static int br_changelink(struct net_dev if (data[IFLA_BR_STP_STATE]) { u32 stp_enabled = nla_get_u32(data[IFLA_BR_STP_STATE]);
- br_stp_set_enabled(br, stp_enabled); + err = br_stp_set_enabled(br, stp_enabled, extack); + if (err) + return err; }
if (data[IFLA_BR_PRIORITY]) { diff --combined net/core/dev.c index 294e59e20080,f8d83922a6af..4c91de39890a --- a/net/core/dev.c +++ b/net/core/dev.c @@@ -398,6 -398,74 +398,74 @@@ static RAW_NOTIFIER_HEAD(netdev_chain) DEFINE_PER_CPU_ALIGNED(struct softnet_data, softnet_data); EXPORT_PER_CPU_SYMBOL(softnet_data);
+ #ifdef CONFIG_LOCKDEP + /* + * register_netdevice() inits txq->_xmit_lock and sets lockdep class + * according to dev->type + */ + static const unsigned short netdev_lock_type[] = { + ARPHRD_NETROM, ARPHRD_ETHER, ARPHRD_EETHER, ARPHRD_AX25, + ARPHRD_PRONET, ARPHRD_CHAOS, ARPHRD_IEEE802, ARPHRD_ARCNET, + ARPHRD_APPLETLK, ARPHRD_DLCI, ARPHRD_ATM, ARPHRD_METRICOM, + ARPHRD_IEEE1394, ARPHRD_EUI64, ARPHRD_INFINIBAND, ARPHRD_SLIP, + ARPHRD_CSLIP, ARPHRD_SLIP6, ARPHRD_CSLIP6, ARPHRD_RSRVD, + ARPHRD_ADAPT, ARPHRD_ROSE, ARPHRD_X25, ARPHRD_HWX25, + ARPHRD_PPP, ARPHRD_CISCO, ARPHRD_LAPB, ARPHRD_DDCMP, + ARPHRD_RAWHDLC, ARPHRD_TUNNEL, ARPHRD_TUNNEL6, ARPHRD_FRAD, + ARPHRD_SKIP, ARPHRD_LOOPBACK, ARPHRD_LOCALTLK, ARPHRD_FDDI, + ARPHRD_BIF, ARPHRD_SIT, ARPHRD_IPDDP, ARPHRD_IPGRE, + ARPHRD_PIMREG, ARPHRD_HIPPI, ARPHRD_ASH, ARPHRD_ECONET, + ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, + ARPHRD_FCFABRIC, ARPHRD_IEEE80211, ARPHRD_IEEE80211_PRISM, + ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET, ARPHRD_PHONET_PIPE, + ARPHRD_IEEE802154, ARPHRD_VOID, ARPHRD_NONE}; + + static const char *const netdev_lock_name[] = { + "_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25", + "_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET", + "_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM", + "_xmit_IEEE1394", "_xmit_EUI64", "_xmit_INFINIBAND", "_xmit_SLIP", + "_xmit_CSLIP", "_xmit_SLIP6", "_xmit_CSLIP6", "_xmit_RSRVD", + "_xmit_ADAPT", "_xmit_ROSE", "_xmit_X25", "_xmit_HWX25", + "_xmit_PPP", "_xmit_CISCO", "_xmit_LAPB", "_xmit_DDCMP", + "_xmit_RAWHDLC", "_xmit_TUNNEL", "_xmit_TUNNEL6", "_xmit_FRAD", + "_xmit_SKIP", "_xmit_LOOPBACK", "_xmit_LOCALTLK", "_xmit_FDDI", + "_xmit_BIF", "_xmit_SIT", "_xmit_IPDDP", "_xmit_IPGRE", + "_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET", + "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL", + "_xmit_FCFABRIC", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM", + "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", "_xmit_PHONET_PIPE", + "_xmit_IEEE802154", "_xmit_VOID", "_xmit_NONE"}; + + static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)]; + + static inline unsigned short netdev_lock_pos(unsigned short dev_type) + { + int i; + + for (i = 0; i < ARRAY_SIZE(netdev_lock_type); i++) + if (netdev_lock_type[i] == dev_type) + return i; + /* the last key is used by default */ + return ARRAY_SIZE(netdev_lock_type) - 1; + } + + static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock, + unsigned short dev_type) + { + int i; + + i = netdev_lock_pos(dev_type); + lockdep_set_class_and_name(lock, &netdev_xmit_lock_key[i], + netdev_lock_name[i]); + } + #else + static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock, + unsigned short dev_type) + { + } + #endif + /******************************************************************************* * * Protocol management and registration routines @@@ -6227,7 -6295,8 +6295,8 @@@ EXPORT_SYMBOL(__napi_schedule_irqoff)
bool napi_complete_done(struct napi_struct *n, int work_done) { - unsigned long flags, val, new; + unsigned long flags, val, new, timeout = 0; + bool ret = true;
/* * 1) Don't let napi dequeue from the cpu poll list @@@ -6239,20 -6308,23 +6308,23 @@@ NAPIF_STATE_IN_BUSY_POLL))) return false;
+ if (work_done) { + if (n->gro_bitmask) + timeout = READ_ONCE(n->dev->gro_flush_timeout); + n->defer_hard_irqs_count = READ_ONCE(n->dev->napi_defer_hard_irqs); + } + if (n->defer_hard_irqs_count > 0) { + n->defer_hard_irqs_count--; + timeout = READ_ONCE(n->dev->gro_flush_timeout); + if (timeout) + ret = false; + } if (n->gro_bitmask) { - unsigned long timeout = 0; - - if (work_done) - timeout = n->dev->gro_flush_timeout; - /* When the NAPI instance uses a timeout and keeps postponing * it, we need to bound somehow the time packets are kept in * the GRO layer */ napi_gro_flush(n, !!timeout); - if (timeout) - hrtimer_start(&n->timer, ns_to_ktime(timeout), - HRTIMER_MODE_REL_PINNED); }
gro_normal_list(n); @@@ -6284,7 -6356,10 +6356,10 @@@ return false; }
- return true; + if (timeout) + hrtimer_start(&n->timer, ns_to_ktime(timeout), + HRTIMER_MODE_REL_PINNED); + return ret; } EXPORT_SYMBOL(napi_complete_done);
@@@ -6464,7 -6539,7 +6539,7 @@@ static enum hrtimer_restart napi_watchd /* Note : we use a relaxed variant of napi_schedule_prep() not setting * NAPI_STATE_MISSED, since we do not react to a device IRQ. */ - if (napi->gro_bitmask && !napi_disable_pending(napi) && + if (!napi_disable_pending(napi) && !test_and_set_bit(NAPI_STATE_SCHED, &napi->state)) __napi_schedule_irqoff(napi);
@@@ -7786,28 -7861,6 +7861,28 @@@ void netdev_bonding_info_change(struct } EXPORT_SYMBOL(netdev_bonding_info_change);
+/** + * netdev_get_xmit_slave - Get the xmit slave of master device + * @skb: The packet + * @all_slaves: assume all the slaves are active + * + * The reference counters are not incremented so the caller must be + * careful with locks. The caller must hold RCU lock. + * %NULL is returned if no slave is found. + */ + +struct net_device *netdev_get_xmit_slave(struct net_device *dev, + struct sk_buff *skb, + bool all_slaves) +{ + const struct net_device_ops *ops = dev->netdev_ops; + + if (!ops->ndo_get_xmit_slave) + return NULL; + return ops->ndo_get_xmit_slave(dev, skb, all_slaves); +} +EXPORT_SYMBOL(netdev_get_xmit_slave); + static void netdev_adjacent_add_links(struct net_device *dev) { struct netdev_adjacent *iter; @@@ -9158,6 -9211,11 +9233,11 @@@ void netif_stacked_transfer_operstate(c else netif_dormant_off(dev);
+ if (rootdev->operstate == IF_OPER_TESTING) + netif_testing_on(dev); + else + netif_testing_off(dev); + if (netif_carrier_ok(rootdev)) netif_carrier_on(dev); else @@@ -9218,7 -9276,7 +9298,7 @@@ static void netdev_init_one_queue(struc { /* Initialize queue lock */ spin_lock_init(&queue->_xmit_lock); - lockdep_set_class(&queue->_xmit_lock, &dev->qdisc_xmit_lock_key); + netdev_set_xmit_lockdep_class(&queue->_xmit_lock, dev->type); queue->xmit_lock_owner = -1; netdev_queue_numa_node_write(queue, NUMA_NO_NODE); queue->dev = dev; @@@ -9265,22 -9323,6 +9345,6 @@@ void netif_tx_stop_all_queues(struct ne } EXPORT_SYMBOL(netif_tx_stop_all_queues);
- static void netdev_register_lockdep_key(struct net_device *dev) - { - lockdep_register_key(&dev->qdisc_tx_busylock_key); - lockdep_register_key(&dev->qdisc_running_key); - lockdep_register_key(&dev->qdisc_xmit_lock_key); - lockdep_register_key(&dev->addr_list_lock_key); - } - - static void netdev_unregister_lockdep_key(struct net_device *dev) - { - lockdep_unregister_key(&dev->qdisc_tx_busylock_key); - lockdep_unregister_key(&dev->qdisc_running_key); - lockdep_unregister_key(&dev->qdisc_xmit_lock_key); - lockdep_unregister_key(&dev->addr_list_lock_key); - } - void netdev_update_lockdep_key(struct net_device *dev) { lockdep_unregister_key(&dev->addr_list_lock_key); @@@ -9847,7 -9889,7 +9911,7 @@@ struct net_device *alloc_netdev_mqs(in
dev_net_set(dev, &init_net);
- netdev_register_lockdep_key(dev); + lockdep_register_key(&dev->addr_list_lock_key);
dev->gso_max_size = GSO_MAX_SIZE; dev->gso_max_segs = GSO_MAX_SEGS; @@@ -9936,7 -9978,7 +10000,7 @@@ void free_netdev(struct net_device *dev free_percpu(dev->xdp_bulkq); dev->xdp_bulkq = NULL;
- netdev_unregister_lockdep_key(dev); + lockdep_unregister_key(&dev->addr_list_lock_key);
/* Compatibility with error handling in drivers */ if (dev->reg_state == NETREG_UNINITIALIZED) { diff --combined net/core/devlink.c index 899edcee7dab,43a9d5be73ca..20f935fa29f5 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@@ -3716,24 -3716,26 +3716,26 @@@ nla_put_failure return err; }
- static void devlink_nl_region_notify(struct devlink_region *region, - struct devlink_snapshot *snapshot, - enum devlink_command cmd) + static struct sk_buff * + devlink_nl_region_notify_build(struct devlink_region *region, + struct devlink_snapshot *snapshot, + enum devlink_command cmd, u32 portid, u32 seq) { struct devlink *devlink = region->devlink; struct sk_buff *msg; void *hdr; int err;
- WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) - return; + return ERR_PTR(-ENOMEM);
- hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); - if (!hdr) + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd); + if (!hdr) { + err = -EMSGSIZE; goto out_free_msg; + }
err = devlink_nl_put_handle(msg, devlink); if (err) @@@ -3757,15 -3759,30 +3759,30 @@@ } genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), - msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); - - return; + return msg;
out_cancel_msg: genlmsg_cancel(msg, hdr); out_free_msg: nlmsg_free(msg); + return ERR_PTR(err); + } + + static void devlink_nl_region_notify(struct devlink_region *region, + struct devlink_snapshot *snapshot, + enum devlink_command cmd) + { + struct devlink *devlink = region->devlink; + struct sk_buff *msg; + + WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); + + msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0); + if (IS_ERR(msg)) + return; + + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), + msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); }
/** @@@ -4069,6 -4086,8 +4086,8 @@@ static in devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info) { struct devlink *devlink = info->user_ptr[0]; + struct devlink_snapshot *snapshot; + struct nlattr *snapshot_id_attr; struct devlink_region *region; const char *region_name; u32 snapshot_id; @@@ -4080,11 -4099,6 +4099,6 @@@ return -EINVAL; }
- if (!info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { - NL_SET_ERR_MSG_MOD(info->extack, "No snapshot id provided"); - return -EINVAL; - } - region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); region = devlink_region_get_by_name(devlink, region_name); if (!region) { @@@ -4102,16 -4116,25 +4116,25 @@@ return -ENOSPC; }
- snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); + snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; + if (snapshot_id_attr) { + snapshot_id = nla_get_u32(snapshot_id_attr);
- if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { - NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use"); - return -EEXIST; - } + if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { + NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use"); + return -EEXIST; + }
- err = __devlink_snapshot_id_insert(devlink, snapshot_id); - if (err) - return err; + err = __devlink_snapshot_id_insert(devlink, snapshot_id); + if (err) + return err; + } else { + err = __devlink_region_snapshot_id_get(devlink, &snapshot_id); + if (err) { + NL_SET_ERR_MSG_MOD(info->extack, "Failed to allocate a new snapshot id"); + return err; + } + }
err = region->ops->snapshot(devlink, info->extack, &data); if (err) @@@ -4121,6 -4144,27 +4144,27 @@@ if (err) goto err_snapshot_create;
+ if (!snapshot_id_attr) { + struct sk_buff *msg; + + snapshot = devlink_region_snapshot_get_by_id(region, + snapshot_id); + if (WARN_ON(!snapshot)) + return -EINVAL; + + msg = devlink_nl_region_notify_build(region, snapshot, + DEVLINK_CMD_REGION_NEW, + info->snd_portid, + info->snd_seq); + err = PTR_ERR_OR_ZERO(msg); + if (err) + goto err_notify; + + err = genlmsg_reply(msg, info); + if (err) + goto err_notify; + } + return 0;
err_snapshot_create: @@@ -4128,6 -4172,10 +4172,10 @@@ err_snapshot_capture: __devlink_snapshot_id_decrement(devlink, snapshot_id); return err; + + err_notify: + devlink_region_snapshot_del(region, snapshot); + return err; }
static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, @@@ -4283,11 -4331,6 +4331,11 @@@ static int devlink_nl_cmd_region_read_d end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); dump = false; + + if (start_offset == end_offset) { + err = 0; + goto nla_put_failure; + } }
err = devlink_nl_region_read_snapshot_fill(skb, devlink, @@@ -5368,7 -5411,6 +5416,7 @@@ int devlink_health_report(struct devlin { enum devlink_health_reporter_state prev_health_state; struct devlink *devlink = reporter->devlink; + unsigned long recover_ts_threshold;
/* write a log message of the current error */ WARN_ON(!msg); @@@ -5379,12 -5421,10 +5427,12 @@@ devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
/* abort if the previous error wasn't recovered */ + recover_ts_threshold = reporter->last_recovery_ts + + msecs_to_jiffies(reporter->graceful_period); if (reporter->auto_recover && (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY || - jiffies - reporter->last_recovery_ts < - msecs_to_jiffies(reporter->graceful_period))) { + (reporter->last_recovery_ts && reporter->recovery_count && + time_is_after_jiffies(recover_ts_threshold)))) { trace_devlink_health_recover_aborted(devlink, reporter->ops->name, reporter->health_state, diff --combined net/core/filter.c index 5cc9276f1023,dfaf5df13722..cb645f74b3d5 --- a/net/core/filter.c +++ b/net/core/filter.c @@@ -256,17 -256,6 +256,6 @@@ BPF_CALL_2(bpf_skb_load_helper_32_no_ca offset); }
- BPF_CALL_0(bpf_get_raw_cpu_id) - { - return raw_smp_processor_id(); - } - - static const struct bpf_func_proto bpf_get_raw_smp_processor_id_proto = { - .func = bpf_get_raw_cpu_id, - .gpl_only = false, - .ret_type = RET_INTEGER, - }; - static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg, struct bpf_insn *insn_buf) { @@@ -2590,8 -2579,8 +2579,8 @@@ BPF_CALL_4(bpf_msg_pop_data, struct sk_ } pop = 0; } else if (pop >= sge->length - a) { - sge->length = a; pop -= (sge->length - a); + sge->length = a; } }
@@@ -4205,36 -4194,19 +4194,19 @@@ static const struct bpf_func_proto bpf_ .arg1_type = ARG_PTR_TO_CTX, };
- BPF_CALL_5(bpf_event_output_data, void *, ctx, struct bpf_map *, map, u64, flags, - void *, data, u64, size) - { - if (unlikely(flags & ~(BPF_F_INDEX_MASK))) - return -EINVAL; - - return bpf_event_output(map, flags, data, size, NULL, 0, NULL); - } + #define SOCKOPT_CC_REINIT (1 << 0)
- static const struct bpf_func_proto bpf_event_output_data_proto = { - .func = bpf_event_output_data, - .gpl_only = true, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - - BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock, - int, level, int, optname, char *, optval, int, optlen) + static int _bpf_setsockopt(struct sock *sk, int level, int optname, + char *optval, int optlen, u32 flags) { - struct sock *sk = bpf_sock->sk; int ret = 0; int val;
if (!sk_fullsock(sk)) return -EINVAL;
+ sock_owned_by_me(sk); + if (level == SOL_SOCKET) { if (optlen != sizeof(int)) return -EINVAL; @@@ -4329,7 -4301,7 +4301,7 @@@ sk->sk_prot->setsockopt == tcp_setsockopt) { if (optname == TCP_CONGESTION) { char name[TCP_CA_NAME_MAX]; - bool reinit = bpf_sock->op > BPF_SOCK_OPS_NEEDS_ECN; + bool reinit = flags & SOCKOPT_CC_REINIT;
strncpy(name, optval, min_t(long, optlen, TCP_CA_NAME_MAX-1)); @@@ -4376,24 -4348,14 +4348,14 @@@ return ret; }
- static const struct bpf_func_proto bpf_setsockopt_proto = { - .func = bpf_setsockopt, - .gpl_only = false, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, - .arg5_type = ARG_CONST_SIZE, - }; - - BPF_CALL_5(bpf_getsockopt, struct bpf_sock_ops_kern *, bpf_sock, - int, level, int, optname, char *, optval, int, optlen) + static int _bpf_getsockopt(struct sock *sk, int level, int optname, + char *optval, int optlen) { - struct sock *sk = bpf_sock->sk; - if (!sk_fullsock(sk)) goto err_clear; + + sock_owned_by_me(sk); + #ifdef CONFIG_INET if (level == SOL_TCP && sk->sk_prot->getsockopt == tcp_getsockopt) { struct inet_connection_sock *icsk; @@@ -4459,8 -4421,71 +4421,71 @@@ err_clear return -EINVAL; }
- static const struct bpf_func_proto bpf_getsockopt_proto = { - .func = bpf_getsockopt, + BPF_CALL_5(bpf_sock_addr_setsockopt, struct bpf_sock_addr_kern *, ctx, + int, level, int, optname, char *, optval, int, optlen) + { + u32 flags = 0; + return _bpf_setsockopt(ctx->sk, level, optname, optval, optlen, + flags); + } + + static const struct bpf_func_proto bpf_sock_addr_setsockopt_proto = { + .func = bpf_sock_addr_setsockopt, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_PTR_TO_MEM, + .arg5_type = ARG_CONST_SIZE, + }; + + BPF_CALL_5(bpf_sock_addr_getsockopt, struct bpf_sock_addr_kern *, ctx, + int, level, int, optname, char *, optval, int, optlen) + { + return _bpf_getsockopt(ctx->sk, level, optname, optval, optlen); + } + + static const struct bpf_func_proto bpf_sock_addr_getsockopt_proto = { + .func = bpf_sock_addr_getsockopt, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_PTR_TO_UNINIT_MEM, + .arg5_type = ARG_CONST_SIZE, + }; + + BPF_CALL_5(bpf_sock_ops_setsockopt, struct bpf_sock_ops_kern *, bpf_sock, + int, level, int, optname, char *, optval, int, optlen) + { + u32 flags = 0; + if (bpf_sock->op > BPF_SOCK_OPS_NEEDS_ECN) + flags |= SOCKOPT_CC_REINIT; + return _bpf_setsockopt(bpf_sock->sk, level, optname, optval, optlen, + flags); + } + + static const struct bpf_func_proto bpf_sock_ops_setsockopt_proto = { + .func = bpf_sock_ops_setsockopt, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, + .arg4_type = ARG_PTR_TO_MEM, + .arg5_type = ARG_CONST_SIZE, + }; + + BPF_CALL_5(bpf_sock_ops_getsockopt, struct bpf_sock_ops_kern *, bpf_sock, + int, level, int, optname, char *, optval, int, optlen) + { + return _bpf_getsockopt(bpf_sock->sk, level, optname, optval, optlen); + } + + static const struct bpf_func_proto bpf_sock_ops_getsockopt_proto = { + .func = bpf_sock_ops_getsockopt, .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, @@@ -5983,52 -6008,7 +6008,7 @@@ bool bpf_helper_changes_pkt_data(void * return false; }
- const struct bpf_func_proto * - bpf_base_func_proto(enum bpf_func_id func_id) - { - switch (func_id) { - case BPF_FUNC_map_lookup_elem: - return &bpf_map_lookup_elem_proto; - case BPF_FUNC_map_update_elem: - return &bpf_map_update_elem_proto; - case BPF_FUNC_map_delete_elem: - return &bpf_map_delete_elem_proto; - case BPF_FUNC_map_push_elem: - return &bpf_map_push_elem_proto; - case BPF_FUNC_map_pop_elem: - return &bpf_map_pop_elem_proto; - case BPF_FUNC_map_peek_elem: - return &bpf_map_peek_elem_proto; - case BPF_FUNC_get_prandom_u32: - return &bpf_get_prandom_u32_proto; - case BPF_FUNC_get_smp_processor_id: - return &bpf_get_raw_smp_processor_id_proto; - case BPF_FUNC_get_numa_node_id: - return &bpf_get_numa_node_id_proto; - case BPF_FUNC_tail_call: - return &bpf_tail_call_proto; - case BPF_FUNC_ktime_get_ns: - return &bpf_ktime_get_ns_proto; - default: - break; - } - - if (!capable(CAP_SYS_ADMIN)) - return NULL; - - switch (func_id) { - case BPF_FUNC_spin_lock: - return &bpf_spin_lock_proto; - case BPF_FUNC_spin_unlock: - return &bpf_spin_unlock_proto; - case BPF_FUNC_trace_printk: - return bpf_get_trace_printk_proto(); - case BPF_FUNC_jiffies64: - return &bpf_jiffies64_proto; - default: - return NULL; - } - } + const struct bpf_func_proto bpf_event_output_data_proto __weak;
static const struct bpf_func_proto * sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) @@@ -6119,6 -6099,22 +6099,22 @@@ sock_addr_func_proto(enum bpf_func_id f return &bpf_sk_storage_get_proto; case BPF_FUNC_sk_storage_delete: return &bpf_sk_storage_delete_proto; + case BPF_FUNC_setsockopt: + switch (prog->expected_attach_type) { + case BPF_CGROUP_INET4_CONNECT: + case BPF_CGROUP_INET6_CONNECT: + return &bpf_sock_addr_setsockopt_proto; + default: + return NULL; + } + case BPF_FUNC_getsockopt: + switch (prog->expected_attach_type) { + case BPF_CGROUP_INET4_CONNECT: + case BPF_CGROUP_INET6_CONNECT: + return &bpf_sock_addr_getsockopt_proto; + default: + return NULL; + } default: return bpf_base_func_proto(func_id); } @@@ -6213,6 -6209,8 +6209,8 @@@ tc_cls_act_func_proto(enum bpf_func_id return &bpf_skb_adjust_room_proto; case BPF_FUNC_skb_change_tail: return &bpf_skb_change_tail_proto; + case BPF_FUNC_skb_change_head: + return &bpf_skb_change_head_proto; case BPF_FUNC_skb_get_tunnel_key: return &bpf_skb_get_tunnel_key_proto; case BPF_FUNC_skb_set_tunnel_key: @@@ -6335,9 -6333,9 +6333,9 @@@ sock_ops_func_proto(enum bpf_func_id fu { switch (func_id) { case BPF_FUNC_setsockopt: - return &bpf_setsockopt_proto; + return &bpf_sock_ops_setsockopt_proto; case BPF_FUNC_getsockopt: - return &bpf_getsockopt_proto; + return &bpf_sock_ops_getsockopt_proto; case BPF_FUNC_sock_ops_cb_flags_set: return &bpf_sock_ops_cb_flags_set_proto; case BPF_FUNC_sock_map_update: @@@ -8786,6 -8784,10 +8784,10 @@@ BPF_CALL_4(sk_select_reuseport, struct
reuse = rcu_dereference(selected_sk->sk_reuseport_cb); if (!reuse) { + /* Lookup in sock_map can return TCP ESTABLISHED sockets. */ + if (sk_is_refcounted(selected_sk)) + sock_put(selected_sk); + /* reuseport_array has only sk with non NULL sk_reuseport_cb. * The only (!reuse) case here is - the sk has already been * unhashed (e.g. by close()), so treat it as -ENOENT. diff --combined net/ipv4/tcp_input.c index b996dc1069c5,7d205b2a733c..66e55e51c550 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@@ -3014,7 -3014,7 +3014,7 @@@ void tcp_rearm_rto(struct sock *sk rto = usecs_to_jiffies(max_t(int, delta_us, 1)); } tcp_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto, - TCP_RTO_MAX, tcp_rtx_queue_head(sk)); + TCP_RTO_MAX); } }
@@@ -3291,7 -3291,7 +3291,7 @@@ static void tcp_ack_probe(struct sock * unsigned long when = tcp_probe0_when(sk, TCP_RTO_MAX);
tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0, - when, TCP_RTO_MAX, NULL); + when, TCP_RTO_MAX); } }
@@@ -3926,6 -3926,10 +3926,6 @@@ void tcp_parse_options(const struct ne */ break; #endif - case TCPOPT_MPTCP: - mptcp_parse_option(skb, ptr, opsize, opt_rx); - break; - case TCPOPT_FASTOPEN: tcp_parse_fastopen_option( opsize - TCPOLEN_FASTOPEN_BASE, @@@ -4323,6 -4327,33 +4323,33 @@@ static void tcp_sack_maybe_coalesce(str } }
+ static void tcp_sack_compress_send_ack(struct sock *sk) + { + struct tcp_sock *tp = tcp_sk(sk); + + if (!tp->compressed_ack) + return; + + if (hrtimer_try_to_cancel(&tp->compressed_ack_timer) == 1) + __sock_put(sk); + + /* Since we have to send one ack finally, + * substract one from tp->compressed_ack to keep + * LINUX_MIB_TCPACKCOMPRESSED accurate. + */ + NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPACKCOMPRESSED, + tp->compressed_ack - 1); + + tp->compressed_ack = 0; + tcp_send_ack(sk); + } + + /* Reasonable amount of sack blocks included in TCP SACK option + * The max is 4, but this becomes 3 if TCP timestamps are there. + * Given that SACK packets might be lost, be conservative and use 2. + */ + #define TCP_SACK_BLOCKS_EXPECTED 2 + static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq) { struct tcp_sock *tp = tcp_sk(sk); @@@ -4335,6 -4366,8 +4362,8 @@@
for (this_sack = 0; this_sack < cur_sacks; this_sack++, sp++) { if (tcp_sack_extend(sp, seq, end_seq)) { + if (this_sack >= TCP_SACK_BLOCKS_EXPECTED) + tcp_sack_compress_send_ack(sk); /* Rotate this_sack to the first one. */ for (; this_sack > 0; this_sack--, sp--) swap(*sp, *(sp - 1)); @@@ -4344,6 -4377,9 +4373,9 @@@ } }
+ if (this_sack >= TCP_SACK_BLOCKS_EXPECTED) + tcp_sack_compress_send_ack(sk); + /* Could not find an adjacent existing SACK, build a new one, * put it at the front, and shift everyone else down. We * always know there is at least one SACK present already here. @@@ -4351,8 -4387,6 +4383,6 @@@ * If the sack array is full, forget about the last one. */ if (this_sack >= TCP_NUM_SACKS) { - if (tp->compressed_ack > TCP_FASTRETRANS_THRESH) - tcp_send_ack(sk); this_sack--; tp->rx_opt.num_sacks--; sp--; @@@ -5271,15 -5305,13 +5301,13 @@@ send_now
if (tp->compressed_ack_rcv_nxt != tp->rcv_nxt) { tp->compressed_ack_rcv_nxt = tp->rcv_nxt; - if (tp->compressed_ack > TCP_FASTRETRANS_THRESH) - NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPACKCOMPRESSED, - tp->compressed_ack - TCP_FASTRETRANS_THRESH); - tp->compressed_ack = 0; + tp->dup_ack_counter = 0; } - - if (++tp->compressed_ack <= TCP_FASTRETRANS_THRESH) + if (tp->dup_ack_counter < TCP_FASTRETRANS_THRESH) { + tp->dup_ack_counter++; goto send_now; - + } + tp->compressed_ack++; if (hrtimer_is_queued(&tp->compressed_ack_timer)) return;
@@@ -5292,8 -5324,9 +5320,9 @@@ delay = min_t(unsigned long, sock_net(sk)->ipv4.sysctl_tcp_comp_sack_delay_ns, rtt * (NSEC_PER_USEC >> 3)/20); sock_hold(sk); - hrtimer_start(&tp->compressed_ack_timer, ns_to_ktime(delay), - HRTIMER_MODE_REL_PINNED_SOFT); + hrtimer_start_range_ns(&tp->compressed_ack_timer, ns_to_ktime(delay), + sock_net(sk)->ipv4.sysctl_tcp_comp_sack_slack_ns, + HRTIMER_MODE_REL_PINNED_SOFT); }
static inline void tcp_ack_snd_check(struct sock *sk) @@@ -5986,6 -6019,9 +6015,6 @@@ static int tcp_rcv_synsent_state_proces tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); tcp_initialize_rcv_mss(sk);
- if (sk_is_mptcp(sk)) - mptcp_rcv_synsent(sk); - /* Remember, tcp_poll() does not lock socket! * Change state from SYN-SENT only after copied_seq * is initialized. */ diff --combined net/ipv6/route.c index 92b420fb4431,3912aac7854d..1ff142393c76 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@@ -984,7 -984,7 +984,7 @@@ int rt6_route_rcv(struct net_device *de gwaddr, dev);
if (rt && !lifetime) { - ip6_del_rt(net, rt); + ip6_del_rt(net, rt, false); rt = NULL; }
@@@ -1385,18 -1385,9 +1385,18 @@@ static struct rt6_info *ip6_rt_pcpu_all } ip6_rt_copy_init(pcpu_rt, res); pcpu_rt->rt6i_flags |= RTF_PCPU; + + if (f6i->nh) + pcpu_rt->sernum = rt_genid_ipv6(dev_net(dev)); + return pcpu_rt; }
+static bool rt6_is_valid(const struct rt6_info *rt6) +{ + return rt6->sernum == rt_genid_ipv6(dev_net(rt6->dst.dev)); +} + /* It should be called with rcu_read_lock() acquired */ static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res) { @@@ -1404,19 -1395,6 +1404,19 @@@
pcpu_rt = this_cpu_read(*res->nh->rt6i_pcpu);
+ if (pcpu_rt && pcpu_rt->sernum && !rt6_is_valid(pcpu_rt)) { + struct rt6_info *prev, **p; + + p = this_cpu_ptr(res->nh->rt6i_pcpu); + prev = xchg(p, NULL); + if (prev) { + dst_dev_put(&prev->dst); + dst_release(&prev->dst); + } + + pcpu_rt = NULL; + } + return pcpu_rt; }
@@@ -2615,9 -2593,6 +2615,9 @@@ static struct dst_entry *ip6_dst_check(
rt = container_of(dst, struct rt6_info, dst);
+ if (rt->sernum) + return rt6_is_valid(rt) ? dst : NULL; + rcu_read_lock();
/* All IPV6 dsts are created with ->obsolete set to the value @@@ -3754,9 -3729,12 +3754,12 @@@ out return err; }
- int ip6_del_rt(struct net *net, struct fib6_info *rt) + int ip6_del_rt(struct net *net, struct fib6_info *rt, bool skip_notify) { - struct nl_info info = { .nl_net = net }; + struct nl_info info = { + .nl_net = net, + .skip_notify = skip_notify + };
return __ip6_del_rt(rt, &info); } @@@ -4277,7 -4255,7 +4280,7 @@@ restart (!idev || idev->cnf.accept_ra != 2) && fib6_info_hold_safe(rt)) { rcu_read_unlock(); - ip6_del_rt(net, rt); + ip6_del_rt(net, rt, false); goto restart; } } @@@ -5579,7 -5557,8 +5582,8 @@@ static int rt6_fill_node(struct net *ne if (nexthop_is_blackhole(rt->nh)) rtm->rtm_type = RTN_BLACKHOLE;
- if (rt6_fill_node_nexthop(skb, rt->nh, &nh_flags) < 0) + if (net->ipv4.sysctl_nexthop_compat_mode && + rt6_fill_node_nexthop(skb, rt->nh, &nh_flags) < 0) goto nla_put_failure;
rtm->rtm_flags |= nh_flags; diff --combined net/mptcp/subflow.c index 67a4e35d4838,87c094702d63..009d5c478062 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@@ -124,11 -124,12 +124,11 @@@ static void subflow_init_req(struct req { struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener); struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); - struct tcp_options_received rx_opt; + struct mptcp_options_received mp_opt;
pr_debug("subflow_req=%p, listener=%p", subflow_req, listener);
- memset(&rx_opt.mptcp, 0, sizeof(rx_opt.mptcp)); - mptcp_get_options(skb, &rx_opt); + mptcp_get_options(skb, &mp_opt);
subflow_req->mp_capable = 0; subflow_req->mp_join = 0; @@@ -141,16 -142,16 +141,16 @@@ return; #endif
- if (rx_opt.mptcp.mp_capable) { + if (mp_opt.mp_capable) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE);
- if (rx_opt.mptcp.mp_join) + if (mp_opt.mp_join) return; - } else if (rx_opt.mptcp.mp_join) { + } else if (mp_opt.mp_join) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX); }
- if (rx_opt.mptcp.mp_capable && listener->request_mptcp) { + if (mp_opt.mp_capable && listener->request_mptcp) { int err;
err = mptcp_token_new_request(req); @@@ -158,13 -159,13 +158,13 @@@ subflow_req->mp_capable = 1;
subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; - } else if (rx_opt.mptcp.mp_join && listener->request_mptcp) { + } else if (mp_opt.mp_join && listener->request_mptcp) { subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; subflow_req->mp_join = 1; - subflow_req->backup = rx_opt.mptcp.backup; - subflow_req->remote_id = rx_opt.mptcp.join_id; - subflow_req->token = rx_opt.mptcp.token; - subflow_req->remote_nonce = rx_opt.mptcp.nonce; + subflow_req->backup = mp_opt.backup; + subflow_req->remote_id = mp_opt.join_id; + subflow_req->token = mp_opt.token; + subflow_req->remote_nonce = mp_opt.nonce; pr_debug("token=%u, remote_nonce=%u", subflow_req->token, subflow_req->remote_nonce); if (!subflow_token_join_request(req, skb)) { @@@ -220,47 -221,23 +220,47 @@@ static bool subflow_thmac_valid(struct static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); + struct mptcp_options_received mp_opt; struct sock *parent = subflow->conn; + struct tcp_sock *tp = tcp_sk(sk);
subflow->icsk_af_ops->sk_rx_dst_set(sk, skb);
- if (inet_sk_state_load(parent) != TCP_ESTABLISHED) { + if (inet_sk_state_load(parent) == TCP_SYN_SENT) { inet_sk_state_store(parent, TCP_ESTABLISHED); parent->sk_state_change(parent); }
- if (subflow->conn_finished || !tcp_sk(sk)->is_mptcp) + /* be sure no special action on any packet other than syn-ack */ + if (subflow->conn_finished) + return; + + subflow->conn_finished = 1; + + mptcp_get_options(skb, &mp_opt); + if (subflow->request_mptcp && mp_opt.mp_capable) { + subflow->mp_capable = 1; + subflow->can_ack = 1; + subflow->remote_key = mp_opt.sndr_key; + pr_debug("subflow=%p, remote_key=%llu", subflow, + subflow->remote_key); + } else if (subflow->request_join && mp_opt.mp_join) { + subflow->mp_join = 1; + subflow->thmac = mp_opt.thmac; + subflow->remote_nonce = mp_opt.nonce; + pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow, + subflow->thmac, subflow->remote_nonce); + } else if (subflow->request_mptcp) { + tp->is_mptcp = 0; + } + + if (!tp->is_mptcp) return;
if (subflow->mp_capable) { pr_debug("subflow=%p, remote_key=%llu", mptcp_subflow_ctx(sk), subflow->remote_key); mptcp_finish_connect(sk); - subflow->conn_finished = 1;
if (skb) { pr_debug("synack seq=%u", TCP_SKB_CB(skb)->seq); @@@ -287,6 -264,7 +287,6 @@@ if (!mptcp_finish_join(sk)) goto do_reset;
- subflow->conn_finished = 1; MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX); } else { do_reset: @@@ -344,7 -322,7 +344,7 @@@ drop
/* validate hmac received in third ACK */ static bool subflow_hmac_valid(const struct request_sock *req, - const struct tcp_options_received *rx_opt) + const struct mptcp_options_received *mp_opt) { const struct mptcp_subflow_request_sock *subflow_req; u8 hmac[MPTCPOPT_HMAC_LEN]; @@@ -361,7 -339,7 +361,7 @@@ subflow_req->local_nonce, hmac);
ret = true; - if (crypto_memneq(hmac, rx_opt->mptcp.hmac, sizeof(hmac))) + if (crypto_memneq(hmac, mp_opt->hmac, sizeof(hmac))) ret = false;
sock_put((struct sock *)msk); @@@ -417,7 -395,7 +417,7 @@@ static struct sock *subflow_syn_recv_so { struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk); struct mptcp_subflow_request_sock *subflow_req; - struct tcp_options_received opt_rx; + struct mptcp_options_received mp_opt; bool fallback_is_fatal = false; struct sock *new_msk = NULL; bool fallback = false; @@@ -425,10 -403,7 +425,10 @@@
pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn);
- opt_rx.mptcp.mp_capable = 0; + /* we need later a valid 'mp_capable' value even when options are not + * parsed + */ + mp_opt.mp_capable = 0; if (tcp_rsk(req)->is_mptcp == 0) goto create_child;
@@@ -443,21 -418,22 +443,21 @@@ goto create_msk; }
- mptcp_get_options(skb, &opt_rx); - if (!opt_rx.mptcp.mp_capable) { + mptcp_get_options(skb, &mp_opt); + if (!mp_opt.mp_capable) { fallback = true; goto create_child; }
create_msk: - new_msk = mptcp_sk_clone(listener->conn, &opt_rx, req); + new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req); if (!new_msk) fallback = true; } else if (subflow_req->mp_join) { fallback_is_fatal = true; - opt_rx.mptcp.mp_join = 0; - mptcp_get_options(skb, &opt_rx); - if (!opt_rx.mptcp.mp_join || - !subflow_hmac_valid(req, &opt_rx)) { + mptcp_get_options(skb, &mp_opt); + if (!mp_opt.mp_join || + !subflow_hmac_valid(req, &mp_opt)) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); return NULL; } @@@ -497,9 -473,9 +497,9 @@@ create_child /* with OoO packets we can reach here without ingress * mpc option */ - ctx->remote_key = opt_rx.mptcp.sndr_key; - ctx->fully_established = opt_rx.mptcp.mp_capable; - ctx->can_ack = opt_rx.mptcp.mp_capable; + ctx->remote_key = mp_opt.sndr_key; + ctx->fully_established = mp_opt.mp_capable; + ctx->can_ack = mp_opt.mp_capable; } else if (ctx->mp_join) { struct mptcp_sock *owner;
@@@ -523,7 -499,7 +523,7 @@@ out /* check for expected invariant - should never trigger, just help * catching eariler subtle bugs */ - WARN_ON_ONCE(*own_req && child && tcp_sk(child)->is_mptcp && + WARN_ON_ONCE(child && *own_req && tcp_sk(child)->is_mptcp && (!mptcp_subflow_ctx(child) || !mptcp_subflow_ctx(child)->conn)); return child; @@@ -845,6 -821,24 +845,24 @@@ bool mptcp_subflow_data_available(struc return subflow->data_avail; }
+ /* If ssk has an mptcp parent socket, use the mptcp rcvbuf occupancy, + * not the ssk one. + * + * In mptcp, rwin is about the mptcp-level connection data. + * + * Data that is still on the ssk rx queue can thus be ignored, + * as far as mptcp peer is concerened that data is still inflight. + * DSS ACK is updated when skb is moved to the mptcp rx queue. + */ + void mptcp_space(const struct sock *ssk, int *space, int *full_space) + { + const struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); + const struct sock *sk = subflow->conn; + + *space = tcp_space(sk); + *full_space = tcp_full_space(sk); + } + static void subflow_data_ready(struct sock *sk) { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); diff --combined net/sched/cls_api.c index c0e5b64b3caf,7e85c91d0752..1ac66176a971 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@@ -39,6 -39,7 +39,7 @@@ #include <net/tc_act/tc_skbedit.h> #include <net/tc_act/tc_ct.h> #include <net/tc_act/tc_mpls.h> + #include <net/tc_act/tc_gate.h> #include <net/flow_offload.h>
extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1]; @@@ -735,8 -736,11 +736,11 @@@ static int tcf_block_offload_cmd(struc INIT_LIST_HEAD(&bo.cb_list);
err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo); - if (err < 0) + if (err < 0) { + if (err != -EOPNOTSUPP) + NL_SET_ERR_MSG(extack, "Driver ndo_setup_tc failed"); return err; + }
return tcf_block_setup(block, &bo); } @@@ -2070,7 -2074,6 +2074,7 @@@ replay err = PTR_ERR(block); goto errout; } + block->classid = parent;
chain_index = tca[TCA_CHAIN] ? nla_get_u32(tca[TCA_CHAIN]) : 0; if (chain_index > TC_ACT_EXT_VAL_MASK) { @@@ -2613,10 -2616,12 +2617,10 @@@ static int tc_dump_tfilter(struct sk_bu return skb->len;
parent = tcm->tcm_parent; - if (!parent) { + if (!parent) q = dev->qdisc; - parent = q->handle; - } else { + else q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent)); - } if (!q) goto out; cops = q->ops->cl_ops; @@@ -2632,7 -2637,6 +2636,7 @@@ block = cops->tcf_block(q, cl, NULL); if (!block) goto out; + parent = block->classid; if (tcf_block_shared(block)) q = NULL; } @@@ -3523,6 -3527,27 +3527,27 @@@ static void tcf_sample_get_group(struc #endif }
+ static void tcf_gate_entry_destructor(void *priv) + { + struct action_gate_entry *oe = priv; + + kfree(oe); + } + + static int tcf_gate_get_entries(struct flow_action_entry *entry, + const struct tc_action *act) + { + entry->gate.entries = tcf_gate_get_list(act); + + if (!entry->gate.entries) + return -EINVAL; + + entry->destructor = tcf_gate_entry_destructor; + entry->destructor_priv = entry->gate.entries; + + return 0; + } + int tc_setup_flow_action(struct flow_action *flow_action, const struct tcf_exts *exts) { @@@ -3669,6 -3694,17 +3694,17 @@@ } else if (is_tcf_skbedit_priority(act)) { entry->id = FLOW_ACTION_PRIORITY; entry->priority = tcf_skbedit_priority(act); + } else if (is_tcf_gate(act)) { + entry->id = FLOW_ACTION_GATE; + entry->gate.index = tcf_gate_index(act); + entry->gate.prio = tcf_gate_prio(act); + entry->gate.basetime = tcf_gate_basetime(act); + entry->gate.cycletime = tcf_gate_cycletime(act); + entry->gate.cycletimeext = tcf_gate_cycletimeext(act); + entry->gate.num_entries = tcf_gate_num_entries(act); + err = tcf_gate_get_entries(entry, act); + if (err) + goto err_out; } else { err = -EOPNOTSUPP; goto err_out_locked; diff --combined net/sched/sch_choke.c index 1bcf8fbfd40e,59ff466ec7cb..bd618b00d319 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@@ -131,7 -131,6 +131,6 @@@ static void choke_drop_by_idx(struct Qd }
struct choke_skb_cb { - u16 classid; u8 keys_valid; struct flow_keys_digest keys; }; @@@ -142,11 -141,6 +141,6 @@@ static inline struct choke_skb_cb *chok return (struct choke_skb_cb *)qdisc_skb_cb(skb)->data; }
- static inline void choke_set_classid(struct sk_buff *skb, u16 classid) - { - choke_skb_cb(skb)->classid = classid; - } - /* * Compare flow of two packets * Returns true only if source and destination address and port match. @@@ -323,8 -317,7 +317,8 @@@ static void choke_reset(struct Qdisc *s
sch->q.qlen = 0; sch->qstats.backlog = 0; - memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *)); + if (q->tab) + memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *)); q->head = q->tail = 0; red_restart(&q->vars); } diff --combined net/smc/smc_ib.c index e7e7c3c6e94a,f0a5064bf9bd..f6fcdae75aae --- a/net/smc/smc_ib.c +++ b/net/smc/smc_ib.c @@@ -249,9 -249,10 +249,10 @@@ static void smc_ib_port_event_work(stru clear_bit(port_idx, &smcibdev->port_event_mask); if (!smc_ib_port_active(smcibdev, port_idx + 1)) { set_bit(port_idx, smcibdev->ports_going_away); - smc_port_terminate(smcibdev, port_idx + 1); + smcr_port_err(smcibdev, port_idx + 1); } else { clear_bit(port_idx, smcibdev->ports_going_away); + smcr_port_add(smcibdev, port_idx + 1); } } } @@@ -389,15 -390,15 +390,15 @@@ void smc_ib_put_memory_region(struct ib ib_dereg_mr(mr); }
- static int smc_ib_map_mr_sg(struct smc_buf_desc *buf_slot) + static int smc_ib_map_mr_sg(struct smc_buf_desc *buf_slot, u8 link_idx) { unsigned int offset = 0; int sg_num;
/* map the largest prefix of a dma mapped SG list */ - sg_num = ib_map_mr_sg(buf_slot->mr_rx[SMC_SINGLE_LINK], - buf_slot->sgt[SMC_SINGLE_LINK].sgl, - buf_slot->sgt[SMC_SINGLE_LINK].orig_nents, + sg_num = ib_map_mr_sg(buf_slot->mr_rx[link_idx], + buf_slot->sgt[link_idx].sgl, + buf_slot->sgt[link_idx].orig_nents, &offset, PAGE_SIZE);
return sg_num; @@@ -405,29 -406,29 +406,29 @@@
/* Allocate a memory region and map the dma mapped SG list of buf_slot */ int smc_ib_get_memory_region(struct ib_pd *pd, int access_flags, - struct smc_buf_desc *buf_slot) + struct smc_buf_desc *buf_slot, u8 link_idx) { - if (buf_slot->mr_rx[SMC_SINGLE_LINK]) + if (buf_slot->mr_rx[link_idx]) return 0; /* already done */
- buf_slot->mr_rx[SMC_SINGLE_LINK] = + buf_slot->mr_rx[link_idx] = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG, 1 << buf_slot->order); - if (IS_ERR(buf_slot->mr_rx[SMC_SINGLE_LINK])) { + if (IS_ERR(buf_slot->mr_rx[link_idx])) { int rc;
- rc = PTR_ERR(buf_slot->mr_rx[SMC_SINGLE_LINK]); - buf_slot->mr_rx[SMC_SINGLE_LINK] = NULL; + rc = PTR_ERR(buf_slot->mr_rx[link_idx]); + buf_slot->mr_rx[link_idx] = NULL; return rc; }
- if (smc_ib_map_mr_sg(buf_slot) != 1) + if (smc_ib_map_mr_sg(buf_slot, link_idx) != 1) return -EINVAL;
return 0; }
/* synchronize buffer usage for cpu access */ - void smc_ib_sync_sg_for_cpu(struct smc_ib_device *smcibdev, + void smc_ib_sync_sg_for_cpu(struct smc_link *lnk, struct smc_buf_desc *buf_slot, enum dma_data_direction data_direction) { @@@ -435,11 -436,11 +436,11 @@@ unsigned int i;
/* for now there is just one DMA address */ - for_each_sg(buf_slot->sgt[SMC_SINGLE_LINK].sgl, sg, - buf_slot->sgt[SMC_SINGLE_LINK].nents, i) { + for_each_sg(buf_slot->sgt[lnk->link_idx].sgl, sg, + buf_slot->sgt[lnk->link_idx].nents, i) { if (!sg_dma_len(sg)) break; - ib_dma_sync_single_for_cpu(smcibdev->ibdev, + ib_dma_sync_single_for_cpu(lnk->smcibdev->ibdev, sg_dma_address(sg), sg_dma_len(sg), data_direction); @@@ -447,7 -448,7 +448,7 @@@ }
/* synchronize buffer usage for device access */ - void smc_ib_sync_sg_for_device(struct smc_ib_device *smcibdev, + void smc_ib_sync_sg_for_device(struct smc_link *lnk, struct smc_buf_desc *buf_slot, enum dma_data_direction data_direction) { @@@ -455,11 -456,11 +456,11 @@@ unsigned int i;
/* for now there is just one DMA address */ - for_each_sg(buf_slot->sgt[SMC_SINGLE_LINK].sgl, sg, - buf_slot->sgt[SMC_SINGLE_LINK].nents, i) { + for_each_sg(buf_slot->sgt[lnk->link_idx].sgl, sg, + buf_slot->sgt[lnk->link_idx].nents, i) { if (!sg_dma_len(sg)) break; - ib_dma_sync_single_for_device(smcibdev->ibdev, + ib_dma_sync_single_for_device(lnk->smcibdev->ibdev, sg_dma_address(sg), sg_dma_len(sg), data_direction); @@@ -467,15 -468,15 +468,15 @@@ }
/* Map a new TX or RX buffer SG-table to DMA */ - int smc_ib_buf_map_sg(struct smc_ib_device *smcibdev, + int smc_ib_buf_map_sg(struct smc_link *lnk, struct smc_buf_desc *buf_slot, enum dma_data_direction data_direction) { int mapped_nents;
- mapped_nents = ib_dma_map_sg(smcibdev->ibdev, - buf_slot->sgt[SMC_SINGLE_LINK].sgl, - buf_slot->sgt[SMC_SINGLE_LINK].orig_nents, + mapped_nents = ib_dma_map_sg(lnk->smcibdev->ibdev, + buf_slot->sgt[lnk->link_idx].sgl, + buf_slot->sgt[lnk->link_idx].orig_nents, data_direction); if (!mapped_nents) return -ENOMEM; @@@ -483,18 -484,18 +484,18 @@@ return mapped_nents; }
- void smc_ib_buf_unmap_sg(struct smc_ib_device *smcibdev, + void smc_ib_buf_unmap_sg(struct smc_link *lnk, struct smc_buf_desc *buf_slot, enum dma_data_direction data_direction) { - if (!buf_slot->sgt[SMC_SINGLE_LINK].sgl->dma_address) + if (!buf_slot->sgt[lnk->link_idx].sgl->dma_address) return; /* already unmapped */
- ib_dma_unmap_sg(smcibdev->ibdev, - buf_slot->sgt[SMC_SINGLE_LINK].sgl, - buf_slot->sgt[SMC_SINGLE_LINK].orig_nents, + ib_dma_unmap_sg(lnk->smcibdev->ibdev, + buf_slot->sgt[lnk->link_idx].sgl, + buf_slot->sgt[lnk->link_idx].orig_nents, data_direction); - buf_slot->sgt[SMC_SINGLE_LINK].sgl->dma_address = 0; + buf_slot->sgt[lnk->link_idx].sgl->dma_address = 0; }
long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev) @@@ -574,13 -575,23 +575,23 @@@ static void smc_ib_add_dev(struct ib_de
/* trigger reading of the port attributes */ port_cnt = smcibdev->ibdev->phys_port_cnt; + pr_warn_ratelimited("smc: adding ib device %s with port count %d\n", + smcibdev->ibdev->name, port_cnt); for (i = 0; i < min_t(size_t, port_cnt, SMC_MAX_PORTS); i++) { set_bit(i, &smcibdev->port_event_mask); /* determine pnetids of the port */ - smc_pnetid_by_dev_port(ibdev->dev.parent, i, - smcibdev->pnetid[i]); + if (smc_pnetid_by_dev_port(ibdev->dev.parent, i, + smcibdev->pnetid[i])) + smc_pnetid_by_table_ib(smcibdev, i + 1); + pr_warn_ratelimited("smc: ib device %s port %d has pnetid " + "%.16s%s\n", + smcibdev->ibdev->name, i + 1, + smcibdev->pnetid[i], + smcibdev->pnetid_by_user[i] ? + " (user defined)" : + ""); } schedule_work(&smcibdev->port_event_work); } @@@ -588,14 -599,17 +599,16 @@@ /* callback function for ib_unregister_client() */ static void smc_ib_remove_dev(struct ib_device *ibdev, void *client_data) { - struct smc_ib_device *smcibdev; + struct smc_ib_device *smcibdev = client_data;
- smcibdev = ib_get_client_data(ibdev, &smc_ib_client); if (!smcibdev || smcibdev->ibdev != ibdev) return; ib_set_client_data(ibdev, &smc_ib_client, NULL); spin_lock(&smc_ib_devices.lock); list_del_init(&smcibdev->list); /* remove from smc_ib_devices */ spin_unlock(&smc_ib_devices.lock); + pr_warn_ratelimited("smc: removing ib device %s\n", + smcibdev->ibdev->name); smc_smcr_terminate_all(smcibdev); smc_ib_cleanup_per_ibdev(smcibdev); ib_unregister_event_handler(&smcibdev->event_handler); diff --combined scripts/mod/modpost.c index 4d4b979d76be,7f7d4ee7b652..5826c6483b85 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@@ -166,7 -166,7 +166,7 @@@ struct symbol * (only for external modules) **/ unsigned int is_static:1; /* 1 if symbol is not global */ enum export export; /* Type of export */ - char name[0]; + char name[]; };
static struct symbol *symbolhash[SYMBOL_HASH_SIZE]; @@@ -2251,6 -2251,7 +2251,7 @@@ static void add_header(struct buffer *b * Include build-salt.h after module.h in order to * inherit the definitions. */ + buf_printf(b, "#define INCLUDE_VERMAGIC\n"); buf_printf(b, "#include <linux/build-salt.h>\n"); buf_printf(b, "#include <linux/vermagic.h>\n"); buf_printf(b, "#include <linux/compiler.h>\n"); diff --combined tools/lib/bpf/libbpf.c index b9335c686353,977add1b73e2..e8ab7b2ce0d5 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@@ -310,6 -310,7 +310,7 @@@ struct bpf_map int map_ifindex; int inner_map_fd; struct bpf_map_def def; + __u32 btf_var_idx; __u32 btf_key_type_id; __u32 btf_value_type_id; __u32 btf_vmlinux_value_type_id; @@@ -318,6 -319,9 +319,9 @@@ enum libbpf_map_type libbpf_type; void *mmaped; struct bpf_struct_ops *st_ops; + struct bpf_map *inner_map; + void **init_slots; + int init_slots_sz; char *pin_path; bool pinned; bool reused; @@@ -389,6 -393,7 +393,7 @@@ struct bpf_object int nr_reloc_sects; int maps_shndx; int btf_maps_shndx; + __u32 btf_maps_sec_btf_id; int text_shndx; int symbols_shndx; int data_shndx; @@@ -1914,109 -1919,54 +1919,54 @@@ static int build_map_pin_path(struct bp return 0; }
- static int bpf_object__init_user_btf_map(struct bpf_object *obj, - const struct btf_type *sec, - int var_idx, int sec_idx, - const Elf_Data *data, bool strict, - const char *pin_root_path) + + static int parse_btf_map_def(struct bpf_object *obj, + struct bpf_map *map, + const struct btf_type *def, + bool strict, bool is_inner, + const char *pin_root_path) { - const struct btf_type *var, *def, *t; - const struct btf_var_secinfo *vi; - const struct btf_var *var_extra; + const struct btf_type *t; const struct btf_member *m; - const char *map_name; - struct bpf_map *map; int vlen, i;
- vi = btf_var_secinfos(sec) + var_idx; - var = btf__type_by_id(obj->btf, vi->type); - var_extra = btf_var(var); - map_name = btf__name_by_offset(obj->btf, var->name_off); - vlen = btf_vlen(var); - - if (map_name == NULL || map_name[0] == '\0') { - pr_warn("map #%d: empty name.\n", var_idx); - return -EINVAL; - } - if ((__u64)vi->offset + vi->size > data->d_size) { - pr_warn("map '%s' BTF data is corrupted.\n", map_name); - return -EINVAL; - } - if (!btf_is_var(var)) { - pr_warn("map '%s': unexpected var kind %u.\n", - map_name, btf_kind(var)); - return -EINVAL; - } - if (var_extra->linkage != BTF_VAR_GLOBAL_ALLOCATED && - var_extra->linkage != BTF_VAR_STATIC) { - pr_warn("map '%s': unsupported var linkage %u.\n", - map_name, var_extra->linkage); - return -EOPNOTSUPP; - } - - def = skip_mods_and_typedefs(obj->btf, var->type, NULL); - if (!btf_is_struct(def)) { - pr_warn("map '%s': unexpected def kind %u.\n", - map_name, btf_kind(var)); - return -EINVAL; - } - if (def->size > vi->size) { - pr_warn("map '%s': invalid def size.\n", map_name); - return -EINVAL; - } - - map = bpf_object__add_map(obj); - if (IS_ERR(map)) - return PTR_ERR(map); - map->name = strdup(map_name); - if (!map->name) { - pr_warn("map '%s': failed to alloc map name.\n", map_name); - return -ENOMEM; - } - map->libbpf_type = LIBBPF_MAP_UNSPEC; - map->def.type = BPF_MAP_TYPE_UNSPEC; - map->sec_idx = sec_idx; - map->sec_offset = vi->offset; - pr_debug("map '%s': at sec_idx %d, offset %zu.\n", - map_name, map->sec_idx, map->sec_offset); - vlen = btf_vlen(def); m = btf_members(def); for (i = 0; i < vlen; i++, m++) { const char *name = btf__name_by_offset(obj->btf, m->name_off);
if (!name) { - pr_warn("map '%s': invalid field #%d.\n", map_name, i); + pr_warn("map '%s': invalid field #%d.\n", map->name, i); return -EINVAL; } if (strcmp(name, "type") == 0) { - if (!get_map_field_int(map_name, obj->btf, m, + if (!get_map_field_int(map->name, obj->btf, m, &map->def.type)) return -EINVAL; pr_debug("map '%s': found type = %u.\n", - map_name, map->def.type); + map->name, map->def.type); } else if (strcmp(name, "max_entries") == 0) { - if (!get_map_field_int(map_name, obj->btf, m, + if (!get_map_field_int(map->name, obj->btf, m, &map->def.max_entries)) return -EINVAL; pr_debug("map '%s': found max_entries = %u.\n", - map_name, map->def.max_entries); + map->name, map->def.max_entries); } else if (strcmp(name, "map_flags") == 0) { - if (!get_map_field_int(map_name, obj->btf, m, + if (!get_map_field_int(map->name, obj->btf, m, &map->def.map_flags)) return -EINVAL; pr_debug("map '%s': found map_flags = %u.\n", - map_name, map->def.map_flags); + map->name, map->def.map_flags); } else if (strcmp(name, "key_size") == 0) { __u32 sz;
- if (!get_map_field_int(map_name, obj->btf, m, &sz)) + if (!get_map_field_int(map->name, obj->btf, m, &sz)) return -EINVAL; pr_debug("map '%s': found key_size = %u.\n", - map_name, sz); + map->name, sz); if (map->def.key_size && map->def.key_size != sz) { pr_warn("map '%s': conflicting key size %u != %u.\n", - map_name, map->def.key_size, sz); + map->name, map->def.key_size, sz); return -EINVAL; } map->def.key_size = sz; @@@ -2026,25 -1976,25 +1976,25 @@@ t = btf__type_by_id(obj->btf, m->type); if (!t) { pr_warn("map '%s': key type [%d] not found.\n", - map_name, m->type); + map->name, m->type); return -EINVAL; } if (!btf_is_ptr(t)) { pr_warn("map '%s': key spec is not PTR: %u.\n", - map_name, btf_kind(t)); + map->name, btf_kind(t)); return -EINVAL; } sz = btf__resolve_size(obj->btf, t->type); if (sz < 0) { pr_warn("map '%s': can't determine key size for type [%u]: %zd.\n", - map_name, t->type, (ssize_t)sz); + map->name, t->type, (ssize_t)sz); return sz; } pr_debug("map '%s': found key [%u], sz = %zd.\n", - map_name, t->type, (ssize_t)sz); + map->name, t->type, (ssize_t)sz); if (map->def.key_size && map->def.key_size != sz) { pr_warn("map '%s': conflicting key size %u != %zd.\n", - map_name, map->def.key_size, (ssize_t)sz); + map->name, map->def.key_size, (ssize_t)sz); return -EINVAL; } map->def.key_size = sz; @@@ -2052,13 -2002,13 +2002,13 @@@ } else if (strcmp(name, "value_size") == 0) { __u32 sz;
- if (!get_map_field_int(map_name, obj->btf, m, &sz)) + if (!get_map_field_int(map->name, obj->btf, m, &sz)) return -EINVAL; pr_debug("map '%s': found value_size = %u.\n", - map_name, sz); + map->name, sz); if (map->def.value_size && map->def.value_size != sz) { pr_warn("map '%s': conflicting value size %u != %u.\n", - map_name, map->def.value_size, sz); + map->name, map->def.value_size, sz); return -EINVAL; } map->def.value_size = sz; @@@ -2068,71 -2018,207 +2018,207 @@@ t = btf__type_by_id(obj->btf, m->type); if (!t) { pr_warn("map '%s': value type [%d] not found.\n", - map_name, m->type); + map->name, m->type); return -EINVAL; } if (!btf_is_ptr(t)) { pr_warn("map '%s': value spec is not PTR: %u.\n", - map_name, btf_kind(t)); + map->name, btf_kind(t)); return -EINVAL; } sz = btf__resolve_size(obj->btf, t->type); if (sz < 0) { pr_warn("map '%s': can't determine value size for type [%u]: %zd.\n", - map_name, t->type, (ssize_t)sz); + map->name, t->type, (ssize_t)sz); return sz; } pr_debug("map '%s': found value [%u], sz = %zd.\n", - map_name, t->type, (ssize_t)sz); + map->name, t->type, (ssize_t)sz); if (map->def.value_size && map->def.value_size != sz) { pr_warn("map '%s': conflicting value size %u != %zd.\n", - map_name, map->def.value_size, (ssize_t)sz); + map->name, map->def.value_size, (ssize_t)sz); return -EINVAL; } map->def.value_size = sz; map->btf_value_type_id = t->type; + } + else if (strcmp(name, "values") == 0) { + int err; + + if (is_inner) { + pr_warn("map '%s': multi-level inner maps not supported.\n", + map->name); + return -ENOTSUP; + } + if (i != vlen - 1) { + pr_warn("map '%s': '%s' member should be last.\n", + map->name, name); + return -EINVAL; + } + if (!bpf_map_type__is_map_in_map(map->def.type)) { + pr_warn("map '%s': should be map-in-map.\n", + map->name); + return -ENOTSUP; + } + if (map->def.value_size && map->def.value_size != 4) { + pr_warn("map '%s': conflicting value size %u != 4.\n", + map->name, map->def.value_size); + return -EINVAL; + } + map->def.value_size = 4; + t = btf__type_by_id(obj->btf, m->type); + if (!t) { + pr_warn("map '%s': map-in-map inner type [%d] not found.\n", + map->name, m->type); + return -EINVAL; + } + if (!btf_is_array(t) || btf_array(t)->nelems) { + pr_warn("map '%s': map-in-map inner spec is not a zero-sized array.\n", + map->name); + return -EINVAL; + } + t = skip_mods_and_typedefs(obj->btf, btf_array(t)->type, + NULL); + if (!btf_is_ptr(t)) { + pr_warn("map '%s': map-in-map inner def is of unexpected kind %u.\n", + map->name, btf_kind(t)); + return -EINVAL; + } + t = skip_mods_and_typedefs(obj->btf, t->type, NULL); + if (!btf_is_struct(t)) { + pr_warn("map '%s': map-in-map inner def is of unexpected kind %u.\n", + map->name, btf_kind(t)); + return -EINVAL; + } + + map->inner_map = calloc(1, sizeof(*map->inner_map)); + if (!map->inner_map) + return -ENOMEM; + map->inner_map->sec_idx = obj->efile.btf_maps_shndx; + map->inner_map->name = malloc(strlen(map->name) + + sizeof(".inner") + 1); + if (!map->inner_map->name) + return -ENOMEM; + sprintf(map->inner_map->name, "%s.inner", map->name); + + err = parse_btf_map_def(obj, map->inner_map, t, strict, + true /* is_inner */, NULL); + if (err) + return err; } else if (strcmp(name, "pinning") == 0) { __u32 val; int err;
- if (!get_map_field_int(map_name, obj->btf, m, &val)) + if (is_inner) { + pr_debug("map '%s': inner def can't be pinned.\n", + map->name); + return -EINVAL; + } + if (!get_map_field_int(map->name, obj->btf, m, &val)) return -EINVAL; pr_debug("map '%s': found pinning = %u.\n", - map_name, val); + map->name, val);
if (val != LIBBPF_PIN_NONE && val != LIBBPF_PIN_BY_NAME) { pr_warn("map '%s': invalid pinning value %u.\n", - map_name, val); + map->name, val); return -EINVAL; } if (val == LIBBPF_PIN_BY_NAME) { err = build_map_pin_path(map, pin_root_path); if (err) { pr_warn("map '%s': couldn't build pin path.\n", - map_name); + map->name); return err; } } } else { if (strict) { pr_warn("map '%s': unknown field '%s'.\n", - map_name, name); + map->name, name); return -ENOTSUP; } pr_debug("map '%s': ignoring unknown field '%s'.\n", - map_name, name); + map->name, name); } }
if (map->def.type == BPF_MAP_TYPE_UNSPEC) { - pr_warn("map '%s': map type isn't specified.\n", map_name); + pr_warn("map '%s': map type isn't specified.\n", map->name); return -EINVAL; }
return 0; }
+ static int bpf_object__init_user_btf_map(struct bpf_object *obj, + const struct btf_type *sec, + int var_idx, int sec_idx, + const Elf_Data *data, bool strict, + const char *pin_root_path) + { + const struct btf_type *var, *def; + const struct btf_var_secinfo *vi; + const struct btf_var *var_extra; + const char *map_name; + struct bpf_map *map; + + vi = btf_var_secinfos(sec) + var_idx; + var = btf__type_by_id(obj->btf, vi->type); + var_extra = btf_var(var); + map_name = btf__name_by_offset(obj->btf, var->name_off); + + if (map_name == NULL || map_name[0] == '\0') { + pr_warn("map #%d: empty name.\n", var_idx); + return -EINVAL; + } + if ((__u64)vi->offset + vi->size > data->d_size) { + pr_warn("map '%s' BTF data is corrupted.\n", map_name); + return -EINVAL; + } + if (!btf_is_var(var)) { + pr_warn("map '%s': unexpected var kind %u.\n", + map_name, btf_kind(var)); + return -EINVAL; + } + if (var_extra->linkage != BTF_VAR_GLOBAL_ALLOCATED && + var_extra->linkage != BTF_VAR_STATIC) { + pr_warn("map '%s': unsupported var linkage %u.\n", + map_name, var_extra->linkage); + return -EOPNOTSUPP; + } + + def = skip_mods_and_typedefs(obj->btf, var->type, NULL); + if (!btf_is_struct(def)) { + pr_warn("map '%s': unexpected def kind %u.\n", + map_name, btf_kind(var)); + return -EINVAL; + } + if (def->size > vi->size) { + pr_warn("map '%s': invalid def size.\n", map_name); + return -EINVAL; + } + + map = bpf_object__add_map(obj); + if (IS_ERR(map)) + return PTR_ERR(map); + map->name = strdup(map_name); + if (!map->name) { + pr_warn("map '%s': failed to alloc map name.\n", map_name); + return -ENOMEM; + } + map->libbpf_type = LIBBPF_MAP_UNSPEC; + map->def.type = BPF_MAP_TYPE_UNSPEC; + map->sec_idx = sec_idx; + map->sec_offset = vi->offset; + map->btf_var_idx = var_idx; + pr_debug("map '%s': at sec_idx %d, offset %zu.\n", + map_name, map->sec_idx, map->sec_offset); + + return parse_btf_map_def(obj, map, def, strict, false, pin_root_path); + } + static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict, const char *pin_root_path) { @@@ -2163,6 -2249,7 +2249,7 @@@ name = btf__name_by_offset(obj->btf, t->name_off); if (strcmp(name, MAPS_ELF_SEC) == 0) { sec = t; + obj->efile.btf_maps_sec_btf_id = i; break; } } @@@ -2549,7 -2636,8 +2636,8 @@@ static int bpf_object__elf_collect(stru
/* Only do relo for section with exec instructions */ if (!section_have_execinstr(obj, sec) && - strcmp(name, ".rel" STRUCT_OPS_SEC)) { + strcmp(name, ".rel" STRUCT_OPS_SEC) && + strcmp(name, ".rel" MAPS_ELF_SEC)) { pr_debug("skip relo %s(%d) for section(%d)\n", name, idx, sec); continue; @@@ -3482,124 -3570,181 +3570,181 @@@ bpf_object__populate_internal_map(struc return 0; }
+ static void bpf_map__destroy(struct bpf_map *map); + + static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map) + { + struct bpf_create_map_attr create_attr; + struct bpf_map_def *def = &map->def; + + memset(&create_attr, 0, sizeof(create_attr)); + + if (obj->caps.name) + create_attr.name = map->name; + create_attr.map_ifindex = map->map_ifindex; + create_attr.map_type = def->type; + create_attr.map_flags = def->map_flags; + create_attr.key_size = def->key_size; + create_attr.value_size = def->value_size; + + if (def->type == BPF_MAP_TYPE_PERF_EVENT_ARRAY && !def->max_entries) { + int nr_cpus; + + nr_cpus = libbpf_num_possible_cpus(); + if (nr_cpus < 0) { + pr_warn("map '%s': failed to determine number of system CPUs: %d\n", + map->name, nr_cpus); + return nr_cpus; + } + pr_debug("map '%s': setting size to %d\n", map->name, nr_cpus); + create_attr.max_entries = nr_cpus; + } else { + create_attr.max_entries = def->max_entries; + } + + if (bpf_map__is_struct_ops(map)) + create_attr.btf_vmlinux_value_type_id = + map->btf_vmlinux_value_type_id; + + create_attr.btf_fd = 0; + create_attr.btf_key_type_id = 0; + create_attr.btf_value_type_id = 0; + if (obj->btf && !bpf_map_find_btf_info(obj, map)) { + create_attr.btf_fd = btf__fd(obj->btf); + create_attr.btf_key_type_id = map->btf_key_type_id; + create_attr.btf_value_type_id = map->btf_value_type_id; + } + + if (bpf_map_type__is_map_in_map(def->type)) { + if (map->inner_map) { + int err; + + err = bpf_object__create_map(obj, map->inner_map); + if (err) { + pr_warn("map '%s': failed to create inner map: %d\n", + map->name, err); + return err; + } + map->inner_map_fd = bpf_map__fd(map->inner_map); + } + if (map->inner_map_fd >= 0) + create_attr.inner_map_fd = map->inner_map_fd; + } + + map->fd = bpf_create_map_xattr(&create_attr); + if (map->fd < 0 && (create_attr.btf_key_type_id || + create_attr.btf_value_type_id)) { + char *cp, errmsg[STRERR_BUFSIZE]; + int err = -errno; + + cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg)); + pr_warn("Error in bpf_create_map_xattr(%s):%s(%d). Retrying without BTF.\n", + map->name, cp, err); + create_attr.btf_fd = 0; + create_attr.btf_key_type_id = 0; + create_attr.btf_value_type_id = 0; + map->btf_key_type_id = 0; + map->btf_value_type_id = 0; + map->fd = bpf_create_map_xattr(&create_attr); + } + + if (map->fd < 0) + return -errno; + + if (bpf_map_type__is_map_in_map(def->type) && map->inner_map) { + bpf_map__destroy(map->inner_map); + zfree(&map->inner_map); + } + + return 0; + } + static int bpf_object__create_maps(struct bpf_object *obj) { - struct bpf_create_map_attr create_attr = {}; - int nr_cpus = 0; - unsigned int i; + struct bpf_map *map; + char *cp, errmsg[STRERR_BUFSIZE]; + unsigned int i, j; int err;
for (i = 0; i < obj->nr_maps; i++) { - struct bpf_map *map = &obj->maps[i]; - struct bpf_map_def *def = &map->def; - char *cp, errmsg[STRERR_BUFSIZE]; - int *pfd = &map->fd; + map = &obj->maps[i];
if (map->pin_path) { err = bpf_object__reuse_map(map); if (err) { - pr_warn("error reusing pinned map %s\n", + pr_warn("map '%s': error reusing pinned map\n", map->name); - return err; + goto err_out; } }
if (map->fd >= 0) { - pr_debug("skip map create (preset) %s: fd=%d\n", + pr_debug("map '%s': skipping creation (preset fd=%d)\n", map->name, map->fd); continue; }
- if (obj->caps.name) - create_attr.name = map->name; - create_attr.map_ifindex = map->map_ifindex; - create_attr.map_type = def->type; - create_attr.map_flags = def->map_flags; - create_attr.key_size = def->key_size; - create_attr.value_size = def->value_size; - if (def->type == BPF_MAP_TYPE_PERF_EVENT_ARRAY && - !def->max_entries) { - if (!nr_cpus) - nr_cpus = libbpf_num_possible_cpus(); - if (nr_cpus < 0) { - pr_warn("failed to determine number of system CPUs: %d\n", - nr_cpus); - err = nr_cpus; - goto err_out; - } - pr_debug("map '%s': setting size to %d\n", - map->name, nr_cpus); - create_attr.max_entries = nr_cpus; - } else { - create_attr.max_entries = def->max_entries; - } - create_attr.btf_fd = 0; - create_attr.btf_key_type_id = 0; - create_attr.btf_value_type_id = 0; - if (bpf_map_type__is_map_in_map(def->type) && - map->inner_map_fd >= 0) - create_attr.inner_map_fd = map->inner_map_fd; - if (bpf_map__is_struct_ops(map)) - create_attr.btf_vmlinux_value_type_id = - map->btf_vmlinux_value_type_id; - - if (obj->btf && !bpf_map_find_btf_info(obj, map)) { - create_attr.btf_fd = btf__fd(obj->btf); - create_attr.btf_key_type_id = map->btf_key_type_id; - create_attr.btf_value_type_id = map->btf_value_type_id; - } - - *pfd = bpf_create_map_xattr(&create_attr); - if (*pfd < 0 && (create_attr.btf_key_type_id || - create_attr.btf_value_type_id)) { - err = -errno; - cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg)); - pr_warn("Error in bpf_create_map_xattr(%s):%s(%d). Retrying without BTF.\n", - map->name, cp, err); - create_attr.btf_fd = 0; - create_attr.btf_key_type_id = 0; - create_attr.btf_value_type_id = 0; - map->btf_key_type_id = 0; - map->btf_value_type_id = 0; - *pfd = bpf_create_map_xattr(&create_attr); - } + err = bpf_object__create_map(obj, map); + if (err) + goto err_out;
- if (*pfd < 0) { - size_t j; - - err = -errno; - err_out: - cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg)); - pr_warn("failed to create map (name: '%s'): %s(%d)\n", - map->name, cp, err); - pr_perm_msg(err); - for (j = 0; j < i; j++) - zclose(obj->maps[j].fd); - return err; - } + pr_debug("map '%s': created successfully, fd=%d\n", map->name, + map->fd);
if (bpf_map__is_internal(map)) { err = bpf_object__populate_internal_map(obj, map); if (err < 0) { - zclose(*pfd); + zclose(map->fd); goto err_out; } }
+ if (map->init_slots_sz) { + for (j = 0; j < map->init_slots_sz; j++) { + const struct bpf_map *targ_map; + int fd; + + if (!map->init_slots[j]) + continue; + + targ_map = map->init_slots[j]; + fd = bpf_map__fd(targ_map); + err = bpf_map_update_elem(map->fd, &j, &fd, 0); + if (err) { + err = -errno; + pr_warn("map '%s': failed to initialize slot [%d] to map '%s' fd=%d: %d\n", + map->name, j, targ_map->name, + fd, err); + goto err_out; + } + pr_debug("map '%s': slot [%d] set to map '%s' fd=%d\n", + map->name, j, targ_map->name, fd); + } + zfree(&map->init_slots); + map->init_slots_sz = 0; + } + if (map->pin_path && !map->pinned) { err = bpf_map__pin(map, NULL); if (err) { - pr_warn("failed to auto-pin map name '%s' at '%s'\n", - map->name, map->pin_path); - return err; + pr_warn("map '%s': failed to auto-pin at '%s': %d\n", + map->name, map->pin_path, err); + zclose(map->fd); + goto err_out; } } - - pr_debug("created map %s: fd=%d\n", map->name, *pfd); }
return 0; + + err_out: + cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg)); + pr_warn("map '%s': failed to create: %s(%d)\n", map->name, cp, err); + pr_perm_msg(err); + for (j = 0; j < i; j++) + zclose(obj->maps[j].fd); + return err; }
static int @@@ -4851,9 -4996,118 +4996,118 @@@ bpf_object__relocate(struct bpf_object return 0; }
- static int bpf_object__collect_struct_ops_map_reloc(struct bpf_object *obj, - GElf_Shdr *shdr, - Elf_Data *data); + static int bpf_object__collect_st_ops_relos(struct bpf_object *obj, + GElf_Shdr *shdr, Elf_Data *data); + + static int bpf_object__collect_map_relos(struct bpf_object *obj, + GElf_Shdr *shdr, Elf_Data *data) + { + int i, j, nrels, new_sz, ptr_sz = sizeof(void *); + const struct btf_var_secinfo *vi = NULL; + const struct btf_type *sec, *var, *def; + const struct btf_member *member; + struct bpf_map *map, *targ_map; + const char *name, *mname; + Elf_Data *symbols; + unsigned int moff; + GElf_Sym sym; + GElf_Rel rel; + void *tmp; + + if (!obj->efile.btf_maps_sec_btf_id || !obj->btf) + return -EINVAL; + sec = btf__type_by_id(obj->btf, obj->efile.btf_maps_sec_btf_id); + if (!sec) + return -EINVAL; + + symbols = obj->efile.symbols; + nrels = shdr->sh_size / shdr->sh_entsize; + for (i = 0; i < nrels; i++) { + if (!gelf_getrel(data, i, &rel)) { + pr_warn(".maps relo #%d: failed to get ELF relo\n", i); + return -LIBBPF_ERRNO__FORMAT; + } + if (!gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &sym)) { + pr_warn(".maps relo #%d: symbol %zx not found\n", + i, (size_t)GELF_R_SYM(rel.r_info)); + return -LIBBPF_ERRNO__FORMAT; + } + name = elf_strptr(obj->efile.elf, obj->efile.strtabidx, + sym.st_name) ? : "<?>"; + if (sym.st_shndx != obj->efile.btf_maps_shndx) { + pr_warn(".maps relo #%d: '%s' isn't a BTF-defined map\n", + i, name); + return -LIBBPF_ERRNO__RELOC; + } + + pr_debug(".maps relo #%d: for %zd value %zd rel.r_offset %zu name %d ('%s')\n", + i, (ssize_t)(rel.r_info >> 32), (size_t)sym.st_value, + (size_t)rel.r_offset, sym.st_name, name); + + for (j = 0; j < obj->nr_maps; j++) { + map = &obj->maps[j]; + if (map->sec_idx != obj->efile.btf_maps_shndx) + continue; + + vi = btf_var_secinfos(sec) + map->btf_var_idx; + if (vi->offset <= rel.r_offset && + rel.r_offset + sizeof(void *) <= vi->offset + vi->size) + break; + } + if (j == obj->nr_maps) { + pr_warn(".maps relo #%d: cannot find map '%s' at rel.r_offset %zu\n", + i, name, (size_t)rel.r_offset); + return -EINVAL; + } + + if (!bpf_map_type__is_map_in_map(map->def.type)) + return -EINVAL; + if (map->def.type == BPF_MAP_TYPE_HASH_OF_MAPS && + map->def.key_size != sizeof(int)) { + pr_warn(".maps relo #%d: hash-of-maps '%s' should have key size %zu.\n", + i, map->name, sizeof(int)); + return -EINVAL; + } + + targ_map = bpf_object__find_map_by_name(obj, name); + if (!targ_map) + return -ESRCH; + + var = btf__type_by_id(obj->btf, vi->type); + def = skip_mods_and_typedefs(obj->btf, var->type, NULL); + if (btf_vlen(def) == 0) + return -EINVAL; + member = btf_members(def) + btf_vlen(def) - 1; + mname = btf__name_by_offset(obj->btf, member->name_off); + if (strcmp(mname, "values")) + return -EINVAL; + + moff = btf_member_bit_offset(def, btf_vlen(def) - 1) / 8; + if (rel.r_offset - vi->offset < moff) + return -EINVAL; + + moff = rel.r_offset - vi->offset - moff; + if (moff % ptr_sz) + return -EINVAL; + moff /= ptr_sz; + if (moff >= map->init_slots_sz) { + new_sz = moff + 1; + tmp = realloc(map->init_slots, new_sz * ptr_sz); + if (!tmp) + return -ENOMEM; + map->init_slots = tmp; + memset(map->init_slots + map->init_slots_sz, 0, + (new_sz - map->init_slots_sz) * ptr_sz); + map->init_slots_sz = new_sz; + } + map->init_slots[moff] = targ_map; + + pr_debug(".maps relo #%d: map '%s' slot [%d] points to map '%s'\n", + i, map->name, moff, name); + } + + return 0; + }
static int bpf_object__collect_reloc(struct bpf_object *obj) { @@@ -4876,21 -5130,17 +5130,17 @@@ }
if (idx == obj->efile.st_ops_shndx) { - err = bpf_object__collect_struct_ops_map_reloc(obj, - shdr, - data); - if (err) - return err; - continue; - } - - prog = bpf_object__find_prog_by_idx(obj, idx); - if (!prog) { - pr_warn("relocation failed: no section(%d)\n", idx); - return -LIBBPF_ERRNO__RELOC; + err = bpf_object__collect_st_ops_relos(obj, shdr, data); + } else if (idx == obj->efile.btf_maps_shndx) { + err = bpf_object__collect_map_relos(obj, shdr, data); + } else { + prog = bpf_object__find_prog_by_idx(obj, idx); + if (!prog) { + pr_warn("relocation failed: no prog in section(%d)\n", idx); + return -LIBBPF_ERRNO__RELOC; + } + err = bpf_program__collect_reloc(prog, shdr, data, obj); } - - err = bpf_program__collect_reloc(prog, shdr, data, obj); if (err) return err; } @@@ -5955,6 -6205,40 +6205,40 @@@ int bpf_object__pin(struct bpf_object * return 0; }
+ static void bpf_map__destroy(struct bpf_map *map) + { + if (map->clear_priv) + map->clear_priv(map, map->priv); + map->priv = NULL; + map->clear_priv = NULL; + + if (map->inner_map) { + bpf_map__destroy(map->inner_map); + zfree(&map->inner_map); + } + + zfree(&map->init_slots); + map->init_slots_sz = 0; + + if (map->mmaped) { + munmap(map->mmaped, bpf_map_mmap_sz(map)); + map->mmaped = NULL; + } + + if (map->st_ops) { + zfree(&map->st_ops->data); + zfree(&map->st_ops->progs); + zfree(&map->st_ops->kern_func_off); + zfree(&map->st_ops); + } + + zfree(&map->name); + zfree(&map->pin_path); + + if (map->fd >= 0) + zclose(map->fd); + } + void bpf_object__close(struct bpf_object *obj) { size_t i; @@@ -5970,29 -6254,8 +6254,8 @@@ btf__free(obj->btf); btf_ext__free(obj->btf_ext);
- for (i = 0; i < obj->nr_maps; i++) { - struct bpf_map *map = &obj->maps[i]; - - if (map->clear_priv) - map->clear_priv(map, map->priv); - map->priv = NULL; - map->clear_priv = NULL; - - if (map->mmaped) { - munmap(map->mmaped, bpf_map_mmap_sz(map)); - map->mmaped = NULL; - } - - if (map->st_ops) { - zfree(&map->st_ops->data); - zfree(&map->st_ops->progs); - zfree(&map->st_ops->kern_func_off); - zfree(&map->st_ops); - } - - zfree(&map->name); - zfree(&map->pin_path); - } + for (i = 0; i < obj->nr_maps; i++) + bpf_map__destroy(&obj->maps[i]);
zfree(&obj->kconfig); zfree(&obj->externs); @@@ -6516,9 -6779,8 +6779,8 @@@ static struct bpf_map *find_struct_ops_ }
/* Collect the reloc from ELF and populate the st_ops->progs[] */ - static int bpf_object__collect_struct_ops_map_reloc(struct bpf_object *obj, - GElf_Shdr *shdr, - Elf_Data *data) + static int bpf_object__collect_st_ops_relos(struct bpf_object *obj, + GElf_Shdr *shdr, Elf_Data *data) { const struct btf_member *member; struct bpf_struct_ops *st_ops; @@@ -6672,6 -6934,7 +6934,7 @@@ int libbpf_find_vmlinux_btf_id(const ch enum bpf_attach_type attach_type) { struct btf *btf; + int err;
btf = libbpf_find_kernel_btf(); if (IS_ERR(btf)) { @@@ -6679,7 -6942,9 +6942,9 @@@ return -EINVAL; }
- return __find_vmlinux_btf_id(btf, name, attach_type); + err = __find_vmlinux_btf_id(btf, name, attach_type); + btf__free(btf); + return err; }
static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd) @@@ -7006,7 -7271,7 +7271,7 @@@ int bpf_prog_load_xattr(const struct bp err = bpf_object__load(obj); if (err) { bpf_object__close(obj); - return -EINVAL; + return err; }
*pobj = obj; @@@ -8035,7 -8300,7 +8300,7 @@@ error struct perf_sample_raw { struct perf_event_header header; uint32_t size; - char data[0]; + char data[]; };
struct perf_sample_lost {