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