The following commit has been merged in the master branch: commit 4a367994254b7faf582998943ad4521715d9cfde Merge: 50d2b8af38e08632e4aa9b44c4dd2da0818b2e3b e370abd95675cb19f10a1594415cbf71d96a181c Author: Stephen Rothwell sfr@canb.auug.org.au Date: Wed Dec 9 12:58:53 2015 +1100
Merge remote-tracking branch 'net-next/master'
diff --combined MAINTAINERS index 460c1c0,8eba565..0c40553 --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -318,7 -318,7 +318,7 @@@ M: Zhang Rui <rui.zhang@intel.com L: linux-acpi@vger.kernel.org W: https://01.org/linux-acpi S: Supported -F: drivers/acpi/video.c +F: drivers/acpi/acpi_video.c
ACPI WMI DRIVER L: platform-driver-x86@vger.kernel.org @@@ -388,14 -388,14 +388,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 @@@ -1420,15 -1420,6 +1420,15 @@@ M: Lennert Buytenhek <kernel@wantstofly 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) @@@ -1526,6 -1517,7 +1526,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 @@@ -1781,7 -1773,7 +1781,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 @@@ -2001,7 -1993,7 +2001,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 @@@ -2090,7 -2082,7 +2090,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 @@@ -2098,7 -2090,7 +2098,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 @@@ -2400,7 -2392,7 +2400,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 @@@ -3111,7 -3103,7 +3111,7 @@@ 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 @@@ -4607,7 -4599,7 +4607,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 @@@ -4992,7 -4984,6 +4992,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 @@@ -5053,7 -5044,7 +5053,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 @@@ -5586,7 -5577,7 +5586,7 @@@ R: Jesse Brandeburg <jesse.brandeburg@i R: Shannon Nelson shannon.nelson@intel.com R: Carolyn Wyborny carolyn.wyborny@intel.com R: Don Skidmore donald.c.skidmore@intel.com -R: Matthew Vick matthew.vick@intel.com +R: Bruce Allan bruce.w.allan@intel.com R: John Ronciak john.ronciak@intel.com R: Mitch Williams mitch.a.williams@intel.com L: intel-wired-lan@lists.osuosl.org @@@ -5621,7 -5612,7 +5621,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 @@@ -5655,7 -5646,7 +5655,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 @@@ -5665,7 -5656,7 +5665,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 @@@ -6716,7 -6707,7 +6716,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 @@@ -6736,13 -6727,13 +6736,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 @@@ -6901,7 -6892,6 +6901,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 @@@ -7184,7 -7174,7 +7184,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 @@@ -7192,7 -7182,7 +7192,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 @@@ -7200,7 -7190,7 +7200,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 @@@ -7209,7 -7199,7 +7209,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 @@@ -7378,6 -7368,13 +7378,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 @@@ -7959,7 -7956,7 +7966,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 @@@ -7985,7 -7982,7 +7992,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 @@@ -8296,7 -8293,7 +8303,7 @@@ F: include/linux/delayacct. F: kernel/delayacct.c
PERFORMANCE EVENTS SUBSYSTEM -M: Peter Zijlstra a.p.zijlstra@chello.nl +M: Peter Zijlstra peterz@infradead.org M: Ingo Molnar mingo@redhat.com M: Arnaldo Carvalho de Melo acme@kernel.org L: linux-kernel@vger.kernel.org @@@ -8448,17 -8445,6 +8455,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 @@@ -8538,7 -8524,7 +8545,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 @@@ -8841,7 -8827,7 +8848,7 @@@ M: Stanislaw Gruszka <sgruszka@redhat.c 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 @@@ -8966,13 -8952,6 +8973,13 @@@ F: drivers/rpmsg F: Documentation/rpmsg.txt F: include/linux/rpmsg.h
+RENESAS ETHERNET DRIVERS +R: Sergei Shtylyov sergei.shtylyov@cogentembedded.com +L: netdev@vger.kernel.org +L: linux-sh@vger.kernel.org +F: drivers/net/ethernet/renesas/ +F: include/linux/sh_eth.h + RESET CONTROLLER FRAMEWORK M: Philipp Zabel p.zabel@pengutronix.de S: Maintained @@@ -9082,7 -9061,7 +9089,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 @@@ -9092,7 -9071,7 +9099,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 @@@ -9101,8 -9080,8 +9108,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 @@@ -9270,7 -9249,7 +9277,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 @@@ -9455,10 -9434,8 +9462,10 @@@ F: include/scsi/sg.
SCSI SUBSYSTEM M: "James E.J. Bottomley" JBottomley@odin.com -L: linux-scsi@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +M: "Martin K. Petersen" martin.petersen@oracle.com +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/ F: include/scsi/ @@@ -9732,7 -9709,7 +9739,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 @@@ -9797,7 -9774,7 +9804,7 @@@ Q: http://patchwork.linuxtv.org/project 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 @@@ -9886,7 -9863,7 +9893,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 @@@ -10827,7 -10804,7 +10834,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 @@@ -11127,7 -11104,6 +11134,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 @@@ -11205,6 -11181,13 +11212,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 @@@ -11301,7 -11284,7 +11315,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 @@@ -11932,7 -11915,7 +11946,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 diff --combined drivers/net/ethernet/intel/i40e/i40e_main.c index 4a9873ec,2b1b655..8e660d9 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@@ -38,8 -38,8 +38,8 @@@ static const char i40e_driver_string[] #define DRV_KERN "-k"
#define DRV_VERSION_MAJOR 1 - #define DRV_VERSION_MINOR 3 - #define DRV_VERSION_BUILD 46 + #define DRV_VERSION_MINOR 4 + #define DRV_VERSION_BUILD 7 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN @@@ -55,6 -55,8 +55,8 @@@ static int i40e_setup_pf_switch(struct static int i40e_setup_misc_vector(struct i40e_pf *pf); static void i40e_determine_queue_usage(struct i40e_pf *pf); static int i40e_setup_pf_filter_control(struct i40e_pf *pf); + static void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut, + u16 rss_table_size, u16 rss_size); static void i40e_fdir_sb_setup(struct i40e_pf *pf); static int i40e_veb_get_bw_info(struct i40e_veb *veb);
@@@ -790,75 -792,6 +792,6 @@@ static void i40e_update_fcoe_stats(stru
#endif /** - * i40e_update_link_xoff_rx - Update XOFF received in link flow control mode - * @pf: the corresponding PF - * - * Update the Rx XOFF counter (PAUSE frames) in link flow control mode - **/ - static void i40e_update_link_xoff_rx(struct i40e_pf *pf) - { - struct i40e_hw_port_stats *osd = &pf->stats_offsets; - struct i40e_hw_port_stats *nsd = &pf->stats; - struct i40e_hw *hw = &pf->hw; - u64 xoff = 0; - - if ((hw->fc.current_mode != I40E_FC_FULL) && - (hw->fc.current_mode != I40E_FC_RX_PAUSE)) - return; - - xoff = nsd->link_xoff_rx; - i40e_stat_update32(hw, I40E_GLPRT_LXOFFRXC(hw->port), - pf->stat_offsets_loaded, - &osd->link_xoff_rx, &nsd->link_xoff_rx); - - /* No new LFC xoff rx */ - if (!(nsd->link_xoff_rx - xoff)) - return; - - } - - /** - * i40e_update_prio_xoff_rx - Update XOFF received in PFC mode - * @pf: the corresponding PF - * - * Update the Rx XOFF counter (PAUSE frames) in PFC mode - **/ - static void i40e_update_prio_xoff_rx(struct i40e_pf *pf) - { - struct i40e_hw_port_stats *osd = &pf->stats_offsets; - struct i40e_hw_port_stats *nsd = &pf->stats; - bool xoff[I40E_MAX_TRAFFIC_CLASS] = {false}; - struct i40e_dcbx_config *dcb_cfg; - struct i40e_hw *hw = &pf->hw; - u16 i; - u8 tc; - - dcb_cfg = &hw->local_dcbx_config; - - /* Collect Link XOFF stats when PFC is disabled */ - if (!dcb_cfg->pfc.pfcenable) { - i40e_update_link_xoff_rx(pf); - return; - } - - for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { - u64 prio_xoff = nsd->priority_xoff_rx[i]; - - i40e_stat_update32(hw, I40E_GLPRT_PXOFFRXC(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xoff_rx[i], - &nsd->priority_xoff_rx[i]); - - /* No new PFC xoff rx */ - if (!(nsd->priority_xoff_rx[i] - prio_xoff)) - continue; - /* Get the TC for given priority */ - tc = dcb_cfg->etscfg.prioritytable[i]; - xoff[tc] = true; - } - } - - /** * i40e_update_vsi_stats - Update the vsi statistics counters. * @vsi: the VSI to be updated * @@@ -881,6 -814,7 +814,7 @@@ static void i40e_update_vsi_stats(struc u64 bytes, packets; unsigned int start; u64 tx_linearize; + u64 tx_force_wb; u64 rx_p, rx_b; u64 tx_p, tx_b; u16 q; @@@ -899,7 -833,7 +833,7 @@@ */ rx_b = rx_p = 0; tx_b = tx_p = 0; - tx_restart = tx_busy = tx_linearize = 0; + tx_restart = tx_busy = tx_linearize = tx_force_wb = 0; rx_page = 0; rx_buf = 0; rcu_read_lock(); @@@ -917,6 -851,7 +851,7 @@@ tx_restart += p->tx_stats.restart_queue; tx_busy += p->tx_stats.tx_busy; tx_linearize += p->tx_stats.tx_linearize; + tx_force_wb += p->tx_stats.tx_force_wb;
/* Rx queue is part of the same block as Tx queue */ p = &p[1]; @@@ -934,6 -869,7 +869,7 @@@ vsi->tx_restart = tx_restart; vsi->tx_busy = tx_busy; vsi->tx_linearize = tx_linearize; + vsi->tx_force_wb = tx_force_wb; vsi->rx_page_failed = rx_page; vsi->rx_buf_failed = rx_buf;
@@@ -1049,12 -985,18 +985,18 @@@ static void i40e_update_pf_stats(struc i40e_stat_update32(hw, I40E_GLPRT_LXONTXC(hw->port), pf->stat_offsets_loaded, &osd->link_xon_tx, &nsd->link_xon_tx); - i40e_update_prio_xoff_rx(pf); /* handles I40E_GLPRT_LXOFFRXC */ + i40e_stat_update32(hw, I40E_GLPRT_LXOFFRXC(hw->port), + pf->stat_offsets_loaded, + &osd->link_xoff_rx, &nsd->link_xoff_rx); i40e_stat_update32(hw, I40E_GLPRT_LXOFFTXC(hw->port), pf->stat_offsets_loaded, &osd->link_xoff_tx, &nsd->link_xoff_tx);
for (i = 0; i < 8; i++) { + i40e_stat_update32(hw, I40E_GLPRT_PXOFFRXC(hw->port, i), + pf->stat_offsets_loaded, + &osd->priority_xoff_rx[i], + &nsd->priority_xoff_rx[i]); i40e_stat_update32(hw, I40E_GLPRT_PXONRXC(hw->port, i), pf->stat_offsets_loaded, &osd->priority_xon_rx[i], @@@ -1547,10 -1489,9 +1489,9 @@@ static int i40e_set_mac(struct net_devi spin_unlock_bh(&vsi->mac_filter_list_lock); }
- i40e_sync_vsi_filters(vsi, false); ether_addr_copy(netdev->dev_addr, addr->sa_data);
- return 0; + return i40e_sync_vsi_filters(vsi); }
/** @@@ -1625,7 -1566,8 +1566,8 @@@ static void i40e_vsi_setup_queue_map(st
switch (vsi->type) { case I40E_VSI_MAIN: - qcount = min_t(int, pf->rss_size, num_tc_qps); + qcount = min_t(int, pf->alloc_rss_size, + num_tc_qps); break; #ifdef I40E_FCOE case I40E_VSI_FCOE: @@@ -1851,13 -1793,12 +1793,12 @@@ static void i40e_cleanup_add_list(struc /** * i40e_sync_vsi_filters - Update the VSI filter list to the HW * @vsi: ptr to the VSI - * @grab_rtnl: whether RTNL needs to be grabbed * * Push any outstanding VSI filter changes through the AdminQ. * * Returns 0 or error value **/ - int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) + int i40e_sync_vsi_filters(struct i40e_vsi *vsi) { struct list_head tmp_del_list, tmp_add_list; struct i40e_mac_filter *f, *ftmp, *fclone; @@@ -1865,8 -1806,9 +1806,9 @@@ bool add_happened = false; int filter_list_len = 0; u32 changed_flags = 0; + i40e_status aq_ret = 0; bool err_cond = false; - i40e_status ret = 0; + int retval = 0; struct i40e_pf *pf; int num_add = 0; int num_del = 0; @@@ -1929,8 -1871,11 +1871,11 @@@ } spin_unlock_bh(&vsi->mac_filter_list_lock);
- if (err_cond) + if (err_cond) { i40e_cleanup_add_list(&tmp_add_list); + retval = -ENOMEM; + goto out; + } }
/* Now process 'del_list' outside the lock */ @@@ -1948,7 -1893,8 +1893,8 @@@ i40e_undo_del_filter_entries(vsi, &tmp_del_list); i40e_undo_add_filter_entries(vsi); spin_unlock_bh(&vsi->mac_filter_list_lock); - return -ENOMEM; + retval = -ENOMEM; + goto out; }
list_for_each_entry_safe(f, ftmp, &tmp_del_list, list) { @@@ -1966,18 -1912,22 +1912,22 @@@
/* flush a full buffer */ if (num_del == filter_list_len) { - ret = i40e_aq_remove_macvlan(&pf->hw, - vsi->seid, del_list, num_del, - NULL); + aq_ret = i40e_aq_remove_macvlan(&pf->hw, + vsi->seid, + del_list, + num_del, + NULL); aq_err = pf->hw.aq.asq_last_status; num_del = 0; memset(del_list, 0, sizeof(*del_list));
- if (ret && aq_err != I40E_AQ_RC_ENOENT) + if (aq_ret && aq_err != I40E_AQ_RC_ENOENT) { + retval = -EIO; dev_err(&pf->pdev->dev, "ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\n", - i40e_stat_str(&pf->hw, ret), + i40e_stat_str(&pf->hw, aq_ret), i40e_aq_str(&pf->hw, aq_err)); + } } /* Release memory for MAC filter entries which were * synced up with HW. @@@ -1987,15 -1937,16 +1937,16 @@@ }
if (num_del) { - ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid, - del_list, num_del, NULL); + aq_ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid, + del_list, num_del, + NULL); aq_err = pf->hw.aq.asq_last_status; num_del = 0;
- if (ret && aq_err != I40E_AQ_RC_ENOENT) + if (aq_ret && aq_err != I40E_AQ_RC_ENOENT) dev_info(&pf->pdev->dev, "ignoring delete macvlan error, err %s aq_err %s\n", - i40e_stat_str(&pf->hw, ret), + i40e_stat_str(&pf->hw, aq_ret), i40e_aq_str(&pf->hw, aq_err)); }
@@@ -2019,7 -1970,8 +1970,8 @@@ spin_lock_bh(&vsi->mac_filter_list_lock); i40e_undo_add_filter_entries(vsi); spin_unlock_bh(&vsi->mac_filter_list_lock); - return -ENOMEM; + retval = -ENOMEM; + goto out; }
list_for_each_entry_safe(f, ftmp, &tmp_add_list, list) { @@@ -2040,13 -1992,13 +1992,13 @@@
/* flush a full buffer */ if (num_add == filter_list_len) { - ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid, - add_list, num_add, - NULL); + aq_ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid, + add_list, num_add, + NULL); aq_err = pf->hw.aq.asq_last_status; num_add = 0;
- if (ret) + if (aq_ret) break; memset(add_list, 0, sizeof(*add_list)); } @@@ -2058,18 -2010,19 +2010,19 @@@ }
if (num_add) { - ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid, - add_list, num_add, NULL); + aq_ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid, + add_list, num_add, NULL); aq_err = pf->hw.aq.asq_last_status; num_add = 0; } kfree(add_list); add_list = NULL;
- if (add_happened && ret && aq_err != I40E_AQ_RC_EINVAL) { + if (add_happened && aq_ret && aq_err != I40E_AQ_RC_EINVAL) { + retval = i40e_aq_rc_to_posix(aq_ret, aq_err); dev_info(&pf->pdev->dev, "add filter failed, err %s aq_err %s\n", - i40e_stat_str(&pf->hw, ret), + i40e_stat_str(&pf->hw, aq_ret), i40e_aq_str(&pf->hw, aq_err)); if ((pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOSPC) && !test_bit(__I40E_FILTER_OVERFLOW_PROMISC, @@@ -2087,16 -2040,19 +2040,19 @@@ bool cur_multipromisc;
cur_multipromisc = !!(vsi->current_netdev_flags & IFF_ALLMULTI); - ret = i40e_aq_set_vsi_multicast_promiscuous(&vsi->back->hw, - vsi->seid, - cur_multipromisc, - NULL); - if (ret) + aq_ret = i40e_aq_set_vsi_multicast_promiscuous(&vsi->back->hw, + vsi->seid, + cur_multipromisc, + NULL); + if (aq_ret) { + retval = i40e_aq_rc_to_posix(aq_ret, + pf->hw.aq.asq_last_status); dev_info(&pf->pdev->dev, "set multi promisc failed, err %s aq_err %s\n", - i40e_stat_str(&pf->hw, ret), + i40e_stat_str(&pf->hw, aq_ret), i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); + } } if ((changed_flags & IFF_PROMISC) || promisc_forced_on) { bool cur_promisc; @@@ -2112,44 -2068,50 +2068,50 @@@ */ if (pf->cur_promisc != cur_promisc) { pf->cur_promisc = cur_promisc; - if (grab_rtnl) - i40e_do_reset_safe(pf, - BIT(__I40E_PF_RESET_REQUESTED)); - else - i40e_do_reset(pf, - BIT(__I40E_PF_RESET_REQUESTED)); + set_bit(__I40E_PF_RESET_REQUESTED, &pf->state); } } else { - ret = i40e_aq_set_vsi_unicast_promiscuous( + aq_ret = i40e_aq_set_vsi_unicast_promiscuous( &vsi->back->hw, vsi->seid, cur_promisc, NULL); - if (ret) + if (aq_ret) { + retval = + i40e_aq_rc_to_posix(aq_ret, + pf->hw.aq.asq_last_status); dev_info(&pf->pdev->dev, "set unicast promisc failed, err %d, aq_err %d\n", - ret, pf->hw.aq.asq_last_status); - ret = i40e_aq_set_vsi_multicast_promiscuous( + aq_ret, pf->hw.aq.asq_last_status); + } + aq_ret = i40e_aq_set_vsi_multicast_promiscuous( &vsi->back->hw, vsi->seid, cur_promisc, NULL); - if (ret) + if (aq_ret) { + retval = + i40e_aq_rc_to_posix(aq_ret, + pf->hw.aq.asq_last_status); dev_info(&pf->pdev->dev, "set multicast promisc failed, err %d, aq_err %d\n", - ret, pf->hw.aq.asq_last_status); + aq_ret, pf->hw.aq.asq_last_status); + } } - ret = i40e_aq_set_vsi_broadcast(&vsi->back->hw, - vsi->seid, - cur_promisc, NULL); - if (ret) + aq_ret = i40e_aq_set_vsi_broadcast(&vsi->back->hw, + vsi->seid, + cur_promisc, NULL); + if (aq_ret) { + retval = i40e_aq_rc_to_posix(aq_ret, + pf->hw.aq.asq_last_status); dev_info(&pf->pdev->dev, "set brdcast promisc failed, err %s, aq_err %s\n", - i40e_stat_str(&pf->hw, ret), + i40e_stat_str(&pf->hw, aq_ret), i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); + } } - + out: clear_bit(__I40E_CONFIG_BUSY, &vsi->state); - return 0; + return retval; }
/** @@@ -2166,8 -2128,15 +2128,15 @@@ static void i40e_sync_filters_subtask(s
for (v = 0; v < pf->num_alloc_vsi; v++) { if (pf->vsi[v] && - (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) - i40e_sync_vsi_filters(pf->vsi[v], true); + (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) { + int ret = i40e_sync_vsi_filters(pf->vsi[v]); + + if (ret) { + /* come back and try again later */ + pf->flags |= I40E_FLAG_FILTER_SYNC; + break; + } + } } }
@@@ -2377,16 -2346,13 +2346,13 @@@ int i40e_vsi_add_vlan(struct i40e_vsi * } }
- /* Make sure to release before sync_vsi_filter because that - * function will lock/unlock as necessary - */ spin_unlock_bh(&vsi->mac_filter_list_lock);
- if (test_bit(__I40E_DOWN, &vsi->back->state) || - test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) - return 0; - - return i40e_sync_vsi_filters(vsi, false); + /* schedule our worker thread which will take care of + * applying the new filter changes + */ + i40e_service_event_schedule(vsi->back); + return 0; }
/** @@@ -2459,16 -2425,13 +2425,13 @@@ int i40e_vsi_kill_vlan(struct i40e_vsi } }
- /* Make sure to release before sync_vsi_filter because that - * function with lock/unlock as necessary - */ spin_unlock_bh(&vsi->mac_filter_list_lock);
- if (test_bit(__I40E_DOWN, &vsi->back->state) || - test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) - return 0; - - return i40e_sync_vsi_filters(vsi, false); + /* schedule our worker thread which will take care of + * applying the new filter changes + */ + i40e_service_event_schedule(vsi->back); + return 0; }
/** @@@ -2711,6 -2674,11 +2674,11 @@@ static void i40e_config_xps_tx_ring(str netif_set_xps_queue(ring->netdev, mask, ring->queue_index); free_cpumask_var(mask); } + + /* schedule our worker thread which will take care of + * applying the new filter changes + */ + i40e_service_event_schedule(vsi->back); }
/** @@@ -4360,17 -4328,41 +4328,41 @@@ static void i40e_detect_recover_hung_qu else val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0);
+ /* Bail out if interrupts are disabled because napi_poll + * execution in-progress or will get scheduled soon. + * napi_poll cleans TX and RX queues and updates 'next_to_clean'. + */ + if (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK)) + return; + head = i40e_get_head(tx_ring);
tx_pending = i40e_get_tx_pending(tx_ring);
- /* Interrupts are disabled and TX pending is non-zero, - * trigger the SW interrupt (don't wait). Worst case - * there will be one extra interrupt which may result - * into not cleaning any queues because queues are cleaned. + /* HW is done executing descriptors, updated HEAD write back, + * but SW hasn't processed those descriptors. If interrupt is + * not generated from this point ON, it could result into + * dev_watchdog detecting timeout on those netdev_queue, + * hence proactively trigger SW interrupt. */ - if (tx_pending && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK))) - i40e_force_wb(vsi, tx_ring->q_vector); + if (tx_pending) { + /* NAPI Poll didn't run and clear since it was set */ + if (test_and_clear_bit(I40E_Q_VECTOR_HUNG_DETECT, + &tx_ring->q_vector->hung_detected)) { + netdev_info(vsi->netdev, "VSI_seid %d, Hung TX queue %d, tx_pending: %d, NTC:0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x\n", + vsi->seid, q_idx, tx_pending, + tx_ring->next_to_clean, head, + tx_ring->next_to_use, + readl(tx_ring->tail)); + netdev_info(vsi->netdev, "VSI_seid %d, Issuing force_wb for TX queue %d, Interrupt Reg: 0x%x\n", + vsi->seid, q_idx, val); + i40e_force_wb(vsi, tx_ring->q_vector); + } else { + /* First Chance - detected possible hung */ + set_bit(I40E_Q_VECTOR_HUNG_DETECT, + &tx_ring->q_vector->hung_detected); + } + } }
/** @@@ -5738,7 -5730,7 +5730,7 @@@ static void i40e_handle_lan_overflow_ev **/ static void i40e_service_event_complete(struct i40e_pf *pf) { - BUG_ON(!test_bit(__I40E_SERVICE_SCHED, &pf->state)); + WARN_ON(!test_bit(__I40E_SERVICE_SCHED, &pf->state));
/* flush memory to make sure state is correct before next watchog */ smp_mb__before_atomic(); @@@ -6013,6 -6005,9 +6005,9 @@@ static void i40e_link_event(struct i40e i40e_status status; bool new_link, old_link;
+ /* save off old link status information */ + pf->hw.phy.link_info_old = pf->hw.phy.link_info; + /* set this to force the get_link_status call to refresh state */ pf->hw.phy.get_link_info = true;
@@@ -6147,13 -6142,9 +6142,9 @@@ unlock static void i40e_handle_link_event(struct i40e_pf *pf, struct i40e_arq_event_info *e) { - struct i40e_hw *hw = &pf->hw; struct i40e_aqc_get_link_status *status = (struct i40e_aqc_get_link_status *)&e->desc.params.raw;
- /* save off old link status information */ - hw->phy.link_info_old = hw->phy.link_info; - /* Do a new status request to re-enable LSE reporting * and load new status information into the hw struct * This completely ignores any state information @@@ -6685,6 -6676,7 +6676,7 @@@ static void i40e_reset_and_rebuild(stru struct i40e_hw *hw = &pf->hw; u8 set_fc_aq_fail = 0; i40e_status ret; + u32 val; u32 v;
/* Now we wait for GRST to settle out. @@@ -6823,6 -6815,20 +6815,20 @@@ } }
+ /* Reconfigure hardware for allowing smaller MSS in the case + * of TSO, so that we avoid the MDD being fired and causing + * a reset in the case of small MSS+TSO. + */ + #define I40E_REG_MSS 0x000E64DC + #define I40E_REG_MSS_MIN_MASK 0x3FF0000 + #define I40E_64BYTE_MSS 0x400000 + val = rd32(hw, I40E_REG_MSS); + if ((val & I40E_REG_MSS_MIN_MASK) > I40E_64BYTE_MSS) { + val &= ~I40E_REG_MSS_MIN_MASK; + val |= I40E_64BYTE_MSS; + wr32(hw, I40E_REG_MSS, val); + } + if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || (pf->hw.aq.fw_maj_ver < 4)) { msleep(75); @@@ -7282,6 -7288,23 +7288,23 @@@ static void i40e_vsi_free_arrays(struc }
/** + * i40e_clear_rss_config_user - clear the user configured RSS hash keys + * and lookup table + * @vsi: Pointer to VSI structure + */ + static void i40e_clear_rss_config_user(struct i40e_vsi *vsi) + { + if (!vsi) + return; + + kfree(vsi->rss_hkey_user); + vsi->rss_hkey_user = NULL; + + kfree(vsi->rss_lut_user); + vsi->rss_lut_user = NULL; + } + + /** * i40e_vsi_clear - Deallocate the VSI provided * @vsi: the VSI being un-configured **/ @@@ -7318,6 -7341,7 +7341,7 @@@ static int i40e_vsi_clear(struct i40e_v i40e_put_lump(pf->irq_pile, vsi->base_vector, vsi->idx);
i40e_vsi_free_arrays(vsi, true); + i40e_clear_rss_config_user(vsi);
pf->vsi[vsi->idx] = NULL; if (vsi->idx < pf->next_vsi) @@@ -7780,7 -7804,8 +7804,8 @@@ static int i40e_setup_misc_vector(struc * @vsi: vsi structure * @seed: RSS hash seed **/ - static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed) + static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed, + u8 *lut, u16 lut_size) { struct i40e_aqc_get_set_rss_key_data rss_key; struct i40e_pf *pf = vsi->back; @@@ -7833,43 -7858,57 +7858,57 @@@ static int i40e_vsi_config_rss(struct i { u8 seed[I40E_HKEY_ARRAY_SIZE]; struct i40e_pf *pf = vsi->back; + u8 *lut; + int ret;
- netdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE); - vsi->rss_size = min_t(int, pf->rss_size, vsi->num_queue_pairs); + if (!(pf->flags & I40E_FLAG_RSS_AQ_CAPABLE)) + return 0;
- if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) - return i40e_config_rss_aq(vsi, seed); + lut = kzalloc(vsi->rss_table_size, GFP_KERNEL); + if (!lut) + return -ENOMEM;
- return 0; + i40e_fill_rss_lut(pf, lut, vsi->rss_table_size, vsi->rss_size); + netdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE); + vsi->rss_size = min_t(int, pf->alloc_rss_size, vsi->num_queue_pairs); + ret = i40e_config_rss_aq(vsi, seed, lut, vsi->rss_table_size); + kfree(lut); + + return ret; }
/** - * i40e_config_rss_reg - Prepare for RSS if used - * @pf: board private structure + * i40e_config_rss_reg - Configure RSS keys and lut by writing registers + * @vsi: Pointer to vsi structure * @seed: RSS hash seed + * @lut: Lookup table + * @lut_size: Lookup table size + * + * Returns 0 on success, negative on failure **/ - static int i40e_config_rss_reg(struct i40e_pf *pf, const u8 *seed) + static int i40e_config_rss_reg(struct i40e_vsi *vsi, const u8 *seed, + const u8 *lut, u16 lut_size) { - struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; + struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; - u32 *seed_dw = (u32 *)seed; - u32 current_queue = 0; - u32 lut = 0; - int i, j; + u8 i;
/* Fill out hash function seed */ - for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) - wr32(hw, I40E_PFQF_HKEY(i), seed_dw[i]); + if (seed) { + u32 *seed_dw = (u32 *)seed;
- for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++) { - lut = 0; - for (j = 0; j < 4; j++) { - if (current_queue == vsi->rss_size) - current_queue = 0; - lut |= ((current_queue) << (8 * j)); - current_queue++; - } - wr32(&pf->hw, I40E_PFQF_HLUT(i), lut); + for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) + wr32(hw, I40E_PFQF_HKEY(i), seed_dw[i]); + } + + if (lut) { + u32 *lut_dw = (u32 *)lut; + + if (lut_size != I40E_HLUT_ARRAY_SIZE) + return -EINVAL; + + for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++) + wr32(hw, I40E_PFQF_HLUT(i), lut_dw[i]); } i40e_flush(hw);
@@@ -7877,18 -7916,101 +7916,101 @@@ }
/** - * i40e_config_rss - Prepare for RSS if used + * i40e_get_rss_reg - Get the RSS keys and lut by reading registers + * @vsi: Pointer to VSI structure + * @seed: Buffer to store the keys + * @lut: Buffer to store the lookup table entries + * @lut_size: Size of buffer to store the lookup table entries + * + * Returns 0 on success, negative on failure + */ + static int i40e_get_rss_reg(struct i40e_vsi *vsi, u8 *seed, + u8 *lut, u16 lut_size) + { + struct i40e_pf *pf = vsi->back; + struct i40e_hw *hw = &pf->hw; + u16 i; + + if (seed) { + u32 *seed_dw = (u32 *)seed; + + for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) + seed_dw[i] = rd32(hw, I40E_PFQF_HKEY(i)); + } + if (lut) { + u32 *lut_dw = (u32 *)lut; + + if (lut_size != I40E_HLUT_ARRAY_SIZE) + return -EINVAL; + for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++) + lut_dw[i] = rd32(hw, I40E_PFQF_HLUT(i)); + } + + return 0; + } + + /** + * i40e_config_rss - Configure RSS keys and lut + * @vsi: Pointer to VSI structure + * @seed: RSS hash seed + * @lut: Lookup table + * @lut_size: Lookup table size + * + * Returns 0 on success, negative on failure + */ + int i40e_config_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) + { + struct i40e_pf *pf = vsi->back; + + if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) + return i40e_config_rss_aq(vsi, seed, lut, lut_size); + else + return i40e_config_rss_reg(vsi, seed, lut, lut_size); + } + + /** + * i40e_get_rss - Get RSS keys and lut + * @vsi: Pointer to VSI structure + * @seed: Buffer to store the keys + * @lut: Buffer to store the lookup table entries + * lut_size: Size of buffer to store the lookup table entries + * + * Returns 0 on success, negative on failure + */ + int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) + { + return i40e_get_rss_reg(vsi, seed, lut, lut_size); + } + + /** + * i40e_fill_rss_lut - Fill the RSS lookup table with default values + * @pf: Pointer to board private structure + * @lut: Lookup table + * @rss_table_size: Lookup table size + * @rss_size: Range of queue number for hashing + */ + static void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut, + u16 rss_table_size, u16 rss_size) + { + u16 i; + + for (i = 0; i < rss_table_size; i++) + lut[i] = i % rss_size; + } + + /** + * i40e_pf_config_rss - Prepare for RSS if used * @pf: board private structure **/ - static int i40e_config_rss(struct i40e_pf *pf) + static int i40e_pf_config_rss(struct i40e_pf *pf) { struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; u8 seed[I40E_HKEY_ARRAY_SIZE]; + u8 *lut; struct i40e_hw *hw = &pf->hw; u32 reg_val; u64 hena; - - netdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE); + int ret;
/* By default we enable TCP/UDP with IPv4/IPv6 ptypes */ hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) | @@@ -7898,8 -8020,6 +8020,6 @@@ wr32(hw, I40E_PFQF_HENA(0), (u32)hena); wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
- vsi->rss_size = min_t(int, pf->rss_size, vsi->num_queue_pairs); - /* Determine the RSS table size based on the hardware capabilities */ reg_val = rd32(hw, I40E_PFQF_CTL_0); reg_val = (pf->rss_table_size == 512) ? @@@ -7907,10 -8027,32 +8027,32 @@@ (reg_val & ~I40E_PFQF_CTL_0_HASHLUTSIZE_512); wr32(hw, I40E_PFQF_CTL_0, reg_val);
- if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) - return i40e_config_rss_aq(pf->vsi[pf->lan_vsi], seed); + /* Determine the RSS size of the VSI */ + if (!vsi->rss_size) + vsi->rss_size = min_t(int, pf->alloc_rss_size, + vsi->num_queue_pairs); + + lut = kzalloc(vsi->rss_table_size, GFP_KERNEL); + if (!lut) + return -ENOMEM; + + /* Use user configured lut if there is one, otherwise use default */ + if (vsi->rss_lut_user) + memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); + else + i40e_fill_rss_lut(pf, lut, vsi->rss_table_size, vsi->rss_size); + + /* Use user configured hash key if there is one, otherwise + * use default. + */ + if (vsi->rss_hkey_user) + memcpy(seed, vsi->rss_hkey_user, I40E_HKEY_ARRAY_SIZE); else - return i40e_config_rss_reg(pf, seed); + netdev_rss_key_fill((void *)seed, I40E_HKEY_ARRAY_SIZE); + ret = i40e_config_rss(vsi, seed, lut, vsi->rss_table_size); + kfree(lut); + + return ret; }
/** @@@ -7935,13 -8077,28 +8077,28 @@@ int i40e_reconfig_rss_queues(struct i40 vsi->req_queue_pairs = queue_count; i40e_prep_for_reset(pf);
- pf->rss_size = new_rss_size; + pf->alloc_rss_size = new_rss_size;
i40e_reset_and_rebuild(pf, true); - i40e_config_rss(pf); + + /* Discard the user configured hash keys and lut, if less + * queues are enabled. + */ + if (queue_count < vsi->rss_size) { + i40e_clear_rss_config_user(vsi); + dev_dbg(&pf->pdev->dev, + "discard user configured hash keys and lut\n"); + } + + /* Reset vsi->rss_size, as number of enabled queues changed */ + vsi->rss_size = min_t(int, pf->alloc_rss_size, + vsi->num_queue_pairs); + + i40e_pf_config_rss(pf); } - dev_info(&pf->pdev->dev, "RSS count: %d\n", pf->rss_size); - return pf->rss_size; + dev_info(&pf->pdev->dev, "RSS count/HW max RSS count: %d/%d\n", + pf->alloc_rss_size, pf->rss_size_max); + return pf->alloc_rss_size; }
/** @@@ -8112,13 -8269,14 +8269,14 @@@ static int i40e_sw_init(struct i40e_pf * maximum might end up larger than the available queues */ pf->rss_size_max = BIT(pf->hw.func_caps.rss_table_entry_width); - pf->rss_size = 1; + pf->alloc_rss_size = 1; pf->rss_table_size = pf->hw.func_caps.rss_table_size; pf->rss_size_max = min_t(int, pf->rss_size_max, pf->hw.func_caps.num_tx_qp); if (pf->hw.func_caps.rss) { pf->flags |= I40E_FLAG_RSS_ENABLED; - pf->rss_size = min_t(int, pf->rss_size_max, num_online_cpus()); + pf->alloc_rss_size = min_t(int, pf->rss_size_max, + num_online_cpus()); }
/* MFP mode enabled */ @@@ -9051,7 -9209,7 +9209,7 @@@ int i40e_vsi_release(struct i40e_vsi *v f->is_vf, f->is_netdev); spin_unlock_bh(&vsi->mac_filter_list_lock);
- i40e_sync_vsi_filters(vsi, false); + i40e_sync_vsi_filters(vsi);
i40e_vsi_delete(vsi); i40e_vsi_free_q_vectors(vsi); @@@ -9947,7 -10105,7 +10105,7 @@@ static int i40e_setup_pf_switch(struct * the hash */ if ((pf->flags & I40E_FLAG_RSS_ENABLED)) - i40e_config_rss(pf); + i40e_pf_config_rss(pf);
/* fill in link information and enable LSE reporting */ i40e_update_link_info(&pf->hw); @@@ -9985,7 -10143,7 +10143,7 @@@ static void i40e_determine_queue_usage( !(pf->flags & I40E_FLAG_MSIX_ENABLED)) { /* one qp for PF, no queues for anything else */ queues_left = 0; - pf->rss_size = pf->num_lan_qps = 1; + pf->alloc_rss_size = pf->num_lan_qps = 1;
/* make sure all the fancies are disabled */ pf->flags &= ~(I40E_FLAG_RSS_ENABLED | @@@ -10002,7 -10160,7 +10160,7 @@@ I40E_FLAG_FD_ATR_ENABLED | I40E_FLAG_DCB_CAPABLE))) { /* one qp for PF */ - pf->rss_size = pf->num_lan_qps = 1; + pf->alloc_rss_size = pf->num_lan_qps = 1; queues_left -= pf->num_lan_qps;
pf->flags &= ~(I40E_FLAG_RSS_ENABLED | @@@ -10072,8 -10230,9 +10230,9 @@@ "qs_avail=%d FD SB=%d lan_qs=%d lan_tc0=%d vf=%d*%d vmdq=%d*%d, remaining=%d\n", pf->hw.func_caps.num_tx_qp, !!(pf->flags & I40E_FLAG_FD_SB_ENABLED), - pf->num_lan_qps, pf->rss_size, pf->num_req_vfs, pf->num_vf_qps, - pf->num_vmdq_vsis, pf->num_vmdq_qps, queues_left); + pf->num_lan_qps, pf->alloc_rss_size, pf->num_req_vfs, + pf->num_vf_qps, pf->num_vmdq_vsis, pf->num_vmdq_qps, + queues_left); #ifdef I40E_FCOE dev_dbg(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps); #endif @@@ -10111,55 -10270,53 +10270,53 @@@ static int i40e_setup_pf_filter_control }
#define INFO_STRING_LEN 255 + #define REMAIN(__x) (INFO_STRING_LEN - (__x)) static void i40e_print_features(struct i40e_pf *pf) { struct i40e_hw *hw = &pf->hw; - char *buf, *string; + char *buf; + int i;
- string = kzalloc(INFO_STRING_LEN, GFP_KERNEL); - if (!string) { - dev_err(&pf->pdev->dev, "Features string allocation failed\n"); + buf = kmalloc(INFO_STRING_LEN, GFP_KERNEL); + if (!buf) return; - } - - buf = string;
- buf += sprintf(string, "Features: PF-id[%d] ", hw->pf_id); + i = snprintf(buf, INFO_STRING_LEN, "Features: PF-id[%d]", hw->pf_id); #ifdef CONFIG_PCI_IOV - buf += sprintf(buf, "VFs: %d ", pf->num_req_vfs); + i += snprintf(&buf[i], REMAIN(i), " VFs: %d", pf->num_req_vfs); #endif - buf += sprintf(buf, "VSIs: %d QP: %d RX: %s ", - pf->hw.func_caps.num_vsis, - pf->vsi[pf->lan_vsi]->num_queue_pairs, - pf->flags & I40E_FLAG_RX_PS_ENABLED ? "PS" : "1BUF"); + i += snprintf(&buf[i], REMAIN(i), " VSIs: %d QP: %d RX: %s", + pf->hw.func_caps.num_vsis, + pf->vsi[pf->lan_vsi]->num_queue_pairs, + pf->flags & I40E_FLAG_RX_PS_ENABLED ? "PS" : "1BUF");
if (pf->flags & I40E_FLAG_RSS_ENABLED) - buf += sprintf(buf, "RSS "); + i += snprintf(&buf[i], REMAIN(i), " RSS"); if (pf->flags & I40E_FLAG_FD_ATR_ENABLED) - buf += sprintf(buf, "FD_ATR "); + i += snprintf(&buf[i], REMAIN(i), " FD_ATR"); if (pf->flags & I40E_FLAG_FD_SB_ENABLED) { - buf += sprintf(buf, "FD_SB "); - buf += sprintf(buf, "NTUPLE "); + i += snprintf(&buf[i], REMAIN(i), " FD_SB"); + i += snprintf(&buf[i], REMAIN(i), " NTUPLE"); } if (pf->flags & I40E_FLAG_DCB_CAPABLE) - buf += sprintf(buf, "DCB "); + i += snprintf(&buf[i], REMAIN(i), " DCB"); #if IS_ENABLED(CONFIG_VXLAN) - buf += sprintf(buf, "VxLAN "); + i += snprintf(&buf[i], REMAIN(i), " VxLAN"); #endif if (pf->flags & I40E_FLAG_PTP) - buf += sprintf(buf, "PTP "); + i += snprintf(&buf[i], REMAIN(i), " PTP"); #ifdef I40E_FCOE if (pf->flags & I40E_FLAG_FCOE_ENABLED) - buf += sprintf(buf, "FCOE "); + i += snprintf(&buf[i], REMAIN(i), " FCOE"); #endif if (pf->flags & I40E_FLAG_VEB_MODE_ENABLED) - buf += sprintf(buf, "VEB "); + i += snprintf(&buf[i], REMAIN(i), " VEB"); else - buf += sprintf(buf, "VEPA "); + i += snprintf(&buf[i], REMAIN(i), " VEPA");
- BUG_ON(buf > (string + INFO_STRING_LEN)); - dev_info(&pf->pdev->dev, "%s\n", string); - kfree(string); + dev_info(&pf->pdev->dev, "%s\n", buf); + kfree(buf); + WARN_ON(i > INFO_STRING_LEN); }
/** @@@ -10183,6 -10340,7 +10340,7 @@@ static int i40e_probe(struct pci_dev *p u16 link_status; int err; u32 len; + u32 val; u32 i; u8 set_fc_aq_fail;
@@@ -10295,13 -10453,17 +10453,23 @@@ /* set up a default setting for link flow control */ pf->hw.fc.requested_mode = I40E_FC_NONE;
+ /* set up the locks for the AQ, do this only once in probe + * and destroy them only once in remove + */ + mutex_init(&hw->aq.asq_mutex); + mutex_init(&hw->aq.arq_mutex); + err = i40e_init_adminq(hw); + if (err) { + if (err == I40E_ERR_FIRMWARE_API_VERSION) + dev_info(&pdev->dev, + "The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n"); + else + dev_info(&pdev->dev, + "The driver for the device stopped because the device firmware failed to init. Try updating your NVM image.\n"); + + goto err_pf_reset; + }
/* provide nvm, fw, api versions */ dev_info(&pdev->dev, "fw %d.%d.%05d api %d.%d nvm %s\n", @@@ -10309,12 -10471,6 +10477,6 @@@ hw->aq.api_maj_ver, hw->aq.api_min_ver, i40e_nvm_version_str(hw));
- if (err) { - dev_info(&pdev->dev, - "The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n"); - goto err_pf_reset; - } - if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) dev_info(&pdev->dev, @@@ -10493,6 -10649,17 +10655,17 @@@ i40e_stat_str(&pf->hw, err), i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
+ /* Reconfigure hardware for allowing smaller MSS in the case + * of TSO, so that we avoid the MDD being fired and causing + * a reset in the case of small MSS+TSO. + */ + val = rd32(hw, I40E_REG_MSS); + if ((val & I40E_REG_MSS_MIN_MASK) > I40E_64BYTE_MSS) { + val &= ~I40E_REG_MSS_MIN_MASK; + val |= I40E_64BYTE_MSS; + wr32(hw, I40E_REG_MSS, val); + } + if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || (pf->hw.aq.fw_maj_ver < 4)) { msleep(75); @@@ -10703,6 -10870,7 +10876,6 @@@ static void i40e_remove(struct pci_dev set_bit(__I40E_DOWN, &pf->state); del_timer_sync(&pf->service_timer); cancel_work_sync(&pf->service_task); - i40e_fdir_teardown(pf);
if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { i40e_free_vfs(pf); @@@ -10745,10 -10913,6 +10918,10 @@@ "Failed to destroy the Admin Queue resources: %d\n", ret_code);
+ /* destroy the locks only once, here */ + mutex_destroy(&hw->aq.arq_mutex); + mutex_destroy(&hw->aq.asq_mutex); + /* Clear all dynamic memory lists of rings, q_vectors, and VSIs */ i40e_clear_interrupt_scheme(pf); for (i = 0; i < pf->num_alloc_vsi; i++) { diff --combined drivers/net/ethernet/intel/i40evf/i40evf_main.c index 99d2cff,b4c632f..af2a145 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@@ -34,7 -34,7 +34,7 @@@ char i40evf_driver_name[] = "i40evf" static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver";
- #define DRV_VERSION "1.3.33" + #define DRV_VERSION "1.4.3" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2015 Intel Corporation."; @@@ -259,7 -259,7 +259,7 @@@ static void i40evf_fire_sw_int(struct i { struct i40e_hw *hw = &adapter->hw; int i; - uint32_t dyn_ctl; + u32 dyn_ctl;
if (mask & 1) { dyn_ctl = rd32(hw, I40E_VFINT_DYN_CTL01); @@@ -307,10 -307,9 +307,9 @@@ static irqreturn_t i40evf_msix_aq(int i struct i40e_hw *hw = &adapter->hw; u32 val;
- /* handle non-queue interrupts */ - rd32(hw, I40E_VFINT_ICR01); - rd32(hw, I40E_VFINT_ICR0_ENA1); - + /* handle non-queue interrupts, these reads clear the registers */ + val = rd32(hw, I40E_VFINT_ICR01); + val = rd32(hw, I40E_VFINT_ICR0_ENA1);
val = rd32(hw, I40E_VFINT_DYN_CTL01) | I40E_VFINT_DYN_CTL01_CLEARPBA_MASK; @@@ -348,8 -347,8 +347,8 @@@ static irqreturn_t i40evf_msix_clean_ri static void i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx) { - struct i40e_q_vector *q_vector = adapter->q_vector[v_idx]; - struct i40e_ring *rx_ring = adapter->rx_rings[r_idx]; + struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx]; + struct i40e_ring *rx_ring = &adapter->rx_rings[r_idx];
rx_ring->q_vector = q_vector; rx_ring->next = q_vector->rx.ring; @@@ -369,8 -368,8 +368,8 @@@ static void i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx) { - struct i40e_q_vector *q_vector = adapter->q_vector[v_idx]; - struct i40e_ring *tx_ring = adapter->tx_rings[t_idx]; + struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx]; + struct i40e_ring *tx_ring = &adapter->tx_rings[t_idx];
tx_ring->q_vector = q_vector; tx_ring->next = q_vector->tx.ring; @@@ -465,7 -464,7 +464,7 @@@ static void i40evf_netpoll(struct net_d return;
for (i = 0; i < q_vectors; i++) - i40evf_msix_clean_rings(0, adapter->q_vector[i]); + i40evf_msix_clean_rings(0, &adapter->q_vectors[i]); }
#endif @@@ -487,7 -486,7 +486,7 @@@ i40evf_request_traffic_irqs(struct i40e q_vectors = adapter->num_msix_vectors - NONQ_VECS;
for (vector = 0; vector < q_vectors; vector++) { - struct i40e_q_vector *q_vector = adapter->q_vector[vector]; + struct i40e_q_vector *q_vector = &adapter->q_vectors[vector];
if (q_vector->tx.ring && q_vector->rx.ring) { snprintf(q_vector->name, sizeof(q_vector->name) - 1, @@@ -532,7 -531,7 +531,7 @@@ free_queue_irqs adapter->msix_entries[vector + NONQ_VECS].vector, NULL); free_irq(adapter->msix_entries[vector + NONQ_VECS].vector, - adapter->q_vector[vector]); + &adapter->q_vectors[vector]); } return err; } @@@ -582,7 -581,7 +581,7 @@@ static void i40evf_free_traffic_irqs(st irq_set_affinity_hint(adapter->msix_entries[i+1].vector, NULL); free_irq(adapter->msix_entries[i+1].vector, - adapter->q_vector[i]); + &adapter->q_vectors[i]); } }
@@@ -611,7 -610,7 +610,7 @@@ static void i40evf_configure_tx(struct int i;
for (i = 0; i < adapter->num_active_queues; i++) - adapter->tx_rings[i]->tail = hw->hw_addr + I40E_QTX_TAIL1(i); + adapter->tx_rings[i].tail = hw->hw_addr + I40E_QTX_TAIL1(i); }
/** @@@ -656,8 -655,8 +655,8 @@@ static void i40evf_configure_rx(struct }
for (i = 0; i < adapter->num_active_queues; i++) { - adapter->rx_rings[i]->tail = hw->hw_addr + I40E_QRX_TAIL1(i); - adapter->rx_rings[i]->rx_buf_len = rx_buf_len; + adapter->rx_rings[i].tail = hw->hw_addr + I40E_QRX_TAIL1(i); + adapter->rx_rings[i].rx_buf_len = rx_buf_len; } }
@@@ -954,7 -953,7 +953,7 @@@ static void i40evf_napi_enable_all(stru for (q_idx = 0; q_idx < q_vectors; q_idx++) { struct napi_struct *napi;
- q_vector = adapter->q_vector[q_idx]; + q_vector = &adapter->q_vectors[q_idx]; napi = &q_vector->napi; napi_enable(napi); } @@@ -971,7 -970,7 +970,7 @@@ static void i40evf_napi_disable_all(str int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
for (q_idx = 0; q_idx < q_vectors; q_idx++) { - q_vector = adapter->q_vector[q_idx]; + q_vector = &adapter->q_vectors[q_idx]; napi_disable(&q_vector->napi); } } @@@ -992,7 -991,7 +991,7 @@@ static void i40evf_configure(struct i40 adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
for (i = 0; i < adapter->num_active_queues; i++) { - struct i40e_ring *ring = adapter->rx_rings[i]; + struct i40e_ring *ring = &adapter->rx_rings[i];
i40evf_alloc_rx_buffers_1buf(ring, ring->count); ring->next_to_use = ring->count - 1; @@@ -1112,16 -1111,10 +1111,10 @@@ i40evf_acquire_msix_vectors(struct i40e **/ static void i40evf_free_queues(struct i40evf_adapter *adapter) { - int i; - if (!adapter->vsi_res) return; - for (i = 0; i < adapter->num_active_queues; i++) { - if (adapter->tx_rings[i]) - kfree_rcu(adapter->tx_rings[i], rcu); - adapter->tx_rings[i] = NULL; - adapter->rx_rings[i] = NULL; - } + kfree(adapter->tx_rings); + kfree(adapter->rx_rings); }
/** @@@ -1136,13 -1129,20 +1129,20 @@@ static int i40evf_alloc_queues(struct i { int i;
+ adapter->tx_rings = kcalloc(adapter->num_active_queues, + sizeof(struct i40e_ring), GFP_KERNEL); + if (!adapter->tx_rings) + goto err_out; + adapter->rx_rings = kcalloc(adapter->num_active_queues, + sizeof(struct i40e_ring), GFP_KERNEL); + if (!adapter->rx_rings) + goto err_out; + for (i = 0; i < adapter->num_active_queues; i++) { struct i40e_ring *tx_ring; struct i40e_ring *rx_ring;
- tx_ring = kzalloc(sizeof(*tx_ring) * 2, GFP_KERNEL); - if (!tx_ring) - goto err_out; + tx_ring = &adapter->tx_rings[i];
tx_ring->queue_index = i; tx_ring->netdev = adapter->netdev; @@@ -1150,14 -1150,12 +1150,12 @@@ tx_ring->count = adapter->tx_desc_count; if (adapter->flags & I40E_FLAG_WB_ON_ITR_CAPABLE) tx_ring->flags |= I40E_TXR_FLAGS_WB_ON_ITR; - adapter->tx_rings[i] = tx_ring;
- rx_ring = &tx_ring[1]; + rx_ring = &adapter->rx_rings[i]; rx_ring->queue_index = i; rx_ring->netdev = adapter->netdev; rx_ring->dev = &adapter->pdev->dev; rx_ring->count = adapter->rx_desc_count; - adapter->rx_rings[i] = rx_ring; }
return 0; @@@ -1207,115 -1205,273 +1205,273 @@@ static int i40evf_set_interrupt_capabil err = i40evf_acquire_msix_vectors(adapter, v_budget);
out: - adapter->netdev->real_num_tx_queues = pairs; + netif_set_real_num_rx_queues(adapter->netdev, pairs); + netif_set_real_num_tx_queues(adapter->netdev, pairs); return err; }
/** - * i40e_configure_rss_aq - Prepare for RSS using AQ commands + * i40e_config_rss_aq - Prepare for RSS using AQ commands * @vsi: vsi structure * @seed: RSS hash seed + * @lut: Lookup table + * @lut_size: Lookup table size + * + * Return 0 on success, negative on failure **/ - static void i40evf_configure_rss_aq(struct i40e_vsi *vsi, const u8 *seed) + static int i40evf_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed, + u8 *lut, u16 lut_size) { - struct i40e_aqc_get_set_rss_key_data rss_key; struct i40evf_adapter *adapter = vsi->back; struct i40e_hw *hw = &adapter->hw; - int ret = 0, i; - u8 *rss_lut; + int ret = 0;
if (!vsi->id) - return; + return -EINVAL;
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ dev_err(&adapter->pdev->dev, "Cannot confiure RSS, command %d pending\n", adapter->current_op); - return; + return -EBUSY; }
- memset(&rss_key, 0, sizeof(rss_key)); - memcpy(&rss_key, seed, sizeof(rss_key)); + if (seed) { + struct i40e_aqc_get_set_rss_key_data *rss_key = + (struct i40e_aqc_get_set_rss_key_data *)seed; + ret = i40evf_aq_set_rss_key(hw, vsi->id, rss_key); + if (ret) { + dev_err(&adapter->pdev->dev, "Cannot set RSS key, err %s aq_err %s\n", + i40evf_stat_str(hw, ret), + i40evf_aq_str(hw, hw->aq.asq_last_status)); + return ret; + } + }
- rss_lut = kzalloc(((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4), GFP_KERNEL); - if (!rss_lut) - return; + if (lut) { + ret = i40evf_aq_set_rss_lut(hw, vsi->id, false, lut, lut_size); + if (ret) { + dev_err(&adapter->pdev->dev, + "Cannot set RSS lut, err %s aq_err %s\n", + i40evf_stat_str(hw, ret), + i40evf_aq_str(hw, hw->aq.asq_last_status)); + return ret; + } + }
- /* Populate the LUT with max no. PF queues in round robin fashion */ - for (i = 0; i <= (I40E_VFQF_HLUT_MAX_INDEX * 4); i++) - rss_lut[i] = i % adapter->num_active_queues; + return ret; + }
- ret = i40evf_aq_set_rss_key(hw, vsi->id, &rss_key); - if (ret) { - dev_err(&adapter->pdev->dev, - "Cannot set RSS key, err %s aq_err %s\n", - i40evf_stat_str(hw, ret), - i40evf_aq_str(hw, hw->aq.asq_last_status)); - return; + /** + * i40evf_config_rss_reg - Configure RSS keys and lut by writing registers + * @vsi: Pointer to vsi structure + * @seed: RSS hash seed + * @lut: Lookup table + * @lut_size: Lookup table size + * + * Returns 0 on success, negative on failure + **/ + static int i40evf_config_rss_reg(struct i40e_vsi *vsi, const u8 *seed, + const u8 *lut, u16 lut_size) + { + struct i40evf_adapter *adapter = vsi->back; + struct i40e_hw *hw = &adapter->hw; + u16 i; + + if (seed) { + u32 *seed_dw = (u32 *)seed; + + for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) + wr32(hw, I40E_VFQF_HKEY(i), seed_dw[i]); }
- ret = i40evf_aq_set_rss_lut(hw, vsi->id, false, rss_lut, - (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4); - if (ret) - dev_err(&adapter->pdev->dev, - "Cannot set RSS lut, err %s aq_err %s\n", - i40evf_stat_str(hw, ret), - i40evf_aq_str(hw, hw->aq.asq_last_status)); + if (lut) { + u32 *lut_dw = (u32 *)lut; + + if (lut_size != I40EVF_HLUT_ARRAY_SIZE) + return -EINVAL; + + for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) + wr32(hw, I40E_VFQF_HLUT(i), lut_dw[i]); + } + i40e_flush(hw); + + return 0; }
/** - * i40e_configure_rss_reg - Prepare for RSS if used - * @adapter: board private structure - * @seed: RSS hash seed + * * i40evf_get_rss_aq - Get RSS keys and lut by using AQ commands + * @vsi: Pointer to vsi structure + * @seed: RSS hash seed + * @lut: Lookup table + * @lut_size: Lookup table size + * + * Return 0 on success, negative on failure **/ - static void i40evf_configure_rss_reg(struct i40evf_adapter *adapter, - const u8 *seed) + static int i40evf_get_rss_aq(struct i40e_vsi *vsi, const u8 *seed, + u8 *lut, u16 lut_size) { + struct i40evf_adapter *adapter = vsi->back; struct i40e_hw *hw = &adapter->hw; - u32 *seed_dw = (u32 *)seed; - u32 cqueue = 0; - u32 lut = 0; - int i, j; + int ret = 0;
- /* Fill out hash function seed */ - for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) - wr32(hw, I40E_VFQF_HKEY(i), seed_dw[i]); - - /* Populate the LUT with max no. PF queues in round robin fashion */ - for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) { - lut = 0; - for (j = 0; j < 4; j++) { - if (cqueue == adapter->num_active_queues) - cqueue = 0; - lut |= ((cqueue) << (8 * j)); - cqueue++; + if (seed) { + ret = i40evf_aq_get_rss_key(hw, vsi->id, + (struct i40e_aqc_get_set_rss_key_data *)seed); + if (ret) { + dev_err(&adapter->pdev->dev, + "Cannot get RSS key, err %s aq_err %s\n", + i40evf_stat_str(hw, ret), + i40evf_aq_str(hw, hw->aq.asq_last_status)); + return ret; } - wr32(hw, I40E_VFQF_HLUT(i), lut); } - i40e_flush(hw); + + if (lut) { + ret = i40evf_aq_get_rss_lut(hw, vsi->id, seed, lut, lut_size); + if (ret) { + dev_err(&adapter->pdev->dev, + "Cannot get RSS lut, err %s aq_err %s\n", + i40evf_stat_str(hw, ret), + i40evf_aq_str(hw, hw->aq.asq_last_status)); + return ret; + } + } + + return ret; }
/** - * i40evf_configure_rss - Prepare for RSS + * * i40evf_get_rss_reg - Get RSS keys and lut by reading registers + * @vsi: Pointer to vsi structure + * @seed: RSS hash seed + * @lut: Lookup table + * @lut_size: Lookup table size + * + * Returns 0 on success, negative on failure + **/ + static int i40evf_get_rss_reg(struct i40e_vsi *vsi, const u8 *seed, + const u8 *lut, u16 lut_size) + { + struct i40evf_adapter *adapter = vsi->back; + struct i40e_hw *hw = &adapter->hw; + u16 i; + + if (seed) { + u32 *seed_dw = (u32 *)seed; + + for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) + seed_dw[i] = rd32(hw, I40E_VFQF_HKEY(i)); + } + + if (lut) { + u32 *lut_dw = (u32 *)lut; + + if (lut_size != I40EVF_HLUT_ARRAY_SIZE) + return -EINVAL; + + for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) + lut_dw[i] = rd32(hw, I40E_VFQF_HLUT(i)); + } + + return 0; + } + + /** + * i40evf_config_rss - Configure RSS keys and lut + * @vsi: Pointer to vsi structure + * @seed: RSS hash seed + * @lut: Lookup table + * @lut_size: Lookup table size + * + * Returns 0 on success, negative on failure + **/ + int i40evf_config_rss(struct i40e_vsi *vsi, const u8 *seed, + u8 *lut, u16 lut_size) + { + struct i40evf_adapter *adapter = vsi->back; + + if (RSS_AQ(adapter)) + return i40evf_config_rss_aq(vsi, seed, lut, lut_size); + else + return i40evf_config_rss_reg(vsi, seed, lut, lut_size); + } + + /** + * i40evf_get_rss - Get RSS keys and lut + * @vsi: Pointer to vsi structure + * @seed: RSS hash seed + * @lut: Lookup table + * @lut_size: Lookup table size + * + * Returns 0 on success, negative on failure + **/ + int i40evf_get_rss(struct i40e_vsi *vsi, const u8 *seed, u8 *lut, u16 lut_size) + { + struct i40evf_adapter *adapter = vsi->back; + + if (RSS_AQ(adapter)) + return i40evf_get_rss_aq(vsi, seed, lut, lut_size); + else + return i40evf_get_rss_reg(vsi, seed, lut, lut_size); + } + + /** + * i40evf_fill_rss_lut - Fill the lut with default values + * @lut: Lookup table to be filled with + * @rss_table_size: Lookup table size + * @rss_size: Range of queue number for hashing + **/ + static void i40evf_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size) + { + u16 i; + + for (i = 0; i < rss_table_size; i++) + lut[i] = i % rss_size; + } + + /** + * i40evf_init_rss - Prepare for RSS * @adapter: board private structure + * + * Return 0 on success, negative on failure **/ - static void i40evf_configure_rss(struct i40evf_adapter *adapter) + static int i40evf_init_rss(struct i40evf_adapter *adapter) { + struct i40e_vsi *vsi = &adapter->vsi; struct i40e_hw *hw = &adapter->hw; u8 seed[I40EVF_HKEY_ARRAY_SIZE]; u64 hena; - - netdev_rss_key_fill((void *)seed, I40EVF_HKEY_ARRAY_SIZE); + u8 *lut; + int ret;
/* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */ hena = I40E_DEFAULT_RSS_HENA; wr32(hw, I40E_VFQF_HENA(0), (u32)hena); wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32));
- if (RSS_AQ(adapter)) - i40evf_configure_rss_aq(&adapter->vsi, seed); + lut = kzalloc(I40EVF_HLUT_ARRAY_SIZE, GFP_KERNEL); + if (!lut) + return -ENOMEM; + + /* Use user configured lut if there is one, otherwise use default */ + if (vsi->rss_lut_user) + memcpy(lut, vsi->rss_lut_user, I40EVF_HLUT_ARRAY_SIZE); + else + i40evf_fill_rss_lut(lut, I40EVF_HLUT_ARRAY_SIZE, + adapter->num_active_queues); + + /* Use user configured hash key if there is one, otherwise + * user default. + */ + if (vsi->rss_hkey_user) + memcpy(seed, vsi->rss_hkey_user, I40EVF_HKEY_ARRAY_SIZE); else - i40evf_configure_rss_reg(adapter, seed); + netdev_rss_key_fill((void *)seed, I40EVF_HKEY_ARRAY_SIZE); + ret = i40evf_config_rss(vsi, seed, lut, I40EVF_HLUT_ARRAY_SIZE); + kfree(lut); + + return ret; }
/** @@@ -1327,21 -1483,22 +1483,22 @@@ **/ static int i40evf_alloc_q_vectors(struct i40evf_adapter *adapter) { - int q_idx, num_q_vectors; + int q_idx = 0, num_q_vectors; struct i40e_q_vector *q_vector;
num_q_vectors = adapter->num_msix_vectors - NONQ_VECS; + adapter->q_vectors = kcalloc(num_q_vectors, sizeof(*q_vector), + GFP_KERNEL); + if (!adapter->q_vectors) + goto err_out;
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { - q_vector = kzalloc(sizeof(*q_vector), GFP_KERNEL); - if (!q_vector) - goto err_out; + q_vector = &adapter->q_vectors[q_idx]; q_vector->adapter = adapter; q_vector->vsi = &adapter->vsi; q_vector->v_idx = q_idx; netif_napi_add(adapter->netdev, &q_vector->napi, i40evf_napi_poll, NAPI_POLL_WEIGHT); - adapter->q_vector[q_idx] = q_vector; }
return 0; @@@ -1349,11 -1506,10 +1506,10 @@@ err_out: while (q_idx) { q_idx--; - q_vector = adapter->q_vector[q_idx]; + q_vector = &adapter->q_vectors[q_idx]; netif_napi_del(&q_vector->napi); - kfree(q_vector); - adapter->q_vector[q_idx] = NULL; } + kfree(adapter->q_vectors); return -ENOMEM; }
@@@ -1374,13 -1530,11 +1530,11 @@@ static void i40evf_free_q_vectors(struc napi_vectors = adapter->num_active_queues;
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { - struct i40e_q_vector *q_vector = adapter->q_vector[q_idx]; - - adapter->q_vector[q_idx] = NULL; + struct i40e_q_vector *q_vector = &adapter->q_vectors[q_idx]; if (q_idx < napi_vectors) netif_napi_del(&q_vector->napi); - kfree(q_vector); } + kfree(adapter->q_vectors); }
/** @@@ -1439,6 -1593,22 +1593,22 @@@ err_set_interrupt }
/** + * i40evf_clear_rss_config_user - Clear user configurations of RSS + * @vsi: Pointer to VSI structure + **/ + static void i40evf_clear_rss_config_user(struct i40e_vsi *vsi) + { + if (!vsi) + return; + + kfree(vsi->rss_hkey_user); + vsi->rss_hkey_user = NULL; + + kfree(vsi->rss_lut_user); + vsi->rss_lut_user = NULL; + } + + /** * i40evf_watchdog_timer - Periodic call-back timer * @data: pointer to adapter disguised as unsigned long **/ @@@ -1565,7 -1735,7 +1735,7 @@@ static void i40evf_watchdog_task(struc * PF, so we don't have to set current_op as we will * not get a response through the ARQ. */ - i40evf_configure_rss(adapter); + i40evf_init_rss(adapter); adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_RSS; goto watchdog_done; } @@@ -1865,8 -2035,8 +2035,8 @@@ void i40evf_free_all_tx_resources(struc int i;
for (i = 0; i < adapter->num_active_queues; i++) - if (adapter->tx_rings[i]->desc) - i40evf_free_tx_resources(adapter->tx_rings[i]); + if (adapter->tx_rings[i].desc) + i40evf_free_tx_resources(&adapter->tx_rings[i]); }
/** @@@ -1884,8 -2054,8 +2054,8 @@@ static int i40evf_setup_all_tx_resource int i, err = 0;
for (i = 0; i < adapter->num_active_queues; i++) { - adapter->tx_rings[i]->count = adapter->tx_desc_count; - err = i40evf_setup_tx_descriptors(adapter->tx_rings[i]); + adapter->tx_rings[i].count = adapter->tx_desc_count; + err = i40evf_setup_tx_descriptors(&adapter->tx_rings[i]); if (!err) continue; dev_err(&adapter->pdev->dev, @@@ -1911,8 -2081,8 +2081,8 @@@ static int i40evf_setup_all_rx_resource int i, err = 0;
for (i = 0; i < adapter->num_active_queues; i++) { - adapter->rx_rings[i]->count = adapter->rx_desc_count; - err = i40evf_setup_rx_descriptors(adapter->rx_rings[i]); + adapter->rx_rings[i].count = adapter->rx_desc_count; + err = i40evf_setup_rx_descriptors(&adapter->rx_rings[i]); if (!err) continue; dev_err(&adapter->pdev->dev, @@@ -1933,8 -2103,8 +2103,8 @@@ void i40evf_free_all_rx_resources(struc int i;
for (i = 0; i < adapter->num_active_queues; i++) - if (adapter->rx_rings[i]->desc) - i40evf_free_rx_resources(adapter->rx_rings[i]); + if (adapter->rx_rings[i].desc) + i40evf_free_rx_resources(&adapter->rx_rings[i]); }
/** @@@ -2263,6 -2433,14 +2433,14 @@@ static void i40evf_init_task(struct wor if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) { err = i40evf_send_vf_config_msg(adapter); goto err; + } else if (err == I40E_ERR_PARAM) { + /* We only get ERR_PARAM if the device is in a very bad + * state or if we've been disabled for previous bad + * behavior. Either way, we're done now. + */ + i40evf_shutdown_adminq(hw); + dev_err(&pdev->dev, "Unable to get VF config due to PF error condition, not retrying\n"); + return; } if (err) { dev_err(&pdev->dev, "Unable to get VF config (%d)\n", @@@ -2313,7 -2491,7 +2491,7 @@@ I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE; if (!RSS_AQ(adapter)) - i40evf_configure_rss(adapter); + i40evf_init_rss(adapter); err = i40evf_request_misc_irq(adapter); if (err) goto err_sw_init; @@@ -2334,7 -2512,6 +2512,6 @@@ if (netdev->features & NETIF_F_GRO) dev_info(&pdev->dev, "GRO is enabled\n");
- dev_info(&pdev->dev, "%s\n", i40evf_driver_string); adapter->state = __I40EVF_DOWN; set_bit(__I40E_DOWN, &adapter->vsi.state); i40evf_misc_irq_enable(adapter); @@@ -2343,7 -2520,7 +2520,7 @@@ adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS; mod_timer_pending(&adapter->watchdog_timer, jiffies + 1); } else { - i40evf_configure_rss(adapter); + i40evf_init_rss(adapter); } return; restart: @@@ -2438,8 -2615,7 +2615,7 @@@ static int i40evf_probe(struct pci_dev
pci_set_master(pdev);
- netdev = alloc_etherdev_mq(sizeof(struct i40evf_adapter), - MAX_TX_QUEUES); + netdev = alloc_etherdev_mq(sizeof(struct i40evf_adapter), MAX_QUEUES); if (!netdev) { err = -ENOMEM; goto err_alloc_etherdev; @@@ -2476,12 -2652,6 +2652,12 @@@ hw->bus.device = PCI_SLOT(pdev->devfn); hw->bus.func = PCI_FUNC(pdev->devfn);
+ /* set up the locks for the AQ, do this only once in probe + * and destroy them only once in remove + */ + mutex_init(&hw->aq.asq_mutex); + mutex_init(&hw->aq.arq_mutex); + INIT_LIST_HEAD(&adapter->mac_filter_list); INIT_LIST_HEAD(&adapter->vlan_filter_list);
@@@ -2632,13 -2802,12 +2808,16 @@@ static void i40evf_remove(struct pci_de
flush_scheduled_work();
+ /* Clear user configurations for RSS */ + i40evf_clear_rss_config_user(&adapter->vsi); + if (hw->aq.asq.count) i40evf_shutdown_adminq(hw);
+ /* destroy the locks only once, here */ + mutex_destroy(&hw->aq.arq_mutex); + mutex_destroy(&hw->aq.asq_mutex); + iounmap(hw->hw_addr); pci_release_regions(pdev);
diff --combined drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index aed8d02,ebd4522..c965f6f --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@@ -65,9 -65,6 +65,6 @@@ #include "ixgbe_common.h" #include "ixgbe_dcb_82599.h" #include "ixgbe_sriov.h" - #ifdef CONFIG_IXGBE_VXLAN - #include <net/vxlan.h> - #endif
char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = @@@ -175,6 -172,8 +172,8 @@@ MODULE_DESCRIPTION("Intel(R) 10 Gigabi MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION);
+ static struct workqueue_struct *ixgbe_wq; + static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev);
static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter, @@@ -316,7 -315,7 +315,7 @@@ static void ixgbe_service_event_schedul if (!test_bit(__IXGBE_DOWN, &adapter->state) && !test_bit(__IXGBE_REMOVING, &adapter->state) && !test_and_set_bit(__IXGBE_SERVICE_SCHED, &adapter->state)) - schedule_work(&adapter->service_task); + queue_work(ixgbe_wq, &adapter->service_task); }
static void ixgbe_remove_adapter(struct ixgbe_hw *hw) @@@ -1635,6 -1634,7 +1634,7 @@@ static void ixgbe_process_skb_fields(st struct sk_buff *skb) { struct net_device *dev = rx_ring->netdev; + u32 flags = rx_ring->q_vector->adapter->flags;
ixgbe_update_rsc_stats(rx_ring, skb);
@@@ -1642,8 -1642,8 +1642,8 @@@
ixgbe_rx_checksum(rx_ring, rx_desc, skb);
- if (unlikely(ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))) - ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector->adapter, skb); + if (unlikely(flags & IXGBE_FLAG_RX_HWTSTAMP_ENABLED)) + ixgbe_ptp_rx_hwtstamp(rx_ring, rx_desc, skb);
if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { @@@ -1659,6 -1659,7 +1659,7 @@@ static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector, struct sk_buff *skb) { + skb_mark_napi_id(skb, &q_vector->napi); if (ixgbe_qv_busy_polling(q_vector)) netif_receive_skb(skb); else @@@ -2123,7 -2124,6 +2124,6 @@@ static int ixgbe_clean_rx_irq(struct ix }
#endif /* IXGBE_FCOE */ - skb_mark_napi_id(skb, &q_vector->napi); ixgbe_rx_skb(q_vector, skb);
/* update budget accounting */ @@@ -2741,7 -2741,7 +2741,7 @@@ static irqreturn_t ixgbe_msix_other(in ixgbe_check_fan_failure(adapter, eicr);
if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) - ixgbe_ptp_check_pps_event(adapter, eicr); + ixgbe_ptp_check_pps_event(adapter);
/* re-enable the original interrupt state, no lsc, no queues */ if (!test_bit(__IXGBE_DOWN, &adapter->state)) @@@ -2757,7 -2757,7 +2757,7 @@@ static irqreturn_t ixgbe_msix_clean_rin /* EIAM disabled interrupts (on this vector) for us */
if (q_vector->rx.ring || q_vector->tx.ring) - napi_schedule(&q_vector->napi); + napi_schedule_irqoff(&q_vector->napi);
return IRQ_HANDLED; } @@@ -2786,7 -2786,8 +2786,8 @@@ int ixgbe_poll(struct napi_struct *napi ixgbe_for_each_ring(ring, q_vector->tx) clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring);
- if (!ixgbe_qv_lock_napi(q_vector)) + /* Exit if we are called by netpoll or busy polling is active */ + if ((budget <= 0) || !ixgbe_qv_lock_napi(q_vector)) return budget;
/* attempt to distribute budget to each queue fairly, but don't allow @@@ -2947,10 -2948,10 +2948,10 @@@ static irqreturn_t ixgbe_intr(int irq,
ixgbe_check_fan_failure(adapter, eicr); if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) - ixgbe_ptp_check_pps_event(adapter, eicr); + ixgbe_ptp_check_pps_event(adapter);
/* would disable interrupts here but EIAM disabled it */ - napi_schedule(&q_vector->napi); + napi_schedule_irqoff(&q_vector->napi);
/* * re-enable link(maybe) and non-queue interrupts, no flush. @@@ -3315,8 -3316,7 +3316,7 @@@ static void ixgbe_configure_srrctl(stru }
/** - * Return a number of entries in the RSS indirection table - * + * ixgbe_rss_indir_tbl_entries - Return RSS indirection table entries * @adapter: device handle * * - 82598/82599/X540: 128 @@@ -3334,8 -3334,7 +3334,7 @@@ u32 ixgbe_rss_indir_tbl_entries(struct }
/** - * Write the RETA table to HW - * + * ixgbe_store_reta - Write the RETA table to HW * @adapter: device handle * * Write the RSS redirection table stored in adapter.rss_indir_tbl[] to HW. @@@ -3374,8 -3373,7 +3373,7 @@@ void ixgbe_store_reta(struct ixgbe_adap }
/** - * Write the RETA table to HW (for x550 devices in SRIOV mode) - * + * ixgbe_store_vfreta - Write the RETA table to HW (x550 devices in SRIOV mode) * @adapter: device handle * * Write the RSS redirection table stored in adapter.rss_indir_tbl[] to HW. @@@ -4034,124 -4032,156 +4032,156 @@@ static int ixgbe_write_mc_addr_list(str #ifdef CONFIG_PCI_IOV void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter) { + struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0]; struct ixgbe_hw *hw = &adapter->hw; int i; - for (i = 0; i < hw->mac.num_rar_entries; i++) { - if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE) - hw->mac.ops.set_rar(hw, i, adapter->mac_table[i].addr, - adapter->mac_table[i].queue, + + for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) { + mac_table->state &= ~IXGBE_MAC_STATE_MODIFIED; + + if (mac_table->state & IXGBE_MAC_STATE_IN_USE) + hw->mac.ops.set_rar(hw, i, + mac_table->addr, + mac_table->pool, IXGBE_RAH_AV); else hw->mac.ops.clear_rar(hw, i); - - adapter->mac_table[i].state &= ~(IXGBE_MAC_STATE_MODIFIED); } } - #endif
+ #endif static void ixgbe_sync_mac_table(struct ixgbe_adapter *adapter) { + struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0]; struct ixgbe_hw *hw = &adapter->hw; int i; - for (i = 0; i < hw->mac.num_rar_entries; i++) { - if (adapter->mac_table[i].state & IXGBE_MAC_STATE_MODIFIED) { - if (adapter->mac_table[i].state & - IXGBE_MAC_STATE_IN_USE) - hw->mac.ops.set_rar(hw, i, - adapter->mac_table[i].addr, - adapter->mac_table[i].queue, - IXGBE_RAH_AV); - else - hw->mac.ops.clear_rar(hw, i);
- adapter->mac_table[i].state &= - ~(IXGBE_MAC_STATE_MODIFIED); - } + for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) { + if (!(mac_table->state & IXGBE_MAC_STATE_MODIFIED)) + continue; + + mac_table->state &= ~IXGBE_MAC_STATE_MODIFIED; + + if (mac_table->state & IXGBE_MAC_STATE_IN_USE) + hw->mac.ops.set_rar(hw, i, + mac_table->addr, + mac_table->pool, + IXGBE_RAH_AV); + else + hw->mac.ops.clear_rar(hw, i); } }
static void ixgbe_flush_sw_mac_table(struct ixgbe_adapter *adapter) { - int i; + struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0]; struct ixgbe_hw *hw = &adapter->hw; + int i;
- for (i = 0; i < hw->mac.num_rar_entries; i++) { - adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED; - adapter->mac_table[i].state &= ~IXGBE_MAC_STATE_IN_USE; - eth_zero_addr(adapter->mac_table[i].addr); - adapter->mac_table[i].queue = 0; + for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) { + mac_table->state |= IXGBE_MAC_STATE_MODIFIED; + mac_table->state &= ~IXGBE_MAC_STATE_IN_USE; } + ixgbe_sync_mac_table(adapter); }
- static int ixgbe_available_rars(struct ixgbe_adapter *adapter) + static int ixgbe_available_rars(struct ixgbe_adapter *adapter, u16 pool) { + struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0]; struct ixgbe_hw *hw = &adapter->hw; int i, count = 0;
- for (i = 0; i < hw->mac.num_rar_entries; i++) { - if (adapter->mac_table[i].state == 0) - count++; + for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) { + /* do not count default RAR as available */ + if (mac_table->state & IXGBE_MAC_STATE_DEFAULT) + continue; + + /* only count unused and addresses that belong to us */ + if (mac_table->state & IXGBE_MAC_STATE_IN_USE) { + if (mac_table->pool != pool) + continue; + } + + count++; } + return count; }
/* this function destroys the first RAR entry */ - static void ixgbe_mac_set_default_filter(struct ixgbe_adapter *adapter, - u8 *addr) + static void ixgbe_mac_set_default_filter(struct ixgbe_adapter *adapter) { + struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0]; struct ixgbe_hw *hw = &adapter->hw;
- memcpy(&adapter->mac_table[0].addr, addr, ETH_ALEN); - adapter->mac_table[0].queue = VMDQ_P(0); - adapter->mac_table[0].state = (IXGBE_MAC_STATE_DEFAULT | - IXGBE_MAC_STATE_IN_USE); - hw->mac.ops.set_rar(hw, 0, adapter->mac_table[0].addr, - adapter->mac_table[0].queue, + memcpy(&mac_table->addr, hw->mac.addr, ETH_ALEN); + mac_table->pool = VMDQ_P(0); + + mac_table->state = IXGBE_MAC_STATE_DEFAULT | IXGBE_MAC_STATE_IN_USE; + + hw->mac.ops.set_rar(hw, 0, mac_table->addr, mac_table->pool, IXGBE_RAH_AV); }
- int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue) + int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter, + const u8 *addr, u16 pool) { + struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0]; struct ixgbe_hw *hw = &adapter->hw; int i;
if (is_zero_ether_addr(addr)) return -EINVAL;
- for (i = 0; i < hw->mac.num_rar_entries; i++) { - if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE) + for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) { + if (mac_table->state & IXGBE_MAC_STATE_IN_USE) continue; - adapter->mac_table[i].state |= (IXGBE_MAC_STATE_MODIFIED | - IXGBE_MAC_STATE_IN_USE); - ether_addr_copy(adapter->mac_table[i].addr, addr); - adapter->mac_table[i].queue = queue; + + ether_addr_copy(mac_table->addr, addr); + mac_table->pool = pool; + + mac_table->state |= IXGBE_MAC_STATE_MODIFIED | + IXGBE_MAC_STATE_IN_USE; + ixgbe_sync_mac_table(adapter); + return i; } + return -ENOMEM; }
- int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue) + int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter, + const u8 *addr, u16 pool) { - /* search table for addr, if found, set to 0 and sync */ - int i; + struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0]; struct ixgbe_hw *hw = &adapter->hw; + int i;
if (is_zero_ether_addr(addr)) return -EINVAL;
- for (i = 0; i < hw->mac.num_rar_entries; i++) { - if (ether_addr_equal(addr, adapter->mac_table[i].addr) && - adapter->mac_table[i].queue == queue) { - adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED; - adapter->mac_table[i].state &= ~IXGBE_MAC_STATE_IN_USE; - eth_zero_addr(adapter->mac_table[i].addr); - adapter->mac_table[i].queue = 0; - ixgbe_sync_mac_table(adapter); - return 0; - } + /* search table for addr, if found clear IN_USE flag and sync */ + for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) { + /* we can only delete an entry if it is in use */ + if (!(mac_table->state & IXGBE_MAC_STATE_IN_USE)) + continue; + /* we only care about entries that belong to the given pool */ + if (mac_table->pool != pool) + continue; + /* we only care about a specific MAC address */ + if (!ether_addr_equal(addr, mac_table->addr)) + continue; + + mac_table->state |= IXGBE_MAC_STATE_MODIFIED; + mac_table->state &= ~IXGBE_MAC_STATE_IN_USE; + + ixgbe_sync_mac_table(adapter); + + return 0; } + return -ENOMEM; } /** @@@ -4169,7 -4199,7 +4199,7 @@@ static int ixgbe_write_uc_addr_list(str int count = 0;
/* return ENOMEM indicating insufficient memory for addresses */ - if (netdev_uc_count(netdev) > ixgbe_available_rars(adapter)) + if (netdev_uc_count(netdev) > ixgbe_available_rars(adapter, vfn)) return -ENOMEM;
if (!netdev_uc_empty(netdev)) { @@@ -4183,6 -4213,25 +4213,25 @@@ return count; }
+ static int ixgbe_uc_sync(struct net_device *netdev, const unsigned char *addr) + { + struct ixgbe_adapter *adapter = netdev_priv(netdev); + int ret; + + ret = ixgbe_add_mac_filter(adapter, addr, VMDQ_P(0)); + + return min_t(int, ret, 0); + } + + static int ixgbe_uc_unsync(struct net_device *netdev, const unsigned char *addr) + { + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + ixgbe_del_mac_filter(adapter, addr, VMDQ_P(0)); + + return 0; + } + /** * ixgbe_set_rx_mode - Unicast, Multicast and Promiscuous mode set * @netdev: network interface device structure @@@ -4238,8 -4287,7 +4287,7 @@@ void ixgbe_set_rx_mode(struct net_devic * sufficient space to store all the addresses then enable * unicast promiscuous mode */ - count = ixgbe_write_uc_addr_list(netdev, VMDQ_P(0)); - if (count < 0) { + if (__dev_uc_sync(netdev, ixgbe_uc_sync, ixgbe_uc_unsync)) { fctrl |= IXGBE_FCTRL_UPE; vmolr |= IXGBE_VMOLR_ROPE; } @@@ -5042,7 -5090,6 +5090,6 @@@ void ixgbe_reset(struct ixgbe_adapter * struct ixgbe_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; int err; - u8 old_addr[ETH_ALEN];
if (ixgbe_removed(hw->hw_addr)) return; @@@ -5078,10 -5125,13 +5125,13 @@@ }
clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state); - /* do not flush user set addresses */ - memcpy(old_addr, &adapter->mac_table[0].addr, netdev->addr_len); + + /* flush entries out of MAC table */ ixgbe_flush_sw_mac_table(adapter); - ixgbe_mac_set_default_filter(adapter, old_addr); + __dev_uc_unsync(netdev, NULL); + + /* do not flush user set addresses */ + ixgbe_mac_set_default_filter(adapter);
/* update SAN MAC vmdq pool selection */ if (hw->mac.san_mac_rar_index) @@@ -6616,10 -6666,8 +6666,8 @@@ static void ixgbe_check_for_bad_vf(stru { struct ixgbe_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; - struct pci_dev *vfdev; + unsigned int vf; u32 gpc; - int pos; - unsigned short vf_id;
if (!(netif_carrier_ok(adapter->netdev))) return; @@@ -6636,26 -6684,17 +6684,17 @@@ if (!pdev) return;
- pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); - if (!pos) - return; - - /* get the device ID for the VF */ - pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id); - /* check status reg for all VFs owned by this PF */ - vfdev = pci_get_device(pdev->vendor, vf_id, NULL); - while (vfdev) { - if (vfdev->is_virtfn && (vfdev->physfn == pdev)) { - u16 status_reg; - - pci_read_config_word(vfdev, PCI_STATUS, &status_reg); - if (status_reg & PCI_STATUS_REC_MASTER_ABORT) - /* issue VFLR */ - ixgbe_issue_vf_flr(adapter, vfdev); - } + for (vf = 0; vf < adapter->num_vfs; ++vf) { + struct pci_dev *vfdev = adapter->vfinfo[vf].vfdev; + u16 status_reg;
- vfdev = pci_get_device(pdev->vendor, vf_id, vfdev); + if (!vfdev) + continue; + pci_read_config_word(vfdev, PCI_STATUS, &status_reg); + if (status_reg != IXGBE_FAILED_READ_CFG_WORD && + status_reg & PCI_STATUS_REC_MASTER_ABORT) + ixgbe_issue_vf_flr(adapter, vfdev); } }
@@@ -7024,6 -7063,7 +7063,7 @@@ static void ixgbe_tx_csum(struct ixgbe_ struct tcphdr *tcphdr; u8 *raw; } transport_hdr; + __be16 frag_off;
if (skb->encapsulation) { network_hdr.raw = skb_inner_network_header(skb); @@@ -7047,13 -7087,17 +7087,17 @@@ case 6: vlan_macip_lens |= transport_hdr.raw - network_hdr.raw; l4_hdr = network_hdr.ipv6->nexthdr; + if (likely((transport_hdr.raw - network_hdr.raw) == + sizeof(struct ipv6hdr))) + break; + ipv6_skip_exthdr(skb, network_hdr.raw - skb->data + + sizeof(struct ipv6hdr), + &l4_hdr, &frag_off); + if (unlikely(frag_off)) + l4_hdr = NEXTHDR_FRAGMENT; break; default: - if (unlikely(net_ratelimit())) { - dev_warn(tx_ring->dev, - "partial checksum but version=%d\n", - network_hdr.ipv4->version); - } + break; }
switch (l4_hdr) { @@@ -7074,16 -7118,18 +7118,18 @@@ default: if (unlikely(net_ratelimit())) { dev_warn(tx_ring->dev, - "partial checksum but l4 proto=%x!\n", - l4_hdr); + "partial checksum, version=%d, l4 proto=%x\n", + network_hdr.ipv4->version, l4_hdr); } - break; + skb_checksum_help(skb); + goto no_csum; }
/* update TX checksum flag */ first->tx_flags |= IXGBE_TX_FLAGS_CSUM; }
+ no_csum: /* vlan_macip_lens: MACLEN, VLAN tag */ vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
@@@ -7659,17 -7705,16 +7705,16 @@@ static int ixgbe_set_mac(struct net_dev struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; struct sockaddr *addr = p; - int ret;
if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL;
- ixgbe_del_mac_filter(adapter, hw->mac.addr, VMDQ_P(0)); memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
- ret = ixgbe_add_mac_filter(adapter, hw->mac.addr, VMDQ_P(0)); - return ret > 0 ? 0 : ret; + ixgbe_mac_set_default_filter(adapter); + + return 0; }
static int @@@ -7920,9 -7965,6 +7965,9 @@@ int ixgbe_setup_tc(struct net_device *d */ if (netif_running(dev)) ixgbe_close(dev); + else + ixgbe_reset(adapter); + ixgbe_clear_interrupt_scheme(adapter);
#ifdef CONFIG_IXGBE_DCB @@@ -8155,7 -8197,10 +8200,10 @@@ static int ixgbe_ndo_fdb_add(struct ndm { /* guarantee we can provide a unique filter for the unicast address */ if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) { - if (IXGBE_MAX_PF_MACVLANS <= netdev_uc_count(dev)) + struct ixgbe_adapter *adapter = netdev_priv(dev); + u16 pool = VMDQ_P(0); + + if (netdev_uc_count(dev) >= ixgbe_available_rars(adapter, pool)) return -ENOMEM; }
@@@ -8873,7 -8918,7 +8921,7 @@@ skip_sriov goto err_sw_init; }
- ixgbe_mac_set_default_filter(adapter, hw->mac.perm_addr); + ixgbe_mac_set_default_filter(adapter);
setup_timer(&adapter->service_timer, &ixgbe_service_timer, (unsigned long) adapter); @@@ -9328,6 -9373,12 +9376,12 @@@ static int __init ixgbe_init_module(voi pr_info("%s - version %s\n", ixgbe_driver_string, ixgbe_driver_version); pr_info("%s\n", ixgbe_copyright);
+ ixgbe_wq = create_singlethread_workqueue(ixgbe_driver_name); + if (!ixgbe_wq) { + pr_err("%s: Failed to create workqueue\n", ixgbe_driver_name); + return -ENOMEM; + } + ixgbe_dbg_init();
ret = pci_register_driver(&ixgbe_driver); @@@ -9359,6 -9410,10 +9413,10 @@@ static void __exit ixgbe_exit_module(vo pci_unregister_driver(&ixgbe_driver);
ixgbe_dbg_exit(); + if (ixgbe_wq) { + destroy_workqueue(ixgbe_wq); + ixgbe_wq = NULL; + } }
#ifdef CONFIG_IXGBE_DCA diff --combined drivers/net/ethernet/qlogic/qed/qed_main.c index 174f734,6b02e11..9d76ce2 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@@ -476,22 -476,41 +476,22 @@@ static irqreturn_t qed_single_int(int i return rc; }
-static int qed_slowpath_irq_req(struct qed_dev *cdev) +int qed_slowpath_irq_req(struct qed_hwfn *hwfn) { - int i = 0, rc = 0; + struct qed_dev *cdev = hwfn->cdev; + int rc = 0; + u8 id;
if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { - /* Request all the slowpath MSI-X vectors */ - for (i = 0; i < cdev->num_hwfns; i++) { - snprintf(cdev->hwfns[i].name, NAME_SIZE, - "sp-%d-%02x:%02x.%02x", - i, cdev->pdev->bus->number, - PCI_SLOT(cdev->pdev->devfn), - cdev->hwfns[i].abs_pf_id); - - rc = request_irq(cdev->int_params.msix_table[i].vector, - qed_msix_sp_int, 0, - cdev->hwfns[i].name, - cdev->hwfns[i].sp_dpc); - if (rc) - break; - - DP_VERBOSE(&cdev->hwfns[i], - (NETIF_MSG_INTR | QED_MSG_SP), + id = hwfn->my_id; + snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x", + id, cdev->pdev->bus->number, + PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); + rc = request_irq(cdev->int_params.msix_table[id].vector, + qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc); + if (!rc) + DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP), "Requested slowpath MSI-X\n"); - } - - if (i != cdev->num_hwfns) { - /* Free already request MSI-X vectors */ - for (i--; i >= 0; i--) { - unsigned int vec = - cdev->int_params.msix_table[i].vector; - synchronize_irq(vec); - free_irq(cdev->int_params.msix_table[i].vector, - cdev->hwfns[i].sp_dpc); - } - } } else { unsigned long flags = 0;
@@@ -515,17 -534,13 +515,17 @@@ static void qed_slowpath_irq_free(struc
if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { for_each_hwfn(cdev, i) { + if (!cdev->hwfns[i].b_int_requested) + break; synchronize_irq(cdev->int_params.msix_table[i].vector); free_irq(cdev->int_params.msix_table[i].vector, cdev->hwfns[i].sp_dpc); } } else { - free_irq(cdev->pdev->irq, cdev); + if (QED_LEADING_HWFN(cdev)->b_int_requested) + free_irq(cdev->pdev->irq, cdev); } + qed_int_disable_post_isr_release(cdev); }
static int qed_nic_stop(struct qed_dev *cdev) @@@ -750,11 -765,16 +750,11 @@@ static int qed_slowpath_start(struct qe if (rc) goto err1;
- /* Request the slowpath IRQ */ - rc = qed_slowpath_irq_req(cdev); - if (rc) - goto err2; - /* Allocate stream for unzipping */ rc = qed_alloc_stream_mem(cdev); if (rc) { DP_NOTICE(cdev, "Failed to allocate stream memory\n"); - goto err3; + goto err2; }
/* Start the slowpath */ @@@ -1115,6 -1135,23 +1115,23 @@@ static int qed_drain(struct qed_dev *cd return 0; }
+ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) + { + struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); + struct qed_ptt *ptt; + int status = 0; + + ptt = qed_ptt_acquire(hwfn); + if (!ptt) + return -EAGAIN; + + status = qed_mcp_set_led(hwfn, ptt, mode); + + qed_ptt_release(hwfn, ptt); + + return status; + } + const struct qed_common_ops qed_common_ops_pass = { .probe = &qed_probe, .remove = &qed_remove, @@@ -1135,6 -1172,7 +1152,7 @@@ .update_msglvl = &qed_init_dp, .chain_alloc = &qed_chain_alloc, .chain_free = &qed_chain_free, + .set_led = &qed_set_led, };
u32 qed_get_protocol_version(enum qed_protocol protocol) diff --combined drivers/net/ethernet/renesas/ravb_main.c index b69e0c2,1cf1226..79e105c --- 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; } }
@@@ -1037,7 -1042,7 +1042,7 @@@ static const char ravb_gstrings_stats[] "rx_queue_1_mcast_packets", "rx_queue_1_errors", "rx_queue_1_crc_errors", - "rx_queue_1_frame_errors_", + "rx_queue_1_frame_errors", "rx_queue_1_length_errors", "rx_queue_1_missed_errors", "rx_queue_1_over_errors", @@@ -1229,7 -1234,8 +1234,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 -1248,8 +1248,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); @@@ -1476,7 -1483,8 +1483,8 @@@ static int ravb_close(struct net_devic 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 -1664,45 +1664,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 -1791,25 +1791,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 -1832,10 +1832,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 -1877,10 +1877,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 -1895,10 +1895,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 b1ebd7c,2406ad4..c7a8e51 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@@ -449,6 -449,109 +449,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) { @@@ -514,6 -617,7 +617,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) { @@@ -671,34 -775,6 +775,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, @@@ -756,80 -832,6 +832,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,
@@@ -987,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; } }
@@@ -1462,7 -1467,6 +1467,7 @@@ static int sh_eth_rx(struct net_device if (mdp->cd->shift_rd0) desc_status >>= 16;
+ skb = mdp->rx_skbuff[entry]; if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 | RD_RFS5 | RD_RFS6 | RD_RFS10)) { ndev->stats.rx_errors++; @@@ -1478,11 -1482,12 +1483,11 @@@ ndev->stats.rx_missed_errors++; if (desc_status & RD_RFS10) ndev->stats.rx_over_errors++; - } else { + } else if (skb) { if (!mdp->cd->hw_swap) sh_eth_soft_swap( phys_to_virt(ALIGN(rxdesc->addr, 4)), pkt_len + 2); - skb = mdp->rx_skbuff[entry]; mdp->rx_skbuff[entry] = NULL; if (mdp->cd->rpadir) skb_reserve(skb, NET_IP_ALIGN); @@@ -3277,13 -3282,6 +3282,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/ppp/pppoe.c index 0a37f84,b8da2ea..f3c6302 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@@ -311,7 -311,7 +311,7 @@@ static void pppoe_flush_dev(struct net_ lock_sock(sk);
if (po->pppoe_dev == dev && - sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { + sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { pppox_unbind_sock(sk); sk->sk_state_change(sk); po->pppoe_dev = NULL; @@@ -500,27 -500,9 +500,9 @@@ static int pppoe_disc_rcv(struct sk_buf
pn = pppoe_pernet(dev_net(dev)); po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex); - if (po) { - struct sock *sk = sk_pppox(po); - - bh_lock_sock(sk); - - /* If the user has locked the socket, just ignore - * the packet. With the way two rcv protocols hook into - * one socket family type, we cannot (easily) distinguish - * what kind of SKB it is during backlog rcv. - */ - if (sock_owned_by_user(sk) == 0) { - /* We're no longer connect at the PPPOE layer, - * and must wait for ppp channel to disconnect us. - */ - sk->sk_state = PPPOX_ZOMBIE; - } - - bh_unlock_sock(sk); + if (po) if (!schedule_work(&po->proto.pppoe.padt_work)) - sock_put(sk); - } + sock_put(sk_pppox(po));
abort: kfree_skb(skb); @@@ -568,9 -550,6 +550,9 @@@ static int pppoe_create(struct net *net sk->sk_family = PF_PPPOX; sk->sk_protocol = PX_PROTO_OE;
+ INIT_WORK(&pppox_sk(sk)->proto.pppoe.padt_work, + pppoe_unbind_sock_work); + return 0; }
@@@ -635,6 -614,8 +617,6 @@@ static int pppoe_connect(struct socket
lock_sock(sk);
- INIT_WORK(&po->proto.pppoe.padt_work, pppoe_unbind_sock_work); - error = -EINVAL; if (sp->sa_protocol != PX_PROTO_OE) goto end; @@@ -664,13 -645,8 +646,13 @@@ po->pppoe_dev = NULL; }
- memset(sk_pppox(po) + 1, 0, - sizeof(struct pppox_sock) - sizeof(struct sock)); + po->pppoe_ifindex = 0; + memset(&po->pppoe_pa, 0, sizeof(po->pppoe_pa)); + memset(&po->pppoe_relay, 0, sizeof(po->pppoe_relay)); + memset(&po->chan, 0, sizeof(po->chan)); + po->next = NULL; + po->num = 0; + sk->sk_state = PPPOX_NONE; }
@@@ -799,7 -775,7 +781,7 @@@ static int pppoe_ioctl(struct socket *s struct pppox_sock *relay_po;
err = -EBUSY; - if (sk->sk_state & (PPPOX_BOUND | PPPOX_ZOMBIE | PPPOX_DEAD)) + if (sk->sk_state & (PPPOX_BOUND | PPPOX_DEAD)) break;
err = -ENOTCONN; @@@ -1226,4 -1202,4 +1208,4 @@@ module_exit(pppoe_exit) MODULE_AUTHOR("Michal Ostrowski mostrows@speakeasy.net"); MODULE_DESCRIPTION("PPP over Ethernet driver"); MODULE_LICENSE("GPL"); - MODULE_ALIAS_NETPROTO(PF_PPPOX); + MODULE_ALIAS_NET_PF_PROTO(PF_PPPOX, PX_PROTO_OE); diff --combined drivers/net/usb/cdc_ncm.c index 1e9843a,b45e5ca..c48c7f8 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@@ -283,6 -283,48 +283,48 @@@ static DEVICE_ATTR(rx_max, S_IRUGO | S_ static DEVICE_ATTR(tx_max, S_IRUGO | S_IWUSR, cdc_ncm_show_tx_max, cdc_ncm_store_tx_max); static DEVICE_ATTR(tx_timer_usecs, S_IRUGO | S_IWUSR, cdc_ncm_show_tx_timer_usecs, cdc_ncm_store_tx_timer_usecs);
+ static ssize_t ndp_to_end_show(struct device *d, struct device_attribute *attr, char *buf) + { + struct usbnet *dev = netdev_priv(to_net_dev(d)); + struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; + + return sprintf(buf, "%c\n", ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END ? 'Y' : 'N'); + } + + static ssize_t ndp_to_end_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) + { + struct usbnet *dev = netdev_priv(to_net_dev(d)); + struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; + bool enable; + + if (strtobool(buf, &enable)) + return -EINVAL; + + /* no change? */ + if (enable == (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) + return len; + + if (enable && !ctx->delayed_ndp16) { + ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); + if (!ctx->delayed_ndp16) + return -ENOMEM; + } + + /* flush pending data before changing flag */ + netif_tx_lock_bh(dev->net); + usbnet_start_xmit(NULL, dev->net); + spin_lock_bh(&ctx->mtx); + if (enable) + ctx->drvflags |= CDC_NCM_FLAG_NDP_TO_END; + else + ctx->drvflags &= ~CDC_NCM_FLAG_NDP_TO_END; + spin_unlock_bh(&ctx->mtx); + netif_tx_unlock_bh(dev->net); + + return len; + } + static DEVICE_ATTR_RW(ndp_to_end); + #define NCM_PARM_ATTR(name, format, tocpu) \ static ssize_t cdc_ncm_show_##name(struct device *d, struct device_attribute *attr, char *buf) \ { \ @@@ -305,6 -347,7 +347,7 @@@ NCM_PARM_ATTR(wNtbOutMaxDatagrams, "%u"
static struct attribute *cdc_ncm_sysfs_attrs[] = { &dev_attr_min_tx_pkt.attr, + &dev_attr_ndp_to_end.attr, &dev_attr_rx_max.attr, &dev_attr_tx_max.attr, &dev_attr_tx_timer_usecs.attr, @@@ -955,18 -998,10 +998,18 @@@ static struct usb_cdc_ncm_ndp16 *cdc_nc * NTH16 header as we would normally do. NDP isn't written to the SKB yet, and * the wNdpIndex field in the header is actually not consistent with reality. It will be later. */ - if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) + if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { if (ctx->delayed_ndp16->dwSignature == sign) return ctx->delayed_ndp16;
+ /* We can only push a single NDP to the end. Return + * NULL to send what we've already got and queue this + * skb for later. + */ + else if (ctx->delayed_ndp16->dwSignature) + return NULL; + } + /* follow the chain of NDPs, looking for a match */ while (ndpoffset) { ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset); diff --combined drivers/net/virtio_net.c index f94ab78,b1ae4cb..767ab11 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@@ -140,12 -140,6 +140,12 @@@ struct virtnet_info
/* CPU hot plug notifier */ struct notifier_block nb; + + /* Control VQ buffers: protected by the rtnl lock */ + struct virtio_net_ctrl_hdr ctrl_hdr; + virtio_net_ctrl_ack ctrl_status; + u8 ctrl_promisc; + u8 ctrl_allmulti; };
struct padded_vnet_hdr { @@@ -522,8 -516,6 +522,6 @@@ static void receive_buf(struct virtnet_ skb_shinfo(skb)->gso_segs = 0; }
- skb_mark_napi_id(skb, &rq->napi); - napi_gro_receive(&rq->napi, skb); return;
@@@ -982,30 -974,31 +980,30 @@@ static bool virtnet_send_command(struc struct scatterlist *out) { struct scatterlist *sgs[4], hdr, stat; - struct virtio_net_ctrl_hdr ctrl; - virtio_net_ctrl_ack status = ~0; unsigned out_num = 0, tmp;
/* Caller should know better */ BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ));
- ctrl.class = class; - ctrl.cmd = cmd; + vi->ctrl_status = ~0; + vi->ctrl_hdr.class = class; + vi->ctrl_hdr.cmd = cmd; /* Add header */ - sg_init_one(&hdr, &ctrl, sizeof(ctrl)); + sg_init_one(&hdr, &vi->ctrl_hdr, sizeof(vi->ctrl_hdr)); sgs[out_num++] = &hdr;
if (out) sgs[out_num++] = out;
/* Add return status. */ - sg_init_one(&stat, &status, sizeof(status)); + sg_init_one(&stat, &vi->ctrl_status, sizeof(vi->ctrl_status)); sgs[out_num] = &stat;
BUG_ON(out_num + 1 > ARRAY_SIZE(sgs)); virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC);
if (unlikely(!virtqueue_kick(vi->cvq))) - return status == VIRTIO_NET_OK; + return vi->ctrl_status == VIRTIO_NET_OK;
/* Spin for a response, the kick causes an ioport write, trapping * into the hypervisor, so the request should be handled immediately. @@@ -1014,7 -1007,7 +1012,7 @@@ !virtqueue_is_broken(vi->cvq)) cpu_relax();
- return status == VIRTIO_NET_OK; + return vi->ctrl_status == VIRTIO_NET_OK; }
static int virtnet_set_mac_address(struct net_device *dev, void *p) @@@ -1156,6 -1149,7 +1154,6 @@@ static void virtnet_set_rx_mode(struct { struct virtnet_info *vi = netdev_priv(dev); struct scatterlist sg[2]; - u8 promisc, allmulti; struct virtio_net_ctrl_mac *mac_data; struct netdev_hw_addr *ha; int uc_count; @@@ -1167,22 -1161,22 +1165,22 @@@ if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) return;
- promisc = ((dev->flags & IFF_PROMISC) != 0); - allmulti = ((dev->flags & IFF_ALLMULTI) != 0); + vi->ctrl_promisc = ((dev->flags & IFF_PROMISC) != 0); + vi->ctrl_allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
- sg_init_one(sg, &promisc, sizeof(promisc)); + sg_init_one(sg, &vi->ctrl_promisc, sizeof(vi->ctrl_promisc));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, VIRTIO_NET_CTRL_RX_PROMISC, sg)) dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", - promisc ? "en" : "dis"); + vi->ctrl_promisc ? "en" : "dis");
- sg_init_one(sg, &allmulti, sizeof(allmulti)); + sg_init_one(sg, &vi->ctrl_allmulti, sizeof(vi->ctrl_allmulti));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, VIRTIO_NET_CTRL_RX_ALLMULTI, sg)) dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", - allmulti ? "en" : "dis"); + vi->ctrl_allmulti ? "en" : "dis");
uc_count = netdev_uc_count(dev); mc_count = netdev_mc_count(dev); @@@ -1616,7 -1610,6 +1614,6 @@@ static int virtnet_alloc_queues(struct vi->rq[i].pages = NULL; netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll, napi_weight); - napi_hash_add(&vi->rq[i].napi);
sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg)); ewma_pkt_len_init(&vi->rq[i].mrg_avg_pkt_len); diff --combined include/linux/netdevice.h index 3143c84,1bb21ff..9cd0b84 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@@ -132,7 -132,9 +132,9 @@@ static inline bool dev_xmit_complete(in * used. */
- #if defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) + #if defined(CONFIG_HYPERV_NET) + # define LL_MAX_HEADER 128 + #elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) # if defined(CONFIG_MAC80211_MESH) # define LL_MAX_HEADER 128 # else @@@ -326,7 -328,8 +328,8 @@@ enum NAPI_STATE_SCHED, /* Poll is scheduled */ NAPI_STATE_DISABLE, /* Disable pending */ NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */ - NAPI_STATE_HASHED, /* In NAPI hash */ + NAPI_STATE_HASHED, /* In NAPI hash (busy polling possible) */ + NAPI_STATE_NO_BUSY_POLL,/* Do not add in napi_hash, no busy polling */ };
enum gro_result { @@@ -461,19 -464,13 +464,13 @@@ static inline void napi_complete(struc }
/** - * napi_by_id - lookup a NAPI by napi_id - * @napi_id: hashed napi_id - * - * lookup @napi_id in napi_hash table - * must be called under rcu_read_lock() - */ - struct napi_struct *napi_by_id(unsigned int napi_id); - - /** * napi_hash_add - add a NAPI to global hashtable * @napi: napi context * * generate a new napi_id and store a @napi under it in napi_hash + * Used for busy polling (CONFIG_NET_RX_BUSY_POLL) + * Note: This is normally automatically done from netif_napi_add(), + * so might disappear in a future linux version. */ void napi_hash_add(struct napi_struct *napi);
@@@ -482,9 -479,14 +479,14 @@@ * @napi: napi context * * Warning: caller must observe rcu grace period - * before freeing memory containing @napi + * before freeing memory containing @napi, if + * this function returns true. + * Note: core networking stack automatically calls it + * from netif_napi_del() + * Drivers might want to call this helper to combine all + * the needed rcu grace periods into a single one. */ - void napi_hash_del(struct napi_struct *napi); + bool napi_hash_del(struct napi_struct *napi);
/** * napi_disable - prevent NAPI from scheduling @@@ -1271,6 -1273,7 +1273,7 @@@ struct net_device_ops * @IFF_NO_QUEUE: device can run without qdisc attached * @IFF_OPENVSWITCH: device is a Open vSwitch master * @IFF_L3MDEV_SLAVE: device is enslaved to an L3 master device + * @IFF_TEAM: device is a team device */ enum netdev_priv_flags { IFF_802_1Q_VLAN = 1<<0, @@@ -1297,6 -1300,7 +1300,7 @@@ IFF_NO_QUEUE = 1<<21, IFF_OPENVSWITCH = 1<<22, IFF_L3MDEV_SLAVE = 1<<23, + IFF_TEAM = 1<<24, };
#define IFF_802_1Q_VLAN IFF_802_1Q_VLAN @@@ -1323,6 -1327,7 +1327,7 @@@ #define IFF_NO_QUEUE IFF_NO_QUEUE #define IFF_OPENVSWITCH IFF_OPENVSWITCH #define IFF_L3MDEV_SLAVE IFF_L3MDEV_SLAVE + #define IFF_TEAM IFF_TEAM
/** * struct net_device - The DEVICE structure. @@@ -1949,6 -1954,26 +1954,26 @@@ void netif_napi_add(struct net_device * int (*poll)(struct napi_struct *, int), int weight);
/** + * netif_tx_napi_add - initialize a napi context + * @dev: network device + * @napi: napi context + * @poll: polling function + * @weight: default weight + * + * This variant of netif_napi_add() should be used from drivers using NAPI + * to exclusively poll a TX queue. + * This will avoid we add it into napi_hash[], thus polluting this hash table. + */ + static inline void netif_tx_napi_add(struct net_device *dev, + struct napi_struct *napi, + int (*poll)(struct napi_struct *, int), + int weight) + { + set_bit(NAPI_STATE_NO_BUSY_POLL, &napi->state); + netif_napi_add(dev, napi, poll, weight); + } + + /** * netif_napi_del - remove a napi context * @napi: napi context * @@@ -2084,8 -2109,26 +2109,26 @@@ struct pcpu_sw_netstats })
#define netdev_alloc_pcpu_stats(type) \ - __netdev_alloc_pcpu_stats(type, GFP_KERNEL); + __netdev_alloc_pcpu_stats(type, GFP_KERNEL)
+ enum netdev_lag_tx_type { + NETDEV_LAG_TX_TYPE_UNKNOWN, + NETDEV_LAG_TX_TYPE_RANDOM, + NETDEV_LAG_TX_TYPE_BROADCAST, + NETDEV_LAG_TX_TYPE_ROUNDROBIN, + NETDEV_LAG_TX_TYPE_ACTIVEBACKUP, + NETDEV_LAG_TX_TYPE_HASH, + }; + + struct netdev_lag_upper_info { + enum netdev_lag_tx_type tx_type; + }; + + struct netdev_lag_lower_state_info { + u8 link_up : 1, + tx_enabled : 1; + }; + #include <linux/notifier.h>
/* netdevice notifier chain. Please remember to update the rtnetlink @@@ -2121,6 -2164,7 +2164,7 @@@ #define NETDEV_CHANGEINFODATA 0x0018 #define NETDEV_BONDING_INFO 0x0019 #define NETDEV_PRECHANGEUPPER 0x001A + #define NETDEV_CHANGELOWERSTATE 0x001B
int register_netdevice_notifier(struct notifier_block *nb); int unregister_netdevice_notifier(struct notifier_block *nb); @@@ -2139,6 -2183,12 +2183,12 @@@ struct netdev_notifier_changeupper_inf struct net_device *upper_dev; /* new upper dev */ bool master; /* is upper dev master */ bool linking; /* is the nofication for link or unlink */ + void *upper_info; /* upper dev info */ + }; + + struct netdev_notifier_changelowerstate_info { + struct netdev_notifier_info info; /* must be first */ + void *lower_state_info; /* is lower dev state */ };
static inline void netdev_notifier_info_init(struct netdev_notifier_info *info, @@@ -3595,15 -3645,15 +3645,15 @@@ struct net_device *netdev_master_upper_ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev); int netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev); int netdev_master_upper_dev_link(struct net_device *dev, - struct net_device *upper_dev); - int netdev_master_upper_dev_link_private(struct net_device *dev, - struct net_device *upper_dev, - void *private); + struct net_device *upper_dev, + void *upper_priv, void *upper_info); void netdev_upper_dev_unlink(struct net_device *dev, struct net_device *upper_dev); void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); void *netdev_lower_dev_get_private(struct net_device *dev, struct net_device *lower_dev); + void netdev_lower_state_changed(struct net_device *lower_dev, + void *lower_state_info);
/* RSS keys are 40 or 52 bytes long */ #define NETDEV_RSS_KEY_LEN 52 @@@ -3611,7 -3661,7 +3661,7 @@@ extern u8 netdev_rss_key[NETDEV_RSS_KEY void netdev_rss_key_fill(void *buffer, size_t len);
int dev_get_nest_level(struct net_device *dev, - bool (*type_check)(struct net_device *dev)); + bool (*type_check)(const struct net_device *dev)); int skb_checksum_help(struct sk_buff *skb); struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t features, bool tx_path); @@@ -3808,32 -3858,32 +3858,32 @@@ static inline void skb_gso_error_unwind skb->mac_len = mac_len; }
- static inline bool netif_is_macvlan(struct net_device *dev) + static inline bool netif_is_macvlan(const struct net_device *dev) { return dev->priv_flags & IFF_MACVLAN; }
- static inline bool netif_is_macvlan_port(struct net_device *dev) + static inline bool netif_is_macvlan_port(const struct net_device *dev) { return dev->priv_flags & IFF_MACVLAN_PORT; }
- static inline bool netif_is_ipvlan(struct net_device *dev) + static inline bool netif_is_ipvlan(const struct net_device *dev) { return dev->priv_flags & IFF_IPVLAN_SLAVE; }
- static inline bool netif_is_ipvlan_port(struct net_device *dev) + static inline bool netif_is_ipvlan_port(const struct net_device *dev) { return dev->priv_flags & IFF_IPVLAN_MASTER; }
- static inline bool netif_is_bond_master(struct net_device *dev) + static inline bool netif_is_bond_master(const struct net_device *dev) { return dev->flags & IFF_MASTER && dev->priv_flags & IFF_BONDING; }
- static inline bool netif_is_bond_slave(struct net_device *dev) + static inline bool netif_is_bond_slave(const struct net_device *dev) { return dev->flags & IFF_SLAVE && dev->priv_flags & IFF_BONDING; } @@@ -3868,6 -3918,26 +3918,26 @@@ static inline bool netif_is_ovs_master( return dev->priv_flags & IFF_OPENVSWITCH; }
+ static inline bool netif_is_team_master(const struct net_device *dev) + { + return dev->priv_flags & IFF_TEAM; + } + + static inline bool netif_is_team_port(const struct net_device *dev) + { + return dev->priv_flags & IFF_TEAM_PORT; + } + + static inline bool netif_is_lag_master(const struct net_device *dev) + { + return netif_is_bond_master(dev) || netif_is_team_master(dev); + } + + static inline bool netif_is_lag_port(const struct net_device *dev) + { + return netif_is_bond_slave(dev) || netif_is_team_port(dev); + } + /* This device needs to keep skb dst for qdisc enqueue or ndo_start_xmit() */ static inline void netif_keep_dst(struct net_device *dev) { diff --combined include/net/sock.h index b1d475b,6f58b84..5e86c38 --- a/include/net/sock.h +++ b/include/net/sock.h @@@ -58,6 -58,7 +58,7 @@@ #include <linux/memcontrol.h> #include <linux/static_key.h> #include <linux/sched.h> + #include <linux/wait.h>
#include <linux/filter.h> #include <linux/rculist_nulls.h> @@@ -740,8 -741,6 +741,8 @@@ enum sock_flags SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */ };
+#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) + static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) { nsk->sk_flags = osk->sk_flags; @@@ -777,9 -776,9 +778,9 @@@ static inline int sk_memalloc_socks(voi
#endif
- static inline gfp_t sk_gfp_atomic(const struct sock *sk, gfp_t gfp_mask) + static inline gfp_t sk_gfp_mask(const struct sock *sk, gfp_t gfp_mask) { - return GFP_ATOMIC | (sk->sk_allocation & __GFP_MEMALLOC); + return gfp_mask | (sk->sk_allocation & __GFP_MEMALLOC); }
static inline void sk_acceptq_removed(struct sock *sk) @@@ -1882,12 -1881,12 +1883,12 @@@ static inline bool sk_has_allocations(c }
/** - * wq_has_sleeper - check if there are any waiting processes + * skwq_has_sleeper - check if there are any waiting processes * @wq: struct socket_wq * * Returns true if socket_wq has waiting processes * - * The purpose of the wq_has_sleeper and sock_poll_wait is to wrap the memory + * The purpose of the skwq_has_sleeper and sock_poll_wait is to wrap the memory * barrier call. They were added due to the race found within the tcp code. * * Consider following tcp code paths: @@@ -1913,15 -1912,9 +1914,9 @@@ * data on the socket. * */ - static inline bool wq_has_sleeper(struct socket_wq *wq) + static inline bool skwq_has_sleeper(struct socket_wq *wq) { - /* We need to be sure we are in sync with the - * add_wait_queue modifications to the wait queue. - * - * This memory barrier is paired in the sock_poll_wait. - */ - smp_mb(); - return wq && waitqueue_active(&wq->wait); + return wq && wq_has_sleeper(&wq->wait); }
/** 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/core/sock.c index d01c8f4,7965ef4..5ae0dce --- a/net/core/sock.c +++ b/net/core/sock.c @@@ -433,6 -433,8 +433,6 @@@ static bool sock_needs_netstamp(const s } }
-#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) - static void sock_disable_timestamp(struct sock *sk, unsigned long flags) { if (sk->sk_flags & flags) { @@@ -2280,7 -2282,7 +2280,7 @@@ static void sock_def_wakeup(struct soc
rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); - if (wq_has_sleeper(wq)) + if (skwq_has_sleeper(wq)) wake_up_interruptible_all(&wq->wait); rcu_read_unlock(); } @@@ -2291,7 -2293,7 +2291,7 @@@ static void sock_def_error_report(struc
rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); - if (wq_has_sleeper(wq)) + if (skwq_has_sleeper(wq)) wake_up_interruptible_poll(&wq->wait, POLLERR); sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); rcu_read_unlock(); @@@ -2303,7 -2305,7 +2303,7 @@@ static void sock_def_readable(struct so
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 | POLLPRI | POLLRDNORM | POLLRDBAND); sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); @@@ -2321,7 -2323,7 +2321,7 @@@ static void sock_def_write_space(struc */ if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { 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);
diff --combined net/ipv6/addrconf.c index a57d3d1,5e9111d..be0afff --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@@ -2455,7 -2455,7 +2455,7 @@@ ok #ifdef CONFIG_IPV6_OPTIMISTIC_DAD if (in6_dev->cnf.optimistic_dad && !net->ipv6.devconf_all->forwarding && sllao) - addr_flags = IFA_F_OPTIMISTIC; + addr_flags |= IFA_F_OPTIMISTIC; #endif
/* Do not allow to create too much of autoconfigured @@@ -3287,7 -3287,8 +3287,8 @@@ static int addrconf_notify(struct notif
case NETDEV_PRE_TYPE_CHANGE: case NETDEV_POST_TYPE_CHANGE: - addrconf_type_change(dev, event); + if (idev) + addrconf_type_change(dev, event); break; }
@@@ -5200,6 -5201,20 +5201,20 @@@ int addrconf_sysctl_forward(struct ctl_ }
static + int addrconf_sysctl_hop_limit(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) + { + struct ctl_table lctl; + int min_hl = 1, max_hl = 255; + + lctl = *ctl; + lctl.extra1 = &min_hl; + lctl.extra2 = &max_hl; + + return proc_dointvec_minmax(&lctl, write, buffer, lenp, ppos); + } + + static int addrconf_sysctl_mtu(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@@ -5454,7 -5469,7 +5469,7 @@@ static struct addrconf_sysctl_tabl .data = &ipv6_devconf.hop_limit, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = addrconf_sysctl_hop_limit, }, { .procname = "mtu", diff --combined net/ipv6/ip6_gre.c index e5ea177,938d03c..f37f18b --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@@ -24,7 -24,6 +24,6 @@@ #include <linux/tcp.h> #include <linux/udp.h> #include <linux/if_arp.h> - #include <linux/mroute.h> #include <linux/init.h> #include <linux/in6.h> #include <linux/inetdevice.h> @@@ -1571,11 -1570,13 +1570,11 @@@ static int ip6gre_changelink(struct net return -EEXIST; } else { t = nt; - - ip6gre_tunnel_unlink(ign, t); - ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); - ip6gre_tunnel_link(ign, t); - netdev_state_change(dev); }
+ ip6gre_tunnel_unlink(ign, t); + ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); + ip6gre_tunnel_link(ign, t); return 0; }
diff --combined net/sctp/socket.c index 9b6cc6d,106bb09..2a1e8ba --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@@ -1952,6 -1952,8 +1952,6 @@@ static int sctp_sendmsg(struct sock *sk
/* Now send the (possibly) fragmented message. */ list_for_each_entry(chunk, &datamsg->chunks, frag_list) { - sctp_chunk_hold(chunk); - /* Do accounting for the write space. */ sctp_set_owner_w(chunk);
@@@ -1964,13 -1966,15 +1964,13 @@@ * breaks. */ err = sctp_primitive_SEND(net, asoc, datamsg); + sctp_datamsg_put(datamsg); /* Did the lower layer accept the chunk? */ - if (err) { - sctp_datamsg_free(datamsg); + if (err) goto out_free; - }
pr_debug("%s: we sent primitively\n", __func__);
- sctp_datamsg_put(datamsg); err = msg_len;
if (unlikely(wait_connect)) { @@@ -6978,7 -6982,7 +6978,7 @@@ void sctp_data_ready(struct sock *sk
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); sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); @@@ -7163,7 -7167,6 +7163,7 @@@ void sctp_copy_sock(struct sock *newsk newsk->sk_type = sk->sk_type; newsk->sk_bound_dev_if = sk->sk_bound_dev_if; newsk->sk_flags = sk->sk_flags; + newsk->sk_tsflags = sk->sk_tsflags; newsk->sk_no_check_tx = sk->sk_no_check_tx; newsk->sk_no_check_rx = sk->sk_no_check_rx; newsk->sk_reuse = sk->sk_reuse; @@@ -7196,9 -7199,6 +7196,9 @@@ newinet->mc_ttl = 1; newinet->mc_index = 0; newinet->mc_list = NULL; + + if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) + net_enable_timestamp(); }
static inline void sctp_copy_descendant(struct sock *sk_to,
linux-merge@lists.open-mesh.org