The following commit has been merged in the master branch:
commit 98d4b10ee61601b236c34587a215cb86e69cf8ba
Merge: c7d565fbc846a5e1f0bc6afa4e122943db276a23 e796f49d826aadb856981c751efc086c6ce11a77
Author: Stephen Rothwell <sfr(a)canb.auug.org.au>
Date: Tue Nov 22 11:56:42 2016 +1100
Merge remote-tracking branch 'net-next/master'
diff --combined MAINTAINERS
index 8c3b7e9,9870812..ab8b3e3
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@@ -35,13 -35,13 +35,13 @@@ trivial patch so apply some common sens
PLEASE check your patch with the automated style checker
(scripts/checkpatch.pl) to catch trivial style violations.
- See Documentation/CodingStyle for guidance here.
+ See Documentation/process/coding-style.rst for guidance here.
PLEASE CC: the maintainers and mailing lists that are generated
by scripts/get_maintainer.pl. The results returned by the
script will be best if you have git installed and are making
your changes in a branch derived from Linus' latest git tree.
- See Documentation/SubmittingPatches for details.
+ See Documentation/process/submitting-patches.rst for details.
PLEASE try to include any credit lines you want added with the
patch. It avoids people being missed off by mistake and makes
@@@ -54,7 -54,7 +54,7 @@@
of the Linux Foundation certificate of contribution and should
include a Signed-off-by: line. The current version of this
"Developer's Certificate of Origin" (DCO) is listed in the file
- Documentation/SubmittingPatches.
+ Documentation/process/submitting-patches.rst.
6. Make sure you have the right to send any changes you make. If you
do changes at work you may find your employer owns the patch
@@@ -1019,7 -1019,6 +1019,7 @@@ L: linux-arm-kernel(a)lists.infradead.or
S: Maintained
N: sun[x456789]i
F: arch/arm/boot/dts/ntc-gr8*
+F: arch/arm64/boot/dts/allwinner/
ARM/Allwinner SoC Clock Support
M: Emilio López <emilio(a)elopez.com.ar>
@@@ -1602,7 -1601,6 +1602,7 @@@ F: arch/arm/mach-qcom
F: arch/arm64/boot/dts/qcom/*
F: drivers/i2c/busses/i2c-qup.c
F: drivers/clk/qcom/
+F: drivers/pinctrl/qcom/
F: drivers/soc/qcom/
F: drivers/spi/spi-qup.c
F: drivers/tty/serial/msm_serial.h
@@@ -1782,7 -1780,9 +1782,7 @@@ F: drivers/media/rc/st_rc.
F: drivers/media/platform/sti/c8sectpfe/
F: drivers/mmc/host/sdhci-st.c
F: drivers/phy/phy-miphy28lp.c
-F: drivers/phy/phy-miphy365x.c
F: drivers/phy/phy-stih407-usb.c
-F: drivers/phy/phy-stih41x-usb.c
F: drivers/pinctrl/pinctrl-st.c
F: drivers/remoteproc/st_remoteproc.c
F: drivers/reset/sti/
@@@ -2530,6 -2530,8 +2530,8 @@@ L: netdev(a)vger.kernel.or
L: linux-kernel(a)vger.kernel.org
S: Supported
F: kernel/bpf/
+ F: tools/testing/selftests/bpf/
+ F: lib/test_bpf.c
BROADCOM B44 10/100 ETHERNET DRIVER
M: Michael Chan <michael.chan(a)broadcom.com>
@@@ -2742,14 -2744,6 +2744,14 @@@ L: bcm-kernel-feedback-list(a)broadcom.co
S: Maintained
F: drivers/mtd/nand/brcmnand/
+BROADCOM STB AVS CPUFREQ DRIVER
+M: Markus Mayer <mmayer(a)broadcom.com>
+M: bcm-kernel-feedback-list(a)broadcom.com
+L: linux-pm(a)vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt
+F: drivers/cpufreq/brcmstb*
+
BROADCOM SPECIFIC AMBA DRIVER (BCMA)
M: Rafał Miłecki <zajec5(a)gmail.com>
L: linux-wireless(a)vger.kernel.org
@@@ -2938,7 -2932,7 +2940,7 @@@ CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVE
M: Kevin Tsai <ktsai(a)capellamicro.com>
S: Maintained
F: drivers/iio/light/cm*
-F: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+F: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst
CAVIUM I2C DRIVER
M: Jan Glauber <jglauber(a)cavium.com>
@@@ -2972,15 -2966,15 +2974,15 @@@ L: linux-media(a)vger.kernel.or
T: git
git://linuxtv.org/media_tree.git
W:
http://linuxtv.org
S: Supported
-F: Documentation/cec.txt
+F: Documentation/media/kapi/cec-core.rst
F: Documentation/media/uapi/cec
-F: drivers/staging/media/cec/
+F: drivers/media/cec/
F: drivers/media/cec-edid.c
F: drivers/media/rc/keymaps/rc-cec.c
F: include/media/cec.h
F: include/media/cec-edid.h
-F: include/linux/cec.h
-F: include/linux/cec-funcs.h
+F: include/uapi/linux/cec.h
+F: include/uapi/linux/cec-funcs.h
CELL BROADBAND ENGINE ARCHITECTURE
M: Arnd Bergmann <arnd(a)arndb.de>
@@@ -3086,7 -3080,7 +3088,7 @@@ M: Harry Wei <harryxiyou(a)gmail.com
L: xiyoulinuxkernelgroup(a)googlegroups.com (subscribers-only)
L: linux-kernel(a)zh-kernel.org (moderated for non-subscribers)
S: Maintained
-F: Documentation/zh_CN/
+F: Documentation/translations/zh_CN/
CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
M: Peter Chen <Peter.Chen(a)nxp.com>
@@@ -7092,7 -7086,6 +7094,7 @@@ F: drivers/scsi/53c700
LED SUBSYSTEM
M: Richard Purdie <rpurdie(a)rpsys.net>
M: Jacek Anaszewski <j.anaszewski(a)samsung.com>
+M: Pavel Machek <pavel(a)ucw.cz>
L: linux-leds(a)vger.kernel.org
T: git
git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git
S: Maintained
@@@ -7734,15 -7727,6 +7736,15 @@@ F: Documentation/devicetree/bindings/me
F: drivers/media/platform/rcar-fcp.c
F: include/media/rcar-fcp.h
+MEDIA DRIVERS FOR RENESAS - FDP1
+M: Kieran Bingham <kieran(a)bingham.xyz>
+L: linux-media(a)vger.kernel.org
+L: linux-renesas-soc(a)vger.kernel.org
+T: git
git://linuxtv.org/media_tree.git
+S: Supported
+F: Documentation/devicetree/bindings/media/renesas,fdp1.txt
+F: drivers/media/platform/rcar_fdp1.c
+
MEDIA DRIVERS FOR RENESAS - VIN
M: Niklas Söderlund <niklas.soderlund(a)ragnatech.se>
L: linux-media(a)vger.kernel.org
@@@ -7849,24 -7833,6 +7851,24 @@@ L: netdev(a)vger.kernel.or
S: Maintained
F: drivers/net/ethernet/mediatek/
+MEDIATEK MEDIA DRIVER
+M: Tiffany Lin <tiffany.lin(a)mediatek.com>
+M: Andrew-CT Chen <andrew-ct.chen(a)mediatek.com>
+S: Supported
+F: drivers/media/platform/mtk-vcodec/
+F: drivers/media/platform/mtk-vpu/
+F: Documentation/devicetree/bindings/media/mediatek-vcodec.txt
+F: Documentation/devicetree/bindings/media/mediatek-vpu.txt
+
+MEDIATEK MDP DRIVER
+M: Minghsiu Tsai <minghsiu.tsai(a)mediatek.com>
+M: Houlong Wei <houlong.wei(a)mediatek.com>
+M: Andrew-CT Chen <andrew-ct.chen(a)mediatek.com>
+S: Supported
+F: drivers/media/platform/mtk-mdp/
+F: drivers/media/platform/mtk-vpu/
+F: Documentation/devicetree/bindings/media/mediatek-mdp.txt
+
MEDIATEK MT7601U WIRELESS LAN DRIVER
M: Jakub Kicinski <kubakici(a)wp.pl>
L: linux-wireless(a)vger.kernel.org
@@@ -7917,13 -7883,6 +7919,13 @@@ W:
http://www.mellanox.co
Q:
http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/mellanox/mlxsw/
+MELLANOX MLXCPLD I2C MUX DRIVER
+M: Vadim Pasternak <vadimp(a)mellanox.com>
+M: Michael Shych <michaelsh(a)mellanox.com>
+L: linux-i2c(a)vger.kernel.org
+S: Supported
+F: drivers/i2c/muxes/i2c-mux-mlxcpld.c
+
MELLANOX MLXCPLD LED DRIVER
M: Vadim Pasternak <vadimp(a)mellanox.com>
L: linux-leds(a)vger.kernel.org
@@@ -8491,7 -8450,6 +8493,6 @@@ F: include/uapi/linux/net_namespace.
F: tools/net/
F: tools/testing/selftests/net/
F: lib/random32.c
- F: lib/test_bpf.c
NETWORKING [IPv4/IPv6]
M: "David S. Miller" <davem(a)davemloft.net>
@@@ -9291,12 -9249,11 +9292,12 @@@ S: Maintaine
F: drivers/pci/host/*layerscape*
PCI DRIVER FOR IMX6
-M: Richard Zhu <Richard.Zhu(a)freescale.com>
+M: Richard Zhu <hongxing.zhu(a)nxp.com>
M: Lucas Stach <l.stach(a)pengutronix.de>
L: linux-pci(a)vger.kernel.org
L: linux-arm-kernel(a)lists.infradead.org (moderated for non-subscribers)
S: Maintained
+F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
F: drivers/pci/host/*imx6*
PCI DRIVER FOR TI KEYSTONE
@@@ -9355,11 -9312,17 +9356,11 @@@ F: drivers/pci/host/pci-exynos.
PCI DRIVER FOR SYNOPSIS DESIGNWARE
M: Jingoo Han <jingoohan1(a)gmail.com>
-M: Pratyush Anand <pratyush.anand(a)gmail.com>
-L: linux-pci(a)vger.kernel.org
-S: Maintained
-F: drivers/pci/host/*designware*
-
-PCI DRIVER FOR SYNOPSYS PROTOTYPING DEVICE
-M: Jose Abreu <Jose.Abreu(a)synopsys.com>
+M: Joao Pinto <Joao.Pinto(a)synopsys.com>
L: linux-pci(a)vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/designware-pcie.txt
-F: drivers/pci/host/pcie-designware-plat.c
+F: drivers/pci/host/*designware*
PCI DRIVER FOR GENERIC OF HOSTS
M: Will Deacon <will.deacon(a)arm.com>
@@@ -9821,7 -9784,7 +9822,7 @@@ M: Hans Verkuil <hverkuil(a)xs4all.nl
L: linux-media(a)vger.kernel.org
T: git
git://linuxtv.org/media_tree.git
S: Maintained
-F: drivers/staging/media/pulse8-cec
+F: drivers/media/usb/pulse8-cec/*
PVRUSB2 VIDEO4LINUX DRIVER
M: Mike Isely <isely(a)pobox.com>
@@@ -11504,7 -11467,7 +11505,7 @@@ STABLE BRANC
M: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
L: stable(a)vger.kernel.org
S: Supported
-F: Documentation/stable_kernel_rules.txt
+F: Documentation/process/stable-kernel-rules.rst
STAGING SUBSYSTEM
M: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
@@@ -11689,7 -11652,6 +11690,7 @@@ S: Supporte
F: arch/arc/
F: Documentation/devicetree/bindings/arc/*
F: Documentation/devicetree/bindings/interrupt-controller/snps,arc*
+F: drivers/clocksource/arc_timer.c
F: drivers/tty/serial/arc_uart.c
T: git
git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git
@@@ -12380,12 -12342,6 +12381,12 @@@ S: Maintaine
F: Documentation/filesystems/udf.txt
F: fs/udf/
+UDRAW TABLET
+M: Bastien Nocera <hadess(a)hadess.net>
+L: linux-input(a)vger.kernel.org
+S: Maintained
+F: drivers/hid/hid-udraw.c
+
UFS FILESYSTEM
M: Evgeniy Dushistov <dushistov(a)mail.ru>
S: Maintained
@@@ -12952,7 -12908,7 +12953,7 @@@ M: Greg Kroah-Hartman <gregkh@linuxfoun
L: devel(a)driverdev.osuosl.org
S: Maintained
T: git
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
-F: Documentation/vme_api.txt
+F: Documentation/driver-api/vme.rst
F: drivers/staging/vme/
F: drivers/vme/
F: include/linux/vme*
@@@ -13176,7 -13132,7 +13177,7 @@@ T: git
git://git.kernel.org/pub/scm/lin
S: Maintained
F: include/linux/workqueue.h
F: kernel/workqueue.c
-F: Documentation/workqueue.txt
+F: Documentation/core-api/workqueue.rst
X-POWERS MULTIFUNCTION PMIC DEVICE DRIVERS
M: Chen-Yu Tsai <wens(a)csie.org>
diff --combined arch/arm/boot/dts/dra72-evm-revc.dts
index 4ea2a0c,3b23b32..c3d939c
--- a/arch/arm/boot/dts/dra72-evm-revc.dts
+++ b/arch/arm/boot/dts/dra72-evm-revc.dts
@@@ -17,22 -17,17 +17,22 @@@
};
};
-&tps65917_regulators {
- ldo2_reg: ldo2 {
- /* LDO2_OUT --> VDDA_1V8_PHY2 */
- regulator-name = "ldo2";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- regulator-boot-on;
+&i2c1 {
+ tps65917: tps65917@58 {
+ reg = <0x58>;
+
+ interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
};
};
+#include "dra72-evm-tps65917.dtsi"
+
+&ldo2_reg {
+ /* LDO2_OUT --> VDDA_1V8_PHY2 */
+ regulator-always-on;
+ regulator-boot-on;
+};
+
&hdmi {
vdda-supply = <&ldo2_reg>;
};
@@@ -64,15 -59,17 +64,17 @@@
&davinci_mdio {
dp83867_0: ethernet-phy@2 {
reg = <2>;
- ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
- ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+ ti,min-output-impedance;
};
dp83867_1: ethernet-phy@3 {
reg = <3>;
- ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
- ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+ ti,min-output-imepdance;
};
};
diff --combined arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
index fa19cfd,1552db0..7ea617e
--- a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
+++ b/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
@@@ -88,10 -88,16 +88,16 @@@
switch0: switch0@0 {
compatible = "marvell,mv88e6085";
+ pinctrl-0 = <&pinctrl_gpio_switch0>;
+ pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
dsa,member = <0 0>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
ports {
#address-cells = <1>;
@@@ -99,16 -105,19 +105,19 @@@
port@0 {
reg = <0>;
label = "lan0";
+ phy-handle = <&switch0phy0>;
};
port@1 {
reg = <1>;
label = "lan1";
+ phy-handle = <&switch0phy1>;
};
port@2 {
reg = <2>;
label = "lan2";
+ phy-handle = <&switch0phy2>;
};
switch0port5: port@5 {
@@@ -133,6 -142,24 +142,24 @@@
};
};
};
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ switch0phy0: switch0phy0@0 {
+ reg = <0>;
+ interrupt-parent = <&switch0>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ switch0phy1: switch1phy0@1 {
+ reg = <1>;
+ interrupt-parent = <&switch0>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH>; };
+ switch0phy2: switch1phy0@2 {
+ reg = <2>;
+ interrupt-parent = <&switch0>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
};
};
@@@ -143,10 -170,16 +170,16 @@@
switch1: switch1@0 {
compatible = "marvell,mv88e6085";
+ pinctrl-0 = <&pinctrl_gpio_switch1>;
+ pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
dsa,member = <0 1>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
ports {
#address-cells = <1>;
@@@ -196,12 -229,18 +229,18 @@@
#size-cells = <0>;
switch1phy0: switch1phy0@0 {
reg = <0>;
+ interrupt-parent = <&switch1>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
switch1phy1: switch1phy0@1 {
reg = <1>;
+ interrupt-parent = <&switch1>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
};
switch1phy2: switch1phy0@2 {
reg = <2>;
+ interrupt-parent = <&switch1>;
+ interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
};
};
};
@@@ -499,6 -538,13 +538,6 @@@
};
};
-&i2c3 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c3>;
- status = "okay";
-};
-
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0>;
@@@ -629,6 -675,18 +668,18 @@@
;
};
+ pinctrl_gpio_switch0: pinctrl-gpio-switch0 {
+ fsl,pins = <
+ VF610_PAD_PTB5__GPIO_27 0x219d
+ >;
+ };
+
+ pinctrl_gpio_switch1: pinctrl-gpio-switch1 {
+ fsl,pins = <
+ VF610_PAD_PTB4__GPIO_26 0x219d
+ >;
+ };
+
pinctrl_i2c_mux_reset: pinctrl-i2c-mux-reset {
fsl,pins = <
VF610_PAD_PTE14__GPIO_119 0x31c2
@@@ -656,6 -714,13 +707,6 @@@
;
};
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- VF610_PAD_PTA30__I2C3_SCL 0x37ff
- VF610_PAD_PTA31__I2C3_SDA 0x37ff
- >;
- };
-
pinctrl_leds_debug: pinctrl-leds-debug {
fsl,pins = <
VF610_PAD_PTD20__GPIO_74 0x31c2
diff --combined arch/arm64/configs/defconfig
index 5fcb484,6be0811..453ba88
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@@ -82,7 -82,6 +82,7 @@@ CONFIG_KEXEC=
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
CONFIG_CPU_IDLE=y
+CONFIG_HIBERNATION=y
CONFIG_ARM_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPUFREQ_DT=y
@@@ -184,10 -183,7 +184,10 @@@ CONFIG_SMC91X=
CONFIG_SMSC911X=y
CONFIG_STMMAC_ETH=m
CONFIG_REALTEK_PHY=m
+CONFIG_MESON_GXL_PHY=m
CONFIG_MICREL_PHY=y
+CONFIG_MDIO_BUS_MUX=y
+CONFIG_MDIO_BUS_MUX_MMIOREG=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
@@@ -238,7 -234,6 +238,7 @@@ CONFIG_I2C_IMX=
CONFIG_I2C_MESON=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_QUP=y
+CONFIG_I2C_RK3X=y
CONFIG_I2C_TEGRA=y
CONFIG_I2C_UNIPHIER_F=y
CONFIG_I2C_RCAR=y
@@@ -254,7 -249,6 +254,7 @@@ CONFIG_SPMI=
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MAX77620=y
CONFIG_PINCTRL_MSM8916=y
+CONFIG_PINCTRL_MSM8994=y
CONFIG_PINCTRL_MSM8996=y
CONFIG_PINCTRL_QDF2XXX=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
@@@ -263,6 -257,7 +263,7 @@@ CONFIG_GPIO_DWAPB=
CONFIG_GPIO_PL061=y
CONFIG_GPIO_RCAR=y
CONFIG_GPIO_XGENE=y
+ CONFIG_GPIO_XGENE_SB=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_MAX77620=y
@@@ -277,7 -272,6 +278,7 @@@ CONFIG_THERMAL=
CONFIG_THERMAL_EMULATION=y
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
+CONFIG_BCM2835_THERMAL=y
CONFIG_EXYNOS_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_RENESAS_WDT=y
@@@ -285,7 -279,6 +286,7 @@@ CONFIG_S3C2410_WATCHDOG=
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MFD_MAX77620=y
+CONFIG_MFD_RK808=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_HI655X_PMIC=y
@@@ -299,24 -292,9 +300,24 @@@ CONFIG_REGULATOR_MAX77620=
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
+CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPS11=y
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_DVB_NET is not set
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_RENESAS_FCP=m
+CONFIG_VIDEO_RENESAS_VSP1=m
CONFIG_DRM=m
CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_RCAR_DU=m
+CONFIG_DRM_RCAR_HDMI=y
+CONFIG_DRM_RCAR_LVDS=y
+CONFIG_DRM_RCAR_VSP=y
CONFIG_DRM_TEGRA=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_I2C_ADV7511=m
@@@ -364,11 -342,9 +365,11 @@@ CONFIG_USB_RENESAS_USBHS_UDC=
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_ARMMMCI=y
+CONFIG_MMC_MESON_GX=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ACPI=y
CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_MMC_SDHCI_MSM=y
@@@ -377,7 -353,6 +378,7 @@@ CONFIG_MMC_SDHI=
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_MMC_DW_K3=y
+CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SUNXI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
@@@ -393,7 -368,6 +394,7 @@@ CONFIG_RTC_DRV_DS3232=
CONFIG_RTC_DRV_EFI=y
CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_SUN6I=y
+CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_TEGRA=y
CONFIG_RTC_DRV_XGENE=y
CONFIG_RTC_DRV_S3C=y
@@@ -414,36 -388,26 +415,36 @@@ CONFIG_XEN_GRANT_DEV_ALLOC=
CONFIG_COMMON_CLK_SCPI=y
CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_S2MPS11=y
+CONFIG_COMMON_CLK_PWM=y
+CONFIG_COMMON_CLK_RK808=y
CONFIG_CLK_QORIQ=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_MSM_GCC_8916=y
+CONFIG_MSM_GCC_8994=y
CONFIG_MSM_MMCC_8996=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_MAILBOX=y
CONFIG_ARM_MHU=y
+CONFIG_PLATFORM_MHU=y
CONFIG_HI6220_MBOX=y
CONFIG_ARM_SMMU=y
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMD=y
CONFIG_QCOM_SMD_RPM=y
+CONFIG_ROCKCHIP_PM_DOMAINS=y
CONFIG_ARCH_TEGRA_132_SOC=y
CONFIG_ARCH_TEGRA_210_SOC=y
+CONFIG_ARCH_TEGRA_186_SOC=y
CONFIG_EXTCON_USB_GPIO=y
CONFIG_PWM=y
+CONFIG_PWM_ROCKCHIP=y
CONFIG_PWM_TEGRA=m
+CONFIG_PWM_MESON=m
CONFIG_COMMON_RESET_HI6220=y
CONFIG_PHY_RCAR_GEN3_USB2=y
CONFIG_PHY_HI6220_USB=y
+CONFIG_PHY_ROCKCHIP_INNO_USB2=y
+CONFIG_PHY_ROCKCHIP_EMMC=y
CONFIG_PHY_XGENE=y
CONFIG_PHY_TEGRA_XUSB=y
CONFIG_ARM_SCPI_PROTOCOL=y
diff --combined drivers/infiniband/core/cma.c
index 2a6fc47,c68f4fe..22fcf28
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@@ -116,7 -116,7 +116,7 @@@ static LIST_HEAD(dev_list)
static LIST_HEAD(listen_any_list);
static DEFINE_MUTEX(lock);
static struct workqueue_struct *cma_wq;
- static int cma_pernet_id;
+ static unsigned int cma_pernet_id;
struct cma_pernet {
struct idr tcp_ps;
@@@ -2438,18 -2438,6 +2438,18 @@@ static int iboe_tos_to_sl(struct net_de
return 0;
}
+static enum ib_gid_type cma_route_gid_type(enum rdma_network_type network_type,
+ unsigned long supported_gids,
+ enum ib_gid_type default_gid)
+{
+ if ((network_type == RDMA_NETWORK_IPV4 ||
+ network_type == RDMA_NETWORK_IPV6) &&
+ test_bit(IB_GID_TYPE_ROCE_UDP_ENCAP, &supported_gids))
+ return IB_GID_TYPE_ROCE_UDP_ENCAP;
+
+ return default_gid;
+}
+
static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
{
struct rdma_route *route = &id_priv->id.route;
@@@ -2475,8 -2463,6 +2475,8 @@@
route->num_paths = 1;
if (addr->dev_addr.bound_dev_if) {
+ unsigned long supported_gids;
+
ndev = dev_get_by_index(&init_net, addr->dev_addr.bound_dev_if);
if (!ndev) {
ret = -ENODEV;
@@@ -2500,12 -2486,7 +2500,12 @@@
route->path_rec->net = &init_net;
route->path_rec->ifindex = ndev->ifindex;
- route->path_rec->gid_type = id_priv->gid_type;
+ supported_gids = roce_gid_type_mask_support(id_priv->id.device,
+ id_priv->id.port_num);
+ route->path_rec->gid_type =
+ cma_route_gid_type(addr->dev_addr.network,
+ supported_gids,
+ id_priv->gid_type);
}
if (!ndev) {
ret = -ENODEV;
diff --combined drivers/infiniband/hw/mlx5/main.c
index 32b09f0,76ed57f..2be65dd
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@@ -1771,13 -1771,13 +1771,13 @@@ static int mlx5_ib_destroy_flow(struct
mutex_lock(&dev->flow_db.lock);
list_for_each_entry_safe(iter, tmp, &handler->list, list) {
- mlx5_del_flow_rule(iter->rule);
+ mlx5_del_flow_rules(iter->rule);
put_flow_table(dev, iter->prio, true);
list_del(&iter->list);
kfree(iter);
}
- mlx5_del_flow_rule(handler->rule);
+ mlx5_del_flow_rules(handler->rule);
put_flow_table(dev, handler->prio, true);
mutex_unlock(&dev->flow_db.lock);
@@@ -1857,7 -1857,7 +1857,7 @@@ static struct mlx5_ib_flow_prio *get_fl
ft = mlx5_create_auto_grouped_flow_table(ns, priority,
num_entries,
num_groups,
- 0);
+ 0, 0);
if (!IS_ERR(ft)) {
prio->refcount = 0;
@@@ -1877,10 -1877,10 +1877,10 @@@ static struct mlx5_ib_flow_handler *cre
{
struct mlx5_flow_table *ft = ft_prio->flow_table;
struct mlx5_ib_flow_handler *handler;
+ struct mlx5_flow_act flow_act = {0};
struct mlx5_flow_spec *spec;
const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr);
unsigned int spec_index;
- u32 action;
int err = 0;
if (!is_valid_attr(flow_attr))
@@@ -1905,12 -1905,12 +1905,12 @@@
}
spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria);
- action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
+ flow_act.action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
- handler->rule = mlx5_add_flow_rule(ft, spec,
- action,
- MLX5_FS_DEFAULT_FLOW_TAG,
- dst);
+ flow_act.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
+ handler->rule = mlx5_add_flow_rules(ft, spec,
+ &flow_act,
+ dst, 1);
if (IS_ERR(handler->rule)) {
err = PTR_ERR(handler->rule);
@@@ -1941,7 -1941,7 +1941,7 @@@ static struct mlx5_ib_flow_handler *cre
handler_dst = create_flow_rule(dev, ft_prio,
flow_attr, dst);
if (IS_ERR(handler_dst)) {
- mlx5_del_flow_rule(handler->rule);
+ mlx5_del_flow_rules(handler->rule);
ft_prio->refcount--;
kfree(handler);
handler = handler_dst;
@@@ -2004,7 -2004,7 +2004,7 @@@ static struct mlx5_ib_flow_handler *cre
&leftovers_specs[LEFTOVERS_UC].flow_attr,
dst);
if (IS_ERR(handler_ucast)) {
- mlx5_del_flow_rule(handler->rule);
+ mlx5_del_flow_rules(handler->rule);
ft_prio->refcount--;
kfree(handler);
handler = handler_ucast;
@@@ -2046,7 -2046,7 +2046,7 @@@ static struct mlx5_ib_flow_handler *cre
return handler_rx;
err_tx:
- mlx5_del_flow_rule(handler_rx->rule);
+ mlx5_del_flow_rules(handler_rx->rule);
ft_rx->refcount--;
kfree(handler_rx);
err:
@@@ -2311,14 -2311,14 +2311,14 @@@ static void mlx5_ib_event(struct mlx5_c
{
struct mlx5_ib_dev *ibdev = (struct mlx5_ib_dev *)context;
struct ib_event ibev;
-
+ bool fatal = false;
u8 port = 0;
switch (event) {
case MLX5_DEV_EVENT_SYS_ERROR:
- ibdev->ib_active = false;
ibev.event = IB_EVENT_DEVICE_FATAL;
mlx5_ib_handle_internal_error(ibdev);
+ fatal = true;
break;
case MLX5_DEV_EVENT_PORT_UP:
@@@ -2358,6 -2358,8 +2358,8 @@@
ibev.event = IB_EVENT_CLIENT_REREGISTER;
port = (u8)param;
break;
+ default:
+ return;
}
ibev.device = &ibdev->ib_dev;
@@@ -2370,9 -2372,6 +2372,9 @@@
if (ibdev->ib_active)
ib_dispatch_event(&ibev);
+
+ if (fatal)
+ ibdev->ib_active = false;
}
static void get_ext_port_caps(struct mlx5_ib_dev *dev)
@@@ -3118,7 -3117,7 +3120,7 @@@ static void *mlx5_ib_add(struct mlx5_co
}
err = init_node_data(dev);
if (err)
- goto err_dealloc;
+ goto err_free_port;
mutex_init(&dev->flow_db.lock);
mutex_init(&dev->cap_mask_mutex);
@@@ -3128,7 -3127,7 +3130,7 @@@
if (ll == IB_LINK_LAYER_ETHERNET) {
err = mlx5_enable_roce(dev);
if (err)
- goto err_dealloc;
+ goto err_free_port;
}
err = create_dev_resources(&dev->devr);
diff --combined drivers/infiniband/hw/mlx5/mlx5_ib.h
index 7d68990,d5d0077..854748b
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@@ -153,7 -153,7 +153,7 @@@ struct mlx5_ib_flow_handler
struct list_head list;
struct ib_flow ibflow;
struct mlx5_ib_flow_prio *prio;
- struct mlx5_flow_rule *rule;
+ struct mlx5_flow_handle *rule;
};
struct mlx5_ib_flow_db {
@@@ -626,8 -626,6 +626,8 @@@ struct mlx5_ib_dev
struct mlx5_ib_resources devr;
struct mlx5_mr_cache cache;
struct timer_list delay_timer;
+ /* Prevents soft lock on massive reg MRs */
+ struct mutex slow_path_mutex;
int fill_delay;
#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
struct ib_odp_caps odp_caps;
diff --combined drivers/media/dvb-core/dvb_net.c
index b9a46d5,0da622f..088914c
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@@ -54,8 -54,6 +54,8 @@@
*
*/
+#define pr_fmt(fmt) "dvb_net: " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@@ -346,7 -344,7 +346,7 @@@ static void dvb_net_ule( struct net_dev
/* Check TS error conditions: sync_byte, transport_error_indicator,
scrambling_control . */
if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) {
- printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n",
+ pr_warn("%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n",
priv->ts_count, ts[0],
(ts[1] & TS_TEI) >> 7,
(ts[3] & TS_SC) >> 6);
@@@ -378,8 -376,8 +378,8 @@@
priv->tscc = ts[3] & 0x0F;
/* There is a pointer field here. */
if (ts[4] > ts_remain) {
- printk(KERN_ERR "%lu: Invalid ULE packet "
- "(pointer field %d)\n", priv->ts_count, ts[4]);
+ pr_err("%lu: Invalid ULE packet (pointer field %d)\n",
+ priv->ts_count, ts[4]);
ts += TS_SZ;
priv->ts_count++;
continue;
@@@ -402,9 -400,8 +402,9 @@@
priv->tscc = (priv->tscc + 1) & 0x0F;
else {
/* TS discontinuity handling: */
- printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
- "expected %#x.\n", priv->ts_count, ts[3] & 0x0F,
priv->tscc);
+ pr_warn("%lu: TS discontinuity: got %#x, expected %#x.\n",
+ priv->ts_count, ts[3] & 0x0F,
+ priv->tscc);
/* Drop partly decoded SNDU, reset state, resync on PUSI. */
if (priv->ule_skb) {
dev_kfree_skb( priv->ule_skb );
@@@ -426,9 -423,8 +426,9 @@@
if (! priv->need_pusi) {
if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain)
{
/* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */
- printk(KERN_WARNING "%lu: Invalid pointer "
- "field: %u.\n", priv->ts_count, *from_where);
+ pr_warn("%lu: Invalid pointer field: %u.\n",
+ priv->ts_count,
+ *from_where);
/* Drop partly decoded SNDU, reset state, resync on PUSI. */
if (priv->ule_skb) {
@@@ -458,10 -454,9 +458,10 @@@
* current TS cell. */
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
- printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
- "got PUSI (pf %d, ts_remain %d). Flushing incomplete
payload.\n",
- priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
+ pr_warn("%lu: Expected %d more SNDU bytes, but got PUSI (pf %d, ts_remain %d).
Flushing incomplete payload.\n",
+ priv->ts_count,
+ priv->ule_sndu_remain,
+ ts[4], ts_remain);
dev_kfree_skb(priv->ule_skb);
/* Prepare for next SNDU. */
reset_ule(priv);
@@@ -480,8 -475,8 +480,8 @@@
* TS.
* Check ts_remain has to be >= 2 here. */
if (ts_remain < 2) {
- printk(KERN_WARNING "Invalid payload packing: only %d "
- "bytes left in TS. Resyncing.\n", ts_remain);
+ pr_warn("Invalid payload packing: only %d bytes left in TS.
Resyncing.\n",
+ ts_remain);
priv->ule_sndu_len = 0;
priv->need_pusi = 1;
ts += TS_SZ;
@@@ -499,9 -494,8 +499,9 @@@
priv->ule_dbit = 0;
if (priv->ule_sndu_len < 5) {
- printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
- "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
+ pr_warn("%lu: Invalid ULE SNDU length %u. Resyncing.\n",
+ priv->ts_count,
+ priv->ule_sndu_len);
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
priv->ule_sndu_len = 0;
@@@ -556,8 -550,8 +556,8 @@@
* prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */
priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN );
if (priv->ule_skb == NULL) {
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
- dev->name);
+ pr_notice("%s: Memory squeeze, dropping packet.\n",
+ dev->name);
dev->stats.rx_dropped++;
return;
}
@@@ -601,11 -595,8 +601,11 @@@
*(tail - 2) << 8 |
*(tail - 1);
if (ule_crc != expected_crc) {
- printk(KERN_WARNING "%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type
%#x, ts_remain %d, next 2: %x.\n",
- priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len,
priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0);
+ pr_warn("%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain
%d, next 2: %x.\n",
+ priv->ts_count, ule_crc, expected_crc,
+ priv->ule_sndu_len, priv->ule_sndu_type,
+ ts_remain,
+ ts_remain > 2 ? *(unsigned short *)from_where : 0);
#ifdef ULE_DEBUG
hexdump( iov[0].iov_base, iov[0].iov_len );
@@@ -696,7 -687,7 +696,7 @@@
int l = handle_ule_extensions(priv);
if (l < 0) {
/* Mandatory extension header unknown or TEST SNDU. Drop it. */
- // printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
+ // pr_warn("Dropping SNDU, extension headers.\n" );
dev_kfree_skb(priv->ule_skb);
goto sndu_done;
}
@@@ -750,10 -741,10 +750,10 @@@
priv->ule_skb = NULL;
priv->ule_sndu_type_1 = 0;
priv->ule_sndu_len = 0;
- // printk(KERN_WARNING "More data in current TS: [%#x %#x %#x %#x]\n",
+ // pr_warn("More data in current TS: [%#x %#x %#x %#x]\n",
// *(from_where + 0), *(from_where + 1),
// *(from_where + 2), *(from_where + 3));
- // printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0);
+ // pr_warn("ts @ %p, stopped @ %p:\n", ts, from_where + 0);
// hexdump(ts, 188);
} else {
new_ts = 1;
@@@ -775,10 -766,10 +775,10 @@@ static int dvb_net_ts_callback(const u
struct net_device *dev = feed->priv;
if (buffer2)
- printk(KERN_WARNING "buffer2 not NULL: %p.\n", buffer2);
+ pr_warn("buffer2 not NULL: %p.\n", buffer2);
if (buffer1_len > 32768)
- printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);
- /* printk("TS callback: %u bytes, %u TS cells @ %p.\n",
+ pr_warn("length > 32k: %zu.\n", buffer1_len);
+ /* pr_info("TS callback: %u bytes, %u TS cells @ %p.\n",
buffer1_len, buffer1_len / TS_SZ, buffer1); */
dvb_net_ule(dev, buffer1, buffer1_len);
return 0;
@@@ -795,7 -786,7 +795,7 @@@ static void dvb_net_sec(struct net_devi
/* note: pkt_len includes a 32bit checksum */
if (pkt_len < 16) {
- printk("%s: IP/MPE packet length = %d too small.\n",
+ pr_warn("%s: IP/MPE packet length = %d too small.\n",
dev->name, pkt_len);
stats->rx_errors++;
stats->rx_length_errors++;
@@@ -833,7 -824,7 +833,7 @@@
* 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte LLC/SNAP
*/
if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) {
- //printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
dev->name);
+ //pr_notice("%s: Memory squeeze, dropping packet.\n", dev->name);
stats->rx_dropped++;
return;
}
@@@ -912,7 -903,7 +912,7 @@@ static int dvb_net_filter_sec_set(struc
*secfilter=NULL;
ret = priv->secfeed->allocate_filter(priv->secfeed, secfilter);
if (ret<0) {
- printk("%s: could not get filter\n", dev->name);
+ pr_err("%s: could not get filter\n", dev->name);
return ret;
}
@@@ -953,7 -944,7 +953,7 @@@ static int dvb_net_feed_start(struct ne
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
mutex_lock(&priv->mutex);
if (priv->tsfeed || priv->secfeed || priv->secfilter ||
priv->multi_secfilter[0])
- printk("%s: BUG %d\n", __func__, __LINE__);
+ pr_err("%s: BUG %d\n", __func__, __LINE__);
priv->secfeed=NULL;
priv->secfilter=NULL;
@@@ -964,15 -955,14 +964,15 @@@
ret=demux->allocate_section_feed(demux, &priv->secfeed,
dvb_net_sec_callback);
if (ret<0) {
- printk("%s: could not allocate section feed\n", dev->name);
+ pr_err("%s: could not allocate section feed\n",
+ dev->name);
goto error;
}
- ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
+ ret = priv->secfeed->set(priv->secfeed, priv->pid, 1);
if (ret<0) {
- printk("%s: could not set section feed\n", dev->name);
+ pr_err("%s: could not set section feed\n", dev->name);
priv->demux->release_section_feed(priv->demux, priv->secfeed);
priv->secfeed=NULL;
goto error;
@@@ -1013,7 -1003,7 +1013,7 @@@
netdev_dbg(dev, "alloc tsfeed\n");
ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
if (ret < 0) {
- printk("%s: could not allocate ts feed\n", dev->name);
+ pr_err("%s: could not allocate ts feed\n", dev->name);
goto error;
}
@@@ -1023,11 -1013,12 +1023,11 @@@
priv->pid, /* pid */
TS_PACKET, /* type */
DMX_PES_OTHER, /* pes type */
- 32768, /* circular buffer size */
timeout /* timeout */
);
if (ret < 0) {
- printk("%s: could not set ts feed\n", dev->name);
+ pr_err("%s: could not set ts feed\n", dev->name);
priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
priv->tsfeed = NULL;
goto error;
@@@ -1076,7 -1067,7 +1076,7 @@@ static int dvb_net_feed_stop(struct net
priv->demux->release_section_feed(priv->demux, priv->secfeed);
priv->secfeed = NULL;
} else
- printk("%s: no feed to stop\n", dev->name);
+ pr_err("%s: no feed to stop\n", dev->name);
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
if (priv->tsfeed) {
if (priv->tsfeed->is_filtering) {
@@@ -1087,7 -1078,7 +1087,7 @@@
priv->tsfeed = NULL;
}
else
- printk("%s: no ts feed to stop\n", dev->name);
+ pr_err("%s: no ts feed to stop\n", dev->name);
} else
ret = -EINVAL;
mutex_unlock(&priv->mutex);
@@@ -1207,7 -1198,6 +1207,6 @@@ static const struct net_device_ops dvb_
.ndo_start_xmit = dvb_net_tx,
.ndo_set_rx_mode = dvb_net_set_multicast_list,
.ndo_set_mac_address = dvb_net_set_mac,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@@ -1218,6 -1208,7 +1217,7 @@@ static void dvb_net_setup(struct net_de
dev->header_ops = &dvb_header_ops;
dev->netdev_ops = &dvb_netdev_ops;
dev->mtu = 4096;
+ dev->max_mtu = 4096;
dev->flags |= IFF_NOARP;
}
@@@ -1288,7 -1279,7 +1288,7 @@@ static int dvb_net_add_if(struct dvb_ne
free_netdev(net);
return result;
}
- printk("dvb_net: created network interface %s\n", net->name);
+ pr_info("created network interface %s\n", net->name);
return if_num;
}
@@@ -1307,7 -1298,7 +1307,7 @@@ static int dvb_net_remove_if(struct dvb
dvb_net_stop(net);
flush_work(&priv->set_multicast_list_wq);
flush_work(&priv->restart_net_feed_wq);
- printk("dvb_net: removed network interface %s\n", net->name);
+ pr_info("removed network interface %s\n", net->name);
unregister_netdev(net);
dvbnet->state[num]=0;
dvbnet->device[num] = NULL;
diff --combined drivers/net/ethernet/arc/emac_main.c
index be865b4,95d8b3e..abc9f2a
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@@ -460,7 -460,7 +460,7 @@@ static void arc_emac_set_rx_mode(struc
if (ndev->flags & IFF_ALLMULTI) {
arc_reg_set(priv, R_LAFL, ~0);
arc_reg_set(priv, R_LAFH, ~0);
- } else {
+ } else if (ndev->flags & IFF_MULTICAST) {
struct netdev_hw_addr *ha;
unsigned int filter[2] = { 0, 0 };
int bit;
@@@ -472,9 -472,6 +472,9 @@@
arc_reg_set(priv, R_LAFL, filter[0]);
arc_reg_set(priv, R_LAFH, filter[1]);
+ } else {
+ arc_reg_set(priv, R_LAFL, 0);
+ arc_reg_set(priv, R_LAFH, 0);
}
}
}
@@@ -636,7 -633,7 +636,7 @@@ static int arc_emac_tx(struct sk_buff *
if (unlikely(dma_mapping_error(&ndev->dev, addr))) {
stats->tx_dropped++;
stats->tx_errors++;
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr);
@@@ -767,6 -764,8 +767,6 @@@ int arc_emac_probe(struct net_device *n
ndev->netdev_ops = &arc_emac_netdev_ops;
ndev->ethtool_ops = &arc_emac_ethtool_ops;
ndev->watchdog_timeo = TX_TIMEOUT;
- /* FIXME :: no multicast support yet */
- ndev->flags &= ~IFF_MULTICAST;
priv = netdev_priv(ndev);
priv->dev = dev;
diff --combined drivers/net/ethernet/broadcom/bnxt/bnxt.c
index e18635b,7401c90..8c7bdbe
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@@ -1499,6 -1499,7 +1499,7 @@@ static int bnxt_async_event_process(str
netdev_warn(bp->dev, "Link speed %d no longer supported\n",
speed);
}
+ set_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT, &bp->sp_event);
/* fall thru */
}
case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
@@@ -3424,13 -3425,7 +3425,7 @@@ static int bnxt_hwrm_vnic_set_rss(struc
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_CFG, -1, -1);
if (set_rss) {
- vnic->hash_type = VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 |
- VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
- VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
- VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
-
- req.hash_type = cpu_to_le32(vnic->hash_type);
-
+ req.hash_type = cpu_to_le32(bp->rss_hash_cfg);
if (vnic->flags & BNXT_VNIC_RSS_FLAG) {
if (BNXT_CHIP_TYPE_NITRO_A0(bp))
max_rings = bp->rx_nr_rings - 1;
@@@ -4934,10 -4929,6 +4929,10 @@@ static void bnxt_del_napi(struct bnxt *
napi_hash_del(&bnapi->napi);
netif_napi_del(&bnapi->napi);
}
+ /* We called napi_hash_del() before netif_napi_del(), we need
+ * to respect an RCU grace period before freeing napi structures.
+ */
+ synchronize_net();
}
static void bnxt_init_napi(struct bnxt *bp)
@@@ -4958,7 -4949,6 +4953,6 @@@
bnapi = bp->bnapi[cp_nr_rings];
netif_napi_add(bp->dev, &bnapi->napi,
bnxt_poll_nitroa0, 64);
- napi_hash_add(&bnapi->napi);
}
} else {
bnapi = bp->bnapi[0];
@@@ -5100,6 -5090,7 +5094,7 @@@ static int bnxt_update_link(struct bnx
struct hwrm_port_phy_qcfg_input req = {0};
struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
u8 link_up = link_info->link_up;
+ u16 diff;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1);
@@@ -5187,6 -5178,23 +5182,23 @@@
link_info->link_up = 0;
}
mutex_unlock(&bp->hwrm_cmd_lock);
+
+ diff = link_info->support_auto_speeds ^ link_info->advertising;
+ if ((link_info->support_auto_speeds | diff) !=
+ link_info->support_auto_speeds) {
+ /* An advertised speed is no longer supported, so we need to
+ * update the advertisement settings. See bnxt_reset() for
+ * comments about the rtnl_lock() sequence below.
+ */
+ clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+ rtnl_lock();
+ link_info->advertising = link_info->support_auto_speeds;
+ if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
+ (link_info->autoneg & BNXT_AUTONEG_SPEED))
+ bnxt_hwrm_set_link_setting(bp, true, false);
+ set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+ rtnl_unlock();
+ }
return 0;
}
@@@ -5351,7 -5359,7 +5363,7 @@@ static int bnxt_hwrm_shutdown_link(stru
return 0;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1);
- req.flags = cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DOWN);
+ req.flags = cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DWN);
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
}
@@@ -5414,6 -5422,12 +5426,12 @@@ static int bnxt_update_phy_setting(stru
update_link = true;
}
+ /* The last close may have shutdown the link, so need to call
+ * PHY_CFG to bring it back up.
+ */
+ if (!netif_carrier_ok(bp->dev))
+ update_link = true;
+
if (!bnxt_eee_config_ok(bp))
update_eee = true;
@@@ -6107,6 -6121,10 +6125,10 @@@ static void bnxt_sp_task(struct work_st
if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event))
bnxt_cfg_ntp_filters(bp);
if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
+ if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
+ &bp->sp_event))
+ bnxt_hwrm_phy_qcaps(bp);
+
rc = bnxt_update_link(bp, true);
if (rc)
netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
@@@ -6294,9 -6312,6 +6316,6 @@@ static int bnxt_change_mtu(struct net_d
{
struct bnxt *bp = netdev_priv(dev);
- if (new_mtu < 60 || new_mtu > 9500)
- return -EINVAL;
-
if (netif_running(dev))
bnxt_close_nic(bp, false, false);
@@@ -6875,6 -6890,10 +6894,10 @@@ static int bnxt_init_one(struct pci_de
dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
dev->priv_flags |= IFF_UNICAST_FLT;
+ /* MTU range: 60 - 9500 */
+ dev->min_mtu = ETH_ZLEN;
+ dev->max_mtu = 9500;
+
#ifdef CONFIG_BNXT_SRIOV
init_waitqueue_head(&bp->sriov_cfg_wait);
#endif
@@@ -6915,6 -6934,19 +6938,19 @@@
#endif
bnxt_set_dflt_rings(bp);
+ /* Default RSS hash cfg. */
+ bp->rss_hash_cfg = VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 |
+ VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
+ VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
+ VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
+ if (!BNXT_CHIP_NUM_57X0X(bp->chip_num) &&
+ !BNXT_CHIP_TYPE_NITRO_A0(bp) &&
+ bp->hwrm_spec_code >= 0x10501) {
+ bp->flags |= BNXT_FLAG_UDP_RSS_CAP;
+ bp->rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 |
+ VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
+ }
+
if (BNXT_PF(bp) && !BNXT_CHIP_TYPE_NITRO_A0(bp)) {
dev->hw_features |= NETIF_F_NTUPLE;
if (bnxt_rfs_capable(bp)) {
diff --combined drivers/net/ethernet/cadence/macb.c
index 533653b,654b5bf..0e489bb
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@@ -32,19 -32,28 +32,28 @@@
#include <linux/of_gpio.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
-
+ #include <linux/ip.h>
+ #include <linux/udp.h>
+ #include <linux/tcp.h>
#include "macb.h"
#define MACB_RX_BUFFER_SIZE 128
#define RX_BUFFER_MULTIPLE 64 /* bytes */
- #define RX_RING_SIZE 512 /* must be power of 2 */
- #define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
- #define TX_RING_SIZE 128 /* must be power of 2 */
- #define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
+ #define DEFAULT_RX_RING_SIZE 512 /* must be power of 2 */
+ #define MIN_RX_RING_SIZE 64
+ #define MAX_RX_RING_SIZE 8192
+ #define RX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \
+ * (bp)->rx_ring_size)
+
+ #define DEFAULT_TX_RING_SIZE 512 /* must be power of 2 */
+ #define MIN_TX_RING_SIZE 64
+ #define MAX_TX_RING_SIZE 4096
+ #define TX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \
+ * (bp)->tx_ring_size)
/* level of occupied TX descriptors under which we wake up TX process */
- #define MACB_TX_WAKEUP_THRESH (3 * TX_RING_SIZE / 4)
+ #define MACB_TX_WAKEUP_THRESH(bp) (3 * (bp)->tx_ring_size / 4)
#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
| MACB_BIT(ISR_ROVR))
@@@ -53,10 -62,13 +62,13 @@@
| MACB_BIT(TXERR))
#define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP))
- #define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1))
- #define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1))
+ /* Max length of transmit frame must be a multiple of 8 bytes */
+ #define MACB_TX_LEN_ALIGN 8
+ #define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1) &
~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
+ #define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1) &
~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
- #define GEM_MTU_MIN_SIZE 68
+ #define GEM_MTU_MIN_SIZE ETH_MIN_MTU
+ #define MACB_NETIF_LSO (NETIF_F_TSO | NETIF_F_UFO)
#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0)
#define MACB_WOL_ENABLED (0x1 << 1)
@@@ -67,45 -79,47 +79,47 @@@
#define MACB_HALT_TIMEOUT 1230
/* Ring buffer accessors */
- static unsigned int macb_tx_ring_wrap(unsigned int index)
+ static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
{
- return index & (TX_RING_SIZE - 1);
+ return index & (bp->tx_ring_size - 1);
}
static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,
unsigned int index)
{
- return &queue->tx_ring[macb_tx_ring_wrap(index)];
+ return &queue->tx_ring[macb_tx_ring_wrap(queue->bp, index)];
}
static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,
unsigned int index)
{
- return &queue->tx_skb[macb_tx_ring_wrap(index)];
+ return &queue->tx_skb[macb_tx_ring_wrap(queue->bp, index)];
}
static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)
{
dma_addr_t offset;
- offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc);
+ offset = macb_tx_ring_wrap(queue->bp, index) *
+ sizeof(struct macb_dma_desc);
return queue->tx_ring_dma + offset;
}
- static unsigned int macb_rx_ring_wrap(unsigned int index)
+ static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)
{
- return index & (RX_RING_SIZE - 1);
+ return index & (bp->rx_ring_size - 1);
}
static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
{
- return &bp->rx_ring[macb_rx_ring_wrap(index)];
+ return &bp->rx_ring[macb_rx_ring_wrap(bp, index)];
}
static void *macb_rx_buffer(struct macb *bp, unsigned int index)
{
- return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
+ return bp->rx_buffers + bp->rx_buffer_size *
+ macb_rx_ring_wrap(bp, index);
}
/* I/O accessors */
@@@ -608,7 -622,8 +622,8 @@@ static void macb_tx_error_task(struct w
*/
if (!(ctrl & MACB_BIT(TX_BUF_EXHAUSTED))) {
netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
- macb_tx_ring_wrap(tail), skb->data);
+ macb_tx_ring_wrap(bp, tail),
+ skb->data);
bp->stats.tx_packets++;
bp->stats.tx_bytes += skb->len;
}
@@@ -700,7 -715,8 +715,8 @@@ static void macb_tx_interrupt(struct ma
/* First, update TX stats if needed */
if (skb) {
netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
- macb_tx_ring_wrap(tail), skb->data);
+ macb_tx_ring_wrap(bp, tail),
+ skb->data);
bp->stats.tx_packets++;
bp->stats.tx_bytes += skb->len;
}
@@@ -720,7 -736,7 +736,7 @@@
queue->tx_tail = tail;
if (__netif_subqueue_stopped(bp->dev, queue_index) &&
CIRC_CNT(queue->tx_head, queue->tx_tail,
- TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH)
+ bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp))
netif_wake_subqueue(bp->dev, queue_index);
}
@@@ -731,8 -747,8 +747,8 @@@ static void gem_rx_refill(struct macb *
dma_addr_t paddr;
while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail,
- RX_RING_SIZE) > 0) {
- entry = macb_rx_ring_wrap(bp->rx_prepared_head);
+ bp->rx_ring_size) > 0) {
+ entry = macb_rx_ring_wrap(bp, bp->rx_prepared_head);
/* Make hw descriptor updates visible to CPU */
rmb();
@@@ -759,7 -775,7 +775,7 @@@
bp->rx_skbuff[entry] = skb;
- if (entry == RX_RING_SIZE - 1)
+ if (entry == bp->rx_ring_size - 1)
paddr |= MACB_BIT(RX_WRAP);
macb_set_addr(&(bp->rx_ring[entry]), paddr);
bp->rx_ring[entry].ctrl = 0;
@@@ -813,7 -829,7 +829,7 @@@ static int gem_rx(struct macb *bp, int
dma_addr_t addr;
bool rxused;
- entry = macb_rx_ring_wrap(bp->rx_tail);
+ entry = macb_rx_ring_wrap(bp, bp->rx_tail);
desc = &bp->rx_ring[entry];
/* Make hw descriptor updates visible to CPU */
@@@ -895,8 -911,8 +911,8 @@@ static int macb_rx_frame(struct macb *b
len = desc->ctrl & bp->rx_frm_len_mask;
netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
- macb_rx_ring_wrap(first_frag),
- macb_rx_ring_wrap(last_frag), len);
+ macb_rx_ring_wrap(bp, first_frag),
+ macb_rx_ring_wrap(bp, last_frag), len);
/* The ethernet header starts NET_IP_ALIGN bytes into the
* first buffer. Since the header is 14 bytes, this makes the
@@@ -969,12 -985,12 +985,12 @@@ static inline void macb_init_rx_ring(st
int i;
addr = bp->rx_buffers_dma;
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < bp->rx_ring_size; i++) {
bp->rx_ring[i].addr = addr;
bp->rx_ring[i].ctrl = 0;
addr += bp->rx_buffer_size;
}
- bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
+ bp->rx_ring[bp->rx_ring_size - 1].addr |= MACB_BIT(RX_WRAP);
}
static int macb_rx(struct macb *bp, int budget)
@@@ -1212,7 -1228,8 +1228,8 @@@ static void macb_poll_controller(struc
static unsigned int macb_tx_map(struct macb *bp,
struct macb_queue *queue,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ unsigned int hdrlen)
{
dma_addr_t mapping;
unsigned int len, entry, i, tx_head = queue->tx_head;
@@@ -1220,15 -1237,28 +1237,28 @@@
struct macb_dma_desc *desc;
unsigned int offset, size, count = 0;
unsigned int f, nr_frags = skb_shinfo(skb)->nr_frags;
- unsigned int eof = 1;
- u32 ctrl;
+ unsigned int eof = 1, mss_mfs = 0;
+ u32 ctrl, lso_ctrl = 0, seq_ctrl = 0;
+
+ /* LSO */
+ if (skb_shinfo(skb)->gso_size != 0) {
+ if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ /* UDP - UFO */
+ lso_ctrl = MACB_LSO_UFO_ENABLE;
+ else
+ /* TCP - TSO */
+ lso_ctrl = MACB_LSO_TSO_ENABLE;
+ }
/* First, map non-paged data */
len = skb_headlen(skb);
+
+ /* first buffer length */
+ size = hdrlen;
+
offset = 0;
while (len) {
- size = min(len, bp->max_tx_length);
- entry = macb_tx_ring_wrap(tx_head);
+ entry = macb_tx_ring_wrap(bp, tx_head);
tx_skb = &queue->tx_skb[entry];
mapping = dma_map_single(&bp->pdev->dev,
@@@ -1247,6 -1277,8 +1277,8 @@@
offset += size;
count++;
tx_head++;
+
+ size = min(len, bp->max_tx_length);
}
/* Then, map paged data from fragments */
@@@ -1257,7 -1289,7 +1289,7 @@@
offset = 0;
while (len) {
size = min(len, bp->max_tx_length);
- entry = macb_tx_ring_wrap(tx_head);
+ entry = macb_tx_ring_wrap(bp, tx_head);
tx_skb = &queue->tx_skb[entry];
mapping = skb_frag_dma_map(&bp->pdev->dev, frag,
@@@ -1295,14 -1327,29 +1327,29 @@@
* to set the end of TX queue
*/
i = tx_head;
- entry = macb_tx_ring_wrap(i);
+ entry = macb_tx_ring_wrap(bp, i);
ctrl = MACB_BIT(TX_USED);
desc = &queue->tx_ring[entry];
desc->ctrl = ctrl;
+ if (lso_ctrl) {
+ if (lso_ctrl == MACB_LSO_UFO_ENABLE)
+ /* include header and FCS in value given to h/w */
+ mss_mfs = skb_shinfo(skb)->gso_size +
+ skb_transport_offset(skb) +
+ ETH_FCS_LEN;
+ else /* TSO */ {
+ mss_mfs = skb_shinfo(skb)->gso_size;
+ /* TCP Sequence Number Source Select
+ * can be set only for TSO
+ */
+ seq_ctrl = 0;
+ }
+ }
+
do {
i--;
- entry = macb_tx_ring_wrap(i);
+ entry = macb_tx_ring_wrap(bp, i);
tx_skb = &queue->tx_skb[entry];
desc = &queue->tx_ring[entry];
@@@ -1311,9 -1358,19 +1358,19 @@@
ctrl |= MACB_BIT(TX_LAST);
eof = 0;
}
- if (unlikely(entry == (TX_RING_SIZE - 1)))
+ if (unlikely(entry == (bp->tx_ring_size - 1)))
ctrl |= MACB_BIT(TX_WRAP);
+ /* First descriptor is header descriptor */
+ if (i == queue->tx_head) {
+ ctrl |= MACB_BF(TX_LSO, lso_ctrl);
+ ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
+ } else
+ /* Only set MSS/MFS on payload descriptors
+ * (second or later descriptor)
+ */
+ ctrl |= MACB_BF(MSS_MFS, mss_mfs);
+
/* Set TX buffer descriptor */
macb_set_addr(desc, tx_skb->mapping);
/* desc->addr must be visible to hardware before clearing
@@@ -1339,6 -1396,43 +1396,43 @@@ dma_error
return 0;
}
+ static netdev_features_t macb_features_check(struct sk_buff *skb,
+ struct net_device *dev,
+ netdev_features_t features)
+ {
+ unsigned int nr_frags, f;
+ unsigned int hdrlen;
+
+ /* Validate LSO compatibility */
+
+ /* there is only one buffer */
+ if (!skb_is_nonlinear(skb))
+ return features;
+
+ /* length of header */
+ hdrlen = skb_transport_offset(skb);
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ hdrlen += tcp_hdrlen(skb);
+
+ /* For LSO:
+ * When software supplies two or more payload buffers all payload buffers
+ * apart from the last must be a multiple of 8 bytes in size.
+ */
+ if (!IS_ALIGNED(skb_headlen(skb) - hdrlen, MACB_TX_LEN_ALIGN))
+ return features & ~MACB_NETIF_LSO;
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ /* No need to check last fragment */
+ nr_frags--;
+ for (f = 0; f < nr_frags; f++) {
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
+
+ if (!IS_ALIGNED(skb_frag_size(frag), MACB_TX_LEN_ALIGN))
+ return features & ~MACB_NETIF_LSO;
+ }
+ return features;
+ }
+
static inline int macb_clear_csum(struct sk_buff *skb)
{
/* no change for packets without checksum offloading */
@@@ -1363,7 -1457,28 +1457,28 @@@ static int macb_start_xmit(struct sk_bu
struct macb *bp = netdev_priv(dev);
struct macb_queue *queue = &bp->queues[queue_index];
unsigned long flags;
- unsigned int count, nr_frags, frag_size, f;
+ unsigned int desc_cnt, nr_frags, frag_size, f;
+ unsigned int hdrlen;
+ bool is_lso, is_udp = 0;
+
+ is_lso = (skb_shinfo(skb)->gso_size != 0);
+
+ if (is_lso) {
+ is_udp = !!(ip_hdr(skb)->protocol == IPPROTO_UDP);
+
+ /* length of headers */
+ if (is_udp)
+ /* only queue eth + ip headers separately for UDP */
+ hdrlen = skb_transport_offset(skb);
+ else
+ hdrlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ if (skb_headlen(skb) < hdrlen) {
+ netdev_err(bp->dev, "Error - LSO headers fragmented!!!\n");
+ /* if this is required, would need to copy to single buffer */
+ return NETDEV_TX_BUSY;
+ }
+ } else
+ hdrlen = min(skb_headlen(skb), bp->max_tx_length);
#if defined(DEBUG) && defined(VERBOSE_DEBUG)
netdev_vdbg(bp->dev,
@@@ -1378,17 -1493,22 +1493,22 @@@
* socket buffer: skb fragments of jumbo frames may need to be
* split into many buffer descriptors.
*/
- count = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length);
+ if (is_lso && (skb_headlen(skb) > hdrlen))
+ /* extra header descriptor if also payload in first buffer */
+ desc_cnt = DIV_ROUND_UP((skb_headlen(skb) - hdrlen), bp->max_tx_length) + 1;
+ else
+ desc_cnt = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length);
nr_frags = skb_shinfo(skb)->nr_frags;
for (f = 0; f < nr_frags; f++) {
frag_size = skb_frag_size(&skb_shinfo(skb)->frags[f]);
- count += DIV_ROUND_UP(frag_size, bp->max_tx_length);
+ desc_cnt += DIV_ROUND_UP(frag_size, bp->max_tx_length);
}
spin_lock_irqsave(&bp->lock, flags);
/* This is a hard error, log it. */
- if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < count) {
+ if (CIRC_SPACE(queue->tx_head, queue->tx_tail,
+ bp->tx_ring_size) < desc_cnt) {
netif_stop_subqueue(dev, queue_index);
spin_unlock_irqrestore(&bp->lock, flags);
netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n",
@@@ -1402,7 -1522,7 +1522,7 @@@
}
/* Map socket buffer for DMA transfer */
- if (!macb_tx_map(bp, queue, skb)) {
+ if (!macb_tx_map(bp, queue, skb, hdrlen)) {
dev_kfree_skb_any(skb);
goto unlock;
}
@@@ -1414,7 -1534,7 +1534,7 @@@
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
- if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < 1)
+ if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)
netif_stop_subqueue(dev, queue_index);
unlock:
@@@ -1453,7 -1573,7 +1573,7 @@@ static void gem_free_rx_buffers(struct
if (!bp->rx_skbuff)
return;
- for (i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < bp->rx_ring_size; i++) {
skb = bp->rx_skbuff[i];
if (!skb)
@@@ -1478,7 -1598,7 +1598,7 @@@ static void macb_free_rx_buffers(struc
{
if (bp->rx_buffers) {
dma_free_coherent(&bp->pdev->dev,
- RX_RING_SIZE * bp->rx_buffer_size,
+ bp->rx_ring_size * bp->rx_buffer_size,
bp->rx_buffers, bp->rx_buffers_dma);
bp->rx_buffers = NULL;
}
@@@ -1491,7 -1611,7 +1611,7 @@@ static void macb_free_consistent(struc
bp->macbgem_ops.mog_free_rx_buffers(bp);
if (bp->rx_ring) {
- dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES,
+ dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES(bp),
bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
}
@@@ -1500,7 -1620,7 +1620,7 @@@
kfree(queue->tx_skb);
queue->tx_skb = NULL;
if (queue->tx_ring) {
- dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES,
+ dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES(bp),
queue->tx_ring, queue->tx_ring_dma);
queue->tx_ring = NULL;
}
@@@ -1511,14 -1631,14 +1631,14 @@@ static int gem_alloc_rx_buffers(struct
{
int size;
- size = RX_RING_SIZE * sizeof(struct sk_buff *);
+ size = bp->rx_ring_size * sizeof(struct sk_buff *);
bp->rx_skbuff = kzalloc(size, GFP_KERNEL);
if (!bp->rx_skbuff)
return -ENOMEM;
-
- netdev_dbg(bp->dev,
- "Allocated %d RX struct sk_buff entries at %p\n",
- RX_RING_SIZE, bp->rx_skbuff);
+ else
+ netdev_dbg(bp->dev,
+ "Allocated %d RX struct sk_buff entries at %p\n",
+ bp->rx_ring_size, bp->rx_skbuff);
return 0;
}
@@@ -1526,7 -1646,7 +1646,7 @@@ static int macb_alloc_rx_buffers(struc
{
int size;
- size = RX_RING_SIZE * bp->rx_buffer_size;
+ size = bp->rx_ring_size * bp->rx_buffer_size;
bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
&bp->rx_buffers_dma, GFP_KERNEL);
if (!bp->rx_buffers)
@@@ -1545,7 -1665,7 +1665,7 @@@ static int macb_alloc_consistent(struc
int size;
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
- size = TX_RING_BYTES;
+ size = TX_RING_BYTES(bp);
queue->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
&queue->tx_ring_dma,
GFP_KERNEL);
@@@ -1556,13 -1676,13 +1676,13 @@@
q, size, (unsigned long)queue->tx_ring_dma,
queue->tx_ring);
- size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
+ size = bp->tx_ring_size * sizeof(struct macb_tx_skb);
queue->tx_skb = kmalloc(size, GFP_KERNEL);
if (!queue->tx_skb)
goto out_err;
}
- size = RX_RING_BYTES;
+ size = RX_RING_BYTES(bp);
bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
&bp->rx_ring_dma, GFP_KERNEL);
if (!bp->rx_ring)
@@@ -1588,11 -1708,11 +1708,11 @@@ static void gem_init_rings(struct macb
int i;
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
- for (i = 0; i < TX_RING_SIZE; i++) {
- macb_set_addr(&(queue->tx_ring[i]), 0);
+ for (i = 0; i < bp->tx_ring_size; i++) {
+ queue->tx_ring[i].addr = 0;
queue->tx_ring[i].ctrl = MACB_BIT(TX_USED);
}
- queue->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+ queue->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
queue->tx_head = 0;
queue->tx_tail = 0;
}
@@@ -1609,13 -1729,13 +1729,13 @@@ static void macb_init_rings(struct mac
macb_init_rx_ring(bp);
- for (i = 0; i < TX_RING_SIZE; i++) {
+ for (i = 0; i < bp->tx_ring_size; i++) {
bp->queues[0].tx_ring[i].addr = 0;
bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED);
}
bp->queues[0].tx_head = 0;
bp->queues[0].tx_tail = 0;
- bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+ bp->queues[0].tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
bp->rx_tail = 0;
}
@@@ -1986,19 -2106,9 +2106,9 @@@ static int macb_close(struct net_devic
static int macb_change_mtu(struct net_device *dev, int new_mtu)
{
- struct macb *bp = netdev_priv(dev);
- u32 max_mtu;
-
if (netif_running(dev))
return -EBUSY;
- max_mtu = ETH_DATA_LEN;
- if (bp->caps & MACB_CAPS_JUMBO)
- max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
-
- if ((new_mtu > max_mtu) || (new_mtu < GEM_MTU_MIN_SIZE))
- return -EINVAL;
-
dev->mtu = new_mtu;
return 0;
@@@ -2158,8 -2268,8 +2268,8 @@@ static void macb_get_regs(struct net_de
regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
| MACB_GREGS_VERSION;
- tail = macb_tx_ring_wrap(bp->queues[0].tx_tail);
- head = macb_tx_ring_wrap(bp->queues[0].tx_head);
+ tail = macb_tx_ring_wrap(bp, bp->queues[0].tx_tail);
+ head = macb_tx_ring_wrap(bp, bp->queues[0].tx_head);
regs_buff[0] = macb_readl(bp, NCR);
regs_buff[1] = macb_or_gem_readl(bp, NCFGR);
@@@ -2214,6 -2324,56 +2324,56 @@@ static int macb_set_wol(struct net_devi
return 0;
}
+ static void macb_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+ {
+ struct macb *bp = netdev_priv(netdev);
+
+ ring->rx_max_pending = MAX_RX_RING_SIZE;
+ ring->tx_max_pending = MAX_TX_RING_SIZE;
+
+ ring->rx_pending = bp->rx_ring_size;
+ ring->tx_pending = bp->tx_ring_size;
+ }
+
+ static int macb_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+ {
+ struct macb *bp = netdev_priv(netdev);
+ u32 new_rx_size, new_tx_size;
+ unsigned int reset = 0;
+
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ return -EINVAL;
+
+ new_rx_size = clamp_t(u32, ring->rx_pending,
+ MIN_RX_RING_SIZE, MAX_RX_RING_SIZE);
+ new_rx_size = roundup_pow_of_two(new_rx_size);
+
+ new_tx_size = clamp_t(u32, ring->tx_pending,
+ MIN_TX_RING_SIZE, MAX_TX_RING_SIZE);
+ new_tx_size = roundup_pow_of_two(new_tx_size);
+
+ if ((new_tx_size == bp->tx_ring_size) &&
+ (new_rx_size == bp->rx_ring_size)) {
+ /* nothing to do */
+ return 0;
+ }
+
+ if (netif_running(bp->dev)) {
+ reset = 1;
+ macb_close(bp->dev);
+ }
+
+ bp->rx_ring_size = new_rx_size;
+ bp->tx_ring_size = new_tx_size;
+
+ if (reset)
+ macb_open(bp->dev);
+
+ return 0;
+ }
+
static const struct ethtool_ops macb_ethtool_ops = {
.get_regs_len = macb_get_regs_len,
.get_regs = macb_get_regs,
@@@ -2223,6 -2383,8 +2383,8 @@@
.set_wol = macb_set_wol,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_ringparam = macb_get_ringparam,
+ .set_ringparam = macb_set_ringparam,
};
static const struct ethtool_ops gem_ethtool_ops = {
@@@ -2235,6 -2397,8 +2397,8 @@@
.get_sset_count = gem_get_sset_count,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_ringparam = macb_get_ringparam,
+ .set_ringparam = macb_set_ringparam,
};
static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@@ -2298,6 -2462,7 +2462,7 @@@ static const struct net_device_ops macb
.ndo_poll_controller = macb_poll_controller,
#endif
.ndo_set_features = macb_set_features,
+ .ndo_features_check = macb_features_check,
};
/* Configure peripheral capabilities according to device tree
@@@ -2429,6 -2594,9 +2594,9 @@@ static int macb_init(struct platform_de
int err;
u32 val;
+ bp->tx_ring_size = DEFAULT_TX_RING_SIZE;
+ bp->rx_ring_size = DEFAULT_RX_RING_SIZE;
+
/* set the queue register mapping once for all: queue0 has a special
* register mapping but we don't want to test the queue index then
* compute the corresponding register offset at run time.
@@@ -2501,6 -2669,11 +2669,11 @@@
/* Set features */
dev->hw_features = NETIF_F_SG;
+
+ /* Check LSO capability */
+ if (GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))
+ dev->hw_features |= MACB_NETIF_LSO;
+
/* Checksum offload is only available on gem with packet buffer */
if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
@@@ -2673,12 -2846,6 +2846,12 @@@ static int at91ether_start_xmit(struct
lp->skb_length = skb->len;
lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len,
DMA_TO_DEVICE);
+ if (dma_mapping_error(NULL, lp->skb_physaddr)) {
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ netdev_err(dev, "%s: DMA mapping error\n", __func__);
+ return NETDEV_TX_OK;
+ }
/* Set address of the data in the Transmit Address register */
macb_writel(lp, TAR, lp->skb_physaddr);
@@@ -2799,7 -2966,6 +2972,6 @@@ static const struct net_device_ops at91
.ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = macb_ioctl,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = at91ether_poll_controller,
#endif
@@@ -3034,6 -3200,13 +3206,13 @@@ static int macb_probe(struct platform_d
goto err_out_free_netdev;
}
+ /* MTU range: 68 - 1500 or 10240 */
+ dev->min_mtu = GEM_MTU_MIN_SIZE;
+ if (bp->caps & MACB_CAPS_JUMBO)
+ dev->max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
+ else
+ dev->max_mtu = ETH_DATA_LEN;
+
mac = of_get_mac_address(np);
if (mac)
ether_addr_copy(bp->dev->dev_addr, mac);
diff --combined drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 8a37012,b192712..090cbc9
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@@ -69,6 -69,25 +69,6 @@@ static inline u8 nicvf_netdev_qidx(stru
return qidx;
}
-static inline void nicvf_set_rx_frame_cnt(struct nicvf *nic,
- struct sk_buff *skb)
-{
- if (skb->len <= 64)
- nic->drv_stats.rx_frames_64++;
- else if (skb->len <= 127)
- nic->drv_stats.rx_frames_127++;
- else if (skb->len <= 255)
- nic->drv_stats.rx_frames_255++;
- else if (skb->len <= 511)
- nic->drv_stats.rx_frames_511++;
- else if (skb->len <= 1023)
- nic->drv_stats.rx_frames_1023++;
- else if (skb->len <= 1518)
- nic->drv_stats.rx_frames_1518++;
- else
- nic->drv_stats.rx_frames_jumbo++;
-}
-
/* The Cavium ThunderX network controller can *only* be found in SoCs
* containing the ThunderX ARM64 CPU implementation. All accesses to the device
* registers on this platform are implicitly strongly ordered with respect
@@@ -473,6 -492,9 +473,6 @@@ int nicvf_set_real_num_queues(struct ne
static int nicvf_init_resources(struct nicvf *nic)
{
int err;
- union nic_mbx mbx = {};
-
- mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
/* Enable Qset */
nicvf_qset_config(nic, true);
@@@ -485,10 -507,14 +485,10 @@@
return err;
}
- /* Send VF config done msg to PF */
- nicvf_write_to_mbx(nic, &mbx);
-
return 0;
}
static void nicvf_snd_pkt_handler(struct net_device *netdev,
- struct cmp_queue *cq,
struct cqe_send_t *cqe_tx,
int cqe_type, int budget,
unsigned int *tx_pkts, unsigned int *tx_bytes)
@@@ -510,7 -536,7 +510,7 @@@
__func__, cqe_tx->sq_qs, cqe_tx->sq_idx,
cqe_tx->sqe_ptr, hdr->subdesc_cnt);
- nicvf_check_cqe_tx_errs(nic, cq, cqe_tx);
+ nicvf_check_cqe_tx_errs(nic, cqe_tx);
skb = (struct sk_buff *)sq->skbuff[cqe_tx->sqe_ptr];
if (skb) {
/* Check for dummy descriptor used for HW TSO offload on 88xx */
@@@ -604,6 -630,8 +604,6 @@@ static void nicvf_rcv_pkt_handler(struc
return;
}
- nicvf_set_rx_frame_cnt(nic, skb);
-
nicvf_set_rxhash(netdev, cqe_rx, skb);
skb_record_rx_queue(skb, rq_idx);
@@@ -675,7 -703,7 +675,7 @@@ loop
work_done++;
break;
case CQE_TYPE_SEND:
- nicvf_snd_pkt_handler(netdev, cq,
+ nicvf_snd_pkt_handler(netdev,
(void *)cq_desc, CQE_TYPE_SEND,
budget, &tx_pkts, &tx_bytes);
tx_done++;
@@@ -712,7 -740,7 +712,7 @@@ done
nic = nic->pnicvf;
if (netif_tx_queue_stopped(txq) && netif_carrier_ok(netdev)) {
netif_tx_start_queue(txq);
- nic->drv_stats.txq_wake++;
+ this_cpu_inc(nic->drv_stats->txq_wake);
if (netif_msg_tx_err(nic))
netdev_warn(netdev,
"%s: Transmit queue wakeup SQ%d\n",
@@@ -1056,7 -1084,7 +1056,7 @@@ static netdev_tx_t nicvf_xmit(struct sk
if (!netif_tx_queue_stopped(txq) && !nicvf_sq_append_skb(nic, skb)) {
netif_tx_stop_queue(txq);
- nic->drv_stats.txq_stop++;
+ this_cpu_inc(nic->drv_stats->txq_stop);
if (netif_msg_tx_err(nic))
netdev_warn(netdev,
"%s: Transmit ring full, stopping SQ%d\n",
@@@ -1161,24 -1189,14 +1161,24 @@@ int nicvf_stop(struct net_device *netde
return 0;
}
+static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
+{
+ union nic_mbx mbx = {};
+
+ mbx.frs.msg = NIC_MBOX_MSG_SET_MAX_FRS;
+ mbx.frs.max_frs = mtu;
+ mbx.frs.vf_id = nic->vf_id;
+
+ return nicvf_send_msg_to_pf(nic, &mbx);
+}
+
int nicvf_open(struct net_device *netdev)
{
- int err, qidx;
+ int cpu, err, qidx;
struct nicvf *nic = netdev_priv(netdev);
struct queue_set *qs = nic->qs;
struct nicvf_cq_poll *cq_poll = NULL;
-
- nic->mtu = netdev->mtu;
+ union nic_mbx mbx = {};
netif_carrier_off(netdev);
@@@ -1230,17 -1248,9 +1230,17 @@@
if (nic->sqs_mode)
nicvf_get_primary_vf_struct(nic);
- /* Configure receive side scaling */
- if (!nic->sqs_mode)
+ /* Configure receive side scaling and MTU */
+ if (!nic->sqs_mode) {
nicvf_rss_init(nic);
+ if (nicvf_update_hw_max_frs(nic, netdev->mtu))
+ goto cleanup;
+
+ /* Clear percpu stats */
+ for_each_possible_cpu(cpu)
+ memset(per_cpu_ptr(nic->drv_stats, cpu), 0,
+ sizeof(struct nicvf_drv_stats));
+ }
err = nicvf_register_interrupts(nic);
if (err)
@@@ -1266,9 -1276,8 +1266,9 @@@
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++)
nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
- nic->drv_stats.txq_stop = 0;
- nic->drv_stats.txq_wake = 0;
+ /* Send VF config done msg to PF */
+ mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
+ nicvf_write_to_mbx(nic, &mbx);
return 0;
cleanup:
@@@ -1288,23 -1297,25 +1288,17 @@@ napi_del
return err;
}
-static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
-{
- union nic_mbx mbx = {};
-
- mbx.frs.msg = NIC_MBOX_MSG_SET_MAX_FRS;
- mbx.frs.max_frs = mtu;
- mbx.frs.vf_id = nic->vf_id;
-
- return nicvf_send_msg_to_pf(nic, &mbx);
-}
-
static int nicvf_change_mtu(struct net_device *netdev, int new_mtu)
{
struct nicvf *nic = netdev_priv(netdev);
- if (new_mtu > NIC_HW_MAX_FRS)
- return -EINVAL;
-
- if (new_mtu < NIC_HW_MIN_FRS)
- return -EINVAL;
-
+ netdev->mtu = new_mtu;
+
+ if (!netif_running(netdev))
+ return 0;
+
if (nicvf_update_hw_max_frs(nic, new_mtu))
return -EINVAL;
- netdev->mtu = new_mtu;
- nic->mtu = new_mtu;
return 0;
}
@@@ -1362,10 -1373,9 +1356,10 @@@ void nicvf_update_lmac_stats(struct nic
void nicvf_update_stats(struct nicvf *nic)
{
- int qidx;
+ int qidx, cpu;
+ u64 tmp_stats = 0;
struct nicvf_hw_stats *stats = &nic->hw_stats;
- struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
+ struct nicvf_drv_stats *drv_stats;
struct queue_set *qs = nic->qs;
#define GET_RX_STATS(reg) \
@@@ -1388,33 -1398,21 +1382,33 @@@
stats->rx_drop_l3_bcast = GET_RX_STATS(RX_DRP_L3BCAST);
stats->rx_drop_l3_mcast = GET_RX_STATS(RX_DRP_L3MCAST);
- stats->tx_bytes_ok = GET_TX_STATS(TX_OCTS);
- stats->tx_ucast_frames_ok = GET_TX_STATS(TX_UCAST);
- stats->tx_bcast_frames_ok = GET_TX_STATS(TX_BCAST);
- stats->tx_mcast_frames_ok = GET_TX_STATS(TX_MCAST);
+ stats->tx_bytes = GET_TX_STATS(TX_OCTS);
+ stats->tx_ucast_frames = GET_TX_STATS(TX_UCAST);
+ stats->tx_bcast_frames = GET_TX_STATS(TX_BCAST);
+ stats->tx_mcast_frames = GET_TX_STATS(TX_MCAST);
stats->tx_drops = GET_TX_STATS(TX_DROP);
- drv_stats->tx_frames_ok = stats->tx_ucast_frames_ok +
- stats->tx_bcast_frames_ok +
- stats->tx_mcast_frames_ok;
- drv_stats->rx_frames_ok = stats->rx_ucast_frames +
- stats->rx_bcast_frames +
- stats->rx_mcast_frames;
- drv_stats->rx_drops = stats->rx_drop_red +
- stats->rx_drop_overrun;
- drv_stats->tx_drops = stats->tx_drops;
+ /* On T88 pass 2.0, the dummy SQE added for TSO notification
+ * via CQE has 'dont_send' set. Hence HW drops the pkt pointed
+ * pointed by dummy SQE and results in tx_drops counter being
+ * incremented. Subtracting it from tx_tso counter will give
+ * exact tx_drops counter.
+ */
+ if (nic->t88 && nic->hw_tso) {
+ for_each_possible_cpu(cpu) {
+ drv_stats = per_cpu_ptr(nic->drv_stats, cpu);
+ tmp_stats += drv_stats->tx_tso;
+ }
+ stats->tx_drops = tmp_stats - stats->tx_drops;
+ }
+ stats->tx_frames = stats->tx_ucast_frames +
+ stats->tx_bcast_frames +
+ stats->tx_mcast_frames;
+ stats->rx_frames = stats->rx_ucast_frames +
+ stats->rx_bcast_frames +
+ stats->rx_mcast_frames;
+ stats->rx_drops = stats->rx_drop_red +
+ stats->rx_drop_overrun;
/* Update RQ and SQ stats */
for (qidx = 0; qidx < qs->rq_cnt; qidx++)
@@@ -1428,17 -1426,18 +1422,17 @@@ static struct rtnl_link_stats64 *nicvf_
{
struct nicvf *nic = netdev_priv(netdev);
struct nicvf_hw_stats *hw_stats = &nic->hw_stats;
- struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
nicvf_update_stats(nic);
stats->rx_bytes = hw_stats->rx_bytes;
- stats->rx_packets = drv_stats->rx_frames_ok;
- stats->rx_dropped = drv_stats->rx_drops;
+ stats->rx_packets = hw_stats->rx_frames;
+ stats->rx_dropped = hw_stats->rx_drops;
stats->multicast = hw_stats->rx_mcast_frames;
- stats->tx_bytes = hw_stats->tx_bytes_ok;
- stats->tx_packets = drv_stats->tx_frames_ok;
- stats->tx_dropped = drv_stats->tx_drops;
+ stats->tx_bytes = hw_stats->tx_bytes;
+ stats->tx_packets = hw_stats->tx_frames;
+ stats->tx_dropped = hw_stats->tx_drops;
return stats;
}
@@@ -1451,7 -1450,7 +1445,7 @@@ static void nicvf_tx_timeout(struct net
netdev_warn(dev, "%s: Transmit timed out, resetting\n",
dev->name);
- nic->drv_stats.tx_timeout++;
+ this_cpu_inc(nic->drv_stats->tx_timeout);
schedule_work(&nic->reset_task);
}
@@@ -1585,12 -1584,6 +1579,12 @@@ static int nicvf_probe(struct pci_dev *
goto err_free_netdev;
}
+ nic->drv_stats = netdev_alloc_pcpu_stats(struct nicvf_drv_stats);
+ if (!nic->drv_stats) {
+ err = -ENOMEM;
+ goto err_free_netdev;
+ }
+
err = nicvf_set_qset_resources(nic);
if (err)
goto err_free_netdev;
@@@ -1631,6 -1624,10 +1625,10 @@@
netdev->netdev_ops = &nicvf_netdev_ops;
netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
+ /* MTU range: 64 - 9200 */
+ netdev->min_mtu = NIC_HW_MIN_FRS;
+ netdev->max_mtu = NIC_HW_MAX_FRS;
+
INIT_WORK(&nic->reset_task, nicvf_reset_task);
err = register_netdev(netdev);
@@@ -1649,8 -1646,6 +1647,8 @@@ err_unregister_interrupts
nicvf_unregister_interrupts(nic);
err_free_netdev:
pci_set_drvdata(pdev, NULL);
+ if (nic->drv_stats)
+ free_percpu(nic->drv_stats);
free_netdev(netdev);
err_release_regions:
pci_release_regions(pdev);
@@@ -1678,8 -1673,6 +1676,8 @@@ static void nicvf_remove(struct pci_de
unregister_netdev(pnetdev);
nicvf_unregister_interrupts(nic);
pci_set_drvdata(pdev, NULL);
+ if (nic->drv_stats)
+ free_percpu(nic->drv_stats);
free_netdev(netdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --combined drivers/net/ethernet/chelsio/cxgb4/sge.c
index e19a0ca,b7d0753..9f60647
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@@ -377,8 -377,8 +377,8 @@@ unmap: dma_unmap_page(dev, be64_to_cp
* Reclaims Tx descriptors from an SGE Tx queue and frees the associated
* Tx buffers. Called with the Tx queue lock held.
*/
- static void free_tx_desc(struct adapter *adap, struct sge_txq *q,
- unsigned int n, bool unmap)
+ void free_tx_desc(struct adapter *adap, struct sge_txq *q,
+ unsigned int n, bool unmap)
{
struct tx_sw_desc *d;
unsigned int cidx = q->cidx;
@@@ -1543,7 -1543,7 +1543,7 @@@ static inline unsigned int calc_tx_flit
* inability to map packets. A periodic timer attempts to restart
* queues so marked.
*/
- static void txq_stop_maperr(struct sge_ofld_txq *q)
+ static void txq_stop_maperr(struct sge_uld_txq *q)
{
q->mapping_err++;
q->q.stops++;
@@@ -1559,7 -1559,7 +1559,7 @@@
* Stops an offload Tx queue that has become full and modifies the packet
* being written to request a wakeup.
*/
- static void ofldtxq_stop(struct sge_ofld_txq *q, struct sk_buff *skb)
+ static void ofldtxq_stop(struct sge_uld_txq *q, struct sk_buff *skb)
{
struct fw_wr_hdr *wr = (struct fw_wr_hdr *)skb->data;
@@@ -1586,7 -1586,7 +1586,7 @@@
* boolean "service_ofldq_running" to make sure that only one instance
* is ever running at a time ...
*/
- static void service_ofldq(struct sge_ofld_txq *q)
+ static void service_ofldq(struct sge_uld_txq *q)
{
u64 *pos, *before, *end;
int credits;
@@@ -1706,7 -1706,7 +1706,7 @@@
*
* Send an offload packet through an SGE offload queue.
*/
- static int ofld_xmit(struct sge_ofld_txq *q, struct sk_buff *skb)
+ static int ofld_xmit(struct sge_uld_txq *q, struct sk_buff *skb)
{
skb->priority = calc_tx_flits_ofld(skb); /* save for restart */
spin_lock(&q->sendq.lock);
@@@ -1735,7 -1735,7 +1735,7 @@@
*/
static void restart_ofldq(unsigned long data)
{
- struct sge_ofld_txq *q = (struct sge_ofld_txq *)data;
+ struct sge_uld_txq *q = (struct sge_uld_txq *)data;
spin_lock(&q->sendq.lock);
q->full = 0; /* the queue actually is completely empty now */
@@@ -1767,17 -1767,23 +1767,23 @@@ static inline unsigned int is_ctrl_pkt(
return skb->queue_mapping & 1;
}
- static inline int ofld_send(struct adapter *adap, struct sk_buff *skb)
+ static inline int uld_send(struct adapter *adap, struct sk_buff *skb,
+ unsigned int tx_uld_type)
{
+ struct sge_uld_txq_info *txq_info;
+ struct sge_uld_txq *txq;
unsigned int idx = skb_txq(skb);
+ txq_info = adap->sge.uld_txq_info[tx_uld_type];
+ txq = &txq_info->uldtxq[idx];
+
if (unlikely(is_ctrl_pkt(skb))) {
/* Single ctrl queue is a requirement for LE workaround path */
if (adap->tids.nsftids)
idx = 0;
return ctrl_xmit(&adap->sge.ctrlq[idx], skb);
}
- return ofld_xmit(&adap->sge.ofldtxq[idx], skb);
+ return ofld_xmit(txq, skb);
}
/**
@@@ -1794,7 -1800,7 +1800,7 @@@ int t4_ofld_send(struct adapter *adap,
int ret;
local_bh_disable();
- ret = ofld_send(adap, skb);
+ ret = uld_send(adap, skb, CXGB4_TX_OFLD);
local_bh_enable();
return ret;
}
@@@ -1813,6 -1819,39 +1819,39 @@@ int cxgb4_ofld_send(struct net_device *
}
EXPORT_SYMBOL(cxgb4_ofld_send);
+ /**
+ * t4_crypto_send - send crypto packet
+ * @adap: the adapter
+ * @skb: the packet
+ *
+ * Sends crypto packet. We use the packet queue_mapping to select the
+ * appropriate Tx queue as follows: bit 0 indicates whether the packet
+ * should be sent as regular or control, bits 1-15 select the queue.
+ */
+ static int t4_crypto_send(struct adapter *adap, struct sk_buff *skb)
+ {
+ int ret;
+
+ local_bh_disable();
+ ret = uld_send(adap, skb, CXGB4_TX_CRYPTO);
+ local_bh_enable();
+ return ret;
+ }
+
+ /**
+ * cxgb4_crypto_send - send crypto packet
+ * @dev: the net device
+ * @skb: the packet
+ *
+ * Sends crypto packet. This is an exported version of @t4_crypto_send,
+ * intended for ULDs.
+ */
+ int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb)
+ {
+ return t4_crypto_send(netdev2adap(dev), skb);
+ }
+ EXPORT_SYMBOL(cxgb4_crypto_send);
+
static inline void copy_frags(struct sk_buff *skb,
const struct pkt_gl *gl, unsigned int offset)
{
@@@ -2479,7 -2518,7 +2518,7 @@@ static void sge_tx_timer_cb(unsigned lo
for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++)
for (m = s->txq_maperr[i]; m; m &= m - 1) {
unsigned long id = __ffs(m) + i * BITS_PER_LONG;
- struct sge_ofld_txq *txq = s->egr_map[id];
+ struct sge_uld_txq *txq = s->egr_map[id];
clear_bit(id, s->txq_maperr);
tasklet_schedule(&txq->qresume_tsk);
@@@ -2799,6 -2838,7 +2838,7 @@@ int t4_sge_alloc_eth_txq(struct adapte
return ret;
}
+ txq->q.q_type = CXGB4_TXQ_ETH;
init_txq(adap, &txq->q, FW_EQ_ETH_CMD_EQID_G(ntohl(c.eqid_pkd)));
txq->txq = netdevq;
txq->tso = txq->tx_cso = txq->vlan_ins = 0;
@@@ -2852,6 -2892,7 +2892,7 @@@ int t4_sge_alloc_ctrl_txq(struct adapte
return ret;
}
+ txq->q.q_type = CXGB4_TXQ_CTRL;
init_txq(adap, &txq->q, FW_EQ_CTRL_CMD_EQID_G(ntohl(c.cmpliqid_eqid)));
txq->adap = adap;
skb_queue_head_init(&txq->sendq);
@@@ -2872,13 -2913,15 +2913,15 @@@ int t4_sge_mod_ctrl_txq(struct adapter
return t4_set_params(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val);
}
- int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
- struct net_device *dev, unsigned int iqid)
+ int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
+ struct net_device *dev, unsigned int iqid,
+ unsigned int uld_type)
{
int ret, nentries;
struct fw_eq_ofld_cmd c;
struct sge *s = &adap->sge;
struct port_info *pi = netdev_priv(dev);
+ int cmd = FW_EQ_OFLD_CMD;
/* Add status entries */
nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
@@@ -2891,7 -2934,9 +2934,9 @@@
return -ENOMEM;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST_F |
+ if (unlikely(uld_type == CXGB4_TX_CRYPTO))
+ cmd = FW_EQ_CTRL_CMD;
+ c.op_to_vfn = htonl(FW_CMD_OP_V(cmd) | FW_CMD_REQUEST_F |
FW_CMD_WRITE_F | FW_CMD_EXEC_F |
FW_EQ_OFLD_CMD_PFN_V(adap->pf) |
FW_EQ_OFLD_CMD_VFN_V(0));
@@@ -2919,6 -2964,7 +2964,7 @@@
return ret;
}
+ txq->q.q_type = CXGB4_TXQ_ULD;
init_txq(adap, &txq->q, FW_EQ_OFLD_CMD_EQID_G(ntohl(c.eqid_pkd)));
txq->adap = adap;
skb_queue_head_init(&txq->sendq);
@@@ -2928,7 -2974,7 +2974,7 @@@
return 0;
}
- static void free_txq(struct adapter *adap, struct sge_txq *q)
+ void free_txq(struct adapter *adap, struct sge_txq *q)
{
struct sge *s = &adap->sge;
@@@ -2951,6 -2997,7 +2997,6 @@@ void free_rspq_fl(struct adapter *adap
rq->cntxt_id, fl_id, 0xffff);
dma_free_coherent(adap->pdev_dev, (rq->size + 1) * rq->iqe_len,
rq->desc, rq->phys_addr);
- napi_hash_del(&rq->napi);
netif_napi_del(&rq->napi);
rq->netdev = NULL;
rq->cntxt_id = rq->abs_id = 0;
@@@ -3025,21 -3072,6 +3071,6 @@@ void t4_free_sge_resources(struct adapt
}
}
- /* clean up offload Tx queues */
- for (i = 0; i < ARRAY_SIZE(adap->sge.ofldtxq); i++) {
- struct sge_ofld_txq *q = &adap->sge.ofldtxq[i];
-
- if (q->q.desc) {
- tasklet_kill(&q->qresume_tsk);
- t4_ofld_eq_free(adap, adap->mbox, adap->pf, 0,
- q->q.cntxt_id);
- free_tx_desc(adap, &q->q, q->q.in_use, false);
- kfree(q->q.sdesc);
- __skb_queue_purge(&q->sendq);
- free_txq(adap, &q->q);
- }
- }
-
/* clean up control Tx queues */
for (i = 0; i < ARRAY_SIZE(adap->sge.ctrlq); i++) {
struct sge_ctrl_txq *cq = &adap->sge.ctrlq[i];
@@@ -3092,12 -3124,34 +3123,34 @@@ void t4_sge_stop(struct adapter *adap
if (s->tx_timer.function)
del_timer_sync(&s->tx_timer);
- for (i = 0; i < ARRAY_SIZE(s->ofldtxq); i++) {
- struct sge_ofld_txq *q = &s->ofldtxq[i];
+ if (is_offload(adap)) {
+ struct sge_uld_txq_info *txq_info;
+
+ txq_info = adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+ if (txq_info) {
+ struct sge_uld_txq *txq = txq_info->uldtxq;
- if (q->q.desc)
- tasklet_kill(&q->qresume_tsk);
+ for_each_ofldtxq(&adap->sge, i) {
+ if (txq->q.desc)
+ tasklet_kill(&txq->qresume_tsk);
+ }
+ }
}
+
+ if (is_pci_uld(adap)) {
+ struct sge_uld_txq_info *txq_info;
+
+ txq_info = adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
+ if (txq_info) {
+ struct sge_uld_txq *txq = txq_info->uldtxq;
+
+ for_each_ofldtxq(&adap->sge, i) {
+ if (txq->q.desc)
+ tasklet_kill(&txq->qresume_tsk);
+ }
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++) {
struct sge_ctrl_txq *cq = &s->ctrlq[i];
diff --combined drivers/net/ethernet/emulex/benet/be_main.c
index 93aa293,3f6152c..7e1633b
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@@ -1406,23 -1406,6 +1406,6 @@@ drop
return NETDEV_TX_OK;
}
- static int be_change_mtu(struct net_device *netdev, int new_mtu)
- {
- struct be_adapter *adapter = netdev_priv(netdev);
- struct device *dev = &adapter->pdev->dev;
-
- if (new_mtu < BE_MIN_MTU || new_mtu > BE_MAX_MTU) {
- dev_info(dev, "MTU must be between %d and %d bytes\n",
- BE_MIN_MTU, BE_MAX_MTU);
- return -EINVAL;
- }
-
- dev_info(dev, "MTU changed from %d to %d bytes\n",
- netdev->mtu, new_mtu);
- netdev->mtu = new_mtu;
- return 0;
- }
-
static inline bool be_in_all_promisc(struct be_adapter *adapter)
{
return (adapter->if_flags & BE_IF_FLAGS_ALL_PROMISCUOUS) ==
@@@ -2813,6 -2796,7 +2796,6 @@@ static void be_evt_queues_destroy(struc
if (eqo->q.created) {
be_eq_clean(eqo);
be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ);
- napi_hash_del(&eqo->napi);
netif_napi_del(&eqo->napi);
free_cpumask_var(eqo->affinity_mask);
}
@@@ -5215,7 -5199,6 +5198,6 @@@ static const struct net_device_ops be_n
.ndo_start_xmit = be_xmit,
.ndo_set_rx_mode = be_set_rx_mode,
.ndo_set_mac_address = be_mac_addr_set,
- .ndo_change_mtu = be_change_mtu,
.ndo_get_stats64 = be_get_stats64,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = be_vlan_add_vid,
@@@ -5265,6 -5248,10 +5247,10 @@@ static void be_netdev_init(struct net_d
netdev->netdev_ops = &be_netdev_ops;
netdev->ethtool_ops = &be_ethtool_ops;
+
+ /* MTU range: 256 - 9000 */
+ netdev->min_mtu = BE_MIN_MTU;
+ netdev->max_mtu = BE_MAX_MTU;
}
static void be_cleanup(struct be_adapter *adapter)
diff --combined drivers/net/ethernet/marvell/sky2.c
index 941c8e2,aa60f4d..b60ad0e
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@@ -2398,16 -2398,6 +2398,6 @@@ static int sky2_change_mtu(struct net_d
u16 ctl, mode;
u32 imask;
- /* MTU size outside the spec */
- if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
- return -EINVAL;
-
- /* MTU > 1500 on yukon FE and FE+ not allowed */
- if (new_mtu > ETH_DATA_LEN &&
- (hw->chip_id == CHIP_ID_YUKON_FE ||
- hw->chip_id == CHIP_ID_YUKON_FE_P))
- return -EINVAL;
-
if (!netif_running(dev)) {
dev->mtu = new_mtu;
netdev_update_features(dev);
@@@ -4808,6 -4798,14 +4798,14 @@@ static struct net_device *sky2_init_net
dev->features |= dev->hw_features;
+ /* MTU range: 60 - 1500 or 9000 */
+ dev->min_mtu = ETH_ZLEN;
+ if (hw->chip_id == CHIP_ID_YUKON_FE ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
+ dev->max_mtu = ETH_DATA_LEN;
+ else
+ dev->max_mtu = ETH_JUMBO_MTU;
+
/* try to get mac address in the following order:
* 1) from device tree data
* 2) from internal registers set by bootloader
@@@ -5220,19 -5218,6 +5218,19 @@@ static SIMPLE_DEV_PM_OPS(sky2_pm_ops, s
static void sky2_shutdown(struct pci_dev *pdev)
{
+ struct sky2_hw *hw = pci_get_drvdata(pdev);
+ int port;
+
+ for (port = 0; port < hw->ports; port++) {
+ struct net_device *ndev = hw->dev[port];
+
+ rtnl_lock();
+ if (netif_running(ndev)) {
+ dev_close(ndev);
+ netif_device_detach(ndev);
+ }
+ rtnl_unlock();
+ }
sky2_suspend(&pdev->dev);
pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
pci_set_power_state(pdev, PCI_D3hot);
diff --combined drivers/net/ethernet/smsc/smsc911x.c
index 65fca9c,be09573..9179cb4
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@@ -1956,11 -1956,6 +1956,6 @@@ static void smsc911x_ethtool_getdrvinfo
sizeof(info->bus_info));
}
- static int smsc911x_ethtool_nwayreset(struct net_device *dev)
- {
- return phy_start_aneg(dev->phydev);
- }
-
static u32 smsc911x_ethtool_getmsglevel(struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
@@@ -2132,7 -2127,7 +2127,7 @@@ static int smsc911x_ethtool_set_eeprom(
static const struct ethtool_ops smsc911x_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_drvinfo = smsc911x_ethtool_getdrvinfo,
- .nway_reset = smsc911x_ethtool_nwayreset,
+ .nway_reset = phy_ethtool_nway_reset,
.get_msglevel = smsc911x_ethtool_getmsglevel,
.set_msglevel = smsc911x_ethtool_setmsglevel,
.get_regs_len = smsc911x_ethtool_getregslen,
@@@ -2152,7 -2147,6 +2147,6 @@@ static const struct net_device_ops smsc
.ndo_get_stats = smsc911x_get_stats,
.ndo_set_rx_mode = smsc911x_set_multicast_list,
.ndo_do_ioctl = smsc911x_do_ioctl,
- .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = smsc911x_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@@ -2584,9 -2578,6 +2578,9 @@@ static int smsc911x_suspend(struct devi
PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ |
PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_);
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+
return 0;
}
@@@ -2596,9 -2587,6 +2590,9 @@@ static int smsc911x_resume(struct devic
struct smsc911x_data *pdata = netdev_priv(ndev);
unsigned int to = 100;
+ pm_runtime_enable(dev);
+ pm_runtime_resume(dev);
+
/* Note 3.11 from the datasheet:
* "When the LAN9220 is in a power saving state, a write of any
* data to the BYTE_TEST register will wake-up the device."
diff --combined drivers/net/ethernet/stmicro/stmmac/Kconfig
index 4b78168,6e9fcc3..d37e32d
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@@ -69,6 -69,17 +69,17 @@@ config DWMAC_MESO
the stmmac device driver. This driver is used for Meson6,
Meson8, Meson8b and GXBB SoCs.
+ config DWMAC_OXNAS
+ tristate "Oxford Semiconductor OXNAS dwmac support"
+ default ARCH_OXNAS
+ depends on OF && COMMON_CLK && (ARCH_OXNAS || COMPILE_TEST)
+ select MFD_SYSCON
+ help
+ Support for Ethernet controller on Oxford Semiconductor OXNAS SoCs.
+
+ This selects the Oxford Semiconductor OXNASSoC glue layer support for
+ the stmmac device driver. This driver is used for OX820.
+
config DWMAC_ROCKCHIP
tristate "Rockchip dwmac support"
default ARCH_ROCKCHIP
@@@ -107,7 -118,7 +118,7 @@@ config DWMAC_ST
config DWMAC_STM32
tristate "STM32 DWMAC support"
default ARCH_STM32
- depends on OF && HAS_IOMEM
+ depends on OF && HAS_IOMEM && (ARCH_STM32 || COMPILE_TEST)
select MFD_SYSCON
---help---
Support for ethernet controller on STM32 SOCs.
diff --combined drivers/net/ethernet/stmicro/stmmac/descs.h
index e3c86d4,4000af4..faeeef7
--- a/drivers/net/ethernet/stmicro/stmmac/descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h
@@@ -87,7 -87,7 +87,7 @@@
#define TDES0_ERROR_SUMMARY BIT(15)
#define TDES0_IP_HEADER_ERROR BIT(16)
#define TDES0_TIME_STAMP_STATUS BIT(17)
- #define TDES0_OWN BIT(31)
+ #define TDES0_OWN ((u32)BIT(31)) /* silence sparse */
/* TDES1 */
#define TDES1_BUFFER1_SIZE_MASK GENMASK(10, 0)
#define TDES1_BUFFER2_SIZE_MASK GENMASK(21, 11)
@@@ -130,7 -130,7 +130,7 @@@
#define ETDES0_FIRST_SEGMENT BIT(28)
#define ETDES0_LAST_SEGMENT BIT(29)
#define ETDES0_INTERRUPT BIT(30)
- #define ETDES0_OWN BIT(31)
+ #define ETDES0_OWN ((u32)BIT(31)) /* silence sparse */
/* TDES1 */
#define ETDES1_BUFFER1_SIZE_MASK GENMASK(12, 0)
#define ETDES1_BUFFER2_SIZE_MASK GENMASK(28, 16)
@@@ -155,34 -155,30 +155,34 @@@
#define ERDES4_L3_L4_FILT_NO_MATCH_MASK GENMASK(27, 26)
/* Extended RDES4 message type definitions */
-#define RDES_EXT_NO_PTP 0
-#define RDES_EXT_SYNC 1
-#define RDES_EXT_FOLLOW_UP 2
-#define RDES_EXT_DELAY_REQ 3
-#define RDES_EXT_DELAY_RESP 4
-#define RDES_EXT_PDELAY_REQ 5
-#define RDES_EXT_PDELAY_RESP 6
-#define RDES_EXT_PDELAY_FOLLOW_UP 7
+#define RDES_EXT_NO_PTP 0x0
+#define RDES_EXT_SYNC 0x1
+#define RDES_EXT_FOLLOW_UP 0x2
+#define RDES_EXT_DELAY_REQ 0x3
+#define RDES_EXT_DELAY_RESP 0x4
+#define RDES_EXT_PDELAY_REQ 0x5
+#define RDES_EXT_PDELAY_RESP 0x6
+#define RDES_EXT_PDELAY_FOLLOW_UP 0x7
+#define RDES_PTP_ANNOUNCE 0x8
+#define RDES_PTP_MANAGEMENT 0x9
+#define RDES_PTP_SIGNALING 0xa
+#define RDES_PTP_PKT_RESERVED_TYPE 0xf
/* Basic descriptor structure for normal and alternate descriptors */
struct dma_desc {
- unsigned int des0;
- unsigned int des1;
- unsigned int des2;
- unsigned int des3;
+ __le32 des0;
+ __le32 des1;
+ __le32 des2;
+ __le32 des3;
};
/* Extended descriptor structure (e.g. >= databook 3.50a) */
struct dma_extended_desc {
struct dma_desc basic; /* Basic descriptors */
- unsigned int des4; /* Extended Status */
- unsigned int des5; /* Reserved */
- unsigned int des6; /* Tx/Rx Timestamp Low */
- unsigned int des7; /* Tx/Rx Timestamp High */
+ __le32 des4; /* Extended Status */
+ __le32 des5; /* Reserved */
+ __le32 des6; /* Tx/Rx Timestamp Low */
+ __le32 des7; /* Tx/Rx Timestamp High */
};
/* Transmit checksum insertion control */
diff --combined drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index a601f8d,bec72d3..41c91c9
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@@ -23,7 -23,7 +23,7 @@@ static int dwmac4_wrback_get_tx_status(
unsigned int tdes3;
int ret = tx_done;
- tdes3 = p->des3;
+ tdes3 = le32_to_cpu(p->des3);
/* Get tx owner first */
if (unlikely(tdes3 & TDES3_OWN))
@@@ -77,9 -77,9 +77,9 @@@ static int dwmac4_wrback_get_rx_status(
struct dma_desc *p)
{
struct net_device_stats *stats = (struct net_device_stats *)data;
- unsigned int rdes1 = p->des1;
- unsigned int rdes2 = p->des2;
- unsigned int rdes3 = p->des3;
+ unsigned int rdes1 = le32_to_cpu(p->des1);
+ unsigned int rdes2 = le32_to_cpu(p->des2);
+ unsigned int rdes3 = le32_to_cpu(p->des3);
int message_type;
int ret = good_frame;
@@@ -123,29 -123,22 +123,29 @@@
x->ipv4_pkt_rcvd++;
if (rdes1 & RDES1_IPV6_HEADER)
x->ipv6_pkt_rcvd++;
- if (message_type == RDES_EXT_SYNC)
- x->rx_msg_type_sync++;
+
+ if (message_type == RDES_EXT_NO_PTP)
+ x->no_ptp_rx_msg_type_ext++;
+ else if (message_type == RDES_EXT_SYNC)
+ x->ptp_rx_msg_type_sync++;
else if (message_type == RDES_EXT_FOLLOW_UP)
- x->rx_msg_type_follow_up++;
+ x->ptp_rx_msg_type_follow_up++;
else if (message_type == RDES_EXT_DELAY_REQ)
- x->rx_msg_type_delay_req++;
+ x->ptp_rx_msg_type_delay_req++;
else if (message_type == RDES_EXT_DELAY_RESP)
- x->rx_msg_type_delay_resp++;
+ x->ptp_rx_msg_type_delay_resp++;
else if (message_type == RDES_EXT_PDELAY_REQ)
- x->rx_msg_type_pdelay_req++;
+ x->ptp_rx_msg_type_pdelay_req++;
else if (message_type == RDES_EXT_PDELAY_RESP)
- x->rx_msg_type_pdelay_resp++;
+ x->ptp_rx_msg_type_pdelay_resp++;
else if (message_type == RDES_EXT_PDELAY_FOLLOW_UP)
- x->rx_msg_type_pdelay_follow_up++;
- else
- x->rx_msg_type_ext_no_ptp++;
+ x->ptp_rx_msg_type_pdelay_follow_up++;
+ else if (message_type == RDES_PTP_ANNOUNCE)
+ x->ptp_rx_msg_type_announce++;
+ else if (message_type == RDES_PTP_MANAGEMENT)
+ x->ptp_rx_msg_type_management++;
+ else if (message_type == RDES_PTP_PKT_RESERVED_TYPE)
+ x->ptp_rx_msg_pkt_reserved_type++;
if (rdes1 & RDES1_PTP_PACKET_TYPE)
x->ptp_frame_type++;
@@@ -176,121 -169,76 +176,122 @@@
static int dwmac4_rd_get_tx_len(struct dma_desc *p)
{
- return (p->des2 & TDES2_BUFFER1_SIZE_MASK);
+ return (le32_to_cpu(p->des2) & TDES2_BUFFER1_SIZE_MASK);
}
static int dwmac4_get_tx_owner(struct dma_desc *p)
{
- return (p->des3 & TDES3_OWN) >> TDES3_OWN_SHIFT;
+ return (le32_to_cpu(p->des3) & TDES3_OWN) >> TDES3_OWN_SHIFT;
}
static void dwmac4_set_tx_owner(struct dma_desc *p)
{
- p->des3 |= TDES3_OWN;
+ p->des3 |= cpu_to_le32(TDES3_OWN);
}
static void dwmac4_set_rx_owner(struct dma_desc *p)
{
- p->des3 |= RDES3_OWN;
+ p->des3 |= cpu_to_le32(RDES3_OWN);
}
static int dwmac4_get_tx_ls(struct dma_desc *p)
{
- return (p->des3 & TDES3_LAST_DESCRIPTOR) >> TDES3_LAST_DESCRIPTOR_SHIFT;
+ return (le32_to_cpu(p->des3) & TDES3_LAST_DESCRIPTOR)
+ >> TDES3_LAST_DESCRIPTOR_SHIFT;
}
static int dwmac4_wrback_get_rx_frame_len(struct dma_desc *p, int rx_coe)
{
- return (p->des3 & RDES3_PACKET_SIZE_MASK);
+ return (le32_to_cpu(p->des3) & RDES3_PACKET_SIZE_MASK);
}
static void dwmac4_rd_enable_tx_timestamp(struct dma_desc *p)
{
- p->des2 |= TDES2_TIMESTAMP_ENABLE;
+ p->des2 |= cpu_to_le32(TDES2_TIMESTAMP_ENABLE);
}
static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p)
{
- return (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS)
- >> TDES3_TIMESTAMP_STATUS_SHIFT;
+ /* Context type from W/B descriptor must be zero */
- if (p->des3 & TDES3_CONTEXT_TYPE)
++ if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE)
+ return -EINVAL;
+
+ /* Tx Timestamp Status is 1 so des0 and des1'll have valid values */
- if (p->des3 & TDES3_TIMESTAMP_STATUS)
++ if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS)
+ return 0;
+
+ return 1;
}
-/* NOTE: For RX CTX bit has to be checked before
- * HAVE a specific function for TX and another one for RX
- */
-static u64 dwmac4_wrback_get_timestamp(void *desc, u32 ats)
+static inline u64 dwmac4_get_timestamp(void *desc, u32 ats)
{
struct dma_desc *p = (struct dma_desc *)desc;
u64 ns;
- ns = p->des0;
+ ns = le32_to_cpu(p->des0);
/* convert high/sec time stamp value to nanosecond */
- ns += p->des1 * 1000000000ULL;
+ ns += le32_to_cpu(p->des1) * 1000000000ULL;
return ns;
}
-static int dwmac4_context_get_rx_timestamp_status(void *desc, u32 ats)
+static int dwmac4_rx_check_timestamp(void *desc)
+{
+ struct dma_desc *p = (struct dma_desc *)desc;
+ u32 own, ctxt;
+ int ret = 1;
+
- own = p->des3 & RDES3_OWN;
- ctxt = ((p->des3 & RDES3_CONTEXT_DESCRIPTOR)
++ own = le32_to_cpu(p->des3) & RDES3_OWN;
++ ctxt = ((le32_to_cpu(p->des3) & RDES3_CONTEXT_DESCRIPTOR)
+ >> RDES3_CONTEXT_DESCRIPTOR_SHIFT);
+
+ if (likely(!own && ctxt)) {
+ if ((p->des0 == 0xffffffff) && (p->des1 == 0xffffffff))
+ /* Corrupted value */
+ ret = -EINVAL;
+ else
+ /* A valid Timestamp is ready to be read */
+ ret = 0;
+ }
+
+ /* Timestamp not ready */
+ return ret;
+}
+
+static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats)
{
struct dma_desc *p = (struct dma_desc *)desc;
+ int ret = -EINVAL;
+
+ /* Get the status from normal w/b descriptor */
- if (likely(p->des3 & TDES3_RS1V)) {
- if (likely(p->des1 & RDES1_TIMESTAMP_AVAILABLE)) {
++ if (likely(le32_to_cpu(p->des3) & TDES3_RS1V)) {
++ if (likely(le32_to_cpu(p->des1) & RDES1_TIMESTAMP_AVAILABLE)) {
+ int i = 0;
+
+ /* Check if timestamp is OK from context descriptor */
+ do {
+ ret = dwmac4_rx_check_timestamp(desc);
+ if (ret < 0)
+ goto exit;
+ i++;
- return (le32_to_cpu(p->des1) & RDES1_TIMESTAMP_AVAILABLE)
- >> RDES1_TIMESTAMP_AVAILABLE_SHIFT;
+ } while ((ret == 1) || (i < 10));
+
+ if (i == 10)
+ ret = -EBUSY;
+ }
+ }
+exit:
+ return ret;
}
static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
int mode, int end)
{
- p->des3 = RDES3_OWN | RDES3_BUFFER1_VALID_ADDR;
+ p->des3 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR);
if (!disable_rx_ic)
- p->des3 |= RDES3_INT_ON_COMPLETION_EN;
+ p->des3 |= cpu_to_le32(RDES3_INT_ON_COMPLETION_EN);
}
static void dwmac4_rd_init_tx_desc(struct dma_desc *p, int mode, int end)
@@@ -305,9 -253,9 +306,9 @@@ static void dwmac4_rd_prepare_tx_desc(s
bool csum_flag, int mode, bool tx_own,
bool ls)
{
- unsigned int tdes3 = p->des3;
+ unsigned int tdes3 = le32_to_cpu(p->des3);
- p->des2 |= (len & TDES2_BUFFER1_SIZE_MASK);
+ p->des2 |= cpu_to_le32(len & TDES2_BUFFER1_SIZE_MASK);
if (is_fs)
tdes3 |= TDES3_FIRST_DESCRIPTOR;
@@@ -335,7 -283,7 +336,7 @@@
*/
wmb();
- p->des3 = tdes3;
+ p->des3 = cpu_to_le32(tdes3);
}
static void dwmac4_rd_prepare_tso_tx_desc(struct dma_desc *p, int is_fs,
@@@ -343,14 -291,14 +344,14 @@@
bool ls, unsigned int tcphdrlen,
unsigned int tcppayloadlen)
{
- unsigned int tdes3 = p->des3;
+ unsigned int tdes3 = le32_to_cpu(p->des3);
if (len1)
- p->des2 |= (len1 & TDES2_BUFFER1_SIZE_MASK);
+ p->des2 |= cpu_to_le32((len1 & TDES2_BUFFER1_SIZE_MASK));
if (len2)
- p->des2 |= (len2 << TDES2_BUFFER2_SIZE_MASK_SHIFT)
- & TDES2_BUFFER2_SIZE_MASK;
+ p->des2 |= cpu_to_le32((len2 << TDES2_BUFFER2_SIZE_MASK_SHIFT)
+ & TDES2_BUFFER2_SIZE_MASK);
if (is_fs) {
tdes3 |= TDES3_FIRST_DESCRIPTOR |
@@@ -378,7 -326,7 +379,7 @@@
*/
wmb();
- p->des3 = tdes3;
+ p->des3 = cpu_to_le32(tdes3);
}
static void dwmac4_release_tx_desc(struct dma_desc *p, int mode)
@@@ -389,7 -337,7 +390,7 @@@
static void dwmac4_rd_set_tx_ic(struct dma_desc *p)
{
- p->des2 |= TDES2_INTERRUPT_ON_COMPLETION;
+ p->des2 |= cpu_to_le32(TDES2_INTERRUPT_ON_COMPLETION);
}
static void dwmac4_display_ring(void *head, unsigned int size, bool rx)
@@@ -402,7 -350,8 +403,8 @@@
for (i = 0; i < size; i++) {
pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
i, (unsigned int)virt_to_phys(p),
- p->des0, p->des1, p->des2, p->des3);
+ le32_to_cpu(p->des0), le32_to_cpu(p->des1),
+ le32_to_cpu(p->des2), le32_to_cpu(p->des3));
p++;
}
}
@@@ -411,8 -360,8 +413,8 @@@ static void dwmac4_set_mss_ctxt(struct
{
p->des0 = 0;
p->des1 = 0;
- p->des2 = mss;
- p->des3 = TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV;
+ p->des2 = cpu_to_le32(mss);
+ p->des3 = cpu_to_le32(TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV);
}
const struct stmmac_desc_ops dwmac4_desc_ops = {
@@@ -426,8 -375,8 +428,8 @@@
.get_rx_frame_len = dwmac4_wrback_get_rx_frame_len,
.enable_tx_timestamp = dwmac4_rd_enable_tx_timestamp,
.get_tx_timestamp_status = dwmac4_wrback_get_tx_timestamp_status,
- .get_timestamp = dwmac4_wrback_get_timestamp,
- .get_rx_timestamp_status = dwmac4_context_get_rx_timestamp_status,
+ .get_rx_timestamp_status = dwmac4_wrback_get_rx_timestamp_status,
+ .get_timestamp = dwmac4_get_timestamp,
.set_tx_ic = dwmac4_rd_set_tx_ic,
.prepare_tx_desc = dwmac4_rd_prepare_tx_desc,
.prepare_tso_tx_desc = dwmac4_rd_prepare_tso_tx_desc,
diff --combined drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index e755493,8295aa9..ce97e52
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@@ -30,7 -30,7 +30,7 @@@ static int enh_desc_get_tx_status(void
struct dma_desc *p, void __iomem *ioaddr)
{
struct net_device_stats *stats = (struct net_device_stats *)data;
- unsigned int tdes0 = p->des0;
+ unsigned int tdes0 = le32_to_cpu(p->des0);
int ret = tx_done;
/* Get tx owner first */
@@@ -95,7 -95,7 +95,7 @@@
static int enh_desc_get_tx_len(struct dma_desc *p)
{
- return (p->des1 & ETDES1_BUFFER1_SIZE_MASK);
+ return (le32_to_cpu(p->des1) & ETDES1_BUFFER1_SIZE_MASK);
}
static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
@@@ -134,8 -134,8 +134,8 @@@
static void enh_desc_get_ext_status(void *data, struct stmmac_extra_stats *x,
struct dma_extended_desc *p)
{
- unsigned int rdes0 = p->basic.des0;
- unsigned int rdes4 = p->des4;
+ unsigned int rdes0 = le32_to_cpu(p->basic.des0);
+ unsigned int rdes4 = le32_to_cpu(p->des4);
if (unlikely(rdes0 & ERDES0_RX_MAC_ADDR)) {
int message_type = (rdes4 & ERDES4_MSG_TYPE_MASK) >> 8;
@@@ -150,30 -150,22 +150,30 @@@
x->ipv4_pkt_rcvd++;
if (rdes4 & ERDES4_IPV6_PKT_RCVD)
x->ipv6_pkt_rcvd++;
- if (message_type == RDES_EXT_SYNC)
- x->rx_msg_type_sync++;
+
+ if (message_type == RDES_EXT_NO_PTP)
+ x->no_ptp_rx_msg_type_ext++;
+ else if (message_type == RDES_EXT_SYNC)
+ x->ptp_rx_msg_type_sync++;
else if (message_type == RDES_EXT_FOLLOW_UP)
- x->rx_msg_type_follow_up++;
+ x->ptp_rx_msg_type_follow_up++;
else if (message_type == RDES_EXT_DELAY_REQ)
- x->rx_msg_type_delay_req++;
+ x->ptp_rx_msg_type_delay_req++;
else if (message_type == RDES_EXT_DELAY_RESP)
- x->rx_msg_type_delay_resp++;
+ x->ptp_rx_msg_type_delay_resp++;
else if (message_type == RDES_EXT_PDELAY_REQ)
- x->rx_msg_type_pdelay_req++;
+ x->ptp_rx_msg_type_pdelay_req++;
else if (message_type == RDES_EXT_PDELAY_RESP)
- x->rx_msg_type_pdelay_resp++;
+ x->ptp_rx_msg_type_pdelay_resp++;
else if (message_type == RDES_EXT_PDELAY_FOLLOW_UP)
- x->rx_msg_type_pdelay_follow_up++;
- else
- x->rx_msg_type_ext_no_ptp++;
+ x->ptp_rx_msg_type_pdelay_follow_up++;
+ else if (message_type == RDES_PTP_ANNOUNCE)
+ x->ptp_rx_msg_type_announce++;
+ else if (message_type == RDES_PTP_MANAGEMENT)
+ x->ptp_rx_msg_type_management++;
+ else if (message_type == RDES_PTP_PKT_RESERVED_TYPE)
+ x->ptp_rx_msg_pkt_reserved_type++;
+
if (rdes4 & ERDES4_PTP_FRAME_TYPE)
x->ptp_frame_type++;
if (rdes4 & ERDES4_PTP_VER)
@@@ -199,7 -191,7 +199,7 @@@ static int enh_desc_get_rx_status(void
struct dma_desc *p)
{
struct net_device_stats *stats = (struct net_device_stats *)data;
- unsigned int rdes0 = p->des0;
+ unsigned int rdes0 = le32_to_cpu(p->des0);
int ret = good_frame;
if (unlikely(rdes0 & RDES0_OWN))
@@@ -265,8 -257,8 +265,8 @@@
static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
int mode, int end)
{
- p->des0 |= RDES0_OWN;
- p->des1 |= ((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK);
+ p->des0 |= cpu_to_le32(RDES0_OWN);
+ p->des1 |= cpu_to_le32((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK);
if (mode == STMMAC_CHAIN_MODE)
ehn_desc_rx_set_on_chain(p);
@@@ -274,12 -266,12 +274,12 @@@
ehn_desc_rx_set_on_ring(p, end);
if (disable_rx_ic)
- p->des1 |= ERDES1_DISABLE_IC;
+ p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC);
}
static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end)
{
- p->des0 &= ~ETDES0_OWN;
+ p->des0 &= cpu_to_le32(~ETDES0_OWN);
if (mode == STMMAC_CHAIN_MODE)
enh_desc_end_tx_desc_on_chain(p);
else
@@@ -288,27 -280,27 +288,27 @@@
static int enh_desc_get_tx_owner(struct dma_desc *p)
{
- return (p->des0 & ETDES0_OWN) >> 31;
+ return (le32_to_cpu(p->des0) & ETDES0_OWN) >> 31;
}
static void enh_desc_set_tx_owner(struct dma_desc *p)
{
- p->des0 |= ETDES0_OWN;
+ p->des0 |= cpu_to_le32(ETDES0_OWN);
}
static void enh_desc_set_rx_owner(struct dma_desc *p)
{
- p->des0 |= RDES0_OWN;
+ p->des0 |= cpu_to_le32(RDES0_OWN);
}
static int enh_desc_get_tx_ls(struct dma_desc *p)
{
- return (p->des0 & ETDES0_LAST_SEGMENT) >> 29;
+ return (le32_to_cpu(p->des0) & ETDES0_LAST_SEGMENT) >> 29;
}
static void enh_desc_release_tx_desc(struct dma_desc *p, int mode)
{
- int ter = (p->des0 & ETDES0_END_RING) >> 21;
+ int ter = (le32_to_cpu(p->des0) & ETDES0_END_RING) >> 21;
memset(p, 0, offsetof(struct dma_desc, des2));
if (mode == STMMAC_CHAIN_MODE)
@@@ -321,7 -313,7 +321,7 @@@ static void enh_desc_prepare_tx_desc(st
bool csum_flag, int mode, bool tx_own,
bool ls)
{
- unsigned int tdes0 = p->des0;
+ unsigned int tdes0 = le32_to_cpu(p->des0);
if (mode == STMMAC_CHAIN_MODE)
enh_set_tx_desc_len_on_chain(p, len);
@@@ -352,12 -344,12 +352,12 @@@
*/
wmb();
- p->des0 = tdes0;
+ p->des0 = cpu_to_le32(tdes0);
}
static void enh_desc_set_tx_ic(struct dma_desc *p)
{
- p->des0 |= ETDES0_INTERRUPT;
+ p->des0 |= cpu_to_le32(ETDES0_INTERRUPT);
}
static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
@@@ -372,18 -364,18 +372,18 @@@
if (rx_coe_type == STMMAC_RX_COE_TYPE1)
csum = 2;
- return (((p->des0 & RDES0_FRAME_LEN_MASK) >> RDES0_FRAME_LEN_SHIFT) -
- csum);
+ return (((le32_to_cpu(p->des0) & RDES0_FRAME_LEN_MASK)
+ >> RDES0_FRAME_LEN_SHIFT) - csum);
}
static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
{
- p->des0 |= ETDES0_TIME_STAMP_ENABLE;
+ p->des0 |= cpu_to_le32(ETDES0_TIME_STAMP_ENABLE);
}
static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
{
- return (p->des0 & ETDES0_TIME_STAMP_STATUS) >> 17;
+ return (le32_to_cpu(p->des0) & ETDES0_TIME_STAMP_STATUS) >> 17;
}
static u64 enh_desc_get_timestamp(void *desc, u32 ats)
@@@ -392,13 -384,13 +392,13 @@@
if (ats) {
struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
- ns = p->des6;
+ ns = le32_to_cpu(p->des6);
/* convert high/sec time stamp value to nanosecond */
- ns += p->des7 * 1000000000ULL;
+ ns += le32_to_cpu(p->des7) * 1000000000ULL;
} else {
struct dma_desc *p = (struct dma_desc *)desc;
- ns = p->des2;
- ns += p->des3 * 1000000000ULL;
+ ns = le32_to_cpu(p->des2);
+ ns += le32_to_cpu(p->des3) * 1000000000ULL;
}
return ns;
@@@ -408,10 -400,11 +408,11 @@@ static int enh_desc_get_rx_timestamp_st
{
if (ats) {
struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
- return (p->basic.des0 & RDES0_IPC_CSUM_ERROR) >> 7;
+ return (le32_to_cpu(p->basic.des0) & RDES0_IPC_CSUM_ERROR) >> 7;
} else {
struct dma_desc *p = (struct dma_desc *)desc;
- if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
+ if ((le32_to_cpu(p->des2) == 0xffffffff) &&
+ (le32_to_cpu(p->des3) == 0xffffffff))
/* timestamp is corrupted, hence don't store it */
return 0;
else
diff --combined drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 4d2a759,758b4e2..dbacb80
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@@ -90,7 -90,6 +90,6 @@@ struct stmmac_priv
struct mac_device_info *hw;
spinlock_t lock;
- struct phy_device *phydev ____cacheline_aligned_in_smp;
int oldlink;
int speed;
int oldduplex;
@@@ -129,7 -128,6 +128,7 @@@
int irq_wake;
spinlock_t ptp_lock;
void __iomem *mmcaddr;
+ void __iomem *ptpaddr;
u32 rx_tail_addr;
u32 tx_tail_addr;
u32 mss;
diff --combined drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index c5d0142,0290d52..d5a8122
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@@ -115,17 -115,14 +115,17 @@@ static const struct stmmac_stats stmmac
STMMAC_STAT(ip_csum_bypassed),
STMMAC_STAT(ipv4_pkt_rcvd),
STMMAC_STAT(ipv6_pkt_rcvd),
- STMMAC_STAT(rx_msg_type_ext_no_ptp),
- STMMAC_STAT(rx_msg_type_sync),
- STMMAC_STAT(rx_msg_type_follow_up),
- STMMAC_STAT(rx_msg_type_delay_req),
- STMMAC_STAT(rx_msg_type_delay_resp),
- STMMAC_STAT(rx_msg_type_pdelay_req),
- STMMAC_STAT(rx_msg_type_pdelay_resp),
- STMMAC_STAT(rx_msg_type_pdelay_follow_up),
+ STMMAC_STAT(no_ptp_rx_msg_type_ext),
+ STMMAC_STAT(ptp_rx_msg_type_sync),
+ STMMAC_STAT(ptp_rx_msg_type_follow_up),
+ STMMAC_STAT(ptp_rx_msg_type_delay_req),
+ STMMAC_STAT(ptp_rx_msg_type_delay_resp),
+ STMMAC_STAT(ptp_rx_msg_type_pdelay_req),
+ STMMAC_STAT(ptp_rx_msg_type_pdelay_resp),
+ STMMAC_STAT(ptp_rx_msg_type_pdelay_follow_up),
+ STMMAC_STAT(ptp_rx_msg_type_announce),
+ STMMAC_STAT(ptp_rx_msg_type_management),
+ STMMAC_STAT(ptp_rx_msg_pkt_reserved_type),
STMMAC_STAT(ptp_frame_type),
STMMAC_STAT(ptp_ver),
STMMAC_STAT(timestamp_dropped),
@@@ -272,25 -269,26 +272,26 @@@ static void stmmac_ethtool_getdrvinfo(s
strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
}
- static int stmmac_ethtool_getsettings(struct net_device *dev,
- struct ethtool_cmd *cmd)
+ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct stmmac_priv *priv = netdev_priv(dev);
- struct phy_device *phy = priv->phydev;
+ struct phy_device *phy = dev->phydev;
int rc;
if (priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII) {
struct rgmii_adv adv;
+ u32 supported, advertising, lp_advertising;
if (!priv->xstats.pcs_link) {
- ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
- cmd->duplex = DUPLEX_UNKNOWN;
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
return 0;
}
- cmd->duplex = priv->xstats.pcs_duplex;
+ cmd->base.duplex = priv->xstats.pcs_duplex;
- ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed);
+ cmd->base.speed = priv->xstats.pcs_speed;
/* Get and convert ADV/LP_ADV from the HW AN registers */
if (!priv->hw->mac->pcs_get_adv_lp)
@@@ -300,45 -298,59 +301,59 @@@
/* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */
+ ethtool_convert_link_mode_to_legacy_u32(
+ &supported, cmd->link_modes.supported);
+ ethtool_convert_link_mode_to_legacy_u32(
+ &advertising, cmd->link_modes.advertising);
+ ethtool_convert_link_mode_to_legacy_u32(
+ &lp_advertising, cmd->link_modes.lp_advertising);
+
if (adv.pause & STMMAC_PCS_PAUSE)
- cmd->advertising |= ADVERTISED_Pause;
+ advertising |= ADVERTISED_Pause;
if (adv.pause & STMMAC_PCS_ASYM_PAUSE)
- cmd->advertising |= ADVERTISED_Asym_Pause;
+ advertising |= ADVERTISED_Asym_Pause;
if (adv.lp_pause & STMMAC_PCS_PAUSE)
- cmd->lp_advertising |= ADVERTISED_Pause;
+ lp_advertising |= ADVERTISED_Pause;
if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE)
- cmd->lp_advertising |= ADVERTISED_Asym_Pause;
+ lp_advertising |= ADVERTISED_Asym_Pause;
/* Reg49[3] always set because ANE is always supported */
- cmd->autoneg = ADVERTISED_Autoneg;
- cmd->supported |= SUPPORTED_Autoneg;
- cmd->advertising |= ADVERTISED_Autoneg;
- cmd->lp_advertising |= ADVERTISED_Autoneg;
+ cmd->base.autoneg = ADVERTISED_Autoneg;
+ supported |= SUPPORTED_Autoneg;
+ advertising |= ADVERTISED_Autoneg;
+ lp_advertising |= ADVERTISED_Autoneg;
if (adv.duplex) {
- cmd->supported |= (SUPPORTED_1000baseT_Full |
- SUPPORTED_100baseT_Full |
- SUPPORTED_10baseT_Full);
- cmd->advertising |= (ADVERTISED_1000baseT_Full |
- ADVERTISED_100baseT_Full |
- ADVERTISED_10baseT_Full);
+ supported |= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_10baseT_Full);
+ advertising |= (ADVERTISED_1000baseT_Full |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Full);
} else {
- cmd->supported |= (SUPPORTED_1000baseT_Half |
- SUPPORTED_100baseT_Half |
- SUPPORTED_10baseT_Half);
- cmd->advertising |= (ADVERTISED_1000baseT_Half |
- ADVERTISED_100baseT_Half |
- ADVERTISED_10baseT_Half);
+ supported |= (SUPPORTED_1000baseT_Half |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_10baseT_Half);
+ advertising |= (ADVERTISED_1000baseT_Half |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_10baseT_Half);
}
if (adv.lp_duplex)
- cmd->lp_advertising |= (ADVERTISED_1000baseT_Full |
- ADVERTISED_100baseT_Full |
- ADVERTISED_10baseT_Full);
+ lp_advertising |= (ADVERTISED_1000baseT_Full |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_10baseT_Full);
else
- cmd->lp_advertising |= (ADVERTISED_1000baseT_Half |
- ADVERTISED_100baseT_Half |
- ADVERTISED_10baseT_Half);
- cmd->port = PORT_OTHER;
+ lp_advertising |= (ADVERTISED_1000baseT_Half |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_10baseT_Half);
+ cmd->base.port = PORT_OTHER;
+
+ ethtool_convert_legacy_u32_to_link_mode(
+ cmd->link_modes.supported, supported);
+ ethtool_convert_legacy_u32_to_link_mode(
+ cmd->link_modes.advertising, advertising);
+ ethtool_convert_legacy_u32_to_link_mode(
+ cmd->link_modes.lp_advertising, lp_advertising);
return 0;
}
@@@ -353,16 -365,16 +368,16 @@@
"link speed / duplex setting\n", dev->name);
return -EBUSY;
}
- cmd->transceiver = XCVR_INTERNAL;
- rc = phy_ethtool_gset(phy, cmd);
+ rc = phy_ethtool_ksettings_get(phy, cmd);
return rc;
}
- static int stmmac_ethtool_setsettings(struct net_device *dev,
- struct ethtool_cmd *cmd)
+ static int
+ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct stmmac_priv *priv = netdev_priv(dev);
- struct phy_device *phy = priv->phydev;
+ struct phy_device *phy = dev->phydev;
int rc;
if (priv->hw->pcs & STMMAC_PCS_RGMII ||
@@@ -370,7 -382,7 +385,7 @@@
u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;
/* Only support ANE */
- if (cmd->autoneg != AUTONEG_ENABLE)
+ if (cmd->base.autoneg != AUTONEG_ENABLE)
return -EINVAL;
mask &= (ADVERTISED_1000baseT_Half |
@@@ -392,7 -404,7 +407,7 @@@
}
spin_lock(&priv->lock);
- rc = phy_ethtool_sset(phy, cmd);
+ rc = phy_ethtool_ksettings_set(phy, cmd);
spin_unlock(&priv->lock);
return rc;
@@@ -471,12 -483,12 +486,12 @@@ stmmac_get_pauseparam(struct net_devic
if (!adv_lp.pause)
return;
} else {
- if (!(priv->phydev->supported & SUPPORTED_Pause) ||
- !(priv->phydev->supported & SUPPORTED_Asym_Pause))
+ if (!(netdev->phydev->supported & SUPPORTED_Pause) ||
+ !(netdev->phydev->supported & SUPPORTED_Asym_Pause))
return;
}
- pause->autoneg = priv->phydev->autoneg;
+ pause->autoneg = netdev->phydev->autoneg;
if (priv->flow_ctrl & FLOW_RX)
pause->rx_pause = 1;
@@@ -490,7 -502,7 +505,7 @@@ stmmac_set_pauseparam(struct net_devic
struct ethtool_pauseparam *pause)
{
struct stmmac_priv *priv = netdev_priv(netdev);
- struct phy_device *phy = priv->phydev;
+ struct phy_device *phy = netdev->phydev;
int new_pause = FLOW_OFF;
if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
@@@ -550,7 -562,7 +565,7 @@@ static void stmmac_get_ethtool_stats(st
}
}
if (priv->eee_enabled) {
- int val = phy_get_eee_err(priv->phydev);
+ int val = phy_get_eee_err(dev->phydev);
if (val)
priv->xstats.phy_eee_wakeup_error_n = val;
}
@@@ -669,7 -681,7 +684,7 @@@ static int stmmac_ethtool_op_get_eee(st
edata->eee_active = priv->eee_active;
edata->tx_lpi_timer = priv->tx_lpi_timer;
- return phy_ethtool_get_eee(priv->phydev, edata);
+ return phy_ethtool_get_eee(dev->phydev, edata);
}
static int stmmac_ethtool_op_set_eee(struct net_device *dev,
@@@ -694,7 -706,7 +709,7 @@@
priv->tx_lpi_timer = edata->tx_lpi_timer;
}
- return phy_ethtool_set_eee(priv->phydev, edata);
+ return phy_ethtool_set_eee(dev->phydev, edata);
}
static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
@@@ -853,13 -865,12 +868,12 @@@ static int stmmac_set_tunable(struct ne
static const struct ethtool_ops stmmac_ethtool_ops = {
.begin = stmmac_check_if_running,
.get_drvinfo = stmmac_ethtool_getdrvinfo,
- .get_settings = stmmac_ethtool_getsettings,
- .set_settings = stmmac_ethtool_setsettings,
.get_msglevel = stmmac_ethtool_getmsglevel,
.set_msglevel = stmmac_ethtool_setmsglevel,
.get_regs = stmmac_ethtool_gregs,
.get_regs_len = stmmac_ethtool_get_regs_len,
.get_link = ethtool_op_get_link,
+ .nway_reset = phy_ethtool_nway_reset,
.get_pauseparam = stmmac_get_pauseparam,
.set_pauseparam = stmmac_set_pauseparam,
.get_ethtool_stats = stmmac_get_ethtool_stats,
@@@ -874,6 -885,8 +888,8 @@@
.set_coalesce = stmmac_set_coalesce,
.get_tunable = stmmac_get_tunable,
.set_tunable = stmmac_set_tunable,
+ .get_link_ksettings = stmmac_ethtool_get_link_ksettings,
+ .set_link_ksettings = stmmac_ethtool_set_link_ksettings,
};
void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --combined drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 1f9ec02,fbd1cd7..2b2906a
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@@ -221,7 -221,8 +221,8 @@@ static inline u32 stmmac_rx_dirty(struc
*/
static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
{
- struct phy_device *phydev = priv->phydev;
+ struct net_device *ndev = priv->dev;
+ struct phy_device *phydev = ndev->phydev;
if (likely(priv->plat->fix_mac_speed))
priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
@@@ -279,6 -280,7 +280,7 @@@ static void stmmac_eee_ctrl_timer(unsig
*/
bool stmmac_eee_init(struct stmmac_priv *priv)
{
+ struct net_device *ndev = priv->dev;
unsigned long flags;
bool ret = false;
@@@ -295,7 -297,7 +297,7 @@@
int tx_lpi_timer = priv->tx_lpi_timer;
/* Check if the PHY supports EEE */
- if (phy_init_eee(priv->phydev, 1)) {
+ if (phy_init_eee(ndev->phydev, 1)) {
/* To manage at run-time if the EEE cannot be supported
* anymore (for example because the lp caps have been
* changed).
@@@ -303,7 -305,7 +305,7 @@@
*/
spin_lock_irqsave(&priv->lock, flags);
if (priv->eee_active) {
- pr_debug("stmmac: disable EEE\n");
+ netdev_dbg(priv->dev, "disable EEE\n");
del_timer_sync(&priv->eee_ctrl_timer);
priv->hw->mac->set_eee_timer(priv->hw, 0,
tx_lpi_timer);
@@@ -327,12 -329,12 +329,12 @@@
tx_lpi_timer);
}
/* Set HW EEE according to the speed */
- priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
+ priv->hw->mac->set_eee_pls(priv->hw, ndev->phydev->link);
ret = true;
spin_unlock_irqrestore(&priv->lock, flags);
- pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
+ netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
}
out:
return ret;
@@@ -340,17 -342,18 +342,17 @@@
/* stmmac_get_tx_hwtstamp - get HW TX timestamps
* @priv: driver private structure
- * @entry : descriptor index to be used.
+ * @p : descriptor pointer
* @skb : the socket buffer
* Description :
* This function will read timestamp from the descriptor & pass it to stack.
* and also perform some sanity checks.
*/
static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
- unsigned int entry, struct sk_buff *skb)
+ struct dma_desc *p, struct sk_buff *skb)
{
struct skb_shared_hwtstamps shhwtstamp;
u64 ns;
- void *desc = NULL;
if (!priv->hwts_tx_en)
return;
@@@ -359,55 -362,58 +361,55 @@@
if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
return;
- if (priv->adv_ts)
- desc = (priv->dma_etx + entry);
- else
- desc = (priv->dma_tx + entry);
-
/* check tx tstamp status */
- if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
- return;
+ if (!priv->hw->desc->get_tx_timestamp_status(p)) {
+ /* get the valid tstamp */
+ ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);
- /* get the valid tstamp */
- ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
+ memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
+ shhwtstamp.hwtstamp = ns_to_ktime(ns);
- memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
- shhwtstamp.hwtstamp = ns_to_ktime(ns);
- /* pass tstamp to stack */
- skb_tstamp_tx(skb, &shhwtstamp);
+ netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns);
+ /* pass tstamp to stack */
+ skb_tstamp_tx(skb, &shhwtstamp);
+ }
return;
}
/* stmmac_get_rx_hwtstamp - get HW RX timestamps
* @priv: driver private structure
- * @entry : descriptor index to be used.
+ * @p : descriptor pointer
+ * @np : next descriptor pointer
* @skb : the socket buffer
* Description :
* This function will read received packet's timestamp from the descriptor
* and pass it to stack. It also perform some sanity checks.
*/
-static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
- unsigned int entry, struct sk_buff *skb)
+static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
+ struct dma_desc *np, struct sk_buff *skb)
{
struct skb_shared_hwtstamps *shhwtstamp = NULL;
u64 ns;
- void *desc = NULL;
if (!priv->hwts_rx_en)
return;
- if (priv->adv_ts)
- desc = (priv->dma_erx + entry);
- else
- desc = (priv->dma_rx + entry);
-
- /* exit if rx tstamp is not valid */
- if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
- return;
+ /* Check if timestamp is available */
+ if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) {
+ /* For GMAC4, the valid timestamp is from CTX next desc. */
+ if (priv->plat->has_gmac4)
+ ns = priv->hw->desc->get_timestamp(np, priv->adv_ts);
+ else
+ ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);
- /* get valid tstamp */
- ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
- shhwtstamp = skb_hwtstamps(skb);
- memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
- shhwtstamp->hwtstamp = ns_to_ktime(ns);
+ netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns);
+ shhwtstamp = skb_hwtstamps(skb);
+ memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
+ shhwtstamp->hwtstamp = ns_to_ktime(ns);
+ } else {
+ netdev_err(priv->dev, "cannot get RX hw timestamp\n");
+ }
}
/**
@@@ -450,8 -456,8 +452,8 @@@ static int stmmac_hwtstamp_ioctl(struc
sizeof(struct hwtstamp_config)))
return -EFAULT;
- pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
- __func__, config.flags, config.tx_type, config.rx_filter);
+ netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x,
rx_filter:0x%x\n",
+ __func__, config.flags, config.tx_type, config.rx_filter);
/* reserved for future extensions */
if (config.flags)
@@@ -594,18 -600,17 +596,18 @@@
priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
if (!priv->hwts_tx_en && !priv->hwts_rx_en)
- priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
+ priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, 0);
else {
value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
tstamp_all | ptp_v2 | ptp_over_ethernet |
ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
ts_master_en | snap_type_sel);
- priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
+ priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, value);
/* program Sub Second Increment reg */
sec_inc = priv->hw->ptp->config_sub_second_increment(
- priv->ioaddr, priv->clk_ptp_rate);
+ priv->ptpaddr, priv->clk_ptp_rate,
+ priv->plat->has_gmac4);
temp = div_u64(1000000000ULL, sec_inc);
/* calculate default added value:
@@@ -615,14 -620,14 +617,14 @@@
*/
temp = (u64)(temp << 32);
priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
- priv->hw->ptp->config_addend(priv->ioaddr,
+ priv->hw->ptp->config_addend(priv->ptpaddr,
priv->default_addend);
/* initialize system time */
ktime_get_real_ts64(&now);
/* lower 32 bits of tv_sec are safe until y2106 */
- priv->hw->ptp->init_systime(priv->ioaddr, (u32)now.tv_sec,
+ priv->hw->ptp->init_systime(priv->ptpaddr, (u32)now.tv_sec,
now.tv_nsec);
}
@@@ -697,7 -702,7 +699,7 @@@ static void stmmac_release_ptp(struct s
static void stmmac_adjust_link(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
- struct phy_device *phydev = priv->phydev;
+ struct phy_device *phydev = dev->phydev;
unsigned long flags;
int new_state = 0;
unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
@@@ -750,9 -755,9 +752,9 @@@
stmmac_hw_fix_mac_speed(priv);
break;
default:
- if (netif_msg_link(priv))
- pr_warn("%s: Speed (%d) not 10/100\n",
- dev->name, phydev->speed);
+ netif_warn(priv, link, priv->dev,
+ "Speed (%d) not 10/100\n",
+ phydev->speed);
break;
}
@@@ -805,10 -810,10 +807,10 @@@ static void stmmac_check_pcs_mode(struc
(interface == PHY_INTERFACE_MODE_RGMII_ID) ||
(interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
- pr_debug("STMMAC: PCS RGMII support enable\n");
+ netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
priv->hw->pcs = STMMAC_PCS_RGMII;
} else if (interface == PHY_INTERFACE_MODE_SGMII) {
- pr_debug("STMMAC: PCS SGMII support enable\n");
+ netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
priv->hw->pcs = STMMAC_PCS_SGMII;
}
}
@@@ -843,15 -848,15 +845,15 @@@ static int stmmac_init_phy(struct net_d
snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
priv->plat->phy_addr);
- pr_debug("stmmac_init_phy: trying to attach to %s\n",
- phy_id_fmt);
+ netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__,
+ phy_id_fmt);
phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
interface);
}
if (IS_ERR_OR_NULL(phydev)) {
- pr_err("%s: Could not attach to PHY\n", dev->name);
+ netdev_err(priv->dev, "Could not attach to PHY\n");
if (!phydev)
return -ENODEV;
@@@ -884,10 -889,8 +886,8 @@@
if (phydev->is_pseudo_fixed_link)
phydev->irq = PHY_POLL;
- pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)"
- " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
-
- priv->phydev = phydev;
+ netdev_dbg(priv->dev, "%s: attached to PHY (UID 0x%x) Link = %d\n",
+ __func__, phydev->phy_id, phydev->link);
return 0;
}
@@@ -973,7 -976,8 +973,8 @@@ static int stmmac_init_rx_buffers(struc
skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
if (!skb) {
- pr_err("%s: Rx init fails; skb is NULL\n", __func__);
+ netdev_err(priv->dev,
+ "%s: Rx init fails; skb is NULL\n", __func__);
return -ENOMEM;
}
priv->rx_skbuff[i] = skb;
@@@ -981,15 -985,15 +982,15 @@@
priv->dma_buf_sz,
DMA_FROM_DEVICE);
if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
- pr_err("%s: DMA mapping error\n", __func__);
+ netdev_err(priv->dev, "%s: DMA mapping error\n", __func__);
dev_kfree_skb_any(skb);
return -EINVAL;
}
if (priv->synopsys_id >= DWMAC_CORE_4_00)
- p->des0 = priv->rx_skbuff_dma[i];
+ p->des0 = cpu_to_le32(priv->rx_skbuff_dma[i]);
else
- p->des2 = priv->rx_skbuff_dma[i];
+ p->des2 = cpu_to_le32(priv->rx_skbuff_dma[i]);
if ((priv->hw->mode->init_desc3) &&
(priv->dma_buf_sz == BUF_SIZE_16KiB))
@@@ -1031,13 -1035,14 +1032,14 @@@ static int init_dma_desc_rings(struct n
priv->dma_buf_sz = bfsize;
- if (netif_msg_probe(priv)) {
- pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
- (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
+ netif_dbg(priv, probe, priv->dev,
+ "(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n",
+ __func__, (u32)priv->dma_rx_phy, (u32)priv->dma_tx_phy);
+
+ /* RX INITIALIZATION */
+ netif_dbg(priv, probe, priv->dev,
+ "SKB addresses:\nskb\t\tskb data\tdma data\n");
- /* RX INITIALIZATION */
- pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
- }
for (i = 0; i < DMA_RX_SIZE; i++) {
struct dma_desc *p;
if (priv->extend_desc)
@@@ -1049,10 -1054,9 +1051,9 @@@
if (ret)
goto err_init_rx_buffers;
- if (netif_msg_probe(priv))
- pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
- priv->rx_skbuff[i]->data,
- (unsigned int)priv->rx_skbuff_dma[i]);
+ netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n",
+ priv->rx_skbuff[i], priv->rx_skbuff[i]->data,
+ (unsigned int)priv->rx_skbuff_dma[i]);
}
priv->cur_rx = 0;
priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE);
@@@ -1337,7 -1341,7 +1338,7 @@@ static void stmmac_tx_clean(struct stmm
priv->dev->stats.tx_packets++;
priv->xstats.tx_pkt_n++;
}
- stmmac_get_tx_hwtstamp(priv, entry, skb);
+ stmmac_get_tx_hwtstamp(priv, p, skb);
}
if (likely(priv->tx_skbuff_dma[entry].buf)) {
@@@ -1382,8 -1386,8 +1383,8 @@@
netif_tx_lock(priv->dev);
if (netif_queue_stopped(priv->dev) &&
stmmac_tx_avail(priv) > STMMAC_TX_THRESH) {
- if (netif_msg_tx_done(priv))
- pr_debug("%s: restart transmit\n", __func__);
+ netif_dbg(priv, tx_done, priv->dev,
+ "%s: restart transmit\n", __func__);
netif_wake_queue(priv->dev);
}
netif_tx_unlock(priv->dev);
@@@ -1483,13 -1487,10 +1484,13 @@@ static void stmmac_mmc_setup(struct stm
unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
- if (priv->synopsys_id >= DWMAC_CORE_4_00)
+ if (priv->synopsys_id >= DWMAC_CORE_4_00) {
+ priv->ptpaddr = priv->ioaddr + PTP_GMAC4_OFFSET;
priv->mmcaddr = priv->ioaddr + MMC_GMAC4_OFFSET;
- else
+ } else {
+ priv->ptpaddr = priv->ioaddr + PTP_GMAC3_X_OFFSET;
priv->mmcaddr = priv->ioaddr + MMC_GMAC3_X_OFFSET;
+ }
dwmac_mmc_intr_all_mask(priv->mmcaddr);
@@@ -1497,7 -1498,7 +1498,7 @@@
dwmac_mmc_ctrl(priv->mmcaddr, mode);
memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
} else
- pr_info(" No MAC Management Counters available\n");
+ netdev_info(priv->dev, "No MAC Management Counters available\n");
}
/**
@@@ -1510,18 -1511,18 +1511,18 @@@
static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
{
if (priv->plat->enh_desc) {
- pr_info(" Enhanced/Alternate descriptors\n");
+ dev_info(priv->device, "Enhanced/Alternate descriptors\n");
/* GMAC older than 3.50 has no extended descriptors */
if (priv->synopsys_id >= DWMAC_CORE_3_50) {
- pr_info("\tEnabled extended descriptors\n");
+ dev_info(priv->device, "Enabled extended descriptors\n");
priv->extend_desc = 1;
} else
- pr_warn("Extended descriptors not supported\n");
+ dev_warn(priv->device, "Extended descriptors not supported\n");
priv->hw->desc = &enh_desc_ops;
} else {
- pr_info(" Normal descriptors\n");
+ dev_info(priv->device, "Normal descriptors\n");
priv->hw->desc = &ndesc_ops;
}
}
@@@ -1562,8 -1563,8 +1563,8 @@@ static void stmmac_check_ether_addr(str
priv->dev->dev_addr, 0);
if (!is_valid_ether_addr(priv->dev->dev_addr))
eth_hw_addr_random(priv->dev);
- pr_info("%s: device MAC address %pM\n", priv->dev->name,
- priv->dev->dev_addr);
+ netdev_info(priv->dev, "device MAC address %pM\n",
+ priv->dev->dev_addr);
}
}
@@@ -1671,7 -1672,8 +1672,8 @@@ static int stmmac_hw_setup(struct net_d
/* DMA initialization and SW reset */
ret = stmmac_init_dma_engine(priv);
if (ret < 0) {
- pr_err("%s: DMA engine initialization failed\n", __func__);
+ netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
+ __func__);
return ret;
}
@@@ -1700,7 -1702,7 +1702,7 @@@
ret = priv->hw->mac->rx_ipc(priv->hw);
if (!ret) {
- pr_warn(" RX IPC Checksum Offload disabled\n");
+ netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n");
priv->plat->rx_coe = STMMAC_RX_COE_NONE;
priv->hw->rx_csum = 0;
}
@@@ -1725,10 -1727,11 +1727,11 @@@
#ifdef CONFIG_DEBUG_FS
ret = stmmac_init_fs(dev);
if (ret < 0)
- pr_warn("%s: failed debugFS registration\n", __func__);
+ netdev_warn(priv->dev, "%s: failed debugFS registration\n",
+ __func__);
#endif
/* Start the ball rolling... */
- pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
+ netdev_dbg(priv->dev, "DMA RX/TX processes started...\n");
priv->hw->dma->start_tx(priv->ioaddr);
priv->hw->dma->start_rx(priv->ioaddr);
@@@ -1783,8 -1786,9 +1786,9 @@@ static int stmmac_open(struct net_devic
priv->hw->pcs != STMMAC_PCS_RTBI) {
ret = stmmac_init_phy(dev);
if (ret) {
- pr_err("%s: Cannot attach to PHY (error: %d)\n",
- __func__, ret);
+ netdev_err(priv->dev,
+ "%s: Cannot attach to PHY (error: %d)\n",
+ __func__, ret);
return ret;
}
}
@@@ -1798,33 -1802,36 +1802,36 @@@
ret = alloc_dma_desc_resources(priv);
if (ret < 0) {
- pr_err("%s: DMA descriptors allocation failed\n", __func__);
+ netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n",
+ __func__);
goto dma_desc_error;
}
ret = init_dma_desc_rings(dev, GFP_KERNEL);
if (ret < 0) {
- pr_err("%s: DMA descriptors initialization failed\n", __func__);
+ netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n",
+ __func__);
goto init_error;
}
ret = stmmac_hw_setup(dev, true);
if (ret < 0) {
- pr_err("%s: Hw setup failed\n", __func__);
+ netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
goto init_error;
}
stmmac_init_tx_coalesce(priv);
- if (priv->phydev)
- phy_start(priv->phydev);
+ if (dev->phydev)
+ phy_start(dev->phydev);
/* Request the IRQ lines */
ret = request_irq(dev->irq, stmmac_interrupt,
IRQF_SHARED, dev->name, dev);
if (unlikely(ret < 0)) {
- pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
- __func__, dev->irq, ret);
+ netdev_err(priv->dev,
+ "%s: ERROR: allocating the IRQ %d (error: %d)\n",
+ __func__, dev->irq, ret);
goto init_error;
}
@@@ -1833,8 -1840,9 +1840,9 @@@
ret = request_irq(priv->wol_irq, stmmac_interrupt,
IRQF_SHARED, dev->name, dev);
if (unlikely(ret < 0)) {
- pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
- __func__, priv->wol_irq, ret);
+ netdev_err(priv->dev,
+ "%s: ERROR: allocating the WoL IRQ %d (%d)\n",
+ __func__, priv->wol_irq, ret);
goto wolirq_error;
}
}
@@@ -1844,8 -1852,9 +1852,9 @@@
ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
dev->name, dev);
if (unlikely(ret < 0)) {
- pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
- __func__, priv->lpi_irq, ret);
+ netdev_err(priv->dev,
+ "%s: ERROR: allocating the LPI IRQ %d (%d)\n",
+ __func__, priv->lpi_irq, ret);
goto lpiirq_error;
}
}
@@@ -1864,8 -1873,8 +1873,8 @@@ wolirq_error
init_error:
free_dma_desc_resources(priv);
dma_desc_error:
- if (priv->phydev)
- phy_disconnect(priv->phydev);
+ if (dev->phydev)
+ phy_disconnect(dev->phydev);
return ret;
}
@@@ -1884,10 -1893,9 +1893,9 @@@ static int stmmac_release(struct net_de
del_timer_sync(&priv->eee_ctrl_timer);
/* Stop and disconnect the PHY */
- if (priv->phydev) {
- phy_stop(priv->phydev);
- phy_disconnect(priv->phydev);
- priv->phydev = NULL;
+ if (dev->phydev) {
+ phy_stop(dev->phydev);
+ phy_disconnect(dev->phydev);
}
netif_stop_queue(dev);
@@@ -1947,7 -1955,7 +1955,7 @@@ static void stmmac_tso_allocator(struc
priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE);
desc = priv->dma_tx + priv->cur_tx;
- desc->des0 = des + (total_len - tmp_len);
+ desc->des0 = cpu_to_le32(des + (total_len - tmp_len));
buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ?
TSO_MAX_BUFF_SIZE : tmp_len;
@@@ -2009,7 -2017,9 +2017,9 @@@ static netdev_tx_t stmmac_tso_xmit(stru
if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
/* This is a hard error, log it. */
- pr_err("%s: Tx Ring full when queue awake\n", __func__);
+ netdev_err(priv->dev,
+ "%s: Tx Ring full when queue awake\n",
+ __func__);
}
spin_unlock(&priv->tx_lock);
return NETDEV_TX_BUSY;
@@@ -2049,11 -2059,11 +2059,11 @@@
priv->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
priv->tx_skbuff[first_entry] = skb;
- first->des0 = des;
+ first->des0 = cpu_to_le32(des);
/* Fill start of payload in buff2 of first descriptor */
if (pay_len)
- first->des1 = des + proto_hdr_len;
+ first->des1 = cpu_to_le32(des + proto_hdr_len);
/* If needed take extra descriptors to fill the remaining payload */
tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE;
@@@ -2082,8 -2092,8 +2092,8 @@@
priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE);
if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
- if (netif_msg_hw(priv))
- pr_debug("%s: stop transmitted packets\n", __func__);
+ netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
+ __func__);
netif_stop_queue(dev);
}
@@@ -2189,7 -2199,9 +2199,9 @@@ static netdev_tx_t stmmac_xmit(struct s
if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
/* This is a hard error, log it. */
- pr_err("%s: Tx Ring full when queue awake\n", __func__);
+ netdev_err(priv->dev,
+ "%s: Tx Ring full when queue awake\n",
+ __func__);
}
return NETDEV_TX_BUSY;
}
@@@ -2242,13 -2254,11 +2254,11 @@@
priv->tx_skbuff[entry] = NULL;
- if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) {
- desc->des0 = des;
- priv->tx_skbuff_dma[entry].buf = desc->des0;
- } else {
- desc->des2 = des;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
- }
+ priv->tx_skbuff_dma[entry].buf = des;
+ if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
+ desc->des0 = cpu_to_le32(des);
+ else
+ desc->des2 = cpu_to_le32(des);
priv->tx_skbuff_dma[entry].map_as_page = true;
priv->tx_skbuff_dma[entry].len = len;
@@@ -2266,9 -2276,10 +2276,10 @@@
if (netif_msg_pktdata(priv)) {
void *tx_head;
- pr_debug("%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d",
- __func__, priv->cur_tx, priv->dirty_tx, first_entry,
- entry, first, nfrags);
+ netdev_dbg(priv->dev,
+ "%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d",
+ __func__, priv->cur_tx, priv->dirty_tx, first_entry,
+ entry, first, nfrags);
if (priv->extend_desc)
tx_head = (void *)priv->dma_etx;
@@@ -2277,13 -2288,13 +2288,13 @@@
priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false);
- pr_debug(">>> frame to be transmitted: ");
+ netdev_dbg(priv->dev, ">>> frame to be transmitted: ");
print_pkt(skb->data, skb->len);
}
if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
- if (netif_msg_hw(priv))
- pr_debug("%s: stop transmitted packets\n", __func__);
+ netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
+ __func__);
netif_stop_queue(dev);
}
@@@ -2319,13 -2330,11 +2330,11 @@@
if (dma_mapping_error(priv->device, des))
goto dma_map_err;
- if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) {
- first->des0 = des;
- priv->tx_skbuff_dma[first_entry].buf = first->des0;
- } else {
- first->des2 = des;
- priv->tx_skbuff_dma[first_entry].buf = first->des2;
- }
+ priv->tx_skbuff_dma[first_entry].buf = des;
+ if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
+ first->des0 = cpu_to_le32(des);
+ else
+ first->des2 = cpu_to_le32(des);
priv->tx_skbuff_dma[first_entry].len = nopaged_len;
priv->tx_skbuff_dma[first_entry].last_segment = last_segment;
@@@ -2362,7 -2371,7 +2371,7 @@@
dma_map_err:
spin_unlock(&priv->tx_lock);
- dev_err(priv->device, "Tx dma map failed\n");
+ netdev_err(priv->dev, "Tx DMA map failed\n");
dev_kfree_skb(skb);
priv->dev->stats.tx_dropped++;
return NETDEV_TX_OK;
@@@ -2433,16 -2442,16 +2442,16 @@@ static inline void stmmac_rx_refill(str
DMA_FROM_DEVICE);
if (dma_mapping_error(priv->device,
priv->rx_skbuff_dma[entry])) {
- dev_err(priv->device, "Rx dma map failed\n");
+ netdev_err(priv->dev, "Rx DMA map failed\n");
dev_kfree_skb(skb);
break;
}
if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) {
- p->des0 = priv->rx_skbuff_dma[entry];
+ p->des0 = cpu_to_le32(priv->rx_skbuff_dma[entry]);
p->des1 = 0;
} else {
- p->des2 = priv->rx_skbuff_dma[entry];
+ p->des2 = cpu_to_le32(priv->rx_skbuff_dma[entry]);
}
if (priv->hw->mode->refill_desc3)
priv->hw->mode->refill_desc3(priv, p);
@@@ -2450,8 -2459,8 +2459,8 @@@
if (priv->rx_zeroc_thresh > 0)
priv->rx_zeroc_thresh--;
- if (netif_msg_rx_status(priv))
- pr_debug("\trefill entry #%d\n", entry);
+ netif_dbg(priv, rx_status, priv->dev,
+ "refill entry #%d\n", entry);
}
wmb();
@@@ -2484,7 -2493,7 +2493,7 @@@ static int stmmac_rx(struct stmmac_pri
if (netif_msg_rx_status(priv)) {
void *rx_head;
- pr_info(">>>>>> %s: descriptor ring:\n", __func__);
- netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__);
++ netdev_info(priv->dev, ">>>>>> %s: descriptor ring:\n",
__func__);
if (priv->extend_desc)
rx_head = (void *)priv->dma_erx;
else
@@@ -2495,7 -2504,6 +2504,7 @@@
while (count < limit) {
int status;
struct dma_desc *p;
+ struct dma_desc *np;
if (priv->extend_desc)
p = (struct dma_desc *)(priv->dma_erx + entry);
@@@ -2515,11 -2523,9 +2524,11 @@@
next_entry = priv->cur_rx;
if (priv->extend_desc)
- prefetch(priv->dma_erx + next_entry);
+ np = (struct dma_desc *)(priv->dma_erx + next_entry);
else
- prefetch(priv->dma_rx + next_entry);
+ np = priv->dma_rx + next_entry;
+
+ prefetch(np);
if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
priv->hw->desc->rx_extended_status(&priv->dev->stats,
@@@ -2546,9 -2552,9 +2555,9 @@@
unsigned int des;
if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
- des = p->des0;
+ des = le32_to_cpu(p->des0);
else
- des = p->des2;
+ des = le32_to_cpu(p->des2);
frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
@@@ -2557,9 -2563,9 +2566,9 @@@
* ignored
*/
if (frame_len > priv->dma_buf_sz) {
- pr_err("%s: len %d larger than size (%d)\n",
- priv->dev->name, frame_len,
- priv->dma_buf_sz);
+ netdev_err(priv->dev,
+ "len %d larger than size (%d)\n",
+ frame_len, priv->dma_buf_sz);
priv->dev->stats.rx_length_errors++;
break;
}
@@@ -2571,11 -2577,11 +2580,11 @@@
frame_len -= ETH_FCS_LEN;
if (netif_msg_rx_status(priv)) {
- pr_info("\tdesc: %p [entry %d] buff=0x%x\n",
- p, entry, des);
- netdev_dbg(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n",
- p, entry, des);
++ netdev_info(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n",
++ p, entry, des);
if (frame_len > ETH_FRAME_LEN)
- pr_debug("\tframe size %d, COE: %d\n",
- frame_len, status);
+ netdev_dbg(priv->dev, "frame size %d, COE: %d\n",
+ frame_len, status);
}
/* The zero-copy is always used for all the sizes
@@@ -2612,8 -2618,9 +2621,9 @@@
} else {
skb = priv->rx_skbuff[entry];
if (unlikely(!skb)) {
- pr_err("%s: Inconsistent Rx chain\n",
- priv->dev->name);
+ netdev_err(priv->dev,
+ "%s: Inconsistent Rx chain\n",
+ priv->dev->name);
priv->dev->stats.rx_dropped++;
break;
}
@@@ -2628,13 -2635,14 +2638,14 @@@
DMA_FROM_DEVICE);
}
- stmmac_get_rx_hwtstamp(priv, entry, skb);
-
if (netif_msg_pktdata(priv)) {
- pr_debug("frame received (%dbytes)", frame_len);
+ netdev_dbg(priv->dev, "frame received (%dbytes)",
+ frame_len);
print_pkt(skb->data, frame_len);
}
+ stmmac_get_rx_hwtstamp(priv, p, np, skb);
+
stmmac_rx_vlan(priv->dev, skb);
skb->protocol = eth_type_trans(skb, priv->dev);
@@@ -2729,26 -2737,12 +2740,12 @@@ static void stmmac_set_rx_mode(struct n
static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
{
struct stmmac_priv *priv = netdev_priv(dev);
- int max_mtu;
if (netif_running(dev)) {
- pr_err("%s: must be stopped to change its MTU\n", dev->name);
+ netdev_err(priv->dev, "must be stopped to change its MTU\n");
return -EBUSY;
}
- if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00))
- max_mtu = JUMBO_LEN;
- else
- max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
-
- if (priv->plat->maxmtu < max_mtu)
- max_mtu = priv->plat->maxmtu;
-
- if ((new_mtu < 46) || (new_mtu > max_mtu)) {
- pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
- return -EINVAL;
- }
-
dev->mtu = new_mtu;
netdev_update_features(dev);
@@@ -2824,7 -2818,7 +2821,7 @@@ static irqreturn_t stmmac_interrupt(in
pm_wakeup_event(priv->device, 0);
if (unlikely(!dev)) {
- pr_err("%s: invalid dev pointer\n", __func__);
+ netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
return IRQ_NONE;
}
@@@ -2882,7 -2876,6 +2879,6 @@@ static void stmmac_poll_controller(stru
*/
static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct stmmac_priv *priv = netdev_priv(dev);
int ret = -EOPNOTSUPP;
if (!netif_running(dev))
@@@ -2892,9 -2885,9 +2888,9 @@@
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSMIIREG:
- if (!priv->phydev)
+ if (!dev->phydev)
return -EINVAL;
- ret = phy_mii_ioctl(priv->phydev, rq, cmd);
+ ret = phy_mii_ioctl(dev->phydev, rq, cmd);
break;
case SIOCSHWTSTAMP:
ret = stmmac_hwtstamp_ioctl(dev, rq);
@@@ -2922,14 -2915,17 +2918,17 @@@ static void sysfs_display_ring(void *he
x = *(u64 *) ep;
seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
i, (unsigned int)virt_to_phys(ep),
- ep->basic.des0, ep->basic.des1,
- ep->basic.des2, ep->basic.des3);
+ le32_to_cpu(ep->basic.des0),
+ le32_to_cpu(ep->basic.des1),
+ le32_to_cpu(ep->basic.des2),
+ le32_to_cpu(ep->basic.des3));
ep++;
} else {
x = *(u64 *) p;
seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
i, (unsigned int)virt_to_phys(ep),
- p->des0, p->des1, p->des2, p->des3);
+ le32_to_cpu(p->des0), le32_to_cpu(p->des1),
+ le32_to_cpu(p->des2), le32_to_cpu(p->des3));
p++;
}
seq_printf(seq, "\n");
@@@ -3054,8 -3050,7 +3053,7 @@@ static int stmmac_init_fs(struct net_de
priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
- pr_err("ERROR %s/%s, debugfs create directory failed\n",
- STMMAC_RESOURCE_NAME, dev->name);
+ netdev_err(priv->dev, "ERROR failed to create debugfs directory\n");
return -ENOMEM;
}
@@@ -3067,7 -3062,7 +3065,7 @@@
&stmmac_rings_status_fops);
if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
- pr_info("ERROR creating stmmac ring debugfs file\n");
+ netdev_err(priv->dev, "ERROR creating stmmac ring debugfs file\n");
debugfs_remove_recursive(priv->dbgfs_dir);
return -ENOMEM;
@@@ -3079,7 -3074,7 +3077,7 @@@
dev, &stmmac_dma_cap_fops);
if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
- pr_info("ERROR creating stmmac MMC debugfs file\n");
+ netdev_err(priv->dev, "ERROR creating stmmac MMC debugfs file\n");
debugfs_remove_recursive(priv->dbgfs_dir);
return -ENOMEM;
@@@ -3151,11 -3146,11 +3149,11 @@@ static int stmmac_hw_init(struct stmmac
} else {
if (chain_mode) {
priv->hw->mode = &chain_mode_ops;
- pr_info(" Chain mode enabled\n");
+ dev_info(priv->device, "Chain mode enabled\n");
priv->mode = STMMAC_CHAIN_MODE;
} else {
priv->hw->mode = &ring_mode_ops;
- pr_info(" Ring mode enabled\n");
+ dev_info(priv->device, "Ring mode enabled\n");
priv->mode = STMMAC_RING_MODE;
}
}
@@@ -3163,7 -3158,7 +3161,7 @@@
/* Get the HW capability (new GMAC newer than 3.50a) */
priv->hw_cap_support = stmmac_get_hw_features(priv);
if (priv->hw_cap_support) {
- pr_info(" DMA HW capability register supported");
+ dev_info(priv->device, "DMA HW capability register supported\n");
/* We can override some gmac/dma configuration fields: e.g.
* enh_desc, tx_coe (e.g. that are passed through the
@@@ -3188,8 -3183,9 +3186,9 @@@
else if (priv->dma_cap.rx_coe_type1)
priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
- } else
- pr_info(" No HW DMA feature register supported");
+ } else {
+ dev_info(priv->device, "No HW DMA feature register supported\n");
+ }
/* To use alternate (extended), normal or GMAC4 descriptor structures */
if (priv->synopsys_id >= DWMAC_CORE_4_00)
@@@ -3199,20 -3195,20 +3198,20 @@@
if (priv->plat->rx_coe) {
priv->hw->rx_csum = priv->plat->rx_coe;
- pr_info(" RX Checksum Offload Engine supported\n");
+ dev_info(priv->device, "RX Checksum Offload Engine supported\n");
if (priv->synopsys_id < DWMAC_CORE_4_00)
- pr_info("\tCOE Type %d\n", priv->hw->rx_csum);
+ dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum);
}
if (priv->plat->tx_coe)
- pr_info(" TX Checksum insertion supported\n");
+ dev_info(priv->device, "TX Checksum insertion supported\n");
if (priv->plat->pmt) {
- pr_info(" Wake-Up On Lan supported\n");
+ dev_info(priv->device, "Wake-Up On Lan supported\n");
device_set_wakeup_capable(priv->device, 1);
}
if (priv->dma_cap.tsoen)
- pr_info(" TSO supported\n");
+ dev_info(priv->device, "TSO supported\n");
return 0;
}
@@@ -3271,8 -3267,8 +3270,8 @@@ int stmmac_dvr_probe(struct device *dev
priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
if (IS_ERR(priv->stmmac_clk)) {
- dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
- __func__);
+ netdev_warn(priv->dev, "%s: warning: cannot get CSR clock\n",
+ __func__);
/* If failed to obtain stmmac_clk and specific clk_csr value
* is NOT passed from the platform, probe fail.
*/
@@@ -3321,7 -3317,7 +3320,7 @@@
if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
ndev->hw_features |= NETIF_F_TSO;
priv->tso = true;
- pr_info(" TSO feature enabled\n");
+ dev_info(priv->device, "TSO feature enabled\n");
}
ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
@@@ -3331,6 -3327,15 +3330,15 @@@
#endif
priv->msg_enable = netif_msg_init(debug, default_msg_level);
+ /* MTU range: 46 - hw-specific max */
+ ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
+ if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00))
+ ndev->max_mtu = JUMBO_LEN;
+ else
+ ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
+ if (priv->plat->maxmtu < ndev->max_mtu)
+ ndev->max_mtu = priv->plat->maxmtu;
+
if (flow_ctrl)
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
@@@ -3341,7 -3346,7 +3349,7 @@@
*/
if ((priv->synopsys_id >= DWMAC_CORE_3_50) &&
(!priv->plat->riwt_off)) {
priv->use_riwt = 1;
- pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
+ netdev_info(priv->dev, "Enable RX Mitigation via HW Watchdog Timer\n");
}
netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
@@@ -3351,7 -3356,8 +3359,8 @@@
ret = register_netdev(ndev);
if (ret) {
- pr_err("%s: ERROR %i registering the device\n", __func__, ret);
+ netdev_err(priv->dev, "%s: ERROR %i registering the device\n",
+ __func__, ret);
goto error_netdev_register;
}
@@@ -3374,8 -3380,9 +3383,9 @@@
/* MDIO bus Registration */
ret = stmmac_mdio_register(ndev);
if (ret < 0) {
- pr_debug("%s: MDIO bus (id: %d) registration failed",
- __func__, priv->plat->bus_id);
+ netdev_err(priv->dev,
+ "%s: MDIO bus (id: %d) registration failed",
+ __func__, priv->plat->bus_id);
goto error_mdio_register;
}
}
@@@ -3408,7 -3415,7 +3418,7 @@@ int stmmac_dvr_remove(struct device *de
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
- pr_info("%s:\n\tremoving driver", __func__);
+ netdev_info(priv->dev, "%s: removing driver", __func__);
priv->hw->dma->stop_rx(priv->ioaddr);
priv->hw->dma->stop_tx(priv->ioaddr);
@@@ -3447,8 -3454,8 +3457,8 @@@ int stmmac_suspend(struct device *dev
if (!ndev || !netif_running(ndev))
return 0;
- if (priv->phydev)
- phy_stop(priv->phydev);
+ if (ndev->phydev)
+ phy_stop(ndev->phydev);
spin_lock_irqsave(&priv->lock, flags);
@@@ -3542,8 -3549,8 +3552,8 @@@ int stmmac_resume(struct device *dev
spin_unlock_irqrestore(&priv->lock, flags);
- if (priv->phydev)
- phy_start(priv->phydev);
+ if (ndev->phydev)
+ phy_start(ndev->phydev);
return 0;
}
diff --combined drivers/net/ethernet/sun/sunbmac.c
index 02f4527,ea89ef3..c4caf48
--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@@ -623,7 -623,6 +623,7 @@@ static int bigmac_init_hw(struct bigma
void __iomem *gregs = bp->gregs;
void __iomem *cregs = bp->creg;
void __iomem *bregs = bp->bregs;
+ __u32 bblk_dvma = (__u32)bp->bblock_dvma;
unsigned char *e = &bp->dev->dev_addr[0];
/* Latch current counters into statistics. */
@@@ -672,9 -671,9 +672,9 @@@
bregs + BMAC_XIFCFG);
/* Tell the QEC where the ring descriptors are. */
- sbus_writel(bp->bblock_dvma + bib_offset(be_rxd, 0),
+ sbus_writel(bblk_dvma + bib_offset(be_rxd, 0),
cregs + CREG_RXDS);
- sbus_writel(bp->bblock_dvma + bib_offset(be_txd, 0),
+ sbus_writel(bblk_dvma + bib_offset(be_txd, 0),
cregs + CREG_TXDS);
/* Setup the FIFO pointers into QEC local memory. */
@@@ -1065,7 -1064,6 +1065,6 @@@ static const struct net_device_ops bigm
.ndo_get_stats = bigmac_get_stats,
.ndo_set_rx_mode = bigmac_set_multicast,
.ndo_tx_timeout = bigmac_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --combined drivers/net/ethernet/sun/sunqe.c
index 9582948,c5ef711..a6bcdcd
--- a/drivers/net/ethernet/sun/sunqe.c
+++ b/drivers/net/ethernet/sun/sunqe.c
@@@ -124,7 -124,7 +124,7 @@@ static void qe_init_rings(struct sunqe
{
struct qe_init_block *qb = qep->qe_block;
struct sunqe_buffers *qbufs = qep->buffers;
- __u32 qbufs_dvma = qep->buffers_dvma;
+ __u32 qbufs_dvma = (__u32)qep->buffers_dvma;
int i;
qep->rx_new = qep->rx_old = qep->tx_new = qep->tx_old = 0;
@@@ -144,7 -144,6 +144,7 @@@ static int qe_init(struct sunqe *qep, i
void __iomem *mregs = qep->mregs;
void __iomem *gregs = qecp->gregs;
unsigned char *e = &qep->dev->dev_addr[0];
+ __u32 qblk_dvma = (__u32)qep->qblock_dvma;
u32 tmp;
int i;
@@@ -153,8 -152,8 +153,8 @@@
return -EAGAIN;
/* Setup initial rx/tx init block pointers. */
- sbus_writel(qep->qblock_dvma + qib_offset(qe_rxd, 0), cregs + CREG_RXDS);
- sbus_writel(qep->qblock_dvma + qib_offset(qe_txd, 0), cregs + CREG_TXDS);
+ sbus_writel(qblk_dvma + qib_offset(qe_rxd, 0), cregs + CREG_RXDS);
+ sbus_writel(qblk_dvma + qib_offset(qe_txd, 0), cregs + CREG_TXDS);
/* Enable/mask the various irq's. */
sbus_writel(0, cregs + CREG_RIMASK);
@@@ -414,7 -413,7 +414,7 @@@ static void qe_rx(struct sunqe *qep
struct net_device *dev = qep->dev;
struct qe_rxd *this;
struct sunqe_buffers *qbufs = qep->buffers;
- __u32 qbufs_dvma = qep->buffers_dvma;
+ __u32 qbufs_dvma = (__u32)qep->buffers_dvma;
int elem = qep->rx_new;
u32 flags;
@@@ -573,7 -572,7 +573,7 @@@ static int qe_start_xmit(struct sk_buf
{
struct sunqe *qep = netdev_priv(dev);
struct sunqe_buffers *qbufs = qep->buffers;
- __u32 txbuf_dvma, qbufs_dvma = qep->buffers_dvma;
+ __u32 txbuf_dvma, qbufs_dvma = (__u32)qep->buffers_dvma;
unsigned char *txbuf;
int len, entry;
@@@ -824,7 -823,6 +824,6 @@@ static const struct net_device_ops qec_
.ndo_start_xmit = qe_start_xmit,
.ndo_set_rx_mode = qe_set_multicast,
.ndo_tx_timeout = qe_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
diff --combined drivers/net/ethernet/ti/cpsw.c
index 58947aa,39d06e8..da40ea5
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@@ -1376,10 -1376,6 +1376,6 @@@ static int cpsw_ndo_open(struct net_dev
ALE_ALL_PORTS, ALE_ALL_PORTS, 0, 0);
if (!cpsw_common_res_usage_state(cpsw)) {
- /* setup tx dma to fixed prio and zero offset */
- cpdma_control_set(cpsw->dma, CPDMA_TX_PRIO_FIXED, 1);
- cpdma_control_set(cpsw->dma, CPDMA_RX_BUFFER_OFFSET, 0);
-
/* disable priority elevation */
__raw_writel(0, &cpsw->regs->ptype);
@@@ -1883,7 -1879,6 +1879,6 @@@ static const struct net_device_ops cpsw
.ndo_set_mac_address = cpsw_ndo_set_mac_address,
.ndo_do_ioctl = cpsw_ndo_ioctl,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
.ndo_tx_timeout = cpsw_ndo_tx_timeout,
.ndo_set_rx_mode = cpsw_ndo_set_rx_mode,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@@ -1967,27 -1962,30 +1962,30 @@@ static int cpsw_get_ts_info(struct net_
return 0;
}
- static int cpsw_get_settings(struct net_device *ndev,
- struct ethtool_cmd *ecmd)
+ static int cpsw_get_link_ksettings(struct net_device *ndev,
+ struct ethtool_link_ksettings *ecmd)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
int slave_no = cpsw_slave_index(cpsw, priv);
if (cpsw->slaves[slave_no].phy)
- return phy_ethtool_gset(cpsw->slaves[slave_no].phy, ecmd);
+ return phy_ethtool_ksettings_get(cpsw->slaves[slave_no].phy,
+ ecmd);
else
return -EOPNOTSUPP;
}
- static int cpsw_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+ static int cpsw_set_link_ksettings(struct net_device *ndev,
+ const struct ethtool_link_ksettings *ecmd)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_common *cpsw = priv->cpsw;
int slave_no = cpsw_slave_index(cpsw, priv);
if (cpsw->slaves[slave_no].phy)
- return phy_ethtool_sset(cpsw->slaves[slave_no].phy, ecmd);
+ return phy_ethtool_ksettings_set(cpsw->slaves[slave_no].phy,
+ ecmd);
else
return -EOPNOTSUPP;
}
@@@ -2245,8 -2243,6 +2243,6 @@@ static const struct ethtool_ops cpsw_et
.set_msglevel = cpsw_set_msglevel,
.get_link = ethtool_op_get_link,
.get_ts_info = cpsw_get_ts_info,
- .get_settings = cpsw_get_settings,
- .set_settings = cpsw_set_settings,
.get_coalesce = cpsw_get_coalesce,
.set_coalesce = cpsw_set_coalesce,
.get_sset_count = cpsw_get_sset_count,
@@@ -2262,6 -2258,8 +2258,8 @@@
.complete = cpsw_ethtool_op_complete,
.get_channels = cpsw_get_channels,
.set_channels = cpsw_set_channels,
+ .get_link_ksettings = cpsw_get_link_ksettings,
+ .set_link_ksettings = cpsw_set_link_ksettings,
};
static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_common *cpsw,
@@@ -2375,11 -2373,8 +2373,11 @@@ static int cpsw_probe_dt(struct cpsw_pl
* to the PHY is the Ethernet MAC DT node.
*/
ret = of_phy_register_fixed_link(slave_node);
- if (ret)
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "failed to register fixed-link phy: %d\n",
ret);
return ret;
+ }
slave_data->phy_node = of_node_get(slave_node);
} else if (parp) {
u32 phyid;
@@@ -2400,7 -2395,6 +2398,7 @@@
}
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
PHY_ID_FMT, mdio->name, phyid);
+ put_device(&mdio->dev);
} else {
dev_err(&pdev->dev,
"No slave[%d] phy_id, phy-handle, or fixed-link property\n",
@@@ -2444,46 -2438,6 +2442,46 @@@ no_phy_slave
return 0;
}
+static void cpsw_remove_dt(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
+ struct cpsw_platform_data *data = &cpsw->data;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *slave_node;
+ int i = 0;
+
+ for_each_available_child_of_node(node, slave_node) {
+ struct cpsw_slave_data *slave_data = &data->slave_data[i];
+
+ if (strcmp(slave_node->name, "slave"))
+ continue;
+
+ if (of_phy_is_fixed_link(slave_node)) {
+ struct phy_device *phydev;
+
+ phydev = of_phy_find_device(slave_node);
+ if (phydev) {
+ fixed_phy_unregister(phydev);
+ /* Put references taken by
+ * of_phy_find_device() and
+ * of_phy_register_fixed_link().
+ */
+ phy_device_free(phydev);
+ phy_device_free(phydev);
+ }
+ }
+
+ of_node_put(slave_data->phy_node);
+
+ i++;
+ if (i == data->slaves)
+ break;
+ }
+
+ of_platform_depopulate(&pdev->dev);
+}
+
static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
{
struct cpsw_common *cpsw = priv->cpsw;
@@@ -2591,9 -2545,6 +2589,9 @@@ static int cpsw_probe(struct platform_d
int irq;
cpsw = devm_kzalloc(&pdev->dev, sizeof(struct cpsw_common), GFP_KERNEL);
+ if (!cpsw)
+ return -ENOMEM;
+
cpsw->dev = &pdev->dev;
ndev = alloc_etherdev_mq(sizeof(struct cpsw_priv), CPSW_MAX_QUEUES);
@@@ -2631,19 -2582,11 +2629,19 @@@
/* Select default pin state */
pinctrl_pm_select_default_state(&pdev->dev);
- if (cpsw_probe_dt(&cpsw->data, pdev)) {
- dev_err(&pdev->dev, "cpsw: platform data missing\n");
- ret = -ENODEV;
+ /* Need to enable clocks with runtime PM api to access module
+ * registers
+ */
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(&pdev->dev);
goto clean_runtime_disable_ret;
}
+
+ ret = cpsw_probe_dt(&cpsw->data, pdev);
+ if (ret)
+ goto clean_dt_ret;
+
data = &cpsw->data;
cpsw->rx_ch_num = 1;
cpsw->tx_ch_num = 1;
@@@ -2663,7 -2606,7 +2661,7 @@@
GFP_KERNEL);
if (!cpsw->slaves) {
ret = -ENOMEM;
- goto clean_runtime_disable_ret;
+ goto clean_dt_ret;
}
for (i = 0; i < data->slaves; i++)
cpsw->slaves[i].slave_num = i;
@@@ -2675,7 -2618,7 +2673,7 @@@
if (IS_ERR(clk)) {
dev_err(priv->dev, "fck is not found\n");
ret = -ENODEV;
- goto clean_runtime_disable_ret;
+ goto clean_dt_ret;
}
cpsw->bus_freq_mhz = clk_get_rate(clk) / 1000000;
@@@ -2683,17 -2626,26 +2681,17 @@@
ss_regs = devm_ioremap_resource(&pdev->dev, ss_res);
if (IS_ERR(ss_regs)) {
ret = PTR_ERR(ss_regs);
- goto clean_runtime_disable_ret;
+ goto clean_dt_ret;
}
cpsw->regs = ss_regs;
- /* Need to enable clocks with runtime PM api to access module
- * registers
- */
- ret = pm_runtime_get_sync(&pdev->dev);
- if (ret < 0) {
- pm_runtime_put_noidle(&pdev->dev);
- goto clean_runtime_disable_ret;
- }
cpsw->version = readl(&cpsw->regs->id_ver);
- pm_runtime_put_sync(&pdev->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
cpsw->wr_regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(cpsw->wr_regs)) {
ret = PTR_ERR(cpsw->wr_regs);
- goto clean_runtime_disable_ret;
+ goto clean_dt_ret;
}
memset(&dma_params, 0, sizeof(dma_params));
@@@ -2730,7 -2682,7 +2728,7 @@@
default:
dev_err(priv->dev, "unknown version 0x%08x\n", cpsw->version);
ret = -ENODEV;
- goto clean_runtime_disable_ret;
+ goto clean_dt_ret;
}
for (i = 0; i < cpsw->data.slaves; i++) {
struct cpsw_slave *slave = &cpsw->slaves[i];
@@@ -2759,7 -2711,7 +2757,7 @@@
if (!cpsw->dma) {
dev_err(priv->dev, "error initializing dma\n");
ret = -ENOMEM;
- goto clean_runtime_disable_ret;
+ goto clean_dt_ret;
}
cpsw->txch[0] = cpdma_chan_create(cpsw->dma, 0, cpsw_tx_handler, 0);
@@@ -2857,23 -2809,16 +2855,23 @@@
ret = cpsw_probe_dual_emac(priv);
if (ret) {
cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
- goto clean_ale_ret;
+ goto clean_unregister_netdev_ret;
}
}
+ pm_runtime_put(&pdev->dev);
+
return 0;
+clean_unregister_netdev_ret:
+ unregister_netdev(ndev);
clean_ale_ret:
cpsw_ale_destroy(cpsw->ale);
clean_dma_ret:
cpdma_ctlr_destroy(cpsw->dma);
+clean_dt_ret:
+ cpsw_remove_dt(pdev);
+ pm_runtime_put_sync(&pdev->dev);
clean_runtime_disable_ret:
pm_runtime_disable(&pdev->dev);
clean_ndev_ret:
@@@ -2899,7 -2844,7 +2897,7 @@@ static int cpsw_remove(struct platform_
cpsw_ale_destroy(cpsw->ale);
cpdma_ctlr_destroy(cpsw->dma);
- of_platform_depopulate(&pdev->dev);
+ cpsw_remove_dt(pdev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
if (cpsw->data.dual_emac)
diff --combined drivers/net/virtio_net.c
index 7276d5a,ca5239a..d4ac7a6
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@@ -1419,17 -1419,6 +1419,6 @@@ static const struct ethtool_ops virtnet
.set_settings = virtnet_set_settings,
};
- #define MIN_MTU 68
- #define MAX_MTU 65535
-
- static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
- {
- if (new_mtu < MIN_MTU || new_mtu > MAX_MTU)
- return -EINVAL;
- dev->mtu = new_mtu;
- return 0;
- }
-
static const struct net_device_ops virtnet_netdev = {
.ndo_open = virtnet_open,
.ndo_stop = virtnet_close,
@@@ -1437,7 -1426,6 +1426,6 @@@
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = virtnet_set_mac_address,
.ndo_set_rx_mode = virtnet_set_rx_mode,
- .ndo_change_mtu = virtnet_change_mtu,
.ndo_get_stats64 = virtnet_stats,
.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
@@@ -1497,11 -1485,6 +1485,11 @@@ static void virtnet_free_queues(struct
netif_napi_del(&vi->rq[i].napi);
}
+ /* We called napi_hash_del() before netif_napi_del(),
+ * we need to respect an RCU grace period before freeing vi->rq
+ */
+ synchronize_net();
+
kfree(vi->rq);
kfree(vi->sq);
}
@@@ -1753,6 -1736,9 +1741,9 @@@ static bool virtnet_validate_features(s
return true;
}
+ #define MIN_MTU ETH_MIN_MTU
+ #define MAX_MTU ETH_MAX_MTU
+
static int virtnet_probe(struct virtio_device *vdev)
{
int i, err;
@@@ -1826,6 -1812,10 +1817,10 @@@
dev->vlan_features = dev->features;
+ /* MTU range: 68 - 65535 */
+ dev->min_mtu = MIN_MTU;
+ dev->max_mtu = MAX_MTU;
+
/* Configuration may specify what MAC to use. Otherwise random. */
if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC))
virtio_cread_bytes(vdev,
@@@ -1880,8 -1870,12 +1875,12 @@@
mtu = virtio_cread16(vdev,
offsetof(struct virtio_net_config,
mtu));
- if (virtnet_change_mtu(dev, mtu))
+ if (mtu < dev->min_mtu) {
__virtio_clear_bit(vdev, VIRTIO_NET_F_MTU);
+ } else {
+ dev->mtu = mtu;
+ dev->max_mtu = mtu;
+ }
}
if (vi->any_header_sg)
diff --combined drivers/net/wireless/mac80211_hwsim.c
index d3bad57,1293f84..1620a5d
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@@ -250,7 -250,7 +250,7 @@@ static inline void hwsim_clear_chanctx_
cp->magic = 0;
}
- static int hwsim_net_id;
+ static unsigned int hwsim_net_id;
static int hwsim_netgroup;
@@@ -587,15 -587,8 +587,8 @@@ struct hwsim_radiotap_ack_hdr
__le16 rt_chbitmask;
} __packed;
- /* MAC80211_HWSIM netlinf family */
- static struct genl_family hwsim_genl_family = {
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .name = "MAC80211_HWSIM",
- .version = 1,
- .maxattr = HWSIM_ATTR_MAX,
- .netnsok = true,
- };
+ /* MAC80211_HWSIM netlink family */
+ static struct genl_family hwsim_genl_family;
enum hwsim_multicast_groups {
HWSIM_MCGRP_CONFIG,
@@@ -826,7 -819,7 +819,7 @@@ static void mac80211_hwsim_set_tsf(stru
data->bcn_delta = do_div(delta, bcn_int);
} else {
data->tsf_offset -= delta;
- data->bcn_delta = -do_div(delta, bcn_int);
+ data->bcn_delta = -(s64)do_div(delta, bcn_int);
}
}
@@@ -2256,35 -2249,51 +2249,51 @@@ static void mac80211_hwsim_get_et_stats
WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
}
+ #define HWSIM_COMMON_OPS \
+ .tx = mac80211_hwsim_tx, \
+ .start = mac80211_hwsim_start, \
+ .stop = mac80211_hwsim_stop, \
+ .add_interface = mac80211_hwsim_add_interface, \
+ .change_interface = mac80211_hwsim_change_interface, \
+ .remove_interface = mac80211_hwsim_remove_interface, \
+ .config = mac80211_hwsim_config, \
+ .configure_filter = mac80211_hwsim_configure_filter, \
+ .bss_info_changed = mac80211_hwsim_bss_info_changed, \
+ .sta_add = mac80211_hwsim_sta_add, \
+ .sta_remove = mac80211_hwsim_sta_remove, \
+ .sta_notify = mac80211_hwsim_sta_notify, \
+ .set_tim = mac80211_hwsim_set_tim, \
+ .conf_tx = mac80211_hwsim_conf_tx, \
+ .get_survey = mac80211_hwsim_get_survey, \
+ CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) \
+ .ampdu_action = mac80211_hwsim_ampdu_action, \
+ .flush = mac80211_hwsim_flush, \
+ .get_tsf = mac80211_hwsim_get_tsf, \
+ .set_tsf = mac80211_hwsim_set_tsf, \
+ .get_et_sset_count = mac80211_hwsim_get_et_sset_count, \
+ .get_et_stats = mac80211_hwsim_get_et_stats, \
+ .get_et_strings = mac80211_hwsim_get_et_strings,
+
static const struct ieee80211_ops mac80211_hwsim_ops = {
- .tx = mac80211_hwsim_tx,
- .start = mac80211_hwsim_start,
- .stop = mac80211_hwsim_stop,
- .add_interface = mac80211_hwsim_add_interface,
- .change_interface = mac80211_hwsim_change_interface,
- .remove_interface = mac80211_hwsim_remove_interface,
- .config = mac80211_hwsim_config,
- .configure_filter = mac80211_hwsim_configure_filter,
- .bss_info_changed = mac80211_hwsim_bss_info_changed,
- .sta_add = mac80211_hwsim_sta_add,
- .sta_remove = mac80211_hwsim_sta_remove,
- .sta_notify = mac80211_hwsim_sta_notify,
- .set_tim = mac80211_hwsim_set_tim,
- .conf_tx = mac80211_hwsim_conf_tx,
- .get_survey = mac80211_hwsim_get_survey,
- CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
- .ampdu_action = mac80211_hwsim_ampdu_action,
+ HWSIM_COMMON_OPS
.sw_scan_start = mac80211_hwsim_sw_scan,
.sw_scan_complete = mac80211_hwsim_sw_scan_complete,
- .flush = mac80211_hwsim_flush,
- .get_tsf = mac80211_hwsim_get_tsf,
- .set_tsf = mac80211_hwsim_set_tsf,
- .get_et_sset_count = mac80211_hwsim_get_et_sset_count,
- .get_et_stats = mac80211_hwsim_get_et_stats,
- .get_et_strings = mac80211_hwsim_get_et_strings,
};
- static struct ieee80211_ops mac80211_hwsim_mchan_ops;
+ static const struct ieee80211_ops mac80211_hwsim_mchan_ops = {
+ HWSIM_COMMON_OPS
+ .hw_scan = mac80211_hwsim_hw_scan,
+ .cancel_hw_scan = mac80211_hwsim_cancel_hw_scan,
+ .sw_scan_start = NULL,
+ .sw_scan_complete = NULL,
+ .remain_on_channel = mac80211_hwsim_roc,
+ .cancel_remain_on_channel = mac80211_hwsim_croc,
+ .add_chanctx = mac80211_hwsim_add_chanctx,
+ .remove_chanctx = mac80211_hwsim_remove_chanctx,
+ .change_chanctx = mac80211_hwsim_change_chanctx,
+ .assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx,
+ .unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx,
+ };
struct hwsim_new_radio_params {
unsigned int channels;
@@@ -2791,7 -2800,6 +2800,6 @@@ static void mac80211_hwsim_free(void
static const struct net_device_ops hwsim_netdev_ops = {
.ndo_start_xmit = hwsim_mon_xmit,
- .ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
@@@ -3236,6 -3244,18 +3244,18 @@@ static const struct genl_ops hwsim_ops[
},
};
+ static struct genl_family hwsim_genl_family __ro_after_init = {
+ .name = "MAC80211_HWSIM",
+ .version = 1,
+ .maxattr = HWSIM_ATTR_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = hwsim_ops,
+ .n_ops = ARRAY_SIZE(hwsim_ops),
+ .mcgrps = hwsim_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
+ };
+
static void destroy_radio(struct work_struct *work)
{
struct mac80211_hwsim_data *data =
@@@ -3283,15 -3303,13 +3303,13 @@@ static struct notifier_block hwsim_netl
.notifier_call = mac80211_hwsim_netlink_notify,
};
- static int hwsim_init_netlink(void)
+ static int __init hwsim_init_netlink(void)
{
int rc;
printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
- rc = genl_register_family_with_ops_groups(&hwsim_genl_family,
- hwsim_ops,
- hwsim_mcgrps);
+ rc = genl_register_family(&hwsim_genl_family);
if (rc)
goto failure;
@@@ -3360,21 -3378,6 +3378,6 @@@ static int __init init_mac80211_hwsim(v
if (channels < 1)
return -EINVAL;
- mac80211_hwsim_mchan_ops = mac80211_hwsim_ops;
- mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
- mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
- mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
- mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
- mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
- mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
- mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
- mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
- mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
- mac80211_hwsim_mchan_ops.assign_vif_chanctx =
- mac80211_hwsim_assign_vif_chanctx;
- mac80211_hwsim_mchan_ops.unassign_vif_chanctx =
- mac80211_hwsim_unassign_vif_chanctx;
-
spin_lock_init(&hwsim_radio_lock);
err = register_pernet_device(&hwsim_net_ops);
diff --combined drivers/thermal/thermal_core.c
index 7daffc1,911fd96..641faab
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@@ -5,9 -5,22 +5,9 @@@
* Copyright (C) 2008 Zhang Rui <rui.zhang(a)intel.com>
* Copyright (C) 2008 Sujith Thomas <sujith.thomas(a)intel.com>
*
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@@ -51,13 -64,6 +51,13 @@@ static atomic_t in_suspend
static struct thermal_governor *def_governor;
+/*
+ * Governor section: set of functions to handle thermal governors
+ *
+ * Functions to help in the life cycle of thermal governors within
+ * the thermal core and by the thermal governor code.
+ */
+
static struct thermal_governor *__find_governor(const char *name)
{
struct thermal_governor *pos;
@@@ -136,16 -142,11 +136,16 @@@ int thermal_register_governor(struct th
mutex_lock(&thermal_governor_lock);
err = -EBUSY;
- if (__find_governor(governor->name) == NULL) {
+ if (!__find_governor(governor->name)) {
+ bool match_default;
+
err = 0;
list_add(&governor->governor_list, &thermal_governor_list);
- if (!def_governor && !strncmp(governor->name,
- DEFAULT_THERMAL_GOVERNOR, THERMAL_NAME_LENGTH))
+ match_default = !strncmp(governor->name,
+ DEFAULT_THERMAL_GOVERNOR,
+ THERMAL_NAME_LENGTH);
+
+ if (!def_governor && match_default)
def_governor = governor;
}
@@@ -187,14 -188,14 +187,14 @@@ void thermal_unregister_governor(struc
mutex_lock(&thermal_governor_lock);
- if (__find_governor(governor->name) == NULL)
+ if (!__find_governor(governor->name))
goto exit;
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node) {
if (!strncasecmp(pos->governor->name, governor->name,
- THERMAL_NAME_LENGTH))
+ THERMAL_NAME_LENGTH))
thermal_set_governor(pos, NULL);
}
@@@ -202,92 -203,195 +202,92 @@@
list_del(&governor->governor_list);
exit:
mutex_unlock(&thermal_governor_lock);
- return;
-}
-
-static int get_idr(struct idr *idr, struct mutex *lock, int *id)
-{
- int ret;
-
- if (lock)
- mutex_lock(lock);
- ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
- if (lock)
- mutex_unlock(lock);
- if (unlikely(ret < 0))
- return ret;
- *id = ret;
- return 0;
-}
-
-static void release_idr(struct idr *idr, struct mutex *lock, int id)
-{
- if (lock)
- mutex_lock(lock);
- idr_remove(idr, id);
- if (lock)
- mutex_unlock(lock);
-}
-
-int get_tz_trend(struct thermal_zone_device *tz, int trip)
-{
- enum thermal_trend trend;
-
- if (tz->emul_temperature || !tz->ops->get_trend ||
- tz->ops->get_trend(tz, trip, &trend)) {
- if (tz->temperature > tz->last_temperature)
- trend = THERMAL_TREND_RAISING;
- else if (tz->temperature < tz->last_temperature)
- trend = THERMAL_TREND_DROPPING;
- else
- trend = THERMAL_TREND_STABLE;
- }
-
- return trend;
}
-EXPORT_SYMBOL(get_tz_trend);
-struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int trip)
+int thermal_zone_device_set_policy(struct thermal_zone_device *tz,
+ char *policy)
{
- struct thermal_instance *pos = NULL;
- struct thermal_instance *target_instance = NULL;
+ struct thermal_governor *gov;
+ int ret = -EINVAL;
+ mutex_lock(&thermal_governor_lock);
mutex_lock(&tz->lock);
- mutex_lock(&cdev->lock);
- list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
- if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev)
{
- target_instance = pos;
- break;
- }
- }
+ gov = __find_governor(strim(policy));
+ if (!gov)
+ goto exit;
- mutex_unlock(&cdev->lock);
- mutex_unlock(&tz->lock);
+ ret = thermal_set_governor(tz, gov);
- return target_instance;
-}
-EXPORT_SYMBOL(get_thermal_instance);
+exit:
+ mutex_unlock(&tz->lock);
+ mutex_unlock(&thermal_governor_lock);
-static void print_bind_err_msg(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int ret)
-{
- dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
- tz->type, cdev->type, ret);
+ return ret;
}
-static void __bind(struct thermal_zone_device *tz, int mask,
- struct thermal_cooling_device *cdev,
- unsigned long *limits,
- unsigned int weight)
+int thermal_build_list_of_policies(char *buf)
{
- int i, ret;
+ struct thermal_governor *pos;
+ ssize_t count = 0;
+ ssize_t size = PAGE_SIZE;
- for (i = 0; i < tz->trips; i++) {
- if (mask & (1 << i)) {
- unsigned long upper, lower;
+ mutex_lock(&thermal_governor_lock);
- upper = THERMAL_NO_LIMIT;
- lower = THERMAL_NO_LIMIT;
- if (limits) {
- lower = limits[i * 2];
- upper = limits[i * 2 + 1];
- }
- ret = thermal_zone_bind_cooling_device(tz, i, cdev,
- upper, lower,
- weight);
- if (ret)
- print_bind_err_msg(tz, cdev, ret);
- }
+ list_for_each_entry(pos, &thermal_governor_list, governor_list) {
+ size = PAGE_SIZE - count;
+ count += scnprintf(buf + count, size, "%s ", pos->name);
}
-}
+ count += scnprintf(buf + count, size, "\n");
-static void __unbind(struct thermal_zone_device *tz, int mask,
- struct thermal_cooling_device *cdev)
-{
- int i;
+ mutex_unlock(&thermal_governor_lock);
- for (i = 0; i < tz->trips; i++)
- if (mask & (1 << i))
- thermal_zone_unbind_cooling_device(tz, i, cdev);
+ return count;
}
-static void bind_cdev(struct thermal_cooling_device *cdev)
+static int __init thermal_register_governors(void)
{
- int i, ret;
- const struct thermal_zone_params *tzp;
- struct thermal_zone_device *pos = NULL;
-
- mutex_lock(&thermal_list_lock);
+ int result;
- list_for_each_entry(pos, &thermal_tz_list, node) {
- if (!pos->tzp && !pos->ops->bind)
- continue;
+ result = thermal_gov_step_wise_register();
+ if (result)
+ return result;
- if (pos->ops->bind) {
- ret = pos->ops->bind(pos, cdev);
- if (ret)
- print_bind_err_msg(pos, cdev, ret);
- continue;
- }
+ result = thermal_gov_fair_share_register();
+ if (result)
+ return result;
- tzp = pos->tzp;
- if (!tzp || !tzp->tbp)
- continue;
+ result = thermal_gov_bang_bang_register();
+ if (result)
+ return result;
- for (i = 0; i < tzp->num_tbps; i++) {
- if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
- continue;
- if (tzp->tbp[i].match(pos, cdev))
- continue;
- tzp->tbp[i].cdev = cdev;
- __bind(pos, tzp->tbp[i].trip_mask, cdev,
- tzp->tbp[i].binding_limits,
- tzp->tbp[i].weight);
- }
- }
+ result = thermal_gov_user_space_register();
+ if (result)
+ return result;
- mutex_unlock(&thermal_list_lock);
+ return thermal_gov_power_allocator_register();
}
-static void bind_tz(struct thermal_zone_device *tz)
+static void thermal_unregister_governors(void)
{
- int i, ret;
- struct thermal_cooling_device *pos = NULL;
- const struct thermal_zone_params *tzp = tz->tzp;
-
- if (!tzp && !tz->ops->bind)
- return;
-
- mutex_lock(&thermal_list_lock);
-
- /* If there is ops->bind, try to use ops->bind */
- if (tz->ops->bind) {
- list_for_each_entry(pos, &thermal_cdev_list, node) {
- ret = tz->ops->bind(tz, pos);
- if (ret)
- print_bind_err_msg(tz, pos, ret);
- }
- goto exit;
- }
-
- if (!tzp || !tzp->tbp)
- goto exit;
-
- list_for_each_entry(pos, &thermal_cdev_list, node) {
- for (i = 0; i < tzp->num_tbps; i++) {
- if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
- continue;
- if (tzp->tbp[i].match(tz, pos))
- continue;
- tzp->tbp[i].cdev = pos;
- __bind(tz, tzp->tbp[i].trip_mask, pos,
- tzp->tbp[i].binding_limits,
- tzp->tbp[i].weight);
- }
- }
-exit:
- mutex_unlock(&thermal_list_lock);
+ thermal_gov_step_wise_unregister();
+ thermal_gov_fair_share_unregister();
+ thermal_gov_bang_bang_unregister();
+ thermal_gov_user_space_unregister();
+ thermal_gov_power_allocator_unregister();
}
+/*
+ * Zone update section: main control loop applied to each zone while monitoring
+ *
+ * in polling mode. The monitoring is done using a workqueue.
+ * Same update may be done on a zone by calling thermal_zone_device_update().
+ *
+ * An update means:
+ * - Non-critical trips will invoke the governor responsible for that zone;
+ * - Hot trips will produce a notification to userspace;
+ * - Critical trip point will cause a system shutdown.
+ */
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
int delay)
{
@@@ -316,15 -420,14 +316,15 @@@ static void monitor_thermal_zone(struc
}
static void handle_non_critical_trips(struct thermal_zone_device *tz,
- int trip, enum thermal_trip_type trip_type)
+ int trip,
+ enum thermal_trip_type trip_type)
{
tz->governor ? tz->governor->throttle(tz, trip) :
def_governor->throttle(tz, trip);
}
static void handle_critical_trips(struct thermal_zone_device *tz,
- int trip, enum thermal_trip_type trip_type)
+ int trip, enum thermal_trip_type trip_type)
{
int trip_temp;
@@@ -368,6 -471,105 +368,6 @@@ static void handle_thermal_trip(struct
monitor_thermal_zone(tz);
}
-/**
- * thermal_zone_get_temp() - returns the temperature of a thermal zone
- * @tz: a valid pointer to a struct thermal_zone_device
- * @temp: a valid pointer to where to store the resulting temperature.
- *
- * When a valid thermal zone reference is passed, it will fetch its
- * temperature and fill @temp.
- *
- * Return: On success returns 0, an error code otherwise
- */
-int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
-{
- int ret = -EINVAL;
- int count;
- int crit_temp = INT_MAX;
- enum thermal_trip_type type;
-
- if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
- goto exit;
-
- mutex_lock(&tz->lock);
-
- ret = tz->ops->get_temp(tz, temp);
-
- if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
- for (count = 0; count < tz->trips; count++) {
- ret = tz->ops->get_trip_type(tz, count, &type);
- if (!ret && type == THERMAL_TRIP_CRITICAL) {
- ret = tz->ops->get_trip_temp(tz, count,
- &crit_temp);
- break;
- }
- }
-
- /*
- * Only allow emulating a temperature when the real temperature
- * is below the critical temperature so that the emulation code
- * cannot hide critical conditions.
- */
- if (!ret && *temp < crit_temp)
- *temp = tz->emul_temperature;
- }
-
- mutex_unlock(&tz->lock);
-exit:
- return ret;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
-
-void thermal_zone_set_trips(struct thermal_zone_device *tz)
-{
- int low = -INT_MAX;
- int high = INT_MAX;
- int trip_temp, hysteresis;
- int i, ret;
-
- mutex_lock(&tz->lock);
-
- if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
- goto exit;
-
- for (i = 0; i < tz->trips; i++) {
- int trip_low;
-
- tz->ops->get_trip_temp(tz, i, &trip_temp);
- tz->ops->get_trip_hyst(tz, i, &hysteresis);
-
- trip_low = trip_temp - hysteresis;
-
- if (trip_low < tz->temperature && trip_low > low)
- low = trip_low;
-
- if (trip_temp > tz->temperature && trip_temp < high)
- high = trip_temp;
- }
-
- /* No need to change trip points */
- if (tz->prev_low_trip == low && tz->prev_high_trip == high)
- goto exit;
-
- tz->prev_low_trip = low;
- tz->prev_high_trip = high;
-
- dev_dbg(&tz->device,
- "new temperature boundaries: %d < x < %d\n", low, high);
-
- /*
- * Set a temperature window. When this window is left the driver
- * must inform the thermal core via thermal_zone_device_update.
- */
- ret = tz->ops->set_trips(tz, low, high);
- if (ret)
- dev_err(&tz->device, "Failed to set trips: %d\n", ret);
-
-exit:
- mutex_unlock(&tz->lock);
-}
-EXPORT_SYMBOL_GPL(thermal_zone_set_trips);
-
static void update_temperature(struct thermal_zone_device *tz)
{
int temp, ret;
@@@ -427,24 -629,6 +427,24 @@@ void thermal_zone_device_update(struct
}
EXPORT_SYMBOL_GPL(thermal_zone_device_update);
+/**
+ * thermal_notify_framework - Sensor drivers use this API to notify framework
+ * @tz: thermal zone device
+ * @trip: indicates which trip point has been crossed
+ *
+ * This function handles the trip events from sensor drivers. It starts
+ * throttling the cooling devices according to the policy configured.
+ * For CRITICAL and HOT trip points, this notifies the respective drivers,
+ * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+ * The throttling policy is based on the configured platform data; if no
+ * platform data is provided, this uses the step_wise throttling policy.
+ */
+void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
+{
+ handle_thermal_trip(tz, trip);
+}
+EXPORT_SYMBOL_GPL(thermal_notify_framework);
+
static void thermal_zone_device_check(struct work_struct *work)
{
struct thermal_zone_device *tz = container_of(work, struct
@@@ -453,12 -637,445 +453,12 @@@
thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
}
-/* sys I/F for thermal zone */
-
-#define to_thermal_zone(_dev) \
- container_of(_dev, struct thermal_zone_device, device)
-
-static ssize_t
-type_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%s\n", tz->type);
-}
-
-static ssize_t
-temp_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int temperature, ret;
-
- ret = thermal_zone_get_temp(tz, &temperature);
-
- if (ret)
- return ret;
-
- return sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-mode_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- enum thermal_device_mode mode;
- int result;
-
- if (!tz->ops->get_mode)
- return -EPERM;
-
- result = tz->ops->get_mode(tz, &mode);
- if (result)
- return result;
-
- return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ?
"enabled"
- : "disabled");
-}
-
-static ssize_t
-mode_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int result;
-
- if (!tz->ops->set_mode)
- return -EPERM;
-
- if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
- result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
- else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
- result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
- else
- result = -EINVAL;
-
- if (result)
- return result;
-
- return count;
-}
-
-static ssize_t
-trip_point_type_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- enum thermal_trip_type type;
- int trip, result;
-
- if (!tz->ops->get_trip_type)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
- return -EINVAL;
-
- result = tz->ops->get_trip_type(tz, trip, &type);
- if (result)
- return result;
-
- switch (type) {
- case THERMAL_TRIP_CRITICAL:
- return sprintf(buf, "critical\n");
- case THERMAL_TRIP_HOT:
- return sprintf(buf, "hot\n");
- case THERMAL_TRIP_PASSIVE:
- return sprintf(buf, "passive\n");
- case THERMAL_TRIP_ACTIVE:
- return sprintf(buf, "active\n");
- default:
- return sprintf(buf, "unknown\n");
- }
-}
-
-static ssize_t
-trip_point_temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->set_trip_temp)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
- return -EINVAL;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- ret = tz->ops->set_trip_temp(tz, trip, temperature);
- if (ret)
- return ret;
-
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return count;
-}
-
-static ssize_t
-trip_point_temp_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->get_trip_temp)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
- return -EINVAL;
-
- ret = tz->ops->get_trip_temp(tz, trip, &temperature);
-
- if (ret)
- return ret;
-
- return sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->set_trip_hyst)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
- return -EINVAL;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- /*
- * We are not doing any check on the 'temperature' value
- * here. The driver implementing 'set_trip_hyst' has to
- * take care of this.
- */
- ret = tz->ops->set_trip_hyst(tz, trip, temperature);
-
- if (!ret)
- thermal_zone_set_trips(tz);
-
- return ret ? ret : count;
-}
-
-static ssize_t
-trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->get_trip_hyst)
- return -EPERM;
-
- if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
- return -EINVAL;
-
- ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
-
- return ret ? ret : sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-passive_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- struct thermal_cooling_device *cdev = NULL;
- int state;
-
- if (!sscanf(buf, "%d\n", &state))
- return -EINVAL;
-
- /* sanity check: values below 1000 millicelcius don't make sense
- * and can cause the system to go into a thermal heart attack
- */
- if (state && state < 1000)
- return -EINVAL;
-
- if (state && !tz->forced_passive) {
- mutex_lock(&thermal_list_lock);
- list_for_each_entry(cdev, &thermal_cdev_list, node) {
- if (!strncmp("Processor", cdev->type,
- sizeof("Processor")))
- thermal_zone_bind_cooling_device(tz,
- THERMAL_TRIPS_NONE, cdev,
- THERMAL_NO_LIMIT,
- THERMAL_NO_LIMIT,
- THERMAL_WEIGHT_DEFAULT);
- }
- mutex_unlock(&thermal_list_lock);
- if (!tz->passive_delay)
- tz->passive_delay = 1000;
- } else if (!state && tz->forced_passive) {
- mutex_lock(&thermal_list_lock);
- list_for_each_entry(cdev, &thermal_cdev_list, node) {
- if (!strncmp("Processor", cdev->type,
- sizeof("Processor")))
- thermal_zone_unbind_cooling_device(tz,
- THERMAL_TRIPS_NONE,
- cdev);
- }
- mutex_unlock(&thermal_list_lock);
- tz->passive_delay = 0;
- }
-
- tz->forced_passive = state;
-
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return count;
-}
-
-static ssize_t
-passive_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%d\n", tz->forced_passive);
-}
-
-static ssize_t
-policy_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int ret = -EINVAL;
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- struct thermal_governor *gov;
- char name[THERMAL_NAME_LENGTH];
-
- snprintf(name, sizeof(name), "%s", buf);
-
- mutex_lock(&thermal_governor_lock);
- mutex_lock(&tz->lock);
-
- gov = __find_governor(strim(name));
- if (!gov)
- goto exit;
-
- ret = thermal_set_governor(tz, gov);
- if (!ret)
- ret = count;
-
-exit:
- mutex_unlock(&tz->lock);
- mutex_unlock(&thermal_governor_lock);
- return ret;
-}
-
-static ssize_t
-policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%s\n", tz->governor->name);
-}
-
-static ssize_t
-available_policies_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct thermal_governor *pos;
- ssize_t count = 0;
- ssize_t size = PAGE_SIZE;
-
- mutex_lock(&thermal_governor_lock);
-
- list_for_each_entry(pos, &thermal_governor_list, governor_list) {
- size = PAGE_SIZE - count;
- count += scnprintf(buf + count, size, "%s ", pos->name);
- }
- count += scnprintf(buf + count, size, "\n");
-
- mutex_unlock(&thermal_governor_lock);
-
- return count;
-}
-
-static ssize_t
-emul_temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int ret = 0;
- int temperature;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- if (!tz->ops->set_emul_temp) {
- mutex_lock(&tz->lock);
- tz->emul_temperature = temperature;
- mutex_unlock(&tz->lock);
- } else {
- ret = tz->ops->set_emul_temp(tz, temperature);
- }
-
- if (!ret)
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return ret ? ret : count;
-}
-static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
-
-static ssize_t
-sustainable_power_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- if (tz->tzp)
- return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
- else
- return -EIO;
-}
-
-static ssize_t
-sustainable_power_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- u32 sustainable_power;
-
- if (!tz->tzp)
- return -EIO;
-
- if (kstrtou32(buf, 10, &sustainable_power))
- return -EINVAL;
-
- tz->tzp->sustainable_power = sustainable_power;
-
- return count;
-}
-static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
- sustainable_power_store);
-
-#define create_s32_tzp_attr(name) \
- static ssize_t \
- name##_show(struct device *dev, struct device_attribute *devattr, \
- char *buf) \
- { \
- struct thermal_zone_device *tz = to_thermal_zone(dev); \
- \
- if (tz->tzp) \
- return sprintf(buf, "%d\n", tz->tzp->name); \
- else \
- return -EIO; \
- } \
- \
- static ssize_t \
- name##_store(struct device *dev, struct device_attribute *devattr, \
- const char *buf, size_t count) \
- { \
- struct thermal_zone_device *tz = to_thermal_zone(dev); \
- s32 value; \
- \
- if (!tz->tzp) \
- return -EIO; \
- \
- if (kstrtos32(buf, 10, &value)) \
- return -EINVAL; \
- \
- tz->tzp->name = value; \
- \
- return count; \
- } \
- static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store)
-
-create_s32_tzp_attr(k_po);
-create_s32_tzp_attr(k_pu);
-create_s32_tzp_attr(k_i);
-create_s32_tzp_attr(k_d);
-create_s32_tzp_attr(integral_cutoff);
-create_s32_tzp_attr(slope);
-create_s32_tzp_attr(offset);
-#undef create_s32_tzp_attr
-
-static struct device_attribute *dev_tzp_attrs[] = {
- &dev_attr_sustainable_power,
- &dev_attr_k_po,
- &dev_attr_k_pu,
- &dev_attr_k_i,
- &dev_attr_k_d,
- &dev_attr_integral_cutoff,
- &dev_attr_slope,
- &dev_attr_offset,
-};
-
-static int create_tzp_attrs(struct device *dev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(dev_tzp_attrs); i++) {
- int ret;
- struct device_attribute *dev_attr = dev_tzp_attrs[i];
-
- ret = device_create_file(dev, dev_attr);
- if (ret)
- return ret;
- }
-
- return 0;
-}
+/*
+ * Power actor section: interface to power actors to estimate power
+ *
+ * Set of functions used to interact to cooling devices that know
+ * how to estimate their devices power consumption.
+ */
/**
* power_actor_get_max_power() - get the maximum power that a cdev can consume
@@@ -510,13 -1127,12 +510,13 @@@ int power_actor_get_min_power(struct th
}
/**
- * power_actor_set_power() - limit the maximum power that a cooling device can consume
+ * power_actor_set_power() - limit the maximum power a cooling device consumes
* @cdev: pointer to &thermal_cooling_device
* @instance: thermal instance to update
* @power: the power in milliwatts
*
- * Set the cooling device to consume at most @power milliwatts.
+ * Set the cooling device to consume at most @power milliwatts. The limit is
+ * expected to be a cap at the maximum power consumption.
*
* Return: 0 on success, -EINVAL if the cooling device does not
* implement the power actor API or -E* for other failures.
@@@ -543,75 -1159,143 +543,75 @@@ int power_actor_set_power(struct therma
return 0;
}
-static DEVICE_ATTR(type, 0444, type_show, NULL);
-static DEVICE_ATTR(temp, 0444, temp_show, NULL);
-static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
-static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
-static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
-static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
-
-/* sys I/F for cooling device */
-#define to_cooling_device(_dev) \
- container_of(_dev, struct thermal_cooling_device, device)
-
-static ssize_t
-thermal_cooling_device_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz,
+ const char *cdev_type, size_t size)
{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
+ struct thermal_cooling_device *cdev = NULL;
- return sprintf(buf, "%s\n", cdev->type);
+ mutex_lock(&thermal_list_lock);
+ list_for_each_entry(cdev, &thermal_cdev_list, node) {
+ /* skip non matching cdevs */
+ if (strncmp(cdev_type, cdev->type, size))
+ continue;
+
+ /* re binding the exception matching the type pattern */
+ thermal_zone_bind_cooling_device(tz, THERMAL_TRIPS_NONE, cdev,
+ THERMAL_NO_LIMIT,
+ THERMAL_NO_LIMIT,
+ THERMAL_WEIGHT_DEFAULT);
+ }
+ mutex_unlock(&thermal_list_lock);
}
-static ssize_t
-thermal_cooling_device_max_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,
+ const char *cdev_type, size_t size)
{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
- int ret;
+ struct thermal_cooling_device *cdev = NULL;
- ret = cdev->ops->get_max_state(cdev, &state);
- if (ret)
- return ret;
- return sprintf(buf, "%ld\n", state);
+ mutex_lock(&thermal_list_lock);
+ list_for_each_entry(cdev, &thermal_cdev_list, node) {
+ /* skip non matching cdevs */
+ if (strncmp(cdev_type, cdev->type, size))
+ continue;
+ /* unbinding the exception matching the type pattern */
+ thermal_zone_unbind_cooling_device(tz, THERMAL_TRIPS_NONE,
+ cdev);
+ }
+ mutex_unlock(&thermal_list_lock);
}
-static ssize_t
-thermal_cooling_device_cur_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+/*
+ * Device management section: cooling devices, zones devices, and binding
+ *
+ * Set of functions provided by the thermal core for:
+ * - cooling devices lifecycle: registration, unregistration,
+ * binding, and unbinding.
+ * - thermal zone devices lifecycle: registration, unregistration,
+ * binding, and unbinding.
+ */
+static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
int ret;
- ret = cdev->ops->get_cur_state(cdev, &state);
- if (ret)
+ if (lock)
+ mutex_lock(lock);
+ ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+ if (lock)
+ mutex_unlock(lock);
+ if (unlikely(ret < 0))
return ret;
- return sprintf(buf, "%ld\n", state);
-}
-
-static ssize_t
-thermal_cooling_device_cur_state_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
- int result;
-
- if (!sscanf(buf, "%ld\n", &state))
- return -EINVAL;
-
- if ((long)state < 0)
- return -EINVAL;
-
- result = cdev->ops->set_cur_state(cdev, state);
- if (result)
- return result;
- return count;
-}
-
-static struct device_attribute dev_attr_cdev_type =
-__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
-static DEVICE_ATTR(max_state, 0444,
- thermal_cooling_device_max_state_show, NULL);
-static DEVICE_ATTR(cur_state, 0644,
- thermal_cooling_device_cur_state_show,
- thermal_cooling_device_cur_state_store);
-
-static ssize_t
-thermal_cooling_device_trip_point_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_instance *instance;
-
- instance =
- container_of(attr, struct thermal_instance, attr);
-
- if (instance->trip == THERMAL_TRIPS_NONE)
- return sprintf(buf, "-1\n");
- else
- return sprintf(buf, "%d\n", instance->trip);
-}
-
-static struct attribute *cooling_device_attrs[] = {
- &dev_attr_cdev_type.attr,
- &dev_attr_max_state.attr,
- &dev_attr_cur_state.attr,
- NULL,
-};
-
-static const struct attribute_group cooling_device_attr_group = {
- .attrs = cooling_device_attrs,
-};
-
-static const struct attribute_group *cooling_device_attr_groups[] = {
- &cooling_device_attr_group,
- NULL,
-};
-
-static ssize_t
-thermal_cooling_device_weight_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_instance *instance;
-
- instance = container_of(attr, struct thermal_instance, weight_attr);
-
- return sprintf(buf, "%d\n", instance->weight);
+ *id = ret;
+ return 0;
}
-static ssize_t
-thermal_cooling_device_weight_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_instance *instance;
- int ret, weight;
-
- ret = kstrtoint(buf, 0, &weight);
- if (ret)
- return ret;
-
- instance = container_of(attr, struct thermal_instance, weight_attr);
- instance->weight = weight;
-
- return count;
+static void release_idr(struct idr *idr, struct mutex *lock, int id)
+{
+ if (lock)
+ mutex_lock(lock);
+ idr_remove(idr, id);
+ if (lock)
+ mutex_unlock(lock);
}
-/* Device management */
/**
* thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone
@@@ -674,7 -1358,8 +674,7 @@@ int thermal_zone_bind_cooling_device(st
if (lower > upper || upper > max_state)
return -EINVAL;
- dev =
- kzalloc(sizeof(struct thermal_instance), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->tz = tz;
@@@ -717,10 -1402,10 +717,10 @@@
mutex_lock(&tz->lock);
mutex_lock(&cdev->lock);
list_for_each_entry(pos, &tz->thermal_instances, tz_node)
- if (pos->tz == tz && pos->trip == trip && pos->cdev ==
cdev) {
- result = -EEXIST;
- break;
- }
+ if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev)
{
+ result = -EEXIST;
+ break;
+ }
if (!result) {
list_add_tail(&dev->tz_node, &tz->thermal_instances);
list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
@@@ -800,8 -1485,8 +800,8 @@@ static void thermal_release(struct devi
sizeof("thermal_zone") - 1)) {
tz = to_thermal_zone(dev);
kfree(tz);
- } else if(!strncmp(dev_name(dev), "cooling_device",
- sizeof("cooling_device") - 1)){
+ } else if (!strncmp(dev_name(dev), "cooling_device",
+ sizeof("cooling_device") - 1)) {
cdev = to_cooling_device(dev);
kfree(cdev);
}
@@@ -812,78 -1497,6 +812,78 @@@ static struct class thermal_class =
.dev_release = thermal_release,
};
+static inline
+void print_bind_err_msg(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int ret)
+{
+ dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
+ tz->type, cdev->type, ret);
+}
+
+static void __bind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev,
+ unsigned long *limits,
+ unsigned int weight)
+{
+ int i, ret;
+
+ for (i = 0; i < tz->trips; i++) {
+ if (mask & (1 << i)) {
+ unsigned long upper, lower;
+
+ upper = THERMAL_NO_LIMIT;
+ lower = THERMAL_NO_LIMIT;
+ if (limits) {
+ lower = limits[i * 2];
+ upper = limits[i * 2 + 1];
+ }
+ ret = thermal_zone_bind_cooling_device(tz, i, cdev,
+ upper, lower,
+ weight);
+ if (ret)
+ print_bind_err_msg(tz, cdev, ret);
+ }
+ }
+}
+
+static void bind_cdev(struct thermal_cooling_device *cdev)
+{
+ int i, ret;
+ const struct thermal_zone_params *tzp;
+ struct thermal_zone_device *pos = NULL;
+
+ mutex_lock(&thermal_list_lock);
+
+ list_for_each_entry(pos, &thermal_tz_list, node) {
+ if (!pos->tzp && !pos->ops->bind)
+ continue;
+
+ if (pos->ops->bind) {
+ ret = pos->ops->bind(pos, cdev);
+ if (ret)
+ print_bind_err_msg(pos, cdev, ret);
+ continue;
+ }
+
+ tzp = pos->tzp;
+ if (!tzp || !tzp->tbp)
+ continue;
+
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(pos, cdev))
+ continue;
+ tzp->tbp[i].cdev = cdev;
+ __bind(pos, tzp->tbp[i].trip_mask, cdev,
+ tzp->tbp[i].binding_limits,
+ tzp->tbp[i].weight);
+ }
+ }
+
+ mutex_unlock(&thermal_list_lock);
+}
+
/**
* __thermal_cooling_device_register() - register a new thermal cooling device
* @np: a pointer to a device tree node.
@@@ -916,7 -1529,7 +916,7 @@@ __thermal_cooling_device_register(struc
!ops->set_cur_state)
return ERR_PTR(-EINVAL);
- cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
+ cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
return ERR_PTR(-ENOMEM);
@@@ -933,7 -1546,7 +933,7 @@@
cdev->ops = ops;
cdev->updated = false;
cdev->device.class = &thermal_class;
- cdev->device.groups = cooling_device_attr_groups;
+ thermal_cooling_device_setup_sysfs(cdev);
cdev->devdata = devdata;
dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
result = device_register(&cdev->device);
@@@ -1006,22 -1619,12 +1006,22 @@@ thermal_of_cooling_device_register(stru
}
EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register);
+static void __unbind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev)
+{
+ int i;
+
+ for (i = 0; i < tz->trips; i++)
+ if (mask & (1 << i))
+ thermal_zone_unbind_cooling_device(tz, i, cdev);
+}
+
/**
- * thermal_cooling_device_unregister - removes the registered thermal cooling device
+ * thermal_cooling_device_unregister - removes a thermal cooling device
* @cdev: the thermal cooling device to remove.
*
- * thermal_cooling_device_unregister() must be called when the device is no
- * longer needed.
+ * thermal_cooling_device_unregister() must be called when a registered
+ * thermal cooling device is no longer needed.
*/
void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
{
@@@ -1035,8 -1638,8 +1035,8 @@@
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_cdev_list, node)
- if (pos == cdev)
- break;
+ if (pos == cdev)
+ break;
if (pos != cdev) {
/* thermal cooling device not found */
mutex_unlock(&thermal_list_lock);
@@@ -1065,49 -1668,171 +1065,49 @@@
mutex_unlock(&thermal_list_lock);
- if (cdev->type[0])
- device_remove_file(&cdev->device, &dev_attr_cdev_type);
- device_remove_file(&cdev->device, &dev_attr_max_state);
- device_remove_file(&cdev->device, &dev_attr_cur_state);
-
release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
device_unregister(&cdev->device);
- return;
}
EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);
-void thermal_cdev_update(struct thermal_cooling_device *cdev)
+static void bind_tz(struct thermal_zone_device *tz)
{
- struct thermal_instance *instance;
- unsigned long target = 0;
+ int i, ret;
+ struct thermal_cooling_device *pos = NULL;
+ const struct thermal_zone_params *tzp = tz->tzp;
- mutex_lock(&cdev->lock);
- /* cooling device is updated*/
- if (cdev->updated) {
- mutex_unlock(&cdev->lock);
+ if (!tzp && !tz->ops->bind)
return;
- }
-
- /* Make sure cdev enters the deepest cooling state */
- list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
- dev_dbg(&cdev->device, "zone%d->target=%lu\n",
- instance->tz->id, instance->target);
- if (instance->target == THERMAL_NO_TARGET)
- continue;
- if (instance->target > target)
- target = instance->target;
- }
- cdev->ops->set_cur_state(cdev, target);
- cdev->updated = true;
- mutex_unlock(&cdev->lock);
- trace_cdev_update(cdev, target);
- dev_dbg(&cdev->device, "set to state %lu\n", target);
-}
-EXPORT_SYMBOL(thermal_cdev_update);
-
-/**
- * thermal_notify_framework - Sensor drivers use this API to notify framework
- * @tz: thermal zone device
- * @trip: indicates which trip point has been crossed
- *
- * This function handles the trip events from sensor drivers. It starts
- * throttling the cooling devices according to the policy configured.
- * For CRITICAL and HOT trip points, this notifies the respective drivers,
- * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
- * The throttling policy is based on the configured platform data; if no
- * platform data is provided, this uses the step_wise throttling policy.
- */
-void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
-{
- handle_thermal_trip(tz, trip);
-}
-EXPORT_SYMBOL_GPL(thermal_notify_framework);
-
-/**
- * create_trip_attrs() - create attributes for trip points
- * @tz: the thermal zone device
- * @mask: Writeable trip point bitmap.
- *
- * helper function to instantiate sysfs entries for every trip
- * point and its properties of a struct thermal_zone_device.
- *
- * Return: 0 on success, the proper error value otherwise.
- */
-static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
-{
- int indx;
- int size = sizeof(struct thermal_attr) * tz->trips;
- tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_type_attrs)
- return -ENOMEM;
-
- tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_temp_attrs) {
- kfree(tz->trip_type_attrs);
- return -ENOMEM;
- }
+ mutex_lock(&thermal_list_lock);
- if (tz->ops->get_trip_hyst) {
- tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_hyst_attrs) {
- kfree(tz->trip_type_attrs);
- kfree(tz->trip_temp_attrs);
- return -ENOMEM;
+ /* If there is ops->bind, try to use ops->bind */
+ if (tz->ops->bind) {
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ ret = tz->ops->bind(tz, pos);
+ if (ret)
+ print_bind_err_msg(tz, pos, ret);
}
+ goto exit;
}
+ if (!tzp || !tzp->tbp)
+ goto exit;
- for (indx = 0; indx < tz->trips; indx++) {
- /* create trip type attribute */
- snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_type", indx);
-
- sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
- tz->trip_type_attrs[indx].attr.attr.name =
- tz->trip_type_attrs[indx].name;
- tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
- tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
-
- device_create_file(&tz->device,
- &tz->trip_type_attrs[indx].attr);
-
- /* create trip temp attribute */
- snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_temp", indx);
-
- sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
- tz->trip_temp_attrs[indx].attr.attr.name =
- tz->trip_temp_attrs[indx].name;
- tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
- tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
- if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
- mask & (1 << indx)) {
- tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
- tz->trip_temp_attrs[indx].attr.store =
- trip_point_temp_store;
- }
-
- device_create_file(&tz->device,
- &tz->trip_temp_attrs[indx].attr);
-
- /* create Optional trip hyst attribute */
- if (!tz->ops->get_trip_hyst)
- continue;
- snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_hyst", indx);
-
- sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
- tz->trip_hyst_attrs[indx].attr.attr.name =
- tz->trip_hyst_attrs[indx].name;
- tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
- tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
- if (tz->ops->set_trip_hyst) {
- tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
- tz->trip_hyst_attrs[indx].attr.store =
- trip_point_hyst_store;
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(tz, pos))
+ continue;
+ tzp->tbp[i].cdev = pos;
+ __bind(tz, tzp->tbp[i].trip_mask, pos,
+ tzp->tbp[i].binding_limits,
+ tzp->tbp[i].weight);
}
-
- device_create_file(&tz->device,
- &tz->trip_hyst_attrs[indx].attr);
- }
- return 0;
-}
-
-static void remove_trip_attrs(struct thermal_zone_device *tz)
-{
- int indx;
-
- for (indx = 0; indx < tz->trips; indx++) {
- device_remove_file(&tz->device,
- &tz->trip_type_attrs[indx].attr);
- device_remove_file(&tz->device,
- &tz->trip_temp_attrs[indx].attr);
- if (tz->ops->get_trip_hyst)
- device_remove_file(&tz->device,
- &tz->trip_hyst_attrs[indx].attr);
}
- kfree(tz->trip_type_attrs);
- kfree(tz->trip_temp_attrs);
- kfree(tz->trip_hyst_attrs);
+exit:
+ mutex_unlock(&thermal_list_lock);
}
/**
@@@ -1134,22 -1859,20 +1134,22 @@@
* in case of error, an ERR_PTR. Caller must check return value with
* IS_ERR*() helpers.
*/
-struct thermal_zone_device *thermal_zone_device_register(const char *type,
- int trips, int mask, void *devdata,
- struct thermal_zone_device_ops *ops,
- struct thermal_zone_params *tzp,
- int passive_delay, int polling_delay)
+struct thermal_zone_device *
+thermal_zone_device_register(const char *type, int trips, int mask,
+ void *devdata, struct thermal_zone_device_ops *ops,
+ struct thermal_zone_params *tzp, int passive_delay,
+ int polling_delay)
{
struct thermal_zone_device *tz;
enum thermal_trip_type trip_type;
int trip_temp;
int result;
int count;
- int passive = 0;
struct thermal_governor *governor;
+ if (!type || strlen(type) == 0)
+ return ERR_PTR(-EINVAL);
+
if (type && strlen(type) >= THERMAL_NAME_LENGTH)
return ERR_PTR(-EINVAL);
@@@ -1162,7 -1885,7 +1162,7 @@@
if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
return ERR_PTR(-EINVAL);
- tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
+ tz = kzalloc(sizeof(*tz), GFP_KERNEL);
if (!tz)
return ERR_PTR(-ENOMEM);
@@@ -1175,7 -1898,7 +1175,7 @@@
return ERR_PTR(result);
}
- strlcpy(tz->type, type ? : "", sizeof(tz->type));
+ strlcpy(tz->type, type, sizeof(tz->type));
tz->ops = ops;
tz->tzp = tzp;
tz->device.class = &thermal_class;
@@@ -1183,13 -1906,6 +1183,13 @@@
tz->trips = trips;
tz->passive_delay = passive_delay;
tz->polling_delay = polling_delay;
+
+ /* sys I/F */
+ /* Add nodes that are always present via .groups */
+ result = thermal_zone_create_device_groups(tz, mask);
+ if (result)
+ goto unregister;
+
/* A new thermal zone needs to be updated anyway. */
atomic_set(&tz->need_update, 1);
@@@ -1201,9 -1917,32 +1201,9 @@@
return ERR_PTR(result);
}
- /* sys I/F */
- if (type) {
- result = device_create_file(&tz->device, &dev_attr_type);
- if (result)
- goto unregister;
- }
-
- result = device_create_file(&tz->device, &dev_attr_temp);
- if (result)
- goto unregister;
-
- if (ops->get_mode) {
- result = device_create_file(&tz->device, &dev_attr_mode);
- if (result)
- goto unregister;
- }
-
- result = create_trip_attrs(tz, mask);
- if (result)
- goto unregister;
-
for (count = 0; count < trips; count++) {
if (tz->ops->get_trip_type(tz, count, &trip_type))
set_bit(count, &tz->trips_disabled);
- if (trip_type == THERMAL_TRIP_PASSIVE)
- passive = 1;
if (tz->ops->get_trip_temp(tz, count, &trip_temp))
set_bit(count, &tz->trips_disabled);
/* Check for bogus trip points */
@@@ -1211,6 -1950,33 +1211,6 @@@
set_bit(count, &tz->trips_disabled);
}
- if (!passive) {
- result = device_create_file(&tz->device, &dev_attr_passive);
- if (result)
- goto unregister;
- }
-
- if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) {
- result = device_create_file(&tz->device, &dev_attr_emul_temp);
- if (result)
- goto unregister;
- }
-
- /* Create policy attribute */
- result = device_create_file(&tz->device, &dev_attr_policy);
- if (result)
- goto unregister;
-
- /* Add thermal zone params */
- result = create_tzp_attrs(&tz->device);
- if (result)
- goto unregister;
-
- /* Create available_policies attribute */
- result = device_create_file(&tz->device, &dev_attr_available_policies);
- if (result)
- goto unregister;
-
/* Update 'this' zone's governor information */
mutex_lock(&thermal_governor_lock);
@@@ -1240,7 -2006,7 +1240,7 @@@
/* Bind cooling devices for this zone */
bind_tz(tz);
- INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
+ INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
thermal_zone_device_reset(tz);
/* Update the new thermal zone and mark it as already updated. */
@@@ -1274,8 -2040,8 +1274,8 @@@ void thermal_zone_device_unregister(str
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node)
- if (pos == tz)
- break;
+ if (pos == tz)
+ break;
if (pos != tz) {
/* thermal zone device not found */
mutex_unlock(&thermal_list_lock);
@@@ -1305,10 -2071,14 +1305,10 @@@
thermal_zone_device_set_polling(tz, 0);
- if (tz->type[0])
- device_remove_file(&tz->device, &dev_attr_type);
- device_remove_file(&tz->device, &dev_attr_temp);
- if (tz->ops->get_mode)
- device_remove_file(&tz->device, &dev_attr_mode);
- device_remove_file(&tz->device, &dev_attr_policy);
- device_remove_file(&tz->device, &dev_attr_available_policies);
- remove_trip_attrs(tz);
+ kfree(tz->trip_type_attrs);
+ kfree(tz->trip_temp_attrs);
+ kfree(tz->trip_hyst_attrs);
+ kfree(tz->trips_attribute_group.attrs);
thermal_set_governor(tz, NULL);
thermal_remove_hwmon_sysfs(tz);
@@@ -1316,7 -2086,7 +1316,7 @@@
idr_destroy(&tz->idr);
mutex_destroy(&tz->lock);
device_unregister(&tz->device);
- return;
+ kfree(tz->device.groups);
}
EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
@@@ -1358,13 -2128,43 +1358,13 @@@ exit
}
EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
-/**
- * thermal_zone_get_slope - return the slope attribute of the thermal zone
- * @tz: thermal zone device with the slope attribute
- *
- * Return: If the thermal zone device has a slope attribute, return it, else
- * return 1.
- */
-int thermal_zone_get_slope(struct thermal_zone_device *tz)
-{
- if (tz && tz->tzp)
- return tz->tzp->slope;
- return 1;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
-
-/**
- * thermal_zone_get_offset - return the offset attribute of the thermal zone
- * @tz: thermal zone device with the offset attribute
- *
- * Return: If the thermal zone device has a offset attribute, return it, else
- * return 0.
- */
-int thermal_zone_get_offset(struct thermal_zone_device *tz)
-{
- if (tz && tz->tzp)
- return tz->tzp->offset;
- return 0;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
-
#ifdef CONFIG_NET
static const struct genl_multicast_group thermal_event_mcgrps[] = {
{ .name = THERMAL_GENL_MCAST_GROUP_NAME, },
};
- static struct genl_family thermal_event_genl_family = {
- .id = GENL_ID_GENERATE,
+ static struct genl_family thermal_event_genl_family __ro_after_init = {
+ .module = THIS_MODULE,
.name = THERMAL_GENL_FAMILY_NAME,
.version = THERMAL_GENL_VERSION,
.maxattr = THERMAL_GENL_ATTR_MAX,
@@@ -1373,7 -2173,7 +1373,7 @@@
};
int thermal_generate_netlink_event(struct thermal_zone_device *tz,
- enum events event)
+ enum events event)
{
struct sk_buff *skb;
struct nlattr *attr;
@@@ -1435,7 -2235,7 +1435,7 @@@
}
EXPORT_SYMBOL_GPL(thermal_generate_netlink_event);
- static int genetlink_init(void)
+ static int __init genetlink_init(void)
{
return genl_register_family(&thermal_event_genl_family);
}
@@@ -1449,8 -2249,40 +1449,8 @@@ static inline int genetlink_init(void)
static inline void genetlink_exit(void) {}
#endif /* !CONFIG_NET */
-static int __init thermal_register_governors(void)
-{
- int result;
-
- result = thermal_gov_step_wise_register();
- if (result)
- return result;
-
- result = thermal_gov_fair_share_register();
- if (result)
- return result;
-
- result = thermal_gov_bang_bang_register();
- if (result)
- return result;
-
- result = thermal_gov_user_space_register();
- if (result)
- return result;
-
- return thermal_gov_power_allocator_register();
-}
-
-static void thermal_unregister_governors(void)
-{
- thermal_gov_step_wise_unregister();
- thermal_gov_fair_share_unregister();
- thermal_gov_bang_bang_unregister();
- thermal_gov_user_space_unregister();
- thermal_gov_power_allocator_unregister();
-}
-
static int thermal_pm_notify(struct notifier_block *nb,
- unsigned long mode, void *_unused)
+ unsigned long mode, void *_unused)
{
struct thermal_zone_device *tz;
diff --combined fs/dlm/netlink.c
index 934ab06,0643ae4..43a96c3
--- a/fs/dlm/netlink.c
+++ b/fs/dlm/netlink.c
@@@ -16,11 -16,7 +16,7 @@@
static uint32_t dlm_nl_seqnum;
static uint32_t listener_nlportid;
- static struct genl_family family = {
- .id = GENL_ID_GENERATE,
- .name = DLM_GENL_NAME,
- .version = DLM_GENL_VERSION,
- };
+ static struct genl_family family;
static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
{
@@@ -69,16 -65,24 +65,24 @@@ static int user_cmd(struct sk_buff *skb
return 0;
}
-static struct genl_ops dlm_nl_ops[] = {
+static const struct genl_ops dlm_nl_ops[] = {
{
.cmd = DLM_CMD_HELLO,
.doit = user_cmd,
},
};
+ static struct genl_family family __ro_after_init = {
+ .name = DLM_GENL_NAME,
+ .version = DLM_GENL_VERSION,
+ .ops = dlm_nl_ops,
+ .n_ops = ARRAY_SIZE(dlm_nl_ops),
+ .module = THIS_MODULE,
+ };
+
int __init dlm_netlink_init(void)
{
- return genl_register_family_with_ops(&family, dlm_nl_ops);
+ return genl_register_family(&family);
}
void dlm_netlink_exit(void)
diff --combined fs/nfsd/nfsctl.c
index be13063,2857e46..f3b2f34
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@@ -217,7 -217,7 +217,7 @@@ static const struct file_operations poo
.release = nfsd_pool_stats_release,
};
-static struct file_operations reply_cache_stats_operations = {
+static const struct file_operations reply_cache_stats_operations = {
.open = nfsd_reply_cache_stats_open,
.read = seq_read,
.llseek = seq_lseek,
@@@ -1201,7 -1201,7 +1201,7 @@@ static int create_proc_exports_entry(vo
}
#endif
- int nfsd_net_id;
+ unsigned int nfsd_net_id;
static __net_init int nfsd_init_net(struct net *net)
{
diff --combined include/linux/bpf_verifier.h
index 6aaf425,ac5b393..7453c12
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@@ -14,7 -14,7 +14,7 @@@
* are obviously wrong for any sort of memory access.
*/
#define BPF_REGISTER_MAX_RANGE (1024 * 1024 * 1024)
-#define BPF_REGISTER_MIN_RANGE -(1024 * 1024 * 1024)
+#define BPF_REGISTER_MIN_RANGE -1
struct bpf_reg_state {
enum bpf_reg_type type;
@@@ -22,15 -22,14 +22,15 @@@
* Used to determine if any memory access using this register will
* result in a bad access.
*/
- u64 min_value, max_value;
+ s64 min_value;
+ u64 max_value;
+ u32 id;
union {
/* valid when type == CONST_IMM | PTR_TO_STACK | UNKNOWN_VALUE */
s64 imm;
/* valid when type == PTR_TO_PACKET* */
struct {
- u32 id;
u16 off;
u16 range;
};
diff --combined include/linux/device.h
index 36d3a98,a00105c..94926d3
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@@ -698,6 -698,25 +698,25 @@@ static inline int devm_add_action_or_re
return ret;
}
+ /**
+ * devm_alloc_percpu - Resource-managed alloc_percpu
+ * @dev: Device to allocate per-cpu memory for
+ * @type: Type to allocate per-cpu memory for
+ *
+ * Managed alloc_percpu. Per-cpu memory allocated with this function is
+ * automatically freed on driver detach.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+ #define devm_alloc_percpu(dev, type) \
+ ((typeof(type) __percpu *)__devm_alloc_percpu((dev), sizeof(type), \
+ __alignof__(type)))
+
+ void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
+ size_t align);
+ void devm_free_percpu(struct device *dev, void __percpu *pdata);
+
struct device_dma_parameters {
/*
* a low level driver may set these to teach IOMMU code about
@@@ -733,7 -752,7 +752,7 @@@
* minimizes board-specific #ifdefs in drivers.
* @driver_data: Private pointer for driver specific info.
* @power: For device power management.
- * See Documentation/power/devices.txt for details.
+ * See Documentation/power/admin-guide/devices.rst for details.
* @pm_domain: Provide callbacks that are executed during system suspend,
* hibernation, system resume and during runtime PM transitions
* along with subsystem-level and driver-level callbacks.
diff --combined include/net/net_namespace.h
index 0940598,d7149e9..af8fe8a
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@@ -170,7 -170,7 +170,7 @@@ static inline struct net *copy_net_ns(u
extern struct list_head net_namespace_list;
struct net *get_net_ns_by_pid(pid_t pid);
-struct net *get_net_ns_by_fd(int pid);
+struct net *get_net_ns_by_fd(int fd);
#ifdef CONFIG_SYSCTL
void ipx_register_sysctl(void);
@@@ -291,7 -291,7 +291,7 @@@ struct pernet_operations
int (*init)(struct net *net);
void (*exit)(struct net *net);
void (*exit_batch)(struct list_head *net_exit_list);
- int *id;
+ unsigned int *id;
size_t size;
};
diff --combined kernel/bpf/verifier.c
index 6a93615,89f787c..8740c5f
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@@ -19,6 -19,7 +19,7 @@@
#include <net/netlink.h>
#include <linux/file.h>
#include <linux/vmalloc.h>
+ #include <linux/stringify.h>
/* bpf_check() is a static code analyzer that walks eBPF program
* instruction by instruction and updates register/stack state.
@@@ -190,6 -191,22 +191,22 @@@ static const char * const reg_type_str[
[PTR_TO_PACKET_END] = "pkt_end",
};
+ #define __BPF_FUNC_STR_FN(x) [BPF_FUNC_ ## x] = __stringify(bpf_ ## x)
+ static const char * const func_id_str[] = {
+ __BPF_FUNC_MAPPER(__BPF_FUNC_STR_FN)
+ };
+ #undef __BPF_FUNC_STR_FN
+
+ static const char *func_id_name(int id)
+ {
+ BUILD_BUG_ON(ARRAY_SIZE(func_id_str) != __BPF_FUNC_MAX_ID);
+
+ if (id >= 0 && id < __BPF_FUNC_MAX_ID && func_id_str[id])
+ return func_id_str[id];
+ else
+ return "unknown";
+ }
+
static void print_verifier_state(struct bpf_verifier_state *state)
{
struct bpf_reg_state *reg;
@@@ -212,12 -229,13 +229,13 @@@
else if (t == CONST_PTR_TO_MAP || t == PTR_TO_MAP_VALUE ||
t == PTR_TO_MAP_VALUE_OR_NULL ||
t == PTR_TO_MAP_VALUE_ADJ)
- verbose("(ks=%d,vs=%d)",
+ verbose("(ks=%d,vs=%d,id=%u)",
reg->map_ptr->key_size,
- reg->map_ptr->value_size);
+ reg->map_ptr->value_size,
+ reg->id);
if (reg->min_value != BPF_REGISTER_MIN_RANGE)
- verbose(",min_value=%llu",
- (unsigned long long)reg->min_value);
+ verbose(",min_value=%lld",
+ (long long)reg->min_value);
if (reg->max_value != BPF_REGISTER_MAX_RANGE)
verbose(",max_value=%llu",
(unsigned long long)reg->max_value);
@@@ -353,7 -371,8 +371,8 @@@ static void print_bpf_insn(struct bpf_i
u8 opcode = BPF_OP(insn->code);
if (opcode == BPF_CALL) {
- verbose("(%02x) call %d\n", insn->code, insn->imm);
+ verbose("(%02x) call %s#%d\n", insn->code,
+ func_id_name(insn->imm), insn->imm);
} else if (insn->code == (BPF_JMP | BPF_JA)) {
verbose("(%02x) goto pc%+d\n",
insn->code, insn->off);
@@@ -447,6 -466,7 +466,7 @@@ static void mark_reg_unknown_value(stru
{
BUG_ON(regno >= MAX_BPF_REG);
regs[regno].type = UNKNOWN_VALUE;
+ regs[regno].id = 0;
regs[regno].imm = 0;
}
@@@ -758,7 -778,7 +778,7 @@@ static int check_mem_access(struct bpf_
* index'es we need to make sure that whatever we use
* will have a set floor within our range.
*/
- if ((s64)reg->min_value < 0) {
+ if (reg->min_value < 0) {
verbose("R%d min value is negative, either use unsigned index or do a if (index
>=0) check.\n",
regno);
return -EACCES;
@@@ -1112,8 -1132,8 +1132,8 @@@ static int check_map_func_compatibility
return 0;
error:
- verbose("cannot pass map_type %d into func %d\n",
- map->map_type, func_id);
+ verbose("cannot pass map_type %d into func %s#%d\n",
+ map->map_type, func_id_name(func_id), func_id);
return -EINVAL;
}
@@@ -1170,7 -1190,7 +1190,7 @@@ static int check_call(struct bpf_verifi
/* find function prototype */
if (func_id < 0 || func_id >= __BPF_FUNC_MAX_ID) {
- verbose("invalid func %d\n", func_id);
+ verbose("invalid func %s#%d\n", func_id_name(func_id), func_id);
return -EINVAL;
}
@@@ -1178,7 -1198,7 +1198,7 @@@
fn = env->prog->aux->ops->get_func_proto(func_id);
if (!fn) {
- verbose("unknown func %d\n", func_id);
+ verbose("unknown func %s#%d\n", func_id_name(func_id), func_id);
return -EINVAL;
}
@@@ -1198,7 -1218,8 +1218,8 @@@
*/
err = check_raw_mode(fn);
if (err) {
- verbose("kernel subsystem misconfigured func %d\n", func_id);
+ verbose("kernel subsystem misconfigured func %s#%d\n",
+ func_id_name(func_id), func_id);
return err;
}
@@@ -1252,9 -1273,10 +1273,10 @@@
return -EINVAL;
}
regs[BPF_REG_0].map_ptr = meta.map_ptr;
+ regs[BPF_REG_0].id = ++env->id_gen;
} else {
- verbose("unknown return type %d of func %d\n",
- fn->ret_type, func_id);
+ verbose("unknown return type %d of func %s#%d\n",
+ fn->ret_type, func_id_name(func_id), func_id);
return -EINVAL;
}
@@@ -1468,8 -1490,7 +1490,8 @@@ static void check_reg_overflow(struct b
{
if (reg->max_value > BPF_REGISTER_MAX_RANGE)
reg->max_value = BPF_REGISTER_MAX_RANGE;
- if ((s64)reg->min_value < BPF_REGISTER_MIN_RANGE)
+ if (reg->min_value < BPF_REGISTER_MIN_RANGE ||
+ reg->min_value > BPF_REGISTER_MAX_RANGE)
reg->min_value = BPF_REGISTER_MIN_RANGE;
}
@@@ -1477,9 -1498,7 +1499,8 @@@ static void adjust_reg_min_max_vals(str
struct bpf_insn *insn)
{
struct bpf_reg_state *regs = env->cur_state.regs, *dst_reg;
- u64 min_val = BPF_REGISTER_MIN_RANGE, max_val = BPF_REGISTER_MAX_RANGE;
+ s64 min_val = BPF_REGISTER_MIN_RANGE;
+ u64 max_val = BPF_REGISTER_MAX_RANGE;
- bool min_set = false, max_set = false;
u8 opcode = BPF_OP(insn->code);
dst_reg = ®s[insn->dst_reg];
@@@ -1502,7 -1521,6 +1523,6 @@@
} else if (insn->imm < BPF_REGISTER_MAX_RANGE &&
(s64)insn->imm > BPF_REGISTER_MIN_RANGE) {
min_val = max_val = insn->imm;
- min_set = max_set = true;
}
/* We don't know anything about what was done to this register, mark it
@@@ -1514,43 -1532,22 +1534,43 @@@
return;
}
+ /* If one of our values was at the end of our ranges then we can't just
+ * do our normal operations to the register, we need to set the values
+ * to the min/max since they are undefined.
+ */
+ if (min_val == BPF_REGISTER_MIN_RANGE)
+ dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
+ if (max_val == BPF_REGISTER_MAX_RANGE)
+ dst_reg->max_value = BPF_REGISTER_MAX_RANGE;
+
switch (opcode) {
case BPF_ADD:
- dst_reg->min_value += min_val;
- dst_reg->max_value += max_val;
+ if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
+ dst_reg->min_value += min_val;
+ if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
+ dst_reg->max_value += max_val;
break;
case BPF_SUB:
- dst_reg->min_value -= min_val;
- dst_reg->max_value -= max_val;
+ if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
+ dst_reg->min_value -= min_val;
+ if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
+ dst_reg->max_value -= max_val;
break;
case BPF_MUL:
- dst_reg->min_value *= min_val;
- dst_reg->max_value *= max_val;
+ if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
+ dst_reg->min_value *= min_val;
+ if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
+ dst_reg->max_value *= max_val;
break;
case BPF_AND:
- /* & is special since it could end up with 0 bits set. */
- dst_reg->min_value &= min_val;
+ /* Disallow AND'ing of negative numbers, ain't nobody got time
+ * for that. Otherwise the minimum is 0 and the max is the max
+ * value we could AND against.
+ */
+ if (min_val < 0)
+ dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
+ else
+ dst_reg->min_value = 0;
dst_reg->max_value = max_val;
break;
case BPF_LSH:
@@@ -1560,25 -1557,24 +1580,25 @@@
*/
if (min_val > ilog2(BPF_REGISTER_MAX_RANGE))
dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
- else
+ else if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
dst_reg->min_value <<= min_val;
if (max_val > ilog2(BPF_REGISTER_MAX_RANGE))
dst_reg->max_value = BPF_REGISTER_MAX_RANGE;
- else
+ else if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
dst_reg->max_value <<= max_val;
break;
case BPF_RSH:
- dst_reg->min_value >>= min_val;
- dst_reg->max_value >>= max_val;
- break;
- case BPF_MOD:
- /* % is special since it is an unsigned modulus, so the floor
- * will always be 0.
+ /* RSH by a negative number is undefined, and the BPF_RSH is an
+ * unsigned shift, so make the appropriate casts.
*/
- dst_reg->min_value = 0;
- dst_reg->max_value = max_val - 1;
+ if (min_val < 0 || dst_reg->min_value < 0)
+ dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
+ else
+ dst_reg->min_value =
+ (u64)(dst_reg->min_value) >> min_val;
+ if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
+ dst_reg->max_value >>= max_val;
break;
default:
reset_reg_range_values(regs, insn->dst_reg);
@@@ -1668,8 -1664,7 +1688,7 @@@ static int check_alu_op(struct bpf_veri
insn->src_reg);
return -EACCES;
}
- regs[insn->dst_reg].type = UNKNOWN_VALUE;
- regs[insn->dst_reg].map_ptr = NULL;
+ mark_reg_unknown_value(regs, insn->dst_reg);
}
} else {
/* case: R = imm
@@@ -1931,6 -1926,38 +1950,38 @@@ static void reg_set_min_max_inv(struct
check_reg_overflow(true_reg);
}
+ static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
+ enum bpf_reg_type type)
+ {
+ struct bpf_reg_state *reg = ®s[regno];
+
+ if (reg->type == PTR_TO_MAP_VALUE_OR_NULL && reg->id == id) {
+ reg->type = type;
+ if (type == UNKNOWN_VALUE)
+ mark_reg_unknown_value(regs, regno);
+ }
+ }
+
+ /* The logic is similar to find_good_pkt_pointers(), both could eventually
+ * be folded together at some point.
+ */
+ static void mark_map_regs(struct bpf_verifier_state *state, u32 regno,
+ enum bpf_reg_type type)
+ {
+ struct bpf_reg_state *regs = state->regs;
+ int i;
+
+ for (i = 0; i < MAX_BPF_REG; i++)
+ mark_map_reg(regs, i, regs[regno].id, type);
+
+ for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
+ if (state->stack_slot_type[i] != STACK_SPILL)
+ continue;
+ mark_map_reg(state->spilled_regs, i / BPF_REG_SIZE,
+ regs[regno].id, type);
+ }
+ }
+
static int check_cond_jmp_op(struct bpf_verifier_env *env,
struct bpf_insn *insn, int *insn_idx)
{
@@@ -2018,18 -2045,13 +2069,13 @@@
if (BPF_SRC(insn->code) == BPF_K &&
insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
dst_reg->type == PTR_TO_MAP_VALUE_OR_NULL) {
- if (opcode == BPF_JEQ) {
- /* next fallthrough insn can access memory via
- * this register
- */
- regs[insn->dst_reg].type = PTR_TO_MAP_VALUE;
- /* branch targer cannot access it, since reg == 0 */
- mark_reg_unknown_value(other_branch->regs,
- insn->dst_reg);
- } else {
- other_branch->regs[insn->dst_reg].type = PTR_TO_MAP_VALUE;
- mark_reg_unknown_value(regs, insn->dst_reg);
- }
+ /* Mark all identical map registers in each branch as either
+ * safe or unknown depending R == 0 or R != 0 conditional.
+ */
+ mark_map_regs(this_branch, insn->dst_reg,
+ opcode == BPF_JEQ ? PTR_TO_MAP_VALUE : UNKNOWN_VALUE);
+ mark_map_regs(other_branch, insn->dst_reg,
+ opcode == BPF_JEQ ? UNKNOWN_VALUE : PTR_TO_MAP_VALUE);
} else if (BPF_SRC(insn->code) == BPF_X && opcode == BPF_JGT &&
dst_reg->type == PTR_TO_PACKET &&
regs[insn->src_reg].type == PTR_TO_PACKET_END) {
diff --combined net/batman-adv/hard-interface.c
index 08ce361,672150b4..61a431a
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@@ -92,8 -92,8 +92,8 @@@ out
*
* Return: result of rtnl_link_ops->get_link_net or @fallback_net
*/
- static const struct net *batadv_getlink_net(const struct net_device *netdev,
- const struct net *fallback_net)
+ static struct net *batadv_getlink_net(const struct net_device *netdev,
+ struct net *fallback_net)
{
if (!netdev->rtnl_link_ops)
return fallback_net;
@@@ -116,9 -116,9 +116,9 @@@
* Return: true if the devices are each others parent, otherwise false
*/
static bool batadv_mutual_parents(const struct net_device *dev1,
- const struct net *net1,
+ struct net *net1,
const struct net_device *dev2,
- const struct net *net2)
+ struct net *net2)
{
int dev1_parent_iflink = dev_get_iflink(dev1);
int dev2_parent_iflink = dev_get_iflink(dev2);
@@@ -154,7 -154,7 +154,7 @@@ static bool batadv_is_on_batman_iface(c
{
struct net *net = dev_net(net_dev);
struct net_device *parent_dev;
- const struct net *parent_net;
+ struct net *parent_net;
bool ret;
/* check if this is a batman-adv mesh interface */
@@@ -202,13 -202,77 +202,77 @@@ static bool batadv_is_valid_iface(cons
}
/**
- * batadv_is_wifi_netdev - check if the given net_device struct is a wifi
- * interface
+ * batadv_get_real_netdevice - check if the given netdev struct is a virtual
+ * interface on top of another 'real' interface
+ * @netdev: the device to check
+ *
+ * Callers must hold the rtnl semaphore. You may want batadv_get_real_netdev()
+ * instead of this.
+ *
+ * Return: the 'real' net device or the original net device and NULL in case
+ * of an error.
+ */
+ static struct net_device *batadv_get_real_netdevice(struct net_device *netdev)
+ {
+ struct batadv_hard_iface *hard_iface = NULL;
+ struct net_device *real_netdev = NULL;
+ struct net *real_net;
+ struct net *net;
+ int ifindex;
+
+ ASSERT_RTNL();
+
+ if (!netdev)
+ return NULL;
+
+ if (netdev->ifindex == dev_get_iflink(netdev)) {
+ dev_hold(netdev);
+ return netdev;
+ }
+
+ hard_iface = batadv_hardif_get_by_netdev(netdev);
+ if (!hard_iface || !hard_iface->soft_iface)
+ goto out;
+
+ net = dev_net(hard_iface->soft_iface);
+ ifindex = dev_get_iflink(netdev);
+ real_net = batadv_getlink_net(netdev, net);
+ real_netdev = dev_get_by_index(real_net, ifindex);
+
+ out:
+ if (hard_iface)
+ batadv_hardif_put(hard_iface);
+ return real_netdev;
+ }
+
+ /**
+ * batadv_get_real_netdev - check if the given net_device struct is a virtual
+ * interface on top of another 'real' interface
* @net_device: the device to check
*
- * Return: true if the net device is a 802.11 wireless device, false otherwise.
+ * Return: the 'real' net device or the original net device and NULL in case
+ * of an error.
*/
- bool batadv_is_wifi_netdev(struct net_device *net_device)
+ struct net_device *batadv_get_real_netdev(struct net_device *net_device)
+ {
+ struct net_device *real_netdev;
+
+ rtnl_lock();
+ real_netdev = batadv_get_real_netdevice(net_device);
+ rtnl_unlock();
+
+ return real_netdev;
+ }
+
+ /**
+ * batadv_is_wext_netdev - check if the given net_device struct is a
+ * wext wifi interface
+ * @net_device: the device to check
+ *
+ * Return: true if the net device is a wext wireless device, false
+ * otherwise.
+ */
+ static bool batadv_is_wext_netdev(struct net_device *net_device)
{
if (!net_device)
return false;
@@@ -221,6 -285,22 +285,22 @@@
return true;
#endif
+ return false;
+ }
+
+ /**
+ * batadv_is_cfg80211_netdev - check if the given net_device struct is a
+ * cfg80211 wifi interface
+ * @net_device: the device to check
+ *
+ * Return: true if the net device is a cfg80211 wireless device, false
+ * otherwise.
+ */
+ static bool batadv_is_cfg80211_netdev(struct net_device *net_device)
+ {
+ if (!net_device)
+ return false;
+
/* cfg80211 drivers have to set ieee80211_ptr */
if (net_device->ieee80211_ptr)
return true;
@@@ -228,6 -308,125 +308,125 @@@
return false;
}
+ /**
+ * batadv_wifi_flags_evaluate - calculate wifi flags for net_device
+ * @net_device: the device to check
+ *
+ * Return: batadv_hard_iface_wifi_flags flags of the device
+ */
+ static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
+ {
+ u32 wifi_flags = 0;
+ struct net_device *real_netdev;
+
+ if (batadv_is_wext_netdev(net_device))
+ wifi_flags |= BATADV_HARDIF_WIFI_WEXT_DIRECT;
+
+ if (batadv_is_cfg80211_netdev(net_device))
+ wifi_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
+
+ real_netdev = batadv_get_real_netdevice(net_device);
+ if (!real_netdev)
+ return wifi_flags;
+
+ if (real_netdev == net_device)
+ goto out;
+
+ if (batadv_is_wext_netdev(real_netdev))
+ wifi_flags |= BATADV_HARDIF_WIFI_WEXT_INDIRECT;
+
+ if (batadv_is_cfg80211_netdev(real_netdev))
+ wifi_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
+
+ out:
+ dev_put(real_netdev);
+ return wifi_flags;
+ }
+
+ /**
+ * batadv_is_cfg80211_hardif - check if the given hardif is a cfg80211 wifi
+ * interface
+ * @hard_iface: the device to check
+ *
+ * Return: true if the net device is a cfg80211 wireless device, false
+ * otherwise.
+ */
+ bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface)
+ {
+ u32 allowed_flags = 0;
+
+ allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
+ allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
+
+ return !!(hard_iface->wifi_flags & allowed_flags);
+ }
+
+ /**
+ * batadv_is_wifi_hardif - check if the given hardif is a wifi interface
+ * @hard_iface: the device to check
+ *
+ * Return: true if the net device is a 802.11 wireless device, false otherwise.
+ */
+ bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface)
+ {
+ if (!hard_iface)
+ return false;
+
+ return hard_iface->wifi_flags != 0;
+ }
+
+ /**
+ * batadv_hardif_no_broadcast - check whether (re)broadcast is necessary
+ * @if_outgoing: the outgoing interface checked and considered for (re)broadcast
+ * @orig_addr: the originator of this packet
+ * @orig_neigh: originator address of the forwarder we just got the packet from
+ * (NULL if we originated)
+ *
+ * Checks whether a packet needs to be (re)broadcasted on the given interface.
+ *
+ * Return:
+ * BATADV_HARDIF_BCAST_NORECIPIENT: No neighbor on interface
+ * BATADV_HARDIF_BCAST_DUPFWD: Just one neighbor, but it is the forwarder
+ * BATADV_HARDIF_BCAST_DUPORIG: Just one neighbor, but it is the originator
+ * BATADV_HARDIF_BCAST_OK: Several neighbors, must broadcast
+ */
+ int batadv_hardif_no_broadcast(struct batadv_hard_iface *if_outgoing,
+ u8 *orig_addr, u8 *orig_neigh)
+ {
+ struct batadv_hardif_neigh_node *hardif_neigh;
+ struct hlist_node *first;
+ int ret = BATADV_HARDIF_BCAST_OK;
+
+ rcu_read_lock();
+
+ /* 0 neighbors -> no (re)broadcast */
+ first = rcu_dereference(hlist_first_rcu(&if_outgoing->neigh_list));
+ if (!first) {
+ ret = BATADV_HARDIF_BCAST_NORECIPIENT;
+ goto out;
+ }
+
+ /* >1 neighbors -> (re)brodcast */
+ if (rcu_dereference(hlist_next_rcu(first)))
+ goto out;
+
+ hardif_neigh = hlist_entry(first, struct batadv_hardif_neigh_node,
+ list);
+
+ /* 1 neighbor, is the originator -> no rebroadcast */
+ if (orig_addr && batadv_compare_eth(hardif_neigh->orig, orig_addr)) {
+ ret = BATADV_HARDIF_BCAST_DUPORIG;
+ /* 1 neighbor, is the one we received from -> no rebroadcast */
+ } else if (orig_neigh &&
+ batadv_compare_eth(hardif_neigh->orig, orig_neigh)) {
+ ret = BATADV_HARDIF_BCAST_DUPFWD;
+ }
+
+ out:
+ rcu_read_unlock();
+ return ret;
+ }
+
static struct batadv_hard_iface *
batadv_hardif_get_active(const struct net_device *soft_iface)
{
@@@ -652,7 -851,6 +851,7 @@@ void batadv_hardif_disable_interface(st
batadv_softif_destroy_sysfs(hard_iface->soft_iface);
}
+ hard_iface->soft_iface = NULL;
batadv_hardif_put(hard_iface);
out:
@@@ -697,7 -895,8 +896,8 @@@ batadv_hardif_add_interface(struct net_
kref_init(&hard_iface->refcount);
hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
- if (batadv_is_wifi_netdev(net_dev))
+ hard_iface->wifi_flags = batadv_wifi_flags_evaluate(net_dev);
+ if (batadv_is_wifi_hardif(hard_iface))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
batadv_v_hardif_init(hard_iface);
@@@ -806,6 -1005,11 +1006,11 @@@ static int batadv_hard_if_event(struct
if (hard_iface == primary_if)
batadv_primary_if_update_addr(bat_priv, NULL);
break;
+ case NETDEV_CHANGEUPPER:
+ hard_iface->wifi_flags = batadv_wifi_flags_evaluate(net_dev);
+ if (batadv_is_wifi_hardif(hard_iface))
+ hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
+ break;
default:
break;
}
diff --combined net/batman-adv/tp_meter.c
index 8af1611,f156452..981e8c5
--- a/net/batman-adv/tp_meter.c
+++ b/net/batman-adv/tp_meter.c
@@@ -615,9 -615,6 +615,6 @@@ static int batadv_tp_send_msg(struct ba
batadv_tp_fill_prerandom(tp_vars, data, data_len);
r = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (r == -1)
- kfree_skb(skb);
-
if (r == NET_XMIT_SUCCESS)
return 0;
@@@ -837,7 -834,6 +834,7 @@@ static int batadv_tp_send(void *arg
primary_if = batadv_primary_if_get_selected(bat_priv);
if (unlikely(!primary_if)) {
err = BATADV_TP_REASON_DST_UNREACHABLE;
+ tp_vars->reason = err;
goto out;
}
@@@ -1207,9 -1203,6 +1204,6 @@@ static int batadv_tp_send_ack(struct ba
/* send the ack */
r = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (r == -1)
- kfree_skb(skb);
-
if (unlikely(r < 0) || (r == NET_XMIT_DROP)) {
ret = BATADV_TP_REASON_DST_UNREACHABLE;
goto out;
diff --combined net/core/net_namespace.c
index 7001da9,35d37b1..a38feac
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@@ -55,7 -55,7 +55,7 @@@ static struct net_generic *net_alloc_ge
return ng;
}
- static int net_assign_generic(struct net *net, int id, void *data)
+ static int net_assign_generic(struct net *net, unsigned int id, void *data)
{
struct net_generic *ng, *old_ng;
@@@ -122,8 -122,7 +122,7 @@@ out
static void ops_free(const struct pernet_operations *ops, struct net *net)
{
if (ops->id && ops->size) {
- int id = *ops->id;
- kfree(net_generic(net, id));
+ kfree(net_generic(net, *ops->id));
}
}
@@@ -219,8 -218,6 +218,8 @@@ int peernet2id_alloc(struct net *net, s
bool alloc;
int id;
+ if (atomic_read(&net->count) == 0)
+ return NETNSA_NSID_NOT_ASSIGNED;
spin_lock_irqsave(&net->nsid_lock, flags);
alloc = atomic_read(&peer->count) == 0 ? false : true;
id = __peernet2id_alloc(net, peer, &alloc);
@@@ -384,7 -381,14 +383,14 @@@ struct net *copy_net_ns(unsigned long f
get_user_ns(user_ns);
- mutex_lock(&net_mutex);
+ rv = mutex_lock_killable(&net_mutex);
+ if (rv < 0) {
+ net_free(net);
+ dec_net_namespaces(ucounts);
+ put_user_ns(user_ns);
+ return ERR_PTR(rv);
+ }
+
net->ucounts = ucounts;
rv = setup_net(net, user_ns);
if (rv == 0) {
@@@ -876,7 -880,7 +882,7 @@@ again
}
return error;
}
- max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
+ max_gen_ptrs = max(max_gen_ptrs, *ops->id);
}
error = __register_pernet_operations(list, ops);
if (error) {
diff --combined net/ipv4/fib_frontend.c
index 161fc0f,d93eea8..121384b
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@@ -151,7 -151,7 +151,7 @@@ static void fib_replace_table(struct ne
int fib_unmerge(struct net *net)
{
- struct fib_table *old, *new;
+ struct fib_table *old, *new, *main_table;
/* attempt to fetch local table if it has been allocated */
old = fib_get_table(net, RT_TABLE_LOCAL);
@@@ -162,21 -162,11 +162,21 @@@
if (!new)
return -ENOMEM;
+ /* table is already unmerged */
+ if (new == old)
+ return 0;
+
/* replace merged table with clean table */
- if (new != old) {
- fib_replace_table(net, old, new);
- fib_free_table(old);
- }
+ fib_replace_table(net, old, new);
+ fib_free_table(old);
+
+ /* attempt to fetch main table if it has been allocated */
+ main_table = fib_get_table(net, RT_TABLE_MAIN);
+ if (!main_table)
+ return 0;
+
+ /* flush local entries from main table */
+ fib_table_flush_external(main_table);
return 0;
}
@@@ -620,6 -610,7 +620,7 @@@ const struct nla_policy rtm_ipv4_policy
[RTA_FLOW] = { .type = NLA_U32 },
[RTA_ENCAP_TYPE] = { .type = NLA_U16 },
[RTA_ENCAP] = { .type = NLA_NESTED },
+ [RTA_UID] = { .type = NLA_U32 },
};
static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
diff --combined net/ipv4/tcp_cong.c
index f9038d6b,38905ec..79c4817
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@@ -68,8 -68,9 +68,9 @@@ int tcp_register_congestion_control(str
{
int ret = 0;
- /* all algorithms must implement ssthresh and cong_avoid ops */
- if (!ca->ssthresh || !(ca->cong_avoid || ca->cong_control)) {
+ /* all algorithms must implement these */
+ if (!ca->ssthresh || !ca->undo_cwnd ||
+ !(ca->cong_avoid || ca->cong_control)) {
pr_err("%s does not implement required ops\n", ca->name);
return -EINVAL;
}
@@@ -200,10 -201,8 +201,10 @@@ static void tcp_reinit_congestion_contr
icsk->icsk_ca_ops = ca;
icsk->icsk_ca_setsockopt = 1;
- if (sk->sk_state != TCP_CLOSE)
+ if (sk->sk_state != TCP_CLOSE) {
+ memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
tcp_init_congestion_control(sk);
+ }
}
/* Manage refcounts on socket close. */
@@@ -443,10 -442,19 +444,19 @@@ u32 tcp_reno_ssthresh(struct sock *sk
}
EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
+ u32 tcp_reno_undo_cwnd(struct sock *sk)
+ {
+ const struct tcp_sock *tp = tcp_sk(sk);
+
+ return max(tp->snd_cwnd, tp->snd_ssthresh << 1);
+ }
+ EXPORT_SYMBOL_GPL(tcp_reno_undo_cwnd);
+
struct tcp_congestion_ops tcp_reno = {
.flags = TCP_CONG_NON_RESTRICTED,
.name = "reno",
.owner = THIS_MODULE,
.ssthresh = tcp_reno_ssthresh,
.cong_avoid = tcp_reno_cong_avoid,
+ .undo_cwnd = tcp_reno_undo_cwnd,
};
diff --combined net/ipv4/udp.c
index 0de9d5d,b949770..b3b6bc5
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@@ -580,7 -580,8 +580,8 @@@ EXPORT_SYMBOL_GPL(udp4_lib_lookup_skb)
* Does increment socket refcount.
*/
#if IS_ENABLED(CONFIG_NETFILTER_XT_MATCH_SOCKET) || \
- IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY)
+ IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY) || \
+ IS_ENABLED(CONFIG_NF_SOCKET_IPV4)
struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
__be32 daddr, __be16 dport, int dif)
{
@@@ -1019,7 -1020,8 +1020,8 @@@ int udp_sendmsg(struct sock *sk, struc
flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE, sk->sk_protocol,
flow_flags,
- faddr, saddr, dport, inet->inet_sport);
+ faddr, saddr, dport, inet->inet_sport,
+ sk->sk_uid);
security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
rt = ip_route_output_flow(net, fl4, sk);
@@@ -1172,6 -1174,120 +1174,120 @@@ out
return ret;
}
+ /* fully reclaim rmem/fwd memory allocated for skb */
+ static void udp_rmem_release(struct sock *sk, int size, int partial)
+ {
+ int amt;
+
+ atomic_sub(size, &sk->sk_rmem_alloc);
+ sk->sk_forward_alloc += size;
+ amt = (sk->sk_forward_alloc - partial) & ~(SK_MEM_QUANTUM - 1);
+ sk->sk_forward_alloc -= amt;
+
+ if (amt)
+ __sk_mem_reduce_allocated(sk, amt >> SK_MEM_QUANTUM_SHIFT);
+ }
+
+ /* Note: called with sk_receive_queue.lock held */
+ void udp_skb_destructor(struct sock *sk, struct sk_buff *skb)
+ {
+ udp_rmem_release(sk, skb->truesize, 1);
+ }
+ EXPORT_SYMBOL(udp_skb_destructor);
+
+ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
+ {
+ struct sk_buff_head *list = &sk->sk_receive_queue;
+ int rmem, delta, amt, err = -ENOMEM;
+ int size = skb->truesize;
+
+ /* try to avoid the costly atomic add/sub pair when the receive
+ * queue is full; always allow at least a packet
+ */
+ rmem = atomic_read(&sk->sk_rmem_alloc);
+ if (rmem && (rmem + size > sk->sk_rcvbuf))
+ goto drop;
+
+ /* we drop only if the receive buf is full and the receive
+ * queue contains some other skb
+ */
+ rmem = atomic_add_return(size, &sk->sk_rmem_alloc);
+ if ((rmem > sk->sk_rcvbuf) && (rmem > size))
+ goto uncharge_drop;
+
+ spin_lock(&list->lock);
+ if (size >= sk->sk_forward_alloc) {
+ amt = sk_mem_pages(size);
+ delta = amt << SK_MEM_QUANTUM_SHIFT;
+ if (!__sk_mem_raise_allocated(sk, delta, amt, SK_MEM_RECV)) {
+ err = -ENOBUFS;
+ spin_unlock(&list->lock);
+ goto uncharge_drop;
+ }
+
+ sk->sk_forward_alloc += delta;
+ }
+
+ sk->sk_forward_alloc -= size;
+
+ /* no need to setup a destructor, we will explicitly release the
+ * forward allocated memory on dequeue
+ */
+ skb->dev = NULL;
+ sock_skb_set_dropcount(sk, skb);
+
+ __skb_queue_tail(list, skb);
+ spin_unlock(&list->lock);
+
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk);
+
+ return 0;
+
+ uncharge_drop:
+ atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
+
+ drop:
+ atomic_inc(&sk->sk_drops);
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(__udp_enqueue_schedule_skb);
+
+ void udp_destruct_sock(struct sock *sk)
+ {
+ /* reclaim completely the forward allocated memory */
+ unsigned int total = 0;
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ total += skb->truesize;
+ kfree_skb(skb);
+ }
+ udp_rmem_release(sk, total, 0);
+
+ inet_sock_destruct(sk);
+ }
+ EXPORT_SYMBOL_GPL(udp_destruct_sock);
+
+ int udp_init_sock(struct sock *sk)
+ {
+ sk->sk_destruct = udp_destruct_sock;
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(udp_init_sock);
+
+ void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
+ {
+ if (unlikely(READ_ONCE(sk->sk_peek_off) >= 0)) {
+ bool slow = lock_sock_fast(sk);
+
+ sk_peek_offset_bwd(sk, len);
+ unlock_sock_fast(sk, slow);
+ }
+ consume_skb(skb);
+ }
+ EXPORT_SYMBOL_GPL(skb_consume_udp);
+
/**
* first_packet_length - return length of first packet in receive queue
* @sk: socket
@@@ -1181,12 -1297,11 +1297,11 @@@
*/
static int first_packet_length(struct sock *sk)
{
- struct sk_buff_head list_kill, *rcvq = &sk->sk_receive_queue;
+ struct sk_buff_head *rcvq = &sk->sk_receive_queue;
struct sk_buff *skb;
+ int total = 0;
int res;
- __skb_queue_head_init(&list_kill);
-
spin_lock_bh(&rcvq->lock);
while ((skb = skb_peek(rcvq)) != NULL &&
udp_lib_checksum_complete(skb)) {
@@@ -1196,18 -1311,13 +1311,13 @@@
IS_UDPLITE(sk));
atomic_inc(&sk->sk_drops);
__skb_unlink(skb, rcvq);
- __skb_queue_tail(&list_kill, skb);
+ total += skb->truesize;
+ kfree_skb(skb);
}
res = skb ? skb->len : -1;
+ if (total)
+ udp_rmem_release(sk, total, 1);
spin_unlock_bh(&rcvq->lock);
-
- if (!skb_queue_empty(&list_kill)) {
- bool slow = lock_sock_fast(sk);
-
- __skb_queue_purge(&list_kill);
- sk_mem_reclaim_partial(sk);
- unlock_sock_fast(sk, slow);
- }
return res;
}
@@@ -1256,15 -1366,13 +1366,13 @@@ int udp_recvmsg(struct sock *sk, struc
int err;
int is_udplite = IS_UDPLITE(sk);
bool checksum_valid = false;
- bool slow;
if (flags & MSG_ERRQUEUE)
return ip_recv_error(sk, msg, len, addr_len);
try_again:
peeking = off = sk_peek_offset(sk, flags);
- skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
- &peeked, &off, &err);
+ skb = __skb_recv_udp(sk, flags, noblock, &peeked, &off, &err);
if (!skb)
return err;
@@@ -1281,7 -1389,8 +1389,8 @@@
* coverage checksum (UDP-Lite), do it before the copy.
*/
- if (copied < ulen || UDP_SKB_CB(skb)->partial_cov || peeking) {
+ if (copied < ulen || peeking ||
+ (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
checksum_valid = !udp_lib_checksum_complete(skb);
if (!checksum_valid)
goto csum_copy_err;
@@@ -1297,13 -1406,12 +1406,12 @@@
}
if (unlikely(err)) {
- trace_kfree_skb(skb, udp_recvmsg);
if (!peeked) {
atomic_inc(&sk->sk_drops);
UDP_INC_STATS(sock_net(sk),
UDP_MIB_INERRORS, is_udplite);
}
- skb_free_datagram_locked(sk, skb);
+ kfree_skb(skb);
return err;
}
@@@ -1322,22 -1430,21 +1430,21 @@@
*addr_len = sizeof(*sin);
}
if (inet->cmsg_flags)
- ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr), off);
+ ip_cmsg_recv_offset(msg, sk, skb, sizeof(struct udphdr), off);
err = copied;
if (flags & MSG_TRUNC)
err = ulen;
- __skb_free_datagram_locked(sk, skb, peeking ? -err : err);
+ skb_consume_udp(sk, skb, peeking ? -err : err);
return err;
csum_copy_err:
- slow = lock_sock_fast(sk);
- if (!skb_kill_datagram(sk, skb, flags)) {
+ if (!__sk_queue_drop_skb(sk, skb, flags)) {
UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
}
- unlock_sock_fast(sk, slow);
+ kfree_skb(skb);
/* starting over for a new packet, but check if we need to yield */
cond_resched();
@@@ -1463,9 -1570,11 +1570,11 @@@ static int __udp_queue_rcv_skb(struct s
sock_rps_save_rxhash(sk, skb);
sk_mark_napi_id(sk, skb);
sk_incoming_cpu_update(sk);
+ } else {
+ sk_mark_napi_id_once(sk, skb);
}
- rc = __sock_queue_rcv_skb(sk, skb);
+ rc = __udp_enqueue_schedule_skb(sk, skb);
if (rc < 0) {
int is_udplite = IS_UDPLITE(sk);
@@@ -1480,7 -1589,6 +1589,6 @@@
}
return 0;
-
}
static struct static_key udp_encap_needed __read_mostly;
@@@ -1502,7 -1610,6 +1610,6 @@@ EXPORT_SYMBOL(udp_encap_enable)
int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
struct udp_sock *up = udp_sk(sk);
- int rc;
int is_udplite = IS_UDPLITE(sk);
/*
@@@ -1589,25 -1696,9 +1696,9 @@@
goto drop;
udp_csum_pull_header(skb);
- if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
- __UDP_INC_STATS(sock_net(sk), UDP_MIB_RCVBUFERRORS,
- is_udplite);
- goto drop;
- }
-
- rc = 0;
ipv4_pktinfo_prepare(sk, skb);
- bh_lock_sock(sk);
- if (!sock_owned_by_user(sk))
- rc = __udp_queue_rcv_skb(sk, skb);
- else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
- bh_unlock_sock(sk);
- goto drop;
- }
- bh_unlock_sock(sk);
-
- return rc;
+ return __udp_queue_rcv_skb(sk, skb);
csum_error:
__UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
@@@ -1652,10 -1743,10 +1743,10 @@@ static int __udp4_lib_mcast_deliver(str
if (use_hash2) {
hash2_any = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum) &
- udp_table.mask;
- hash2 = udp4_portaddr_hash(net, daddr, hnum) & udp_table.mask;
+ udptable->mask;
+ hash2 = udp4_portaddr_hash(net, daddr, hnum) & udptable->mask;
start_lookup:
- hslot = &udp_table.hash2[hash2];
+ hslot = &udptable->hash2[hash2];
offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node);
}
@@@ -2217,13 -2308,13 +2308,13 @@@ struct proto udp_prot =
.connect = ip4_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
+ .init = udp_init_sock,
.destroy = udp_destroy_sock,
.setsockopt = udp_setsockopt,
.getsockopt = udp_getsockopt,
.sendmsg = udp_sendmsg,
.recvmsg = udp_recvmsg,
.sendpage = udp_sendpage,
- .backlog_rcv = __udp_queue_rcv_skb,
.release_cb = ip4_datagram_release_cb,
.hash = udp_lib_hash,
.unhash = udp_lib_unhash,
diff --combined net/ipv6/ip6_tunnel.c
index 0a4759b,d3c619e..1f49fb1
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@@ -83,7 -83,7 +83,7 @@@ static int ip6_tnl_dev_init(struct net_
static void ip6_tnl_dev_setup(struct net_device *dev);
static struct rtnl_link_ops ip6_link_ops __read_mostly;
- static int ip6_tnl_net_id __read_mostly;
+ static unsigned int ip6_tnl_net_id __read_mostly;
struct ip6_tnl_net {
/* the IPv6 tunnel fallback device */
struct net_device *fb_tnl_dev;
@@@ -1034,7 -1034,6 +1034,7 @@@ int ip6_tnl_xmit(struct sk_buff *skb, s
int mtu;
unsigned int psh_hlen = sizeof(struct ipv6hdr) + t->encap_hlen;
unsigned int max_headroom = psh_hlen;
+ bool use_cache = false;
u8 hop_limit;
int err = -1;
@@@ -1067,15 -1066,7 +1067,15 @@@
memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
neigh_release(neigh);
- } else if (!fl6->flowi6_mark)
+ } else if (!(t->parms.flags &
+ (IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) {
+ /* enable the cache only only if the routing decision does
+ * not depend on the current inner header value
+ */
+ use_cache = true;
+ }
+
+ if (use_cache)
dst = dst_cache_get(&t->dst_cache);
if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
@@@ -1159,14 -1150,14 +1159,14 @@@ route_lookup
if (t->encap.type != TUNNEL_ENCAP_NONE)
goto tx_err_dst_release;
} else {
- if (!fl6->flowi6_mark && ndst)
+ if (use_cache && ndst)
dst_cache_set_ip6(&t->dst_cache, ndst, &fl6->saddr);
}
skb_dst_set(skb, dst);
if (encap_limit >= 0) {
init_tel_txopt(&opt, encap_limit);
- ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
+ ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL, NULL);
}
/* Calculate max headroom for all the headers and adjust
@@@ -1249,6 -1240,8 +1249,8 @@@ ip4ip6_tnl_xmit(struct sk_buff *skb, st
fl6.flowi6_mark = skb->mark;
}
+ fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1;
@@@ -1327,6 -1320,8 +1329,8 @@@ ip6ip6_tnl_xmit(struct sk_buff *skb, st
fl6.flowi6_mark = skb->mark;
}
+ fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1;
@@@ -1646,7 -1641,7 +1650,7 @@@ int ip6_tnl_change_mtu(struct net_devic
struct ip6_tnl *tnl = netdev_priv(dev);
if (tnl->parms.proto == IPPROTO_IPIP) {
- if (new_mtu < 68)
+ if (new_mtu < ETH_MIN_MTU)
return -EINVAL;
} else {
if (new_mtu < IPV6_MIN_MTU)
@@@ -1799,6 -1794,8 +1803,8 @@@ ip6_tnl_dev_init_gen(struct net_device
dev->mtu = ETH_DATA_LEN - t_hlen;
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
dev->mtu -= 8;
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = 0xFFF8 - dev->hard_header_len;
return 0;
diff --combined net/ipv6/ip6_vti.c
index c299c1e,c476bb8..f4b4a4a
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@@ -64,7 -64,7 +64,7 @@@ static int vti6_dev_init(struct net_dev
static void vti6_dev_setup(struct net_device *dev);
static struct rtnl_link_ops vti6_link_ops __read_mostly;
- static int vti6_net_id __read_mostly;
+ static unsigned int vti6_net_id __read_mostly;
struct vti6_net {
/* the vti6 tunnel fallback device */
struct net_device *fb_tnl_dev;
@@@ -608,9 -608,10 +608,10 @@@ static int vti6_err(struct sk_buff *skb
return 0;
if (type == NDISC_REDIRECT)
- ip6_redirect(skb, net, skb->dev->ifindex, 0);
+ ip6_redirect(skb, net, skb->dev->ifindex, 0,
+ sock_net_uid(net, NULL));
else
- ip6_update_pmtu(skb, net, info, 0, 0);
+ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x);
return 0;
@@@ -812,30 -813,11 +813,11 @@@ vti6_ioctl(struct net_device *dev, stru
return err;
}
- /**
- * vti6_tnl_change_mtu - change mtu manually for tunnel device
- * @dev: virtual device associated with tunnel
- * @new_mtu: the new mtu
- *
- * Return:
- * 0 on success,
- * %-EINVAL if mtu too small
- **/
- static int vti6_change_mtu(struct net_device *dev, int new_mtu)
- {
- if (new_mtu < IPV6_MIN_MTU)
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
- }
-
static const struct net_device_ops vti6_netdev_ops = {
.ndo_init = vti6_dev_init,
.ndo_uninit = vti6_dev_uninit,
.ndo_start_xmit = vti6_tnl_xmit,
.ndo_do_ioctl = vti6_ioctl,
- .ndo_change_mtu = vti6_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip6_tnl_get_iflink,
};
@@@ -855,6 -837,8 +837,8 @@@ static void vti6_dev_setup(struct net_d
dev->type = ARPHRD_TUNNEL6;
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr);
dev->mtu = ETH_DATA_LEN;
+ dev->min_mtu = IPV6_MIN_MTU;
+ dev->max_mtu = IP_MAX_MTU;
dev->flags |= IFF_NOARP;
dev->addr_len = sizeof(struct in6_addr);
netif_keep_dst(dev);
@@@ -1138,33 -1122,6 +1122,33 @@@ static struct xfrm6_protocol vti_ipcomp
.priority = 100,
};
+static bool is_vti6_tunnel(const struct net_device *dev)
+{
+ return dev->netdev_ops == &vti6_netdev_ops;
+}
+
+static int vti6_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct ip6_tnl *t = netdev_priv(dev);
+
+ if (!is_vti6_tunnel(dev))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_DOWN:
+ if (!net_eq(t->net, dev_net(dev)))
+ xfrm_garbage_collect(t->net);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block vti6_notifier_block __read_mostly = {
+ .notifier_call = vti6_device_event,
+};
+
/**
* vti6_tunnel_init - register protocol and reserve needed resources
*
@@@ -1175,8 -1132,6 +1159,8 @@@ static int __init vti6_tunnel_init(void
const char *msg;
int err;
+ register_netdevice_notifier(&vti6_notifier_block);
+
msg = "tunnel device";
err = register_pernet_device(&vti6_net_ops);
if (err < 0)
@@@ -1209,7 -1164,6 +1193,7 @@@ xfrm_proto_ah_failed
xfrm_proto_esp_failed:
unregister_pernet_device(&vti6_net_ops);
pernet_dev_failed:
+ unregister_netdevice_notifier(&vti6_notifier_block);
pr_err("vti6 init: failed to register %s\n", msg);
return err;
}
@@@ -1224,7 -1178,6 +1208,7 @@@ static void __exit vti6_tunnel_cleanup(
xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
unregister_pernet_device(&vti6_net_ops);
+ unregister_netdevice_notifier(&vti6_notifier_block);
}
module_init(vti6_tunnel_init);
diff --combined net/ipv6/udp.c
index e5056d4,8fd4d89..ba25ec2
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@@ -302,7 -302,8 +302,8 @@@ EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb)
* Does increment socket refcount.
*/
#if IS_ENABLED(CONFIG_NETFILTER_XT_MATCH_SOCKET) || \
- IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY)
+ IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TPROXY) || \
+ IS_ENABLED(CONFIG_NF_SOCKET_IPV6)
struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16
sport,
const struct in6_addr *daddr, __be16 dport, int dif)
{
@@@ -334,7 -335,6 +335,6 @@@ int udpv6_recvmsg(struct sock *sk, stru
int is_udplite = IS_UDPLITE(sk);
bool checksum_valid = false;
int is_udp4;
- bool slow;
if (flags & MSG_ERRQUEUE)
return ipv6_recv_error(sk, msg, len, addr_len);
@@@ -344,8 -344,7 +344,7 @@@
try_again:
peeking = off = sk_peek_offset(sk, flags);
- skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
- &peeked, &off, &err);
+ skb = __skb_recv_udp(sk, flags, noblock, &peeked, &off, &err);
if (!skb)
return err;
@@@ -364,7 -363,8 +363,8 @@@
* coverage checksum (UDP-Lite), do it before the copy.
*/
- if (copied < ulen || UDP_SKB_CB(skb)->partial_cov || peeking) {
+ if (copied < ulen || peeking ||
+ (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
checksum_valid = !udp_lib_checksum_complete(skb);
if (!checksum_valid)
goto csum_copy_err;
@@@ -378,7 -378,6 +378,6 @@@
goto csum_copy_err;
}
if (unlikely(err)) {
- trace_kfree_skb(skb, udpv6_recvmsg);
if (!peeked) {
atomic_inc(&sk->sk_drops);
if (is_udp4)
@@@ -388,7 -387,7 +387,7 @@@
UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS,
is_udplite);
}
- skb_free_datagram_locked(sk, skb);
+ kfree_skb(skb);
return err;
}
if (!peeked) {
@@@ -427,7 -426,7 +426,7 @@@
if (is_udp4) {
if (inet->cmsg_flags)
- ip_cmsg_recv_offset(msg, skb,
+ ip_cmsg_recv_offset(msg, sk, skb,
sizeof(struct udphdr), off);
} else {
if (np->rxopt.all)
@@@ -438,12 -437,11 +437,11 @@@
if (flags & MSG_TRUNC)
err = ulen;
- __skb_free_datagram_locked(sk, skb, peeking ? -err : err);
+ skb_consume_udp(sk, skb, peeking ? -err : err);
return err;
csum_copy_err:
- slow = lock_sock_fast(sk);
- if (!skb_kill_datagram(sk, skb, flags)) {
+ if (!__sk_queue_drop_skb(sk, skb, flags)) {
if (is_udp4) {
UDP_INC_STATS(sock_net(sk),
UDP_MIB_CSUMERRORS, is_udplite);
@@@ -456,7 -454,7 +454,7 @@@
UDP_MIB_INERRORS, is_udplite);
}
}
- unlock_sock_fast(sk, slow);
+ kfree_skb(skb);
/* starting over for a new packet, but check if we need to yield */
cond_resched();
@@@ -522,9 -520,11 +520,11 @@@ static int __udpv6_queue_rcv_skb(struc
sock_rps_save_rxhash(sk, skb);
sk_mark_napi_id(sk, skb);
sk_incoming_cpu_update(sk);
+ } else {
+ sk_mark_napi_id_once(sk, skb);
}
- rc = __sock_queue_rcv_skb(sk, skb);
+ rc = __udp_enqueue_schedule_skb(sk, skb);
if (rc < 0) {
int is_udplite = IS_UDPLITE(sk);
@@@ -536,6 -536,7 +536,7 @@@
kfree_skb(skb);
return -1;
}
+
return 0;
}
@@@ -557,7 -558,6 +558,6 @@@ EXPORT_SYMBOL(udpv6_encap_enable)
int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
struct udp_sock *up = udp_sk(sk);
- int rc;
int is_udplite = IS_UDPLITE(sk);
if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
@@@ -623,25 -623,10 +623,10 @@@
goto drop;
udp_csum_pull_header(skb);
- if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
- __UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_RCVBUFERRORS, is_udplite);
- goto drop;
- }
skb_dst_drop(skb);
- bh_lock_sock(sk);
- rc = 0;
- if (!sock_owned_by_user(sk))
- rc = __udpv6_queue_rcv_skb(sk, skb);
- else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) {
- bh_unlock_sock(sk);
- goto drop;
- }
- bh_unlock_sock(sk);
-
- return rc;
+ return __udpv6_queue_rcv_skb(sk, skb);
csum_error:
__UDP6_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
@@@ -706,10 -691,10 +691,10 @@@ static int __udp6_lib_mcast_deliver(str
if (use_hash2) {
hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) &
- udp_table.mask;
- hash2 = udp6_portaddr_hash(net, daddr, hnum) & udp_table.mask;
+ udptable->mask;
+ hash2 = udp6_portaddr_hash(net, daddr, hnum) & udptable->mask;
start_lookup:
- hslot = &udp_table.hash2[hash2];
+ hslot = &udptable->hash2[hash2];
offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node);
}
@@@ -1156,6 -1141,7 +1141,7 @@@ do_udp_sendmsg
fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_uid = sk->sk_uid;
sockc.tsflags = sk->sk_tsflags;
if (msg->msg_controllen) {
@@@ -1434,12 -1420,12 +1420,12 @@@ struct proto udpv6_prot =
.connect = ip6_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
+ .init = udp_init_sock,
.destroy = udpv6_destroy_sock,
.setsockopt = udpv6_setsockopt,
.getsockopt = udpv6_getsockopt,
.sendmsg = udpv6_sendmsg,
.recvmsg = udpv6_recvmsg,
- .backlog_rcv = __udpv6_queue_rcv_skb,
.release_cb = ip6_datagram_release_cb,
.hash = udp_lib_hash,
.unhash = udp_lib_unhash,
diff --combined net/l2tp/l2tp_eth.c
index 3dc97b4,e2c6ae0..5b90eb6
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@@ -97,7 -97,7 +97,7 @@@ static int l2tp_eth_dev_xmit(struct sk_
unsigned int len = skb->len;
int ret = l2tp_xmit_skb(session, skb, session->hdr_len);
- if (likely(ret == NET_XMIT_SUCCESS)) {
+ if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
atomic_long_add(len, &priv->tx_bytes);
atomic_long_inc(&priv->tx_packets);
} else {
@@@ -259,6 -259,8 +259,8 @@@ static int l2tp_eth_create(struct net *
session->mtu = dev->mtu - session->hdr_len;
dev->mtu = session->mtu;
dev->needed_headroom += session->hdr_len;
+ dev->min_mtu = 0;
+ dev->max_mtu = ETH_MAX_MTU;
priv = netdev_priv(dev);
priv->dev = dev;
diff --combined net/l2tp/l2tp_ip6.c
index 9978d01,1cea54f..667ec90
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@@ -269,6 -269,8 +269,6 @@@ static int l2tp_ip6_bind(struct sock *s
int addr_type;
int err;
- if (!sock_flag(sk, SOCK_ZAPPED))
- return -EINVAL;
if (addr->l2tp_family != AF_INET6)
return -EINVAL;
if (addr_len < sizeof(*addr))
@@@ -294,9 -296,6 +294,9 @@@
lock_sock(sk);
err = -EINVAL;
+ if (!sock_flag(sk, SOCK_ZAPPED))
+ goto out_unlock;
+
if (sk->sk_state != TCP_CLOSE)
goto out_unlock;
@@@ -520,6 -519,7 +520,7 @@@ static int l2tp_ip6_sendmsg(struct soc
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_mark = sk->sk_mark;
+ fl6.flowi6_uid = sk->sk_uid;
ipc6.hlimit = -1;
ipc6.tclass = -1;
diff --combined net/mac80211/sta_info.c
index 8e05032,236d47e..1711bae
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@@ -688,7 -688,7 +688,7 @@@ static void __sta_info_recalc_tim(struc
}
/* No need to do anything if the driver does all */
- if (!local->ops->set_tim)
+ if (ieee80211_hw_check(&local->hw, AP_LINK_PS))
return;
if (sta->dead)
@@@ -709,7 -709,7 +709,7 @@@
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
unsigned long tids;
- if (ignore_for_tim & BIT(ac))
+ if (ignore_for_tim & ieee80211_ac_to_qos_mask[ac])
continue;
indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) ||
@@@ -1389,7 -1389,7 +1389,7 @@@ ieee80211_sta_ps_more_data(struct sta_i
return true;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- if (ignored_acs & BIT(ac))
+ if (ignored_acs & ieee80211_ac_to_qos_mask[ac])
continue;
if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
@@@ -1414,7 -1414,7 +1414,7 @@@ ieee80211_sta_ps_get_frames(struct sta_
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
unsigned long tids;
- if (ignored_acs & BIT(ac))
+ if (ignored_acs & ieee80211_ac_to_qos_mask[ac])
continue;
tids = ieee80211_tids_for_ac(ac);
@@@ -1482,7 -1482,7 +1482,7 @@@ ieee80211_sta_ps_deliver_response(struc
BIT(find_highest_prio_tid(driver_release_tids));
if (skb_queue_empty(&frames) && !driver_release_tids) {
- int tid;
+ int tid, ac;
/*
* For PS-Poll, this can only happen due to a race condition
@@@ -1500,7 -1500,10 +1500,10 @@@
*/
/* This will evaluate to 1, 3, 5 or 7. */
- tid = 7 - ((ffs(~ignored_acs) - 1) << 1);
+ for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++)
+ if (ignored_acs & BIT(ac))
+ continue;
+ tid = 7 - 2 * ac;
ieee80211_send_null_response(sta, tid, reason, true, false);
} else if (!driver_release_tids) {
@@@ -1871,10 -1874,7 +1874,7 @@@ int sta_info_move_state(struct sta_inf
if (!sta->sta.support_p2p_ps)
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
} else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
- (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !sta->sdata->u.vlan.sta))
- atomic_dec(&sta->sdata->bss->num_mcast_sta);
+ ieee80211_vif_dec_num_mcast(sta->sdata);
clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
ieee80211_clear_fast_xmit(sta);
ieee80211_clear_fast_rx(sta);
@@@ -1882,10 -1882,7 +1882,7 @@@
break;
case IEEE80211_STA_AUTHORIZED:
if (sta->sta_state == IEEE80211_STA_ASSOC) {
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
- (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
- !sta->sdata->u.vlan.sta))
- atomic_inc(&sta->sdata->bss->num_mcast_sta);
+ ieee80211_vif_inc_num_mcast(sta->sdata);
set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
ieee80211_check_fast_xmit(sta);
ieee80211_check_fast_rx(sta);
diff --combined net/mac80211/tx.c
index bd5f4be,62ccaf6..2c21b70
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@@ -331,9 -331,8 +331,8 @@@ ieee80211_tx_h_check_assoc(struct ieee8
I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
return TX_DROP;
}
- } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP &&
- ieee80211_is_data(hdr->frame_control) &&
- !atomic_read(&tx->sdata->u.ap.num_mcast_sta))) {
+ } else if (unlikely(ieee80211_is_data(hdr->frame_control) &&
+ ieee80211_vif_get_num_mcast_if(tx->sdata) == 0)) {
/*
* No associated STAs - no need to send multicast
* frames.
@@@ -935,7 -934,7 +934,7 @@@ ieee80211_tx_h_fragment(struct ieee8021
if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
return TX_CONTINUE;
- if (tx->local->ops->set_frag_threshold)
+ if (ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG))
return TX_CONTINUE;
/*
@@@ -1501,6 -1500,7 +1500,6 @@@ static bool ieee80211_queue_skb(struct
struct sta_info *sta,
struct sk_buff *skb)
{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct fq *fq = &local->fq;
struct ieee80211_vif *vif;
struct txq_info *txqi;
@@@ -1525,6 -1525,8 +1524,6 @@@
if (!txqi)
return false;
- info->control.vif = vif;
-
spin_lock_bh(&fq->lock);
ieee80211_txq_enqueue(local, txqi, skb);
spin_unlock_bh(&fq->lock);
@@@ -2798,7 -2800,7 +2797,7 @@@ void ieee80211_check_fast_xmit(struct s
/* fast-xmit doesn't handle fragmentation at all */
if (local->hw.wiphy->frag_threshold != (u32)-1 &&
- !local->ops->set_frag_threshold)
+ !ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG))
goto out;
rcu_read_lock();
@@@ -3057,11 -3059,12 +3056,12 @@@ static bool ieee80211_amsdu_prepare_hea
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
- struct ethhdr amsdu_hdr;
+ struct ethhdr *amsdu_hdr;
int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
int subframe_len = skb->len - hdr_len;
void *data;
- u8 *qc;
+ u8 *qc, *h_80211_src, *h_80211_dst;
+ const u8 *bssid;
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
return false;
@@@ -3069,19 -3072,44 +3069,44 @@@
if (info->control.flags & IEEE80211_TX_CTRL_AMSDU)
return true;
- if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(amsdu_hdr),
+ if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr),
&subframe_len))
return false;
- amsdu_hdr.h_proto = cpu_to_be16(subframe_len);
- memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN);
- memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN);
+ data = skb_push(skb, sizeof(*amsdu_hdr));
+ memmove(data, data + sizeof(*amsdu_hdr), hdr_len);
+ hdr = data;
+ amsdu_hdr = data + hdr_len;
+ /* h_80211_src/dst is addr* field within hdr */
+ h_80211_src = data + fast_tx->sa_offs;
+ h_80211_dst = data + fast_tx->da_offs;
+
+ amsdu_hdr->h_proto = cpu_to_be16(subframe_len);
+ ether_addr_copy(amsdu_hdr->h_source, h_80211_src);
+ ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst);
+
+ /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA
+ * fields needs to be changed to BSSID for A-MSDU frames depending
+ * on FromDS/ToDS values.
+ */
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ bssid = sdata->u.mgd.bssid;
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ bssid = sdata->vif.addr;
+ break;
+ default:
+ bssid = NULL;
+ }
- data = skb_push(skb, sizeof(amsdu_hdr));
- memmove(data, data + sizeof(amsdu_hdr), hdr_len);
- memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr));
+ if (bssid && ieee80211_has_fromds(hdr->frame_control))
+ ether_addr_copy(h_80211_src, bssid);
+
+ if (bssid && ieee80211_has_tods(hdr->frame_control))
+ ether_addr_copy(h_80211_dst, bssid);
- hdr = data;
qc = ieee80211_get_qos_ctl(hdr);
*qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
@@@ -3210,6 -3238,7 +3235,6 @@@ static void ieee80211_xmit_fast_finish(
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
- *ieee80211_get_qos_ctl(hdr) = tid;
hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
} else {
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
@@@ -3334,11 -3363,6 +3359,11 @@@ static bool ieee80211_xmit_fast(struct
(tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
+ if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+ *ieee80211_get_qos_ctl(hdr) = tid;
+ }
+
__skb_queue_head_init(&tx.skbs);
tx.flags = IEEE80211_TX_UNICAST;
@@@ -3427,11 -3451,6 +3452,11 @@@ begin
goto begin;
}
+ if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
+ info->flags |= IEEE80211_TX_CTL_AMPDU;
+ else
+ info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
struct sta_info *sta = container_of(txq->sta, struct sta_info,
sta);
diff --combined net/socket.c
index 73dc69f,f9e26c6..e2584c5
--- a/net/socket.c
+++ b/net/socket.c
@@@ -341,23 -341,8 +341,23 @@@ static const struct xattr_handler sockf
.get = sockfs_xattr_get,
};
+static int sockfs_security_xattr_set(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *suffix, const void *value,
+ size_t size, int flags)
+{
+ /* Handled by LSM. */
+ return -EAGAIN;
+}
+
+static const struct xattr_handler sockfs_security_xattr_handler = {
+ .prefix = XATTR_SECURITY_PREFIX,
+ .set = sockfs_security_xattr_set,
+};
+
static const struct xattr_handler *sockfs_xattr_handlers[] = {
&sockfs_xattr_handler,
+ &sockfs_security_xattr_handler,
NULL
};
@@@ -533,8 -518,22 +533,22 @@@ static ssize_t sockfs_listxattr(struct
return used;
}
+ int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
+ {
+ int err = simple_setattr(dentry, iattr);
+
+ if (!err) {
+ struct socket *sock = SOCKET_I(d_inode(dentry));
+
+ sock->sk->sk_uid = iattr->ia_uid;
+ }
+
+ return err;
+ }
+
static const struct inode_operations sockfs_inode_ops = {
.listxattr = sockfs_listxattr,
+ .setattr = sockfs_setattr,
};
/**
@@@ -892,6 -891,11 +906,11 @@@ static long sock_do_ioctl(struct net *n
* what to do with it - that's up to the protocol still.
*/
+ static struct ns_common *get_net_ns(struct ns_common *ns)
+ {
+ return &get_net(container_of(ns, struct net, ns))->ns;
+ }
+
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
struct socket *sock;
@@@ -960,6 -964,13 +979,13 @@@
err = dlci_ioctl_hook(cmd, argp);
mutex_unlock(&dlci_ioctl_mutex);
break;
+ case SIOCGSKNS:
+ err = -EPERM;
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+ break;
+
+ err = open_related_ns(&net->ns, get_net_ns);
+ break;
default:
err = sock_do_ioctl(net, sock, cmd, arg);
break;
@@@ -3110,6 -3121,7 +3136,7 @@@ static int compat_sock_ioctl_trans(stru
case SIOCSIFVLAN:
case SIOCADDDLCI:
case SIOCDELDLCI:
+ case SIOCGSKNS:
return sock_ioctl(file, cmd, arg);
case SIOCGIFFLAGS:
diff --combined net/sunrpc/svcsock.c
index a4bc982,78da4ae..135ec2c
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@@ -39,6 -39,7 +39,7 @@@
#include <net/checksum.h>
#include <net/ip.h>
#include <net/ipv6.h>
+ #include <net/udp.h>
#include <net/tcp.h>
#include <net/tcp_states.h>
#include <asm/uaccess.h>
@@@ -129,6 -130,18 +130,18 @@@ static void svc_release_skb(struct svc_
}
}
+ static void svc_release_udp_skb(struct svc_rqst *rqstp)
+ {
+ struct sk_buff *skb = rqstp->rq_xprt_ctxt;
+
+ if (skb) {
+ rqstp->rq_xprt_ctxt = NULL;
+
+ dprintk("svc: service %p, releasing skb %p\n", rqstp, skb);
+ consume_skb(skb);
+ }
+ }
+
union svc_pktinfo_u {
struct in_pktinfo pkti;
struct in6_pktinfo pkti6;
@@@ -438,21 -451,6 +451,21 @@@ static int svc_tcp_has_wspace(struct sv
return !test_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
}
+static void svc_tcp_kill_temp_xprt(struct svc_xprt *xprt)
+{
+ struct svc_sock *svsk;
+ struct socket *sock;
+ struct linger no_linger = {
+ .l_onoff = 1,
+ .l_linger = 0,
+ };
+
+ svsk = container_of(xprt, struct svc_sock, sk_xprt);
+ sock = svsk->sk_sock;
+ kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
+ (char *)&no_linger, sizeof(no_linger));
+}
+
/*
* See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo
*/
@@@ -549,7 -547,7 +562,7 @@@ static int svc_udp_recvfrom(struct svc_
err = kernel_recvmsg(svsk->sk_sock, &msg, NULL,
0, 0, MSG_PEEK | MSG_DONTWAIT);
if (err >= 0)
- skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err);
+ skb = skb_recv_udp(svsk->sk_sk, 0, 1, &err);
if (skb == NULL) {
if (err != -EAGAIN) {
@@@ -590,7 -588,7 +603,7 @@@
goto out_free;
}
local_bh_enable();
- skb_free_datagram_locked(svsk->sk_sk, skb);
+ consume_skb(skb);
} else {
/* we can use it in-place */
rqstp->rq_arg.head[0].iov_base = skb->data;
@@@ -617,8 -615,7 +630,7 @@@
return len;
out_free:
- trace_kfree_skb(skb, svc_udp_recvfrom);
- skb_free_datagram_locked(svsk->sk_sk, skb);
+ kfree_skb(skb);
return 0;
}
@@@ -663,10 -660,6 +675,10 @@@ static struct svc_xprt *svc_udp_accept(
return NULL;
}
+static void svc_udp_kill_temp_xprt(struct svc_xprt *xprt)
+{
+}
+
static struct svc_xprt *svc_udp_create(struct svc_serv *serv,
struct net *net,
struct sockaddr *sa, int salen,
@@@ -679,14 -672,13 +691,14 @@@ static struct svc_xprt_ops svc_udp_ops
.xpo_create = svc_udp_create,
.xpo_recvfrom = svc_udp_recvfrom,
.xpo_sendto = svc_udp_sendto,
- .xpo_release_rqst = svc_release_skb,
+ .xpo_release_rqst = svc_release_udp_skb,
.xpo_detach = svc_sock_detach,
.xpo_free = svc_sock_free,
.xpo_prep_reply_hdr = svc_udp_prep_reply_hdr,
.xpo_has_wspace = svc_udp_has_wspace,
.xpo_accept = svc_udp_accept,
.xpo_secure_port = svc_sock_secure_port,
+ .xpo_kill_temp_xprt = svc_udp_kill_temp_xprt,
};
static struct svc_xprt_class svc_udp_class = {
@@@ -1262,7 -1254,6 +1274,7 @@@ static struct svc_xprt_ops svc_tcp_ops
.xpo_has_wspace = svc_tcp_has_wspace,
.xpo_accept = svc_tcp_accept,
.xpo_secure_port = svc_sock_secure_port,
+ .xpo_kill_temp_xprt = svc_tcp_kill_temp_xprt,
};
static struct svc_xprt_class svc_tcp_class = {
diff --combined net/tipc/socket.c
index db32777,22d92f0..4916d8f
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@@ -1,7 -1,7 +1,7 @@@
/*
* net/tipc/socket.c: TIPC socket API
*
- * Copyright (c) 2001-2007, 2012-2015, Ericsson AB
+ * Copyright (c) 2001-2007, 2012-2016, Ericsson AB
* Copyright (c) 2004-2008, 2010-2013, Wind River Systems
* All rights reserved.
*
@@@ -44,44 -44,43 +44,43 @@@
#include "bcast.h"
#include "netlink.h"
- #define SS_LISTENING -1 /* socket is listening */
- #define SS_READY -2 /* socket is connectionless */
-
#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */
#define CONN_PROBING_INTERVAL msecs_to_jiffies(3600000) /* [ms] => 1 h */
#define TIPC_FWD_MSG 1
- #define TIPC_CONN_OK 0
- #define TIPC_CONN_PROBING 1
#define TIPC_MAX_PORT 0xffffffff
#define TIPC_MIN_PORT 1
+ enum {
+ TIPC_LISTEN = TCP_LISTEN,
+ TIPC_ESTABLISHED = TCP_ESTABLISHED,
+ TIPC_OPEN = TCP_CLOSE,
+ TIPC_DISCONNECTING = TCP_CLOSE_WAIT,
+ TIPC_CONNECTING = TCP_SYN_SENT,
+ };
+
/**
* struct tipc_sock - TIPC socket structure
* @sk: socket - interacts with 'port' and with user via the socket API
- * @connected: non-zero if port is currently connected to a peer port
* @conn_type: TIPC type used when connection was established
* @conn_instance: TIPC instance used when connection was established
* @published: non-zero if port has one or more associated names
* @max_pkt: maximum packet size "hint" used when building messages sent by
port
* @portid: unique port identity in TIPC socket hash table
* @phdr: preformatted message header used when sending messages
- * @port_list: adjacent ports in TIPC's global list of ports
* @publications: list of publications for port
* @pub_count: total # of publications port has made during its lifetime
* @probing_state:
- * @probing_intv:
* @conn_timeout: the time we can wait for an unresponded setup request
* @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue
* @link_cong: non-zero if owner must sleep because of link congestion
* @sent_unacked: # messages sent by socket, and not yet acked by peer
* @rcv_unacked: # messages read by user, but not yet acked back to peer
- * @remote: 'connected' peer for dgram/rdm
+ * @peer: 'connected' peer for dgram/rdm
* @node: hash table node
* @rcu: rcu struct for tipc_sock
*/
struct tipc_sock {
struct sock sk;
- int connected;
u32 conn_type;
u32 conn_instance;
int published;
@@@ -91,17 -90,16 +90,16 @@@
struct list_head sock_list;
struct list_head publications;
u32 pub_count;
- u32 probing_state;
- unsigned long probing_intv;
uint conn_timeout;
atomic_t dupl_rcvcnt;
+ bool probe_unacked;
bool link_cong;
u16 snt_unacked;
u16 snd_win;
u16 peer_caps;
u16 rcv_unacked;
u16 rcv_win;
- struct sockaddr_tipc remote;
+ struct sockaddr_tipc peer;
struct rhash_head node;
struct rcu_head rcu;
};
@@@ -129,8 -127,54 +127,8 @@@ static const struct proto_ops packet_op
static const struct proto_ops stream_ops;
static const struct proto_ops msg_ops;
static struct proto tipc_proto;
-
static const struct rhashtable_params tsk_rht_params;
-/*
- * Revised TIPC socket locking policy:
- *
- * Most socket operations take the standard socket lock when they start
- * and hold it until they finish (or until they need to sleep). Acquiring
- * this lock grants the owner exclusive access to the fields of the socket
- * data structures, with the exception of the backlog queue. A few socket
- * operations can be done without taking the socket lock because they only
- * read socket information that never changes during the life of the socket.
- *
- * Socket operations may acquire the lock for the associated TIPC port if they
- * need to perform an operation on the port. If any routine needs to acquire
- * both the socket lock and the port lock it must take the socket lock first
- * to avoid the risk of deadlock.
- *
- * The dispatcher handling incoming messages cannot grab the socket lock in
- * the standard fashion, since invoked it runs at the BH level and cannot block.
- * Instead, it checks to see if the socket lock is currently owned by someone,
- * and either handles the message itself or adds it to the socket's backlog
- * queue; in the latter case the queued message is processed once the process
- * owning the socket lock releases it.
- *
- * NOTE: Releasing the socket lock while an operation is sleeping overcomes
- * the problem of a blocked socket operation preventing any other operations
- * from occurring. However, applications must be careful if they have
- * multiple threads trying to send (or receive) on the same socket, as these
- * operations might interfere with each other. For example, doing a connect
- * and a receive at the same time might allow the receive to consume the
- * ACK message meant for the connect. While additional work could be done
- * to try and overcome this, it doesn't seem to be worthwhile at the present.
- *
- * NOTE: Releasing the socket lock while an operation is sleeping also ensures
- * that another operation that must be performed in a non-blocking manner is
- * not delayed for very long because the lock has already been taken.
- *
- * NOTE: This code assumes that certain fields of a port/socket pair are
- * constant over its lifetime; such fields can be examined without taking
- * the socket lock and/or port lock, and do not need to be re-read even
- * after resuming processing after waiting. These fields include:
- * - socket type
- * - pointer to socket sk structure (aka tipc_sock structure)
- * - pointer to port structure
- * - port reference
- */
-
static u32 tsk_own_node(struct tipc_sock *tsk)
{
return msg_prevnode(&tsk->phdr);
@@@ -248,6 -292,21 +246,21 @@@ static void tsk_rej_rx_queue(struct soc
tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
}
+ static bool tipc_sk_connected(struct sock *sk)
+ {
+ return sk->sk_state == TIPC_ESTABLISHED;
+ }
+
+ /* tipc_sk_type_connectionless - check if the socket is datagram socket
+ * @sk: socket
+ *
+ * Returns true if connection less, false otherwise
+ */
+ static bool tipc_sk_type_connectionless(struct sock *sk)
+ {
+ return sk->sk_type == SOCK_RDM || sk->sk_type == SOCK_DGRAM;
+ }
+
/* tsk_peer_msg - verify if message was sent by connected port's peer
*
* Handles cases where the node's network address has changed from
@@@ -255,12 -314,13 +268,13 @@@
*/
static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg)
{
- struct tipc_net *tn = net_generic(sock_net(&tsk->sk), tipc_net_id);
+ struct sock *sk = &tsk->sk;
+ struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id);
u32 peer_port = tsk_peer_port(tsk);
u32 orig_node;
u32 peer_node;
- if (unlikely(!tsk->connected))
+ if (unlikely(!tipc_sk_connected(sk)))
return false;
if (unlikely(msg_origport(msg) != peer_port))
@@@ -281,6 -341,45 +295,45 @@@
return false;
}
+ /* tipc_set_sk_state - set the sk_state of the socket
+ * @sk: socket
+ *
+ * Caller must hold socket lock
+ *
+ * Returns 0 on success, errno otherwise
+ */
+ static int tipc_set_sk_state(struct sock *sk, int state)
+ {
+ int oldsk_state = sk->sk_state;
+ int res = -EINVAL;
+
+ switch (state) {
+ case TIPC_OPEN:
+ res = 0;
+ break;
+ case TIPC_LISTEN:
+ case TIPC_CONNECTING:
+ if (oldsk_state == TIPC_OPEN)
+ res = 0;
+ break;
+ case TIPC_ESTABLISHED:
+ if (oldsk_state == TIPC_CONNECTING ||
+ oldsk_state == TIPC_OPEN)
+ res = 0;
+ break;
+ case TIPC_DISCONNECTING:
+ if (oldsk_state == TIPC_CONNECTING ||
+ oldsk_state == TIPC_ESTABLISHED)
+ res = 0;
+ break;
+ }
+
+ if (!res)
+ sk->sk_state = state;
+
+ return res;
+ }
+
/**
* tipc_sk_create - create a TIPC socket
* @net: network namespace (must be default network)
@@@ -298,7 -397,6 +351,6 @@@ static int tipc_sk_create(struct net *n
{
struct tipc_net *tn;
const struct proto_ops *ops;
- socket_state state;
struct sock *sk;
struct tipc_sock *tsk;
struct tipc_msg *msg;
@@@ -310,16 -408,13 +362,13 @@@
switch (sock->type) {
case SOCK_STREAM:
ops = &stream_ops;
- state = SS_UNCONNECTED;
break;
case SOCK_SEQPACKET:
ops = &packet_ops;
- state = SS_UNCONNECTED;
break;
case SOCK_DGRAM:
case SOCK_RDM:
ops = &msg_ops;
- state = SS_READY;
break;
default:
return -EPROTOTYPE;
@@@ -340,14 -435,15 +389,15 @@@
/* Finish initializing socket data structures */
sock->ops = ops;
- sock->state = state;
sock_init_data(sock, sk);
+ tipc_set_sk_state(sk, TIPC_OPEN);
if (tipc_sk_insert(tsk)) {
pr_warn("Socket create failed; port number exhausted\n");
return -EINVAL;
}
msg_set_origport(msg, tsk->portid);
setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk);
+ sk->sk_shutdown = 0;
sk->sk_backlog_rcv = tipc_backlog_rcv;
sk->sk_rcvbuf = sysctl_tipc_rmem[1];
sk->sk_data_ready = tipc_data_ready;
@@@ -360,11 -456,12 +410,12 @@@
tsk->snd_win = tsk_adv_blocks(RCVBUF_MIN);
tsk->rcv_win = tsk->snd_win;
- if (sock->state == SS_READY) {
+ if (tipc_sk_type_connectionless(sk)) {
tsk_set_unreturnable(tsk, true);
if (sock->type == SOCK_DGRAM)
tsk_set_unreliable(tsk, true);
}
+
return 0;
}
@@@ -375,6 -472,44 +426,44 @@@ static void tipc_sk_callback(struct rcu
sock_put(&tsk->sk);
}
+ /* Caller should hold socket lock for the socket. */
+ static void __tipc_shutdown(struct socket *sock, int error)
+ {
+ struct sock *sk = sock->sk;
+ struct tipc_sock *tsk = tipc_sk(sk);
+ struct net *net = sock_net(sk);
+ u32 dnode = tsk_peer_node(tsk);
+ struct sk_buff *skb;
+
+ /* Reject all unreceived messages, except on an active connection
+ * (which disconnects locally & sends a 'FIN+' to peer).
+ */
+ while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ if (TIPC_SKB_CB(skb)->bytes_read) {
+ kfree_skb(skb);
+ } else {
+ if (!tipc_sk_type_connectionless(sk) &&
+ sk->sk_state != TIPC_DISCONNECTING) {
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+ tipc_node_remove_conn(net, dnode, tsk->portid);
+ }
+ tipc_sk_respond(sk, skb, error);
+ }
+ }
+ if (sk->sk_state != TIPC_DISCONNECTING) {
+ skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
+ TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
+ tsk_own_node(tsk), tsk_peer_port(tsk),
+ tsk->portid, error);
+ if (skb)
+ tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
+ if (!tipc_sk_type_connectionless(sk)) {
+ tipc_node_remove_conn(net, dnode, tsk->portid);
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+ }
+ }
+ }
+
/**
* tipc_release - destroy a TIPC socket
* @sock: socket to destroy
@@@ -394,10 -529,7 +483,7 @@@
static int tipc_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct net *net;
struct tipc_sock *tsk;
- struct sk_buff *skb;
- u32 dnode;
/*
* Exit if socket isn't fully initialized (occurs when a failed accept()
@@@ -406,47 -538,16 +492,16 @@@
if (sk == NULL)
return 0;
- net = sock_net(sk);
tsk = tipc_sk(sk);
lock_sock(sk);
- /*
- * Reject all unreceived messages, except on an active connection
- * (which disconnects locally & sends a 'FIN+' to peer)
- */
- dnode = tsk_peer_node(tsk);
- while (sock->state != SS_DISCONNECTING) {
- skb = __skb_dequeue(&sk->sk_receive_queue);
- if (skb == NULL)
- break;
- if (TIPC_SKB_CB(skb)->handle != NULL)
- kfree_skb(skb);
- else {
- if ((sock->state == SS_CONNECTING) ||
- (sock->state == SS_CONNECTED)) {
- sock->state = SS_DISCONNECTING;
- tsk->connected = 0;
- tipc_node_remove_conn(net, dnode, tsk->portid);
- }
- tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
- }
- }
-
+ __tipc_shutdown(sock, TIPC_ERR_NO_PORT);
+ sk->sk_shutdown = SHUTDOWN_MASK;
tipc_sk_withdraw(tsk, 0, NULL);
sk_stop_timer(sk, &sk->sk_timer);
tipc_sk_remove(tsk);
- if (tsk->connected) {
- skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
- TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
- tsk_own_node(tsk), tsk_peer_port(tsk),
- tsk->portid, TIPC_ERR_NO_PORT);
- if (skb)
- tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
- tipc_node_remove_conn(net, dnode, tsk->portid);
- }
/* Reject any messages that accumulated in backlog queue */
- sock->state = SS_DISCONNECTING;
release_sock(sk);
call_rcu(&tsk->rcu, tipc_sk_callback);
@@@ -532,13 -633,14 +587,14 @@@ static int tipc_getname(struct socket *
int *uaddr_len, int peer)
{
struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
- struct tipc_sock *tsk = tipc_sk(sock->sk);
+ struct sock *sk = sock->sk;
+ struct tipc_sock *tsk = tipc_sk(sk);
struct tipc_net *tn = net_generic(sock_net(sock->sk), tipc_net_id);
memset(addr, 0, sizeof(*addr));
if (peer) {
- if ((sock->state != SS_CONNECTED) &&
- ((peer != 2) || (sock->state != SS_DISCONNECTING)))
+ if ((!tipc_sk_connected(sk)) &&
+ ((peer != 2) || (sk->sk_state != TIPC_DISCONNECTING)))
return -ENOTCONN;
addr->addr.id.ref = tsk_peer_port(tsk);
addr->addr.id.node = tsk_peer_node(tsk);
@@@ -570,28 -672,6 +626,6 @@@
* exits. TCP and other protocols seem to rely on higher level poll routines
* to handle any preventable race conditions, so TIPC will do the same ...
*
- * TIPC sets the returned events as follows:
- *
- * socket state flags set
- * ------------ ---------
- * unconnected no read flags
- * POLLOUT if port is not congested
- *
- * connecting POLLIN/POLLRDNORM if ACK/NACK in rx queue
- * no write flags
- *
- * connected POLLIN/POLLRDNORM if data in rx queue
- * POLLOUT if port is not congested
- *
- * disconnecting POLLIN/POLLRDNORM/POLLHUP
- * no write flags
- *
- * listening POLLIN if SYN in rx queue
- * no write flags
- *
- * ready POLLIN/POLLRDNORM if data in rx queue
- * [connectionless] POLLOUT (since port cannot be congested)
- *
* IMPORTANT: The fact that a read or write operation is indicated does NOT
* imply that the operation will succeed, merely that it should be performed
* and will not block.
@@@ -605,22 -685,29 +639,29 @@@ static unsigned int tipc_poll(struct fi
sock_poll_wait(file, sk_sleep(sk), wait);
- switch ((int)sock->state) {
- case SS_UNCONNECTED:
- if (!tsk->link_cong)
- mask |= POLLOUT;
- break;
- case SS_READY:
- case SS_CONNECTED:
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLRDHUP | POLLIN | POLLRDNORM;
+ if (sk->sk_shutdown == SHUTDOWN_MASK)
+ mask |= POLLHUP;
+
+ switch (sk->sk_state) {
+ case TIPC_ESTABLISHED:
if (!tsk->link_cong && !tsk_conn_cong(tsk))
mask |= POLLOUT;
/* fall thru' */
- case SS_CONNECTING:
- case SS_LISTENING:
+ case TIPC_LISTEN:
+ case TIPC_CONNECTING:
if (!skb_queue_empty(&sk->sk_receive_queue))
mask |= (POLLIN | POLLRDNORM);
break;
- case SS_DISCONNECTING:
+ case TIPC_OPEN:
+ if (!tsk->link_cong)
+ mask |= POLLOUT;
+ if (tipc_sk_type_connectionless(sk) &&
+ (!skb_queue_empty(&sk->sk_receive_queue)))
+ mask |= (POLLIN | POLLRDNORM);
+ break;
+ case TIPC_DISCONNECTING:
mask = (POLLIN | POLLRDNORM | POLLHUP);
break;
}
@@@ -651,6 -738,9 +692,9 @@@ static int tipc_sendmcast(struct socke
uint mtu;
int rc;
+ if (!timeo && tsk->link_cong)
+ return -ELINKCONG;
+
msg_set_type(mhdr, TIPC_MCAST_MSG);
msg_set_lookup_scope(mhdr, TIPC_CLUSTER_SCOPE);
msg_set_destport(mhdr, 0);
@@@ -763,7 -853,7 +807,7 @@@ static void tipc_sk_proto_rcv(struct ti
if (!tsk_peer_msg(tsk, hdr))
goto exit;
- tsk->probing_state = TIPC_CONN_OK;
+ tsk->probe_unacked = false;
if (mtyp == CONN_PROBE) {
msg_set_type(hdr, CONN_PROBE_REPLY);
@@@ -786,25 -876,25 +830,25 @@@ exit
static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct sock *sk = sock->sk;
struct tipc_sock *tsk = tipc_sk(sk);
- DEFINE_WAIT(wait);
int done;
do {
int err = sock_error(sk);
if (err)
return err;
- if (sock->state == SS_DISCONNECTING)
+ if (sk->sk_shutdown & SEND_SHUTDOWN)
return -EPIPE;
if (!*timeo_p)
return -EAGAIN;
if (signal_pending(current))
return sock_intr_errno(*timeo_p);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
- done = sk_wait_event(sk, timeo_p, !tsk->link_cong);
- finish_wait(sk_sleep(sk), &wait);
+ add_wait_queue(sk_sleep(sk), &wait);
+ done = sk_wait_event(sk, timeo_p, !tsk->link_cong, &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
} while (!done);
return 0;
}
@@@ -844,6 -934,7 +888,7 @@@ static int __tipc_sendmsg(struct socke
struct tipc_msg *mhdr = &tsk->phdr;
u32 dnode, dport;
struct sk_buff_head pktchain;
+ bool is_connectionless = tipc_sk_type_connectionless(sk);
struct sk_buff *skb;
struct tipc_name_seq *seq;
struct iov_iter save;
@@@ -854,18 -945,18 +899,18 @@@
if (dsz > TIPC_MAX_USER_MSG_SIZE)
return -EMSGSIZE;
if (unlikely(!dest)) {
- if (tsk->connected && sock->state == SS_READY)
- dest = &tsk->remote;
+ if (is_connectionless && tsk->peer.family == AF_TIPC)
+ dest = &tsk->peer;
else
return -EDESTADDRREQ;
} else if (unlikely(m->msg_namelen < sizeof(*dest)) ||
dest->family != AF_TIPC) {
return -EINVAL;
}
- if (unlikely(sock->state != SS_READY)) {
- if (sock->state == SS_LISTENING)
+ if (!is_connectionless) {
+ if (sk->sk_state == TIPC_LISTEN)
return -EPIPE;
- if (sock->state != SS_UNCONNECTED)
+ if (sk->sk_state != TIPC_OPEN)
return -EISCONN;
if (tsk->published)
return -EOPNOTSUPP;
@@@ -917,8 -1008,8 +962,8 @@@ new_mtu
TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong;
rc = tipc_node_xmit(net, &pktchain, dnode, tsk->portid);
if (likely(!rc)) {
- if (sock->state != SS_READY)
- sock->state = SS_CONNECTING;
+ if (!is_connectionless)
+ tipc_set_sk_state(sk, TIPC_CONNECTING);
return dsz;
}
if (rc == -ELINKCONG) {
@@@ -940,30 -1031,30 +985,30 @@@
static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct sock *sk = sock->sk;
struct tipc_sock *tsk = tipc_sk(sk);
- DEFINE_WAIT(wait);
int done;
do {
int err = sock_error(sk);
if (err)
return err;
- if (sock->state == SS_DISCONNECTING)
+ if (sk->sk_state == TIPC_DISCONNECTING)
return -EPIPE;
- else if (sock->state != SS_CONNECTED)
+ else if (!tipc_sk_connected(sk))
return -ENOTCONN;
if (!*timeo_p)
return -EAGAIN;
if (signal_pending(current))
return sock_intr_errno(*timeo_p);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+ add_wait_queue(sk_sleep(sk), &wait);
done = sk_wait_event(sk, timeo_p,
(!tsk->link_cong &&
!tsk_conn_cong(tsk)) ||
- !tsk->connected);
- finish_wait(sk_sleep(sk), &wait);
+ !tipc_sk_connected(sk), &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
} while (!done);
return 0;
}
@@@ -1018,14 -1109,17 +1063,17 @@@ static int __tipc_send_stream(struct so
if (dsz > (uint)INT_MAX)
return -EMSGSIZE;
- if (unlikely(sock->state != SS_CONNECTED)) {
- if (sock->state == SS_DISCONNECTING)
+ if (unlikely(!tipc_sk_connected(sk))) {
+ if (sk->sk_state == TIPC_DISCONNECTING)
return -EPIPE;
else
return -ENOTCONN;
}
timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
+ if (!timeo && tsk->link_cong)
+ return -ELINKCONG;
+
dnode = tsk_peer_node(tsk);
skb_queue_head_init(&pktchain);
@@@ -1099,10 -1193,8 +1147,8 @@@ static void tipc_sk_finish_conn(struct
msg_set_lookup_scope(msg, 0);
msg_set_hdr_sz(msg, SHORT_H_SIZE);
- tsk->probing_intv = CONN_PROBING_INTERVAL;
- tsk->probing_state = TIPC_CONN_OK;
- tsk->connected = 1;
- sk_reset_timer(sk, &sk->sk_timer, jiffies + tsk->probing_intv);
+ sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTERVAL);
+ tipc_set_sk_state(sk, TIPC_ESTABLISHED);
tipc_node_add_conn(net, peer_node, tsk->portid, peer_port);
tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid);
tsk->peer_caps = tipc_node_get_capabilities(net, peer_node);
@@@ -1210,13 -1302,14 +1256,14 @@@ static int tipc_sk_anc_data_recv(struc
static void tipc_sk_send_ack(struct tipc_sock *tsk)
{
- struct net *net = sock_net(&tsk->sk);
+ struct sock *sk = &tsk->sk;
+ struct net *net = sock_net(sk);
struct sk_buff *skb = NULL;
struct tipc_msg *msg;
u32 peer_port = tsk_peer_port(tsk);
u32 dnode = tsk_peer_node(tsk);
- if (!tsk->connected)
+ if (!tipc_sk_connected(sk))
return;
skb = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE, 0,
dnode, tsk_own_node(tsk), peer_port,
@@@ -1245,7 -1338,7 +1292,7 @@@ static int tipc_wait_for_rcvmsg(struct
for (;;) {
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
- if (sock->state == SS_DISCONNECTING) {
+ if (sk->sk_shutdown & RCV_SHUTDOWN) {
err = -ENOTCONN;
break;
}
@@@ -1286,6 -1379,7 +1333,7 @@@ static int tipc_recvmsg(struct socket *
struct tipc_sock *tsk = tipc_sk(sk);
struct sk_buff *buf;
struct tipc_msg *msg;
+ bool is_connectionless = tipc_sk_type_connectionless(sk);
long timeo;
unsigned int sz;
u32 err;
@@@ -1297,7 -1391,7 +1345,7 @@@
lock_sock(sk);
- if (unlikely(sock->state == SS_UNCONNECTED)) {
+ if (!is_connectionless && unlikely(sk->sk_state == TIPC_OPEN)) {
res = -ENOTCONN;
goto exit;
}
@@@ -1342,8 -1436,8 +1390,8 @@@ restart
goto exit;
res = sz;
} else {
- if ((sock->state == SS_READY) ||
- ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
+ if (is_connectionless || err == TIPC_CONN_SHUTDOWN ||
+ m->msg_control)
res = 0;
else
res = -ECONNRESET;
@@@ -1352,7 -1446,7 +1400,7 @@@
if (unlikely(flags & MSG_PEEK))
goto exit;
- if (likely(sock->state != SS_READY)) {
+ if (likely(!is_connectionless)) {
tsk->rcv_unacked += tsk_inc(tsk, hlen + sz);
if (unlikely(tsk->rcv_unacked >= (tsk->rcv_win / 4)))
tipc_sk_send_ack(tsk);
@@@ -1383,7 -1477,7 +1431,7 @@@ static int tipc_recv_stream(struct sock
struct tipc_msg *msg;
long timeo;
unsigned int sz;
- int sz_to_copy, target, needed;
+ int target;
int sz_copied = 0;
u32 err;
int res = 0, hlen;
@@@ -1394,7 -1488,7 +1442,7 @@@
lock_sock(sk);
- if (unlikely(sock->state == SS_UNCONNECTED)) {
+ if (unlikely(sk->sk_state == TIPC_OPEN)) {
res = -ENOTCONN;
goto exit;
}
@@@ -1431,11 -1525,13 +1479,13 @@@ restart
/* Capture message data (if valid) & compute return value (always) */
if (!err) {
- u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
+ u32 offset = TIPC_SKB_CB(buf)->bytes_read;
+ u32 needed;
+ int sz_to_copy;
sz -= offset;
needed = (buf_len - sz_copied);
- sz_to_copy = (sz <= needed) ? sz : needed;
+ sz_to_copy = min(sz, needed);
res = skb_copy_datagram_msg(buf, hlen + offset, m, sz_to_copy);
if (res)
@@@ -1445,8 -1541,8 +1495,8 @@@
if (sz_to_copy < sz) {
if (!(flags & MSG_PEEK))
- TIPC_SKB_CB(buf)->handle =
- (void *)(unsigned long)(offset + sz_to_copy);
+ TIPC_SKB_CB(buf)->bytes_read =
+ offset + sz_to_copy;
goto exit;
}
} else {
@@@ -1528,49 -1624,31 +1578,31 @@@ static bool filter_connect(struct tipc_
{
struct sock *sk = &tsk->sk;
struct net *net = sock_net(sk);
- struct socket *sock = sk->sk_socket;
struct tipc_msg *hdr = buf_msg(skb);
if (unlikely(msg_mcast(hdr)))
return false;
- switch ((int)sock->state) {
- case SS_CONNECTED:
-
- /* Accept only connection-based messages sent by peer */
- if (unlikely(!tsk_peer_msg(tsk, hdr)))
- return false;
-
- if (unlikely(msg_errcode(hdr))) {
- sock->state = SS_DISCONNECTING;
- tsk->connected = 0;
- /* Let timer expire on it's own */
- tipc_node_remove_conn(net, tsk_peer_node(tsk),
- tsk->portid);
- }
- return true;
-
- case SS_CONNECTING:
-
+ switch (sk->sk_state) {
+ case TIPC_CONNECTING:
/* Accept only ACK or NACK message */
if (unlikely(!msg_connected(hdr)))
return false;
if (unlikely(msg_errcode(hdr))) {
- sock->state = SS_DISCONNECTING;
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
sk->sk_err = ECONNREFUSED;
return true;
}
if (unlikely(!msg_isdata(hdr))) {
- sock->state = SS_DISCONNECTING;
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
sk->sk_err = EINVAL;
return true;
}
tipc_sk_finish_conn(tsk, msg_origport(hdr), msg_orignode(hdr));
msg_set_importance(&tsk->phdr, msg_importance(hdr));
- sock->state = SS_CONNECTED;
/* If 'ACK+' message, add to socket receive queue */
if (msg_data_sz(hdr))
@@@ -1584,18 -1662,31 +1616,31 @@@
msg_set_dest_droppable(hdr, 1);
return false;
- case SS_LISTENING:
- case SS_UNCONNECTED:
-
+ case TIPC_OPEN:
+ case TIPC_DISCONNECTING:
+ break;
+ case TIPC_LISTEN:
/* Accept only SYN message */
if (!msg_connected(hdr) && !(msg_errcode(hdr)))
return true;
break;
- case SS_DISCONNECTING:
- break;
+ case TIPC_ESTABLISHED:
+ /* Accept only connection-based messages sent by peer */
+ if (unlikely(!tsk_peer_msg(tsk, hdr)))
+ return false;
+
+ if (unlikely(msg_errcode(hdr))) {
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+ /* Let timer expire on it's own */
+ tipc_node_remove_conn(net, tsk_peer_node(tsk),
+ tsk->portid);
+ sk->sk_state_change(sk);
+ }
+ return true;
default:
- pr_err("Unknown socket state %u\n", sock->state);
+ pr_err("Unknown sk_state %u\n", sk->sk_state);
}
+
return false;
}
@@@ -1646,7 -1737,6 +1691,6 @@@ static unsigned int rcvbuf_limit(struc
static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
struct sk_buff_head *xmitq)
{
- struct socket *sock = sk->sk_socket;
struct tipc_sock *tsk = tipc_sk(sk);
struct tipc_msg *hdr = buf_msg(skb);
unsigned int limit = rcvbuf_limit(sk, skb);
@@@ -1672,7 -1762,7 +1716,7 @@@
}
/* Reject if wrong message type for current socket state */
- if (unlikely(sock->state == SS_READY)) {
+ if (tipc_sk_type_connectionless(sk)) {
if (msg_connected(hdr)) {
err = TIPC_ERR_NO_PORT;
goto reject;
@@@ -1689,7 -1779,7 +1733,7 @@@
}
/* Enqueue message */
- TIPC_SKB_CB(skb)->handle = NULL;
+ TIPC_SKB_CB(skb)->bytes_read = 0;
__skb_queue_tail(&sk->sk_receive_queue, skb);
skb_set_owner_r(skb, sk);
@@@ -1839,8 -1929,8 +1883,8 @@@ xmit
static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
{
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct sock *sk = sock->sk;
- DEFINE_WAIT(wait);
int done;
do {
@@@ -1852,9 -1942,10 +1896,10 @@@
if (signal_pending(current))
return sock_intr_errno(*timeo_p);
- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
- done = sk_wait_event(sk, timeo_p, sock->state != SS_CONNECTING);
- finish_wait(sk_sleep(sk), &wait);
+ add_wait_queue(sk_sleep(sk), &wait);
+ done = sk_wait_event(sk, timeo_p,
+ sk->sk_state != TIPC_CONNECTING, &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
} while (!done);
return 0;
}
@@@ -1876,21 -1967,19 +1921,19 @@@ static int tipc_connect(struct socket *
struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
struct msghdr m = {NULL,};
long timeout = (flags & O_NONBLOCK) ? 0 : tsk->conn_timeout;
- socket_state previous;
+ int previous;
int res = 0;
lock_sock(sk);
/* DGRAM/RDM connect(), just save the destaddr */
- if (sock->state == SS_READY) {
+ if (tipc_sk_type_connectionless(sk)) {
if (dst->family == AF_UNSPEC) {
- memset(&tsk->remote, 0, sizeof(struct sockaddr_tipc));
- tsk->connected = 0;
+ memset(&tsk->peer, 0, sizeof(struct sockaddr_tipc));
} else if (destlen != sizeof(struct sockaddr_tipc)) {
res = -EINVAL;
} else {
- memcpy(&tsk->remote, dest, destlen);
- tsk->connected = 1;
+ memcpy(&tsk->peer, dest, destlen);
}
goto exit;
}
@@@ -1906,9 -1995,10 +1949,10 @@@
goto exit;
}
- previous = sock->state;
- switch (sock->state) {
- case SS_UNCONNECTED:
+ previous = sk->sk_state;
+
+ switch (sk->sk_state) {
+ case TIPC_OPEN:
/* Send a 'SYN-' to destination */
m.msg_name = dest;
m.msg_namelen = destlen;
@@@ -1923,27 -2013,29 +1967,29 @@@
if ((res < 0) && (res != -EWOULDBLOCK))
goto exit;
- /* Just entered SS_CONNECTING state; the only
+ /* Just entered TIPC_CONNECTING state; the only
* difference is that return value in non-blocking
* case is EINPROGRESS, rather than EALREADY.
*/
res = -EINPROGRESS;
- case SS_CONNECTING:
- if (previous == SS_CONNECTING)
- res = -EALREADY;
- if (!timeout)
+ /* fall thru' */
+ case TIPC_CONNECTING:
+ if (!timeout) {
+ if (previous == TIPC_CONNECTING)
+ res = -EALREADY;
goto exit;
+ }
timeout = msecs_to_jiffies(timeout);
/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
res = tipc_wait_for_connect(sock, &timeout);
break;
- case SS_CONNECTED:
+ case TIPC_ESTABLISHED:
res = -EISCONN;
break;
default:
res = -EINVAL;
- break;
}
+
exit:
release_sock(sk);
return res;
@@@ -1962,15 -2054,9 +2008,9 @@@ static int tipc_listen(struct socket *s
int res;
lock_sock(sk);
-
- if (sock->state != SS_UNCONNECTED)
- res = -EINVAL;
- else {
- sock->state = SS_LISTENING;
- res = 0;
- }
-
+ res = tipc_set_sk_state(sk, TIPC_LISTEN);
release_sock(sk);
+
return res;
}
@@@ -1996,9 -2082,6 +2036,6 @@@ static int tipc_wait_for_accept(struct
err = 0;
if (!skb_queue_empty(&sk->sk_receive_queue))
break;
- err = -EINVAL;
- if (sock->state != SS_LISTENING)
- break;
err = -EAGAIN;
if (!timeo)
break;
@@@ -2029,7 -2112,7 +2066,7 @@@ static int tipc_accept(struct socket *s
lock_sock(sk);
- if (sock->state != SS_LISTENING) {
+ if (sk->sk_state != TIPC_LISTEN) {
res = -EINVAL;
goto exit;
}
@@@ -2040,7 -2123,7 +2077,7 @@@
buf = skb_peek(&sk->sk_receive_queue);
- res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
+ res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 0);
if (res)
goto exit;
security_sk_clone(sock->sk, new_sock->sk);
@@@ -2060,7 -2143,6 +2097,6 @@@
/* Connect new socket to it's peer */
tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg));
- new_sock->state = SS_CONNECTED;
tsk_set_importance(new_tsock, msg_importance(msg));
if (msg_named(msg)) {
@@@ -2100,13 -2182,6 +2136,6 @@@ exit
static int tipc_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
- struct net *net = sock_net(sk);
- struct tipc_sock *tsk = tipc_sk(sk);
- struct sk_buff *skb;
- u32 dnode = tsk_peer_node(tsk);
- u32 dport = tsk_peer_port(tsk);
- u32 onode = tipc_own_addr(net);
- u32 oport = tsk->portid;
int res;
if (how != SHUT_RDWR)
@@@ -2114,45 -2189,17 +2143,17 @@@
lock_sock(sk);
- switch (sock->state) {
- case SS_CONNECTING:
- case SS_CONNECTED:
-
- restart:
- dnode = tsk_peer_node(tsk);
-
- /* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
- skb = __skb_dequeue(&sk->sk_receive_queue);
- if (skb) {
- if (TIPC_SKB_CB(skb)->handle != NULL) {
- kfree_skb(skb);
- goto restart;
- }
- tipc_sk_respond(sk, skb, TIPC_CONN_SHUTDOWN);
- } else {
- skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
- TIPC_CONN_MSG, SHORT_H_SIZE,
- 0, dnode, onode, dport, oport,
- TIPC_CONN_SHUTDOWN);
- if (skb)
- tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
- }
- tsk->connected = 0;
- sock->state = SS_DISCONNECTING;
- tipc_node_remove_conn(net, dnode, tsk->portid);
- /* fall through */
-
- case SS_DISCONNECTING:
+ __tipc_shutdown(sock, TIPC_CONN_SHUTDOWN);
+ sk->sk_shutdown = SEND_SHUTDOWN;
+ if (sk->sk_state == TIPC_DISCONNECTING) {
/* Discard any unreceived messages */
__skb_queue_purge(&sk->sk_receive_queue);
/* Wake up anyone sleeping in poll */
sk->sk_state_change(sk);
res = 0;
- break;
-
- default:
+ } else {
res = -ENOTCONN;
}
@@@ -2169,17 -2216,16 +2170,16 @@@ static void tipc_sk_timeout(unsigned lo
u32 own_node = tsk_own_node(tsk);
bh_lock_sock(sk);
- if (!tsk->connected) {
+ if (!tipc_sk_connected(sk)) {
bh_unlock_sock(sk);
goto exit;
}
peer_port = tsk_peer_port(tsk);
peer_node = tsk_peer_node(tsk);
- if (tsk->probing_state == TIPC_CONN_PROBING) {
+ if (tsk->probe_unacked) {
if (!sock_owned_by_user(sk)) {
- sk->sk_socket->state = SS_DISCONNECTING;
- tsk->connected = 0;
+ tipc_set_sk_state(sk, TIPC_DISCONNECTING);
tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk),
tsk_peer_port(tsk));
sk->sk_state_change(sk);
@@@ -2188,13 -2234,15 +2188,15 @@@
sk_reset_timer(sk, &sk->sk_timer, (HZ / 20));
}
- } else {
- skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE,
- INT_H_SIZE, 0, peer_node, own_node,
- peer_port, tsk->portid, TIPC_OK);
- tsk->probing_state = TIPC_CONN_PROBING;
- sk_reset_timer(sk, &sk->sk_timer, jiffies + tsk->probing_intv);
+ bh_unlock_sock(sk);
+ goto exit;
}
+
+ skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE,
+ INT_H_SIZE, 0, peer_node, own_node,
+ peer_port, tsk->portid, TIPC_OK);
+ tsk->probe_unacked = true;
+ sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTERVAL);
bh_unlock_sock(sk);
if (skb)
tipc_node_xmit_skb(sock_net(sk), skb, peer_node, tsk->portid);
@@@ -2205,11 -2253,12 +2207,12 @@@ exit
static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
struct tipc_name_seq const *seq)
{
- struct net *net = sock_net(&tsk->sk);
+ struct sock *sk = &tsk->sk;
+ struct net *net = sock_net(sk);
struct publication *publ;
u32 key;
- if (tsk->connected)
+ if (tipc_sk_connected(sk))
return -EINVAL;
key = tsk->portid + tsk->pub_count + 1;
if (key == tsk->portid)
@@@ -2667,6 -2716,7 +2670,7 @@@ static int __tipc_nl_add_sk(struct sk_b
struct nlattr *attrs;
struct net *net = sock_net(skb->sk);
struct tipc_net *tn = net_generic(net, tipc_net_id);
+ struct sock *sk = &tsk->sk;
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
&tipc_genl_family, NLM_F_MULTI, TIPC_NL_SOCK_GET);
@@@ -2681,7 -2731,7 +2685,7 @@@
if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tn->own_addr))
goto attr_msg_cancel;
- if (tsk->connected) {
+ if (tipc_sk_connected(sk)) {
err = __tipc_nl_add_sk_con(skb, tsk);
if (err)
goto attr_msg_cancel;
diff --combined net/unix/af_unix.c
index 6f72508,6a705d0..310882f
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@@ -315,7 -315,7 +315,7 @@@ static struct sock *unix_find_socket_by
&unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
struct dentry *dentry = unix_sk(s)->path.dentry;
- if (dentry && d_real_inode(dentry) == i) {
+ if (dentry && d_backing_inode(dentry) == i) {
sock_hold(s);
goto found;
}
@@@ -913,7 -913,7 +913,7 @@@ static struct sock *unix_find_other(str
err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
if (err)
goto fail;
- inode = d_real_inode(path.dentry);
+ inode = d_backing_inode(path.dentry);
err = inode_permission(inode, MAY_WRITE);
if (err)
goto put_fail;
@@@ -1040,7 -1040,7 +1040,7 @@@ static int unix_bind(struct socket *soc
goto out_up;
}
addr->hash = UNIX_HASH_SIZE;
- hash = d_real_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
+ hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
spin_lock(&unix_table_lock);
u->path = path;
list = &unix_socket_table[hash];
@@@ -2113,8 -2113,8 +2113,8 @@@ static int unix_dgram_recvmsg(struct so
mutex_lock(&u->iolock);
skip = sk_peek_offset(sk, flags);
- skb = __skb_try_recv_datagram(sk, flags, &peeked, &skip, &err,
- &last);
+ skb = __skb_try_recv_datagram(sk, flags, NULL, &peeked, &skip,
+ &err, &last);
if (skb)
break;
@@@ -2199,8 -2199,7 +2199,8 @@@ out
* Sleep until more data has arrived. But check for races..
*/
static long unix_stream_data_wait(struct sock *sk, long timeo,
- struct sk_buff *last, unsigned int last_len)
+ struct sk_buff *last, unsigned int last_len,
+ bool freezable)
{
struct sk_buff *tail;
DEFINE_WAIT(wait);
@@@ -2221,10 -2220,7 +2221,10 @@@
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
unix_state_unlock(sk);
- timeo = freezable_schedule_timeout(timeo);
+ if (freezable)
+ timeo = freezable_schedule_timeout(timeo);
+ else
+ timeo = schedule_timeout(timeo);
unix_state_lock(sk);
if (sock_flag(sk, SOCK_DEAD))
@@@ -2254,8 -2250,7 +2254,8 @@@ struct unix_stream_read_state
unsigned int splice_flags;
};
-static int unix_stream_read_generic(struct unix_stream_read_state *state)
+static int unix_stream_read_generic(struct unix_stream_read_state *state,
+ bool freezable)
{
struct scm_cookie scm;
struct socket *sock = state->socket;
@@@ -2335,7 -2330,7 +2335,7 @@@ again
mutex_unlock(&u->iolock);
timeo = unix_stream_data_wait(sk, timeo, last,
- last_len);
+ last_len, freezable);
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
@@@ -2477,7 -2472,7 +2477,7 @@@ static int unix_stream_recvmsg(struct s
.flags = flags
};
- return unix_stream_read_generic(&state);
+ return unix_stream_read_generic(&state, true);
}
static int unix_stream_splice_actor(struct sk_buff *skb,
@@@ -2508,7 -2503,7 +2508,7 @@@ static ssize_t unix_stream_splice_read(
flags & SPLICE_F_NONBLOCK)
state.flags = MSG_DONTWAIT;
- return unix_stream_read_generic(&state);
+ return unix_stream_read_generic(&state, false);
}
static int unix_shutdown(struct socket *sock, int mode)
diff --combined net/wireless/core.h
index f0c0c8a,fb2fcd5..ec5f333
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@@ -71,7 -71,6 +71,7 @@@ struct cfg80211_registered_device
struct list_head bss_list;
struct rb_root bss_tree;
u32 bss_generation;
+ u32 bss_entries;
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
struct sk_buff *scan_msg;
struct cfg80211_sched_scan_request __rcu *sched_scan_req;
@@@ -346,7 -345,7 +346,7 @@@ int cfg80211_mlme_auth(struct cfg80211_
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx,
- const u8 *sae_data, int sae_data_len);
+ const u8 *auth_data, int auth_data_len);
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ieee80211_channel *chan,
@@@ -476,7 -475,7 +476,7 @@@ int ieee80211_get_ratemask(struct ieee8
u32 *mask);
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- u32 beacon_int);
+ enum nl80211_iftype iftype, u32 beacon_int);
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype, int num);
diff --combined net/wireless/util.c
index 659b507,88725f8..e9d040d
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@@ -13,6 -13,7 +13,7 @@@
#include <net/dsfield.h>
#include <linux/if_vlan.h>
#include <linux/mpls.h>
+ #include <linux/gcd.h>
#include "core.h"
#include "rdev-ops.h"
@@@ -1158,8 -1159,7 +1159,8 @@@ static u32 cfg80211_calculate_bitrate_v
58500000,
65000000,
78000000,
- 0,
+ /* not in the spec, but some devices use this: */
+ 86500000,
},
{ 13500000,
27000000,
@@@ -1378,6 -1378,25 +1379,25 @@@ static bool ieee80211_id_in_list(const
return false;
}
+ static size_t skip_ie(const u8 *ies, size_t ielen, size_t pos)
+ {
+ /* we assume a validly formed IEs buffer */
+ u8 len = ies[pos + 1];
+
+ pos += 2 + len;
+
+ /* the IE itself must have 255 bytes for fragments to follow */
+ if (len < 255)
+ return pos;
+
+ while (pos < ielen && ies[pos] == WLAN_EID_FRAGMENT) {
+ len = ies[pos + 1];
+ pos += 2 + len;
+ }
+
+ return pos;
+ }
+
size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
const u8 *ids, int n_ids,
const u8 *after_ric, int n_after_ric,
@@@ -1387,14 -1406,14 +1407,14 @@@
while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
- pos += 2 + ies[pos + 1];
+ pos = skip_ie(ies, ielen, pos);
while (pos < ielen &&
!ieee80211_id_in_list(after_ric, n_after_ric,
ies[pos]))
- pos += 2 + ies[pos + 1];
+ pos = skip_ie(ies, ielen, pos);
} else {
- pos += 2 + ies[pos + 1];
+ pos = skip_ie(ies, ielen, pos);
}
}
@@@ -1555,31 -1574,57 +1575,57 @@@ bool ieee80211_chandef_to_operating_cla
}
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
- int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- u32 beacon_int)
+ static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
+ u32 *beacon_int_gcd,
+ bool *beacon_int_different)
{
struct wireless_dev *wdev;
- int res = 0;
- if (beacon_int < 10 || beacon_int > 10000)
- return -EINVAL;
+ *beacon_int_gcd = 0;
+ *beacon_int_different = false;
- list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
if (!wdev->beacon_interval)
continue;
- if (wdev->beacon_interval != beacon_int) {
- res = -EINVAL;
- break;
+
+ if (!*beacon_int_gcd) {
+ *beacon_int_gcd = wdev->beacon_interval;
+ continue;
}
+
+ if (wdev->beacon_interval == *beacon_int_gcd)
+ continue;
+
+ *beacon_int_different = true;
+ *beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval);
}
- return res;
+ if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
+ if (*beacon_int_gcd)
+ *beacon_int_different = true;
+ *beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
+ }
+ }
+
+ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
+ enum nl80211_iftype iftype, u32 beacon_int)
+ {
+ /*
+ * This is just a basic pre-condition check; if interface combinations
+ * are possible the driver must already be checking those with a call
+ * to cfg80211_check_combinations(), in which case we'll validate more
+ * through the cfg80211_calculate_bi_data() call and code in
+ * cfg80211_iter_combinations().
+ */
+
+ if (beacon_int < 10 || beacon_int > 10000)
+ return -EINVAL;
+
+ return 0;
}
int cfg80211_iter_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES],
+ struct iface_combination_params *params,
void (*iter)(const struct ieee80211_iface_combination *c,
void *data),
void *data)
@@@ -1589,8 -1634,23 +1635,23 @@@
int i, j, iftype;
int num_interfaces = 0;
u32 used_iftypes = 0;
+ u32 beacon_int_gcd;
+ bool beacon_int_different;
+
+ /*
+ * This is a bit strange, since the iteration used to rely only on
+ * the data given by the driver, but here it now relies on context,
+ * in form of the currently operating interfaces.
+ * This is OK for all current users, and saves us from having to
+ * push the GCD calculations into all the drivers.
+ * In the future, this should probably rely more on data that's in
+ * cfg80211 already - the only thing not would appear to be any new
+ * interfaces (while being brought up) and channel/radar data.
+ */
+ cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
+ &beacon_int_gcd, &beacon_int_different);
- if (radar_detect) {
+ if (params->radar_detect) {
rcu_read_lock();
regdom = rcu_dereference(cfg80211_regdomain);
if (regdom)
@@@ -1599,8 -1659,8 +1660,8 @@@
}
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
- num_interfaces += iftype_num[iftype];
- if (iftype_num[iftype] > 0 &&
+ num_interfaces += params->iftype_num[iftype];
+ if (params->iftype_num[iftype] > 0 &&
!(wiphy->software_iftypes & BIT(iftype)))
used_iftypes |= BIT(iftype);
}
@@@ -1614,7 -1674,7 +1675,7 @@@
if (num_interfaces > c->max_interfaces)
continue;
- if (num_different_channels > c->num_different_channels)
+ if (params->num_different_channels > c->num_different_channels)
continue;
limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
@@@ -1629,16 -1689,17 +1690,17 @@@
all_iftypes |= limits[j].types;
if (!(limits[j].types & BIT(iftype)))
continue;
- if (limits[j].max < iftype_num[iftype])
+ if (limits[j].max < params->iftype_num[iftype])
goto cont;
- limits[j].max -= iftype_num[iftype];
+ limits[j].max -= params->iftype_num[iftype];
}
}
- if (radar_detect != (c->radar_detect_widths & radar_detect))
+ if (params->radar_detect !=
+ (c->radar_detect_widths & params->radar_detect))
goto cont;
- if (radar_detect && c->radar_detect_regions &&
+ if (params->radar_detect && c->radar_detect_regions &&
!(c->radar_detect_regions & BIT(region)))
goto cont;
@@@ -1650,6 -1711,14 +1712,14 @@@
if ((all_iftypes & used_iftypes) != used_iftypes)
goto cont;
+ if (beacon_int_gcd) {
+ if (c->beacon_int_min_gcd &&
+ beacon_int_gcd < c->beacon_int_min_gcd)
+ goto cont;
+ if (!c->beacon_int_min_gcd && beacon_int_different)
+ goto cont;
+ }
+
/* This combination covered all interface types and
* supported the requested numbers, so we're good.
*/
@@@ -1672,14 -1741,11 +1742,11 @@@ cfg80211_iter_sum_ifcombs(const struct
}
int cfg80211_check_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES])
+ struct iface_combination_params *params)
{
int err, num = 0;
- err = cfg80211_iter_combinations(wiphy, num_different_channels,
- radar_detect, iftype_num,
+ err = cfg80211_iter_combinations(wiphy, params,
cfg80211_iter_sum_ifcombs, &num);
if (err)
return err;
--
LinuxNextTracking