The following commit has been merged in the master branch: commit f142c3284c9a86e590fd2890f9b62251dd9c9871 Merge: 2ede594ac51b39b92ae58f0f0ca40255c0491eb5 adc176c5472214971d77c1a61c83db9b01e9cdc7 Author: Stephen Rothwell sfr@canb.auug.org.au Date: Mon Dec 5 11:59:11 2016 +1100
Merge remote-tracking branch 'net-next/master'
diff --combined MAINTAINERS index b1cadd8,e773ad5..94b03b6 --- 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 @@@ -1026,7 -1026,6 +1026,7 @@@ L: linux-arm-kernel@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@elopez.com.ar @@@ -1487,9 -1486,8 +1487,9 @@@ L: linux-arm-kernel@lists.infradead.or L: linux-oxnas@lists.tuxfamily.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-oxnas/ -F: arch/arm/boot/dts/oxnas* +F: arch/arm/boot/dts/ox8*.dtsi F: arch/arm/boot/dts/wd-mbwe.dts +F: arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts N: oxnas
ARM/Mediatek RTC DRIVER @@@ -1610,7 -1608,6 +1610,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 @@@ -1790,7 -1787,9 +1790,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/ @@@ -2538,6 -2537,8 +2538,8 @@@ L: netdev@vger.kernel.or L: linux-kernel@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@broadcom.com @@@ -2750,14 -2751,6 +2752,14 @@@ L: bcm-kernel-feedback-list@broadcom.co S: Maintained F: drivers/mtd/nand/brcmnand/
+BROADCOM STB AVS CPUFREQ DRIVER +M: Markus Mayer mmayer@broadcom.com +M: bcm-kernel-feedback-list@broadcom.com +L: linux-pm@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@gmail.com L: linux-wireless@vger.kernel.org @@@ -2772,7 -2765,7 +2774,7 @@@ S: Supporte F: drivers/net/ethernet/broadcom/bcmsysport.*
BROADCOM VULCAN ARM64 SOC -M: Jayachandran C. jchandra@broadcom.com +M: Jayachandran C. c.jayachandran@gmail.com M: bcm-kernel-feedback-list@broadcom.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@@ -2946,7 -2939,7 +2948,7 @@@ CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVE M: Kevin Tsai ktsai@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@cavium.com @@@ -2980,15 -2973,15 +2982,15 @@@ L: linux-media@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@arndb.de @@@ -3094,7 -3087,7 +3096,7 @@@ M: Harry Wei <harryxiyou@gmail.com L: xiyoulinuxkernelgroup@googlegroups.com (subscribers-only) L: linux-kernel@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@nxp.com @@@ -3350,7 -3343,6 +3352,7 @@@ L: linux-pm@vger.kernel.or S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git T: git git://git.linaro.org/people/vireshk/linux.git (For ARM Updates) +B: https://bugzilla.kernel.org F: Documentation/cpu-freq/ F: drivers/cpufreq/ F: include/linux/cpufreq.h @@@ -3390,7 -3382,6 +3392,7 @@@ M: Daniel Lezcano <daniel.lezcano@linar L: linux-pm@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git +B: https://bugzilla.kernel.org F: drivers/cpuidle/* F: include/linux/cpuidle.h
@@@ -6300,11 -6291,9 +6302,11 @@@ S: Maintaine F: drivers/platform/x86/intel-vbtn.c
INTEL IDLE DRIVER +M: Jacob Pan jacob.jun.pan@linux.intel.com M: Len Brown lenb@kernel.org L: linux-pm@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git +B: https://bugzilla.kernel.org S: Supported F: drivers/idle/intel_idle.c
@@@ -7578,8 -7567,10 +7580,10 @@@ S: Maintaine MARVELL 88E6XXX ETHERNET SWITCH FABRIC DRIVER M: Andrew Lunn andrew@lunn.ch M: Vivien Didelot vivien.didelot@savoirfairelinux.com + L: netdev@vger.kernel.org S: Maintained F: drivers/net/dsa/mv88e6xxx/ + F: Documentation/devicetree/bindings/net/dsa/marvell.txt
MARVELL ARMADA DRM SUPPORT M: Russell King rmk+kernel@armlinux.org.uk @@@ -7747,15 -7738,6 +7751,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@bingham.xyz +L: linux-media@vger.kernel.org +L: linux-renesas-soc@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@ragnatech.se L: linux-media@vger.kernel.org @@@ -7862,24 -7844,6 +7866,24 @@@ L: netdev@vger.kernel.or S: Maintained F: drivers/net/ethernet/mediatek/
+MEDIATEK MEDIA DRIVER +M: Tiffany Lin tiffany.lin@mediatek.com +M: Andrew-CT Chen andrew-ct.chen@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@mediatek.com +M: Houlong Wei houlong.wei@mediatek.com +M: Andrew-CT Chen andrew-ct.chen@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@wp.pl L: linux-wireless@vger.kernel.org @@@ -7930,15 -7894,6 +7934,15 @@@ W: http://www.mellanox.co Q: http://patchwork.ozlabs.org/project/netdev/list/ F: drivers/net/ethernet/mellanox/mlxsw/
+MELLANOX MLXCPLD I2C AND MUX DRIVER +M: Vadim Pasternak vadimp@mellanox.com +M: Michael Shych michaelsh@mellanox.com +L: linux-i2c@vger.kernel.org +S: Supported +F: drivers/i2c/busses/i2c-mlxcpld.c +F: drivers/i2c/muxes/i2c-mux-mlxcpld.c +F: Documentation/i2c/busses/i2c-mlxcpld + MELLANOX MLXCPLD LED DRIVER M: Vadim Pasternak vadimp@mellanox.com L: linux-leds@vger.kernel.org @@@ -8506,7 -8461,6 +8510,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@davemloft.net @@@ -9017,11 -8971,9 +9020,11 @@@ F: drivers/of/resolver.
OPENRISC ARCHITECTURE M: Jonas Bonn jonas@southpole.se -W: http://openrisc.net +M: Stefan Kristiansson stefan.kristiansson@saunalahti.fi +M: Stafford Horne shorne@gmail.com +L: openrisc@lists.librecores.org +W: http://openrisc.io S: Maintained -T: git git://openrisc.net/~jonas/linux F: arch/openrisc/
OPENVSWITCH @@@ -9839,7 -9791,7 +9842,7 @@@ M: Hans Verkuil <hverkuil@xs4all.nl L: linux-media@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@pobox.com @@@ -10464,7 -10416,7 +10467,7 @@@ F: arch/s390/pci F: drivers/pci/hotplug/s390_pci_hpc.c
S390 ZCRYPT DRIVER -M: Ingo Tuchscherer ingo.tuchscherer@de.ibm.com +M: Harald Freudenberger freude@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported @@@ -10659,12 -10611,6 +10662,12 @@@ S: Maintaine F: Documentation/devicetree/bindings/serial/ F: drivers/tty/serial/
+SERIAL IR RECEIVER +M: Sean Young sean@mess.org +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/rc/serial_ir.c + STI CEC DRIVER M: Benjamin Gaignard benjamin.gaignard@linaro.org L: kernel@stlinux.com @@@ -11528,7 -11474,7 +11531,7 @@@ STABLE BRANC M: Greg Kroah-Hartman gregkh@linuxfoundation.org L: stable@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@linuxfoundation.org @@@ -11714,7 -11660,6 +11717,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
@@@ -11975,16 -11920,6 +11978,16 @@@ S: Maintaine F: arch/xtensa/ F: drivers/irqchip/irq-xtensa-*
+Texas Instruments' System Control Interface (TISCI) Protocol Driver +M: Nishanth Menon nm@ti.com +M: Tero Kristo t-kristo@ti.com +M: Santosh Shilimkar ssantosh@kernel.org +L: linux-arm-kernel@lists.infradead.org +S: Maintained +F: Documentation/devicetree/bindings/arm/keystone/ti,sci.txt +F: drivers/firmware/ti_sci* +F: include/linux/soc/ti/ti_sci_protocol.h + THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER M: Hans Verkuil hverkuil@xs4all.nl L: linux-media@vger.kernel.org @@@ -12415,12 -12350,6 +12418,12 @@@ S: Maintaine F: Documentation/filesystems/udf.txt F: fs/udf/
+UDRAW TABLET +M: Bastien Nocera hadess@hadess.net +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/hid/hid-udraw.c + UFS FILESYSTEM M: Evgeniy Dushistov dushistov@mail.ru S: Maintained @@@ -12987,7 -12916,7 +12990,7 @@@ M: Greg Kroah-Hartman <gregkh@linuxfoun L: devel@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* @@@ -13211,7 -13140,7 +13214,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@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/boot/dts/broadcom/ns2-svk.dts index 3461907,c4d5442..de8d379 --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts @@@ -56,6 -56,10 +56,10 @@@ }; };
+ &enet { + status = "ok"; + }; + &pci_phy0 { status = "ok"; }; @@@ -157,10 -161,6 +161,10 @@@ status = "ok"; };
+&sdio1 { + status = "ok"; +}; + &nand { nandcs@0 { compatible = "brcm,nandcs"; @@@ -178,6 -178,7 +182,7 @@@ &mdio_mux_iproc { mdio@10 { gphy0: eth-phy@10 { + enet-phy-lane-swap; reg = <0x10>; }; }; @@@ -191,37 -192,3 +196,37 @@@ groups = "nand_grp"; }; }; + +&qspi { + bspi-sel = <0>; + flash: m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p80"; + reg = <0x0>; + spi-max-frequency = <12500000>; + m25p,fast-read; + spi-cpol; + spi-cpha; + + partition@0 { + label = "boot"; + reg = <0x00000000 0x000a0000>; + }; + + partition@a0000 { + label = "env"; + reg = <0x000a0000 0x00060000>; + }; + + partition@100000 { + label = "system"; + reg = <0x00100000 0x00600000>; + }; + + partition@700000 { + label = "rootfs"; + reg = <0x00700000 0x01900000>; + }; + }; +}; diff --combined arch/arm64/boot/dts/broadcom/ns2.dtsi index 863503d,773ed59..07704b5 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@@ -133,9 -133,6 +133,9 @@@
status = "disabled";
+ phys = <&pci_phy0>; + phy-names = "pcie-phy"; + msi-parent = <&msi0>; msi0: msi@20020000 { compatible = "brcm,iproc-msi"; @@@ -174,9 -171,6 +174,9 @@@
status = "disabled";
+ phys = <&pci_phy1>; + phy-names = "pcie-phy"; + msi-parent = <&msi4>; msi4: msi@50020000 { compatible = "brcm,iproc-msi"; @@@ -197,42 -191,18 +197,54 @@@
#include "ns2-clock.dtsi"
+ pdc0: iproc-pdc0@612c0000 { + compatible = "brcm,iproc-pdc-mbox"; + reg = <0x612c0000 0x445>; /* PDC FS0 regs */ + interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <1>; + brcm,rx-status-len = <32>; + brcm,use-bcm-hdr; + }; + + pdc1: iproc-pdc1@612e0000 { + compatible = "brcm,iproc-pdc-mbox"; + reg = <0x612e0000 0x445>; /* PDC FS1 regs */ + interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <1>; + brcm,rx-status-len = <32>; + brcm,use-bcm-hdr; + }; + + pdc2: iproc-pdc2@61300000 { + compatible = "brcm,iproc-pdc-mbox"; + reg = <0x61300000 0x445>; /* PDC FS2 regs */ + interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <1>; + brcm,rx-status-len = <32>; + brcm,use-bcm-hdr; + }; + + pdc3: iproc-pdc3@61320000 { + compatible = "brcm,iproc-pdc-mbox"; + reg = <0x61320000 0x445>; /* PDC FS3 regs */ + interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <1>; + brcm,rx-status-len = <32>; + brcm,use-bcm-hdr; + }; + + enet: ethernet@61000000 { + compatible = "brcm,ns2-amac"; + reg = <0x61000000 0x1000>, + <0x61090000 0x1000>, + <0x61030000 0x100>; + reg-names = "amac_base", "idm_base", "nicpm_base"; + interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>; + phy-handle = <&gphy0>; + phy-mode = "rgmii"; + status = "disabled"; + }; + dma0: dma@61360000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x61360000 0x1000>; @@@ -290,7 -260,7 +302,7 @@@ <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>; - mmu-masters; + #iommu-cells = <1>; };
pinctrl: pinctrl@6501d130 { @@@ -607,23 -577,5 +619,23 @@@
brcm,nand-has-wp; }; + + qspi: spi@66470200 { + compatible = "brcm,spi-bcm-qspi", "brcm,spi-ns2-qspi"; + reg = <0x66470200 0x184>, + <0x66470000 0x124>, + <0x67017408 0x004>, + <0x664703a0 0x01c>; + reg-names = "mspi", "bspi", "intr_regs", + "intr_status_reg"; + interrupts = <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "spi_l1_intr"; + clocks = <&iprocmed>; + clock-names = "iprocmed"; + num-cs = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; }; diff --combined arch/arm64/boot/dts/marvell/armada-3720-db.dts index a260ae2,a59d36c..89de0a7 --- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts @@@ -56,7 -56,7 +56,7 @@@ stdout-path = "serial0:115200n8"; };
- memory { + memory@0 { device_type = "memory"; reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; @@@ -81,3 -81,26 +81,26 @@@ &pcie0 { status = "okay"; }; + + &mdio { + status = "okay"; + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; + + ð0 { + phy-mode = "rgmii-id"; + phy = <&phy0>; + status = "okay"; + }; + + ð1 { + phy-mode = "sgmii"; + phy = <&phy1>; + status = "okay"; + }; diff --combined arch/arm64/boot/dts/marvell/armada-37xx.dtsi index eba2e38,3b8eb45..bab5c6f --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi @@@ -91,7 -91,7 +91,7 @@@ #size-cells = <2>; ranges;
- internal-regs { + internal-regs@d0000000 { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; @@@ -140,6 -140,29 +140,29 @@@ }; };
+ eth0: ethernet@30000 { + compatible = "marvell,armada-3700-neta"; + reg = <0x30000 0x4000>; + interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&sb_periph_clk 8>; + status = "disabled"; + }; + + mdio: mdio@32004 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,orion-mdio"; + reg = <0x32004 0x4>; + }; + + eth1: ethernet@40000 { + compatible = "marvell,armada-3700-neta"; + reg = <0x40000 0x4000>; + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&sb_periph_clk 7>; + status = "disabled"; + }; + usb3: usb@58000 { compatible = "marvell,armada3700-xhci", "generic-xhci"; diff --combined arch/arm64/configs/defconfig index 0bba32a,6be0811..869dded --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@@ -11,6 -11,7 +11,6 @@@ CONFIG_TASK_XACCT= CONFIG_TASK_IO_ACCOUNTING=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y @@@ -33,7 -34,6 +33,7 @@@ CONFIG_MODULE_UNLOAD= # CONFIG_IOSCHED_DEADLINE is not set CONFIG_ARCH_SUNXI=y CONFIG_ARCH_ALPINE=y +CONFIG_ARCH_BCM2835=y CONFIG_ARCH_BCM_IPROC=y CONFIG_ARCH_BERLIN=y CONFIG_ARCH_EXYNOS=y @@@ -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 @@@ -148,7 -147,6 +148,7 @@@ CONFIG_MTD_SPI_NOR= CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=m CONFIG_VIRTIO_BLK=y +CONFIG_EEPROM_AT25=m CONFIG_SRAM=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y @@@ -185,10 -183,7 +185,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 @@@ -199,7 -194,6 +199,7 @@@ CONFIG_USB_NET_SMSC75XX= CONFIG_USB_NET_SMSC95XX=m CONFIG_USB_NET_PLUSB=m CONFIG_USB_NET_MCS7830=m +CONFIG_BRCMFMAC=m CONFIG_WL18XX=m CONFIG_WLCORE_SDIO=m CONFIG_INPUT_EVDEV=y @@@ -212,9 -206,6 +212,9 @@@ CONFIG_SERIO_AMBAKMI= CONFIG_LEGACY_PTY_COUNT=16 CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_BCM2835AUX=y CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_8250_MT6577=y CONFIG_SERIAL_8250_UNIPHIER=y @@@ -238,21 -229,17 +238,21 @@@ CONFIG_VIRTIO_CONSOLE= CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_BCM2835=m CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_IMX=y 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 CONFIG_I2C_CROS_EC_TUNNEL=y CONFIG_SPI=y CONFIG_SPI_MESON_SPIFC=m +CONFIG_SPI_BCM2835=m +CONFIG_SPI_BCM2835AUX=m CONFIG_SPI_ORION=y CONFIG_SPI_PL022=y CONFIG_SPI_QUP=y @@@ -262,14 -249,15 +262,15 @@@ 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 -CONFIG_GPIO_SYSFS=y CONFIG_GPIO_DWAPB=y 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 @@@ -284,16 -272,13 +285,16 @@@ 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_BCM2835_WDT=y CONFIG_RENESAS_WDT=y CONFIG_S3C2410_WATCHDOG=y 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 @@@ -307,26 -292,10 +308,26 @@@ 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_VC4=m CONFIG_DRM_PANEL_SIMPLE=m CONFIG_DRM_I2C_ADV7511=m CONFIG_DRM_HISI_KIRIN=m @@@ -341,7 -310,6 +342,7 @@@ CONFIG_LOGO= CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y +CONFIG_SND_BCM2835_SOC_I2S=m CONFIG_SND_SOC_RCAR=y CONFIG_SND_SOC_SAMSUNG=y CONFIG_SND_SOC_AK4613=y @@@ -374,11 -342,9 +375,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 @@@ -387,7 -353,6 +388,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 @@@ -403,13 -368,11 +404,13 @@@ 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 CONFIG_DMADEVICES=y CONFIG_PL330_DMA=y +CONFIG_DMA_BCM2835=m CONFIG_TEGRA20_APB_DMA=y CONFIG_QCOM_BAM_DMA=y CONFIG_QCOM_HIDMA_MGMT=y @@@ -425,39 -388,26 +426,39 @@@ 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_BCM2835_MBOX=y CONFIG_HI6220_MBOX=y CONFIG_ARM_SMMU=y +CONFIG_RASPBERRYPI_POWER=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_BCM2835=m +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 @@@ -465,7 -415,6 +466,7 @@@ CONFIG_ACPI= CONFIG_IIO=y CONFIG_EXYNOS_ADC=y CONFIG_PWM_SAMSUNG=y +CONFIG_RASPBERRYPI_FIRMWARE=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_EXT4_FS_POSIX_ACL=y diff --combined drivers/media/dvb-core/dvb_net.c index bd833b0,0da622f..dfc03a9 --- 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> @@@ -311,589 -309,451 +311,589 @@@ static inline void reset_ule( struct dv * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of * TS cells of a single PID. */ -static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) -{ - struct dvb_net_priv *priv = netdev_priv(dev); - unsigned long skipped = 0L; - const u8 *ts, *ts_end, *from_where = NULL; - u8 ts_remain = 0, how_much = 0, new_ts = 1; - struct ethhdr *ethh = NULL; - bool error = false;
+struct dvb_net_ule_handle { + struct net_device *dev; + struct dvb_net_priv *priv; + struct ethhdr *ethh; + const u8 *buf; + size_t buf_len; + unsigned long skipped; + const u8 *ts, *ts_end, *from_where; + u8 ts_remain, how_much, new_ts; + bool error; #ifdef ULE_DEBUG - /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ + /* + * The code inside ULE_DEBUG keeps a history of the + * last 100 TS cells processed. + */ static unsigned char ule_hist[100*TS_SZ]; static unsigned char *ule_where = ule_hist, ule_dump; #endif +};
- /* For all TS cells in current buffer. - * Appearently, we are called for every single TS cell. - */ - for (ts = buf, ts_end = buf + buf_len; ts < ts_end; /* no default incr. */ ) { - - if (new_ts) { - /* We are about to process a new TS cell. */ +static int dvb_net_ule_new_ts_cell(struct dvb_net_ule_handle *h) +{ + /* We are about to process a new TS cell. */
#ifdef ULE_DEBUG - if (ule_where >= &ule_hist[100*TS_SZ]) ule_where = ule_hist; - memcpy( ule_where, ts, TS_SZ ); - if (ule_dump) { - hexdump( ule_where, TS_SZ ); - ule_dump = 0; - } - ule_where += TS_SZ; + if (h->ule_where >= &h->ule_hist[100*TS_SZ]) + h->ule_where = h->ule_hist; + memcpy(h->ule_where, h->ts, TS_SZ); + if (h->ule_dump) { + hexdump(h->ule_where, TS_SZ); + h->ule_dump = 0; + } + h->ule_where += TS_SZ; #endif
- /* 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", - priv->ts_count, ts[0], - (ts[1] & TS_TEI) >> 7, - (ts[3] & TS_SC) >> 6); - - /* Drop partly decoded SNDU, reset state, resync on PUSI. */ - if (priv->ule_skb) { - dev_kfree_skb( priv->ule_skb ); - /* Prepare for next SNDU. */ - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; - } - reset_ule(priv); - priv->need_pusi = 1; + /* + * Check TS h->error conditions: sync_byte, transport_error_indicator, + * scrambling_control . + */ + if ((h->ts[0] != TS_SYNC) || (h->ts[1] & TS_TEI) || + ((h->ts[3] & TS_SC) != 0)) { + pr_warn("%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n", + h->priv->ts_count, h->ts[0], + (h->ts[1] & TS_TEI) >> 7, + (h->ts[3] & TS_SC) >> 6); + + /* Drop partly decoded SNDU, reset state, resync on PUSI. */ + if (h->priv->ule_skb) { + dev_kfree_skb(h->priv->ule_skb); + /* Prepare for next SNDU. */ + h->dev->stats.rx_errors++; + h->dev->stats.rx_frame_errors++; + } + reset_ule(h->priv); + h->priv->need_pusi = 1;
- /* Continue with next TS cell. */ - ts += TS_SZ; - priv->ts_count++; - continue; - } + /* Continue with next TS cell. */ + h->ts += TS_SZ; + h->priv->ts_count++; + return 1; + } + + h->ts_remain = 184; + h->from_where = h->ts + 4;
- ts_remain = 184; - from_where = ts + 4; + return 0; +} + +static int dvb_net_ule_ts_pusi(struct dvb_net_ule_handle *h) +{ + if (h->ts[1] & TS_PUSI) { + /* Find beginning of first ULE SNDU in current TS cell. */ + /* Synchronize continuity counter. */ + h->priv->tscc = h->ts[3] & 0x0F; + /* There is a pointer field here. */ + if (h->ts[4] > h->ts_remain) { + pr_err("%lu: Invalid ULE packet (pointer field %d)\n", + h->priv->ts_count, h->ts[4]); + h->ts += TS_SZ; + h->priv->ts_count++; + return 1; } - /* Synchronize on PUSI, if required. */ - if (priv->need_pusi) { - if (ts[1] & TS_PUSI) { - /* Find beginning of first ULE SNDU in current TS cell. */ - /* Synchronize continuity counter. */ - 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]); - ts += TS_SZ; - priv->ts_count++; - continue; - } - /* Skip to destination of pointer field. */ - from_where = &ts[5] + ts[4]; - ts_remain -= 1 + ts[4]; - skipped = 0; - } else { - skipped++; - ts += TS_SZ; - priv->ts_count++; - continue; - } + /* Skip to destination of pointer field. */ + h->from_where = &h->ts[5] + h->ts[4]; + h->ts_remain -= 1 + h->ts[4]; + h->skipped = 0; + } else { + h->skipped++; + h->ts += TS_SZ; + h->priv->ts_count++; + return 1; + } + + return 0; +} + +static int dvb_net_ule_new_ts(struct dvb_net_ule_handle *h) +{ + /* Check continuity counter. */ + if ((h->ts[3] & 0x0F) == h->priv->tscc) + h->priv->tscc = (h->priv->tscc + 1) & 0x0F; + else { + /* TS discontinuity handling: */ + pr_warn("%lu: TS discontinuity: got %#x, expected %#x.\n", + h->priv->ts_count, h->ts[3] & 0x0F, + h->priv->tscc); + /* Drop partly decoded SNDU, reset state, resync on PUSI. */ + if (h->priv->ule_skb) { + dev_kfree_skb(h->priv->ule_skb); + /* Prepare for next SNDU. */ + // reset_ule(h->priv); moved to below. + h->dev->stats.rx_errors++; + h->dev->stats.rx_frame_errors++; } + reset_ule(h->priv); + /* skip to next PUSI. */ + h->priv->need_pusi = 1; + return 1; + } + /* + * If we still have an incomplete payload, but PUSI is + * set; some TS cells are missing. + * This is only possible here, if we missed exactly 16 TS + * cells (continuity counter wrap). + */ + if (h->ts[1] & TS_PUSI) { + if (!h->priv->need_pusi) { + if (!(*h->from_where < (h->ts_remain-1)) || + *h->from_where != h->priv->ule_sndu_remain) { + /* + * Pointer field is invalid. + * Drop this TS cell and any started ULE SNDU. + */ + pr_warn("%lu: Invalid pointer field: %u.\n", + h->priv->ts_count, + *h->from_where);
- if (new_ts) { - /* Check continuity counter. */ - if ((ts[3] & 0x0F) == priv->tscc) - 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); - /* Drop partly decoded SNDU, reset state, resync on PUSI. */ - if (priv->ule_skb) { - dev_kfree_skb( priv->ule_skb ); - /* Prepare for next SNDU. */ - // reset_ule(priv); moved to below. - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; + /* + * Drop partly decoded SNDU, reset state, + * resync on PUSI. + */ + if (h->priv->ule_skb) { + h->error = true; + dev_kfree_skb(h->priv->ule_skb); } - reset_ule(priv); - /* skip to next PUSI. */ - priv->need_pusi = 1; - continue; - } - /* If we still have an incomplete payload, but PUSI is - * set; some TS cells are missing. - * This is only possible here, if we missed exactly 16 TS - * cells (continuity counter wrap). */ - if (ts[1] & TS_PUSI) { - 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); - - /* Drop partly decoded SNDU, reset state, resync on PUSI. */ - if (priv->ule_skb) { - error = true; - dev_kfree_skb(priv->ule_skb); - } - - if (error || priv->ule_sndu_remain) { - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; - error = false; - } - - reset_ule(priv); - priv->need_pusi = 1; - continue; - } - /* Skip pointer field (we're processing a - * packed payload). */ - from_where += 1; - ts_remain -= 1; - } else - priv->need_pusi = 0; - - if (priv->ule_sndu_remain > 183) { - /* Current SNDU lacks more data than there could be available in the - * 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); - dev_kfree_skb(priv->ule_skb); - /* Prepare for next SNDU. */ - reset_ule(priv); - /* Resync: go to where pointer field points to: start of next ULE SNDU. */ - from_where += ts[4]; - ts_remain -= ts[4]; + + if (h->error || h->priv->ule_sndu_remain) { + h->dev->stats.rx_errors++; + h->dev->stats.rx_frame_errors++; + h->error = false; } + + reset_ule(h->priv); + h->priv->need_pusi = 1; + return 1; } + /* + * Skip pointer field (we're processing a + * packed payload). + */ + h->from_where += 1; + h->ts_remain -= 1; + } else + h->priv->need_pusi = 0; + + if (h->priv->ule_sndu_remain > 183) { + /* + * Current SNDU lacks more data than there + * could be available in the current TS cell. + */ + h->dev->stats.rx_errors++; + h->dev->stats.rx_length_errors++; + pr_warn("%lu: Expected %d more SNDU bytes, but got PUSI (pf %d, h->ts_remain %d). Flushing incomplete payload.\n", + h->priv->ts_count, + h->priv->ule_sndu_remain, + h->ts[4], h->ts_remain); + dev_kfree_skb(h->priv->ule_skb); + /* Prepare for next SNDU. */ + reset_ule(h->priv); + /* + * Resync: go to where pointer field points to: + * start of next ULE SNDU. + */ + h->from_where += h->ts[4]; + h->ts_remain -= h->ts[4]; } + } + return 0; +}
- /* Check if new payload needs to be started. */ - if (priv->ule_skb == NULL) { - /* Start a new payload with skb. - * Find ULE header. It is only guaranteed that the - * length field (2 bytes) is contained in the current - * 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); - priv->ule_sndu_len = 0; - priv->need_pusi = 1; - ts += TS_SZ; - continue; - }
- if (! priv->ule_sndu_len) { - /* Got at least two bytes, thus extrace the SNDU length. */ - priv->ule_sndu_len = from_where[0] << 8 | from_where[1]; - if (priv->ule_sndu_len & 0x8000) { - /* D-Bit is set: no dest mac present. */ - priv->ule_sndu_len &= 0x7FFF; - priv->ule_dbit = 1; - } else - 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); - dev->stats.rx_errors++; - dev->stats.rx_length_errors++; - priv->ule_sndu_len = 0; - priv->need_pusi = 1; - new_ts = 1; - ts += TS_SZ; - priv->ts_count++; - continue; - } - ts_remain -= 2; /* consume the 2 bytes SNDU length. */ - from_where += 2; - } +/* + * Start a new payload with skb. + * Find ULE header. It is only guaranteed that the + * length field (2 bytes) is contained in the current + * TS. + * Check h.ts_remain has to be >= 2 here. + */ +static int dvb_net_ule_new_payload(struct dvb_net_ule_handle *h) +{ + if (h->ts_remain < 2) { + pr_warn("Invalid payload packing: only %d bytes left in TS. Resyncing.\n", + h->ts_remain); + h->priv->ule_sndu_len = 0; + h->priv->need_pusi = 1; + h->ts += TS_SZ; + return 1; + } + + if (!h->priv->ule_sndu_len) { + /* Got at least two bytes, thus extrace the SNDU length. */ + h->priv->ule_sndu_len = h->from_where[0] << 8 | + h->from_where[1]; + if (h->priv->ule_sndu_len & 0x8000) { + /* D-Bit is set: no dest mac present. */ + h->priv->ule_sndu_len &= 0x7FFF; + h->priv->ule_dbit = 1; + } else + h->priv->ule_dbit = 0; + + if (h->priv->ule_sndu_len < 5) { + pr_warn("%lu: Invalid ULE SNDU length %u. Resyncing.\n", + h->priv->ts_count, + h->priv->ule_sndu_len); + h->dev->stats.rx_errors++; + h->dev->stats.rx_length_errors++; + h->priv->ule_sndu_len = 0; + h->priv->need_pusi = 1; + h->new_ts = 1; + h->ts += TS_SZ; + h->priv->ts_count++; + return 1; + } + h->ts_remain -= 2; /* consume the 2 bytes SNDU length. */ + h->from_where += 2; + } + + h->priv->ule_sndu_remain = h->priv->ule_sndu_len + 2; + /* + * State of current TS: + * h->ts_remain (remaining bytes in the current TS cell) + * 0 ule_type is not available now, we need the next TS cell + * 1 the first byte of the ule_type is present + * >=2 full ULE header present, maybe some payload data as well. + */ + switch (h->ts_remain) { + case 1: + h->priv->ule_sndu_remain--; + h->priv->ule_sndu_type = h->from_where[0] << 8; + + /* first byte of ule_type is set. */ + h->priv->ule_sndu_type_1 = 1; + h->ts_remain -= 1; + h->from_where += 1; + /* fallthrough */ + case 0: + h->new_ts = 1; + h->ts += TS_SZ; + h->priv->ts_count++; + return 1; + + default: /* complete ULE header is present in current TS. */ + /* Extract ULE type field. */ + if (h->priv->ule_sndu_type_1) { + h->priv->ule_sndu_type_1 = 0; + h->priv->ule_sndu_type |= h->from_where[0]; + h->from_where += 1; /* points to payload start. */ + h->ts_remain -= 1; + } else { + /* Complete type is present in new TS. */ + h->priv->ule_sndu_type = h->from_where[0] << 8 | + h->from_where[1]; + h->from_where += 2; /* points to payload start. */ + h->ts_remain -= 2; + } + break; + } + + /* + * Allocate the skb (decoder target buffer) with the correct size, + * as follows: + * + * prepare for the largest case: bridged SNDU with MAC address + * (dbit = 0). + */ + h->priv->ule_skb = dev_alloc_skb(h->priv->ule_sndu_len + + ETH_HLEN + ETH_ALEN); + if (!h->priv->ule_skb) { + pr_notice("%s: Memory squeeze, dropping packet.\n", + h->dev->name); + h->dev->stats.rx_dropped++; + return -1; + } + + /* This includes the CRC32 _and_ dest mac, if !dbit. */ + h->priv->ule_sndu_remain = h->priv->ule_sndu_len; + h->priv->ule_skb->dev = h->dev; + /* + * Leave space for Ethernet or bridged SNDU header + * (eth hdr plus one MAC addr). + */ + skb_reserve(h->priv->ule_skb, ETH_HLEN + ETH_ALEN); + + return 0; +} +
- priv->ule_sndu_remain = priv->ule_sndu_len + 2; +static int dvb_net_ule_should_drop(struct dvb_net_ule_handle *h) +{ + static const u8 bc_addr[ETH_ALEN] = { [0 ... ETH_ALEN - 1] = 0xff }; + + /* + * The destination MAC address is the next data in the skb. It comes + * before any extension headers. + * + * Check if the payload of this SNDU should be passed up the stack. + */ + if (h->priv->rx_mode == RX_MODE_PROMISC) + return 0; + + if (h->priv->ule_skb->data[0] & 0x01) { + /* multicast or broadcast */ + if (!ether_addr_equal(h->priv->ule_skb->data, bc_addr)) { + /* multicast */ + if (h->priv->rx_mode == RX_MODE_MULTI) { + int i; + + for (i = 0; i < h->priv->multi_num && + !ether_addr_equal(h->priv->ule_skb->data, + h->priv->multi_macs[i]); + i++) + ; + if (i == h->priv->multi_num) + return 1; + } else if (h->priv->rx_mode != RX_MODE_ALL_MULTI) + return 1; /* no broadcast; */ /* - * State of current TS: - * ts_remain (remaining bytes in the current TS cell) - * 0 ule_type is not available now, we need the next TS cell - * 1 the first byte of the ule_type is present - * >=2 full ULE header present, maybe some payload data as well. + * else: + * all multicast mode: accept all multicast packets */ - switch (ts_remain) { - case 1: - priv->ule_sndu_remain--; - priv->ule_sndu_type = from_where[0] << 8; - priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ - ts_remain -= 1; from_where += 1; - /* Continue w/ next TS. */ - case 0: - new_ts = 1; - ts += TS_SZ; - priv->ts_count++; - continue; - - default: /* complete ULE header is present in current TS. */ - /* Extract ULE type field. */ - if (priv->ule_sndu_type_1) { - priv->ule_sndu_type_1 = 0; - priv->ule_sndu_type |= from_where[0]; - from_where += 1; /* points to payload start. */ - ts_remain -= 1; - } else { - /* Complete type is present in new TS. */ - priv->ule_sndu_type = from_where[0] << 8 | from_where[1]; - from_where += 2; /* points to payload start. */ - ts_remain -= 2; - } - break; - } + } + /* else: broadcast */ + } else if (!ether_addr_equal(h->priv->ule_skb->data, h->dev->dev_addr)) + return 1;
- /* Allocate the skb (decoder target buffer) with the correct size, as follows: - * 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); - dev->stats.rx_dropped++; - return; - } + return 0; +} + + +static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h, + u32 ule_crc, u32 expected_crc) +{ + u8 dest_addr[ETH_ALEN]; + + if (ule_crc != expected_crc) { + pr_warn("%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n", + h->priv->ts_count, ule_crc, expected_crc, + h->priv->ule_sndu_len, h->priv->ule_sndu_type, + h->ts_remain, + h->ts_remain > 2 ? + *(unsigned short *)h->from_where : 0); + + #ifdef ULE_DEBUG + hexdump(iov[0].iov_base, iov[0].iov_len); + hexdump(iov[1].iov_base, iov[1].iov_len); + hexdump(iov[2].iov_base, iov[2].iov_len); + + if (h->ule_where == h->ule_hist) { + hexdump(&h->ule_hist[98*TS_SZ], TS_SZ); + hexdump(&h->ule_hist[99*TS_SZ], TS_SZ); + } else if (h->ule_where == &h->ule_hist[TS_SZ]) { + hexdump(&h->ule_hist[99*TS_SZ], TS_SZ); + hexdump(h->ule_hist, TS_SZ); + } else { + hexdump(h->ule_where - TS_SZ - TS_SZ, TS_SZ); + hexdump(h->ule_where - TS_SZ, TS_SZ); + } + h->ule_dump = 1; + #endif + + h->dev->stats.rx_errors++; + h->dev->stats.rx_crc_errors++; + dev_kfree_skb(h->priv->ule_skb); + + return; + } + + /* CRC32 verified OK. */ + + /* CRC32 was OK, so remove it from skb. */ + h->priv->ule_skb->tail -= 4; + h->priv->ule_skb->len -= 4; + + if (!h->priv->ule_dbit) { + if (dvb_net_ule_should_drop(h)) { +#ifdef ULE_DEBUG + netdev_dbg(h->dev, + "Dropping SNDU: MAC destination address does not match: dest addr: %pM, h->dev addr: %pM\n", + h->priv->ule_skb->data, h->dev->dev_addr); +#endif + dev_kfree_skb(h->priv->ule_skb); + return; + } + + skb_copy_from_linear_data(h->priv->ule_skb, dest_addr, + ETH_ALEN); + skb_pull(h->priv->ule_skb, ETH_ALEN); + } + + /* Handle ULE Extension Headers. */ + if (h->priv->ule_sndu_type < ETH_P_802_3_MIN) { + /* There is an extension header. Handle it accordingly. */ + int l = handle_ule_extensions(h->priv); + + if (l < 0) { + /* + * Mandatory extension header unknown or TEST SNDU. + * Drop it. + */ + + // pr_warn("Dropping SNDU, extension headers.\n" ); + dev_kfree_skb(h->priv->ule_skb); + return; + } + skb_pull(h->priv->ule_skb, l); + } + + /* + * Construct/assure correct ethernet header. + * Note: in bridged mode (h->priv->ule_bridged != 0) + * we already have the (original) ethernet + * header at the start of the payload (after + * optional dest. address and any extension + * headers). + */ + if (!h->priv->ule_bridged) { + skb_push(h->priv->ule_skb, ETH_HLEN); + h->ethh = (struct ethhdr *)h->priv->ule_skb->data; + if (!h->priv->ule_dbit) { + /* + * dest_addr buffer is only valid if + * h->priv->ule_dbit == 0 + */ + memcpy(h->ethh->h_dest, dest_addr, ETH_ALEN); + eth_zero_addr(h->ethh->h_source); + } else /* zeroize source and dest */ + memset(h->ethh, 0, ETH_ALEN * 2);
- /* This includes the CRC32 _and_ dest mac, if !dbit. */ - priv->ule_sndu_remain = priv->ule_sndu_len; - priv->ule_skb->dev = dev; - /* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */ - skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN ); + h->ethh->h_proto = htons(h->priv->ule_sndu_type); + } + /* else: skb is in correct state; nothing to do. */ + h->priv->ule_bridged = 0; + + /* Stuff into kernel's protocol stack. */ + h->priv->ule_skb->protocol = dvb_net_eth_type_trans(h->priv->ule_skb, + h->dev); + /* + * If D-bit is set (i.e. destination MAC address not present), + * receive the packet anyhow. + */ +#if 0 + if (h->priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) + h->priv->ule_skb->pkt_type = PACKET_HOST; +#endif + h->dev->stats.rx_packets++; + h->dev->stats.rx_bytes += h->priv->ule_skb->len; + netif_rx(h->priv->ule_skb); +} + +static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len) +{ + int ret; + struct dvb_net_ule_handle h = { + .dev = dev, + .buf = buf, + .buf_len = buf_len, + .skipped = 0L, + .ts = NULL, + .ts_end = NULL, + .from_where = NULL, + .ts_remain = 0, + .how_much = 0, + .new_ts = 1, + .ethh = NULL, + .error = false, +#ifdef ULE_DEBUG + .ule_where = ule_hist, +#endif + }; + + /* + * For all TS cells in current buffer. + * Appearently, we are called for every single TS cell. + */ + for (h.ts = h.buf, h.ts_end = h.buf + h.buf_len; + h.ts < h.ts_end; /* no incr. */) { + if (h.new_ts) { + /* We are about to process a new TS cell. */ + if (dvb_net_ule_new_ts_cell(&h)) + continue; + } + + /* Synchronize on PUSI, if required. */ + if (h.priv->need_pusi) { + if (dvb_net_ule_ts_pusi(&h)) + continue; + } + + if (h.new_ts) { + if (dvb_net_ule_new_ts(&h)) + continue; + } + + /* Check if new payload needs to be started. */ + if (h.priv->ule_skb == NULL) { + ret = dvb_net_ule_new_payload(&h); + if (ret < 0) + return; + if (ret) + continue; }
/* Copy data into our current skb. */ - how_much = min(priv->ule_sndu_remain, (int)ts_remain); - memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much); - priv->ule_sndu_remain -= how_much; - ts_remain -= how_much; - from_where += how_much; + h.how_much = min(h.priv->ule_sndu_remain, (int)h.ts_remain); + memcpy(skb_put(h.priv->ule_skb, h.how_much), + h.from_where, h.how_much); + h.priv->ule_sndu_remain -= h.how_much; + h.ts_remain -= h.how_much; + h.from_where += h.how_much;
/* Check for complete payload. */ - if (priv->ule_sndu_remain <= 0) { + if (h.priv->ule_sndu_remain <= 0) { /* Check CRC32, we've got it in our skb already. */ - __be16 ulen = htons(priv->ule_sndu_len); - __be16 utype = htons(priv->ule_sndu_type); + __be16 ulen = htons(h.priv->ule_sndu_len); + __be16 utype = htons(h.priv->ule_sndu_type); const u8 *tail; struct kvec iov[3] = { { &ulen, sizeof ulen }, { &utype, sizeof utype }, - { priv->ule_skb->data, priv->ule_skb->len - 4 } + { h.priv->ule_skb->data, + h.priv->ule_skb->len - 4 } }; u32 ule_crc = ~0L, expected_crc; - if (priv->ule_dbit) { + if (h.priv->ule_dbit) { /* Set D-bit for CRC32 verification, * if it was set originally. */ ulen |= htons(0x8000); }
ule_crc = iov_crc32(ule_crc, iov, 3); - tail = skb_tail_pointer(priv->ule_skb); + tail = skb_tail_pointer(h.priv->ule_skb); expected_crc = *(tail - 4) << 24 | *(tail - 3) << 16 | *(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);
-#ifdef ULE_DEBUG - hexdump( iov[0].iov_base, iov[0].iov_len ); - hexdump( iov[1].iov_base, iov[1].iov_len ); - hexdump( iov[2].iov_base, iov[2].iov_len ); - - if (ule_where == ule_hist) { - hexdump( &ule_hist[98*TS_SZ], TS_SZ ); - hexdump( &ule_hist[99*TS_SZ], TS_SZ ); - } else if (ule_where == &ule_hist[TS_SZ]) { - hexdump( &ule_hist[99*TS_SZ], TS_SZ ); - hexdump( ule_hist, TS_SZ ); - } else { - hexdump( ule_where - TS_SZ - TS_SZ, TS_SZ ); - hexdump( ule_where - TS_SZ, TS_SZ ); - } - ule_dump = 1; -#endif + dvb_net_ule_check_crc(&h, ule_crc, expected_crc);
- dev->stats.rx_errors++; - dev->stats.rx_crc_errors++; - dev_kfree_skb(priv->ule_skb); - } else { - /* CRC32 verified OK. */ - u8 dest_addr[ETH_ALEN]; - static const u8 bc_addr[ETH_ALEN] = - { [ 0 ... ETH_ALEN-1] = 0xff }; - - /* CRC32 was OK. Remove it from skb. */ - priv->ule_skb->tail -= 4; - priv->ule_skb->len -= 4; - - if (!priv->ule_dbit) { - /* - * The destination MAC address is the - * next data in the skb. It comes - * before any extension headers. - * - * Check if the payload of this SNDU - * should be passed up the stack. - */ - register int drop = 0; - if (priv->rx_mode != RX_MODE_PROMISC) { - if (priv->ule_skb->data[0] & 0x01) { - /* multicast or broadcast */ - if (!ether_addr_equal(priv->ule_skb->data, bc_addr)) { - /* multicast */ - if (priv->rx_mode == RX_MODE_MULTI) { - int i; - for(i = 0; i < priv->multi_num && - !ether_addr_equal(priv->ule_skb->data, - priv->multi_macs[i]); i++) - ; - if (i == priv->multi_num) - drop = 1; - } else if (priv->rx_mode != RX_MODE_ALL_MULTI) - drop = 1; /* no broadcast; */ - /* else: all multicast mode: accept all multicast packets */ - } - /* else: broadcast */ - } - else if (!ether_addr_equal(priv->ule_skb->data, dev->dev_addr)) - drop = 1; - /* else: destination address matches the MAC address of our receiver device */ - } - /* else: promiscuous mode; pass everything up the stack */ - - if (drop) { -#ifdef ULE_DEBUG - netdev_dbg(dev, "Dropping SNDU: MAC destination address does not match: dest addr: %pM, dev addr: %pM\n", - priv->ule_skb->data, dev->dev_addr); -#endif - dev_kfree_skb(priv->ule_skb); - goto sndu_done; - } - else - { - skb_copy_from_linear_data(priv->ule_skb, - dest_addr, - ETH_ALEN); - skb_pull(priv->ule_skb, ETH_ALEN); - } - } - - /* Handle ULE Extension Headers. */ - if (priv->ule_sndu_type < ETH_P_802_3_MIN) { - /* There is an extension header. Handle it accordingly. */ - 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" ); - dev_kfree_skb(priv->ule_skb); - goto sndu_done; - } - skb_pull(priv->ule_skb, l); - } - - /* - * Construct/assure correct ethernet header. - * Note: in bridged mode (priv->ule_bridged != - * 0) we already have the (original) ethernet - * header at the start of the payload (after - * optional dest. address and any extension - * headers). - */ - - if (!priv->ule_bridged) { - skb_push(priv->ule_skb, ETH_HLEN); - ethh = (struct ethhdr *)priv->ule_skb->data; - if (!priv->ule_dbit) { - /* dest_addr buffer is only valid if priv->ule_dbit == 0 */ - memcpy(ethh->h_dest, dest_addr, ETH_ALEN); - eth_zero_addr(ethh->h_source); - } - else /* zeroize source and dest */ - memset( ethh, 0, ETH_ALEN*2 ); - - ethh->h_proto = htons(priv->ule_sndu_type); - } - /* else: skb is in correct state; nothing to do. */ - priv->ule_bridged = 0; - - /* Stuff into kernel's protocol stack. */ - priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev); - /* If D-bit is set (i.e. destination MAC address not present), - * receive the packet anyhow. */ - /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) - priv->ule_skb->pkt_type = PACKET_HOST; */ - dev->stats.rx_packets++; - dev->stats.rx_bytes += priv->ule_skb->len; - netif_rx(priv->ule_skb); - } - sndu_done: /* Prepare for next SNDU. */ - reset_ule(priv); + reset_ule(h.priv); }
/* More data in current TS (look at the bytes following the CRC32)? */ - if (ts_remain >= 2 && *((unsigned short *)from_where) != 0xFFFF) { + if (h.ts_remain >= 2 && *((unsigned short *)h.from_where) != 0xFFFF) { /* Next ULE SNDU starts right there. */ - new_ts = 0; - 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", - // *(from_where + 0), *(from_where + 1), - // *(from_where + 2), *(from_where + 3)); - // printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0); - // hexdump(ts, 188); + h.new_ts = 0; + h.priv->ule_skb = NULL; + h.priv->ule_sndu_type_1 = 0; + h.priv->ule_sndu_len = 0; + // pr_warn("More data in current TS: [%#x %#x %#x %#x]\n", + // *(h.from_where + 0), *(h.from_where + 1), + // *(h.from_where + 2), *(h.from_where + 3)); + // pr_warn("h.ts @ %p, stopped @ %p:\n", h.ts, h.from_where + 0); + // hexdump(h.ts, 188); } else { - new_ts = 1; - ts += TS_SZ; - priv->ts_count++; - if (priv->ule_skb == NULL) { - priv->need_pusi = 1; - priv->ule_sndu_type_1 = 0; - priv->ule_sndu_len = 0; + h.new_ts = 1; + h.ts += TS_SZ; + h.priv->ts_count++; + if (h.priv->ule_skb == NULL) { + h.priv->need_pusi = 1; + h.priv->ule_sndu_type_1 = 0; + h.priv->ule_sndu_len = 0; } } } /* for all available TS cells */ @@@ -906,10 -766,10 +906,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; @@@ -926,7 -786,7 +926,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++; @@@ -964,7 -824,7 +964,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; } @@@ -1043,7 -903,7 +1043,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; }
@@@ -1084,7 -944,7 +1084,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; @@@ -1095,15 -955,14 +1095,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; @@@ -1144,7 -1003,7 +1144,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; }
@@@ -1154,11 -1013,12 +1154,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; @@@ -1207,7 -1067,7 +1207,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) { @@@ -1218,7 -1078,7 +1218,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); @@@ -1338,7 -1198,6 +1338,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, };
@@@ -1349,6 -1208,7 +1348,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; } @@@ -1419,7 -1279,7 +1419,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; } @@@ -1438,7 -1298,7 +1438,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/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/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@intel.com * Copyright (C) 2008 Sujith Thomas sujith.thomas@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/nfs/inode.c index 75f5a9c,ce42dd0..51ed027 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@@ -634,28 -634,15 +634,28 @@@ void nfs_setattr_update_inode(struct in } EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
-static void nfs_request_parent_use_readdirplus(struct dentry *dentry) +static void nfs_readdirplus_parent_cache_miss(struct dentry *dentry) { struct dentry *parent;
+ if (!nfs_server_capable(d_inode(dentry), NFS_CAP_READDIRPLUS)) + return; parent = dget_parent(dentry); nfs_force_use_readdirplus(d_inode(parent)); dput(parent); }
+static void nfs_readdirplus_parent_cache_hit(struct dentry *dentry) +{ + struct dentry *parent; + + if (!nfs_server_capable(d_inode(dentry), NFS_CAP_READDIRPLUS)) + return; + parent = dget_parent(dentry); + nfs_advise_use_readdirplus(d_inode(parent)); + dput(parent); +} + static bool nfs_need_revalidate_inode(struct inode *inode) { if (NFS_I(inode)->cache_validity & @@@ -696,10 -683,10 +696,10 @@@ int nfs_getattr(struct vfsmount *mnt, s if (need_atime || nfs_need_revalidate_inode(inode)) { struct nfs_server *server = NFS_SERVER(inode);
- if (server->caps & NFS_CAP_READDIRPLUS) - nfs_request_parent_use_readdirplus(dentry); + nfs_readdirplus_parent_cache_miss(dentry); err = __nfs_revalidate_inode(server, inode); - } + } else + nfs_readdirplus_parent_cache_hit(dentry); if (!err) { generic_fillattr(inode, stat); stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode)); @@@ -715,7 -702,8 +715,7 @@@ EXPORT_SYMBOL_GPL(nfs_getattr) static void nfs_init_lock_context(struct nfs_lock_context *l_ctx) { atomic_set(&l_ctx->count, 1); - l_ctx->lockowner.l_owner = current->files; - l_ctx->lockowner.l_pid = current->tgid; + l_ctx->lockowner = current->files; INIT_LIST_HEAD(&l_ctx->list); atomic_set(&l_ctx->io_count, 0); } @@@ -726,7 -714,9 +726,7 @@@ static struct nfs_lock_context *__nfs_f struct nfs_lock_context *pos = head;
do { - if (pos->lockowner.l_owner != current->files) - continue; - if (pos->lockowner.l_pid != current->tgid) + if (pos->lockowner != current->files) continue; atomic_inc(&pos->count); return pos; @@@ -809,9 -799,7 +809,9 @@@ void nfs_close_context(struct nfs_open_ } EXPORT_SYMBOL_GPL(nfs_close_context);
-struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode) +struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, + fmode_t f_mode, + struct file *filp) { struct nfs_open_context *ctx; struct rpc_cred *cred = rpc_lookup_cred(); @@@ -830,7 -818,6 +830,7 @@@ ctx->mode = f_mode; ctx->flags = 0; ctx->error = 0; + ctx->flock_owner = (fl_owner_t)filp; nfs_init_lock_context(&ctx->lock_context); ctx->lock_context.open_context = ctx; INIT_LIST_HEAD(&ctx->list); @@@ -955,7 -942,7 +955,7 @@@ int nfs_open(struct inode *inode, struc { struct nfs_open_context *ctx;
- ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode); + ctx = alloc_nfs_open_context(file_dentry(filp), filp->f_mode, filp); if (IS_ERR(ctx)) return PTR_ERR(ctx); nfs_file_set_open_context(filp, ctx); @@@ -1330,7 -1317,7 +1330,7 @@@ static int nfs_check_inode_attributes(s invalid |= NFS_INO_INVALID_ATIME;
if (invalid != 0) - nfs_set_cache_invalid(inode, invalid); + nfs_set_cache_invalid(inode, invalid | NFS_INO_REVAL_FORCED);
nfsi->read_cache_jiffies = fattr->time_start; return 0; @@@ -2028,7 -2015,7 +2028,7 @@@ static void nfsiod_stop(void destroy_workqueue(wq); }
- int nfs_net_id; + unsigned int nfs_net_id; EXPORT_SYMBOL_GPL(nfs_net_id);
static int nfs_net_init(struct net *net) 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/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 init/Kconfig index 172f80e,405120b..b4f1fdc --- a/init/Kconfig +++ b/init/Kconfig @@@ -1154,6 -1154,18 +1154,18 @@@ config CGROUP_PER
Say N if unsure.
+ config CGROUP_BPF + bool "Support for eBPF programs attached to cgroups" + depends on BPF_SYSCALL && SOCK_CGROUP_DATA + help + Allow attaching eBPF programs to a cgroup using the bpf(2) + syscall command BPF_PROG_ATTACH. + + In which context these programs are accessed depends on the type + of attachment. For instance, programs that are attached using + BPF_CGROUP_INET_INGRESS will be executed on the ingress path of + inet sockets. + config CGROUP_DEBUG bool "Example controller" default n @@@ -1306,7 -1318,7 +1318,7 @@@ config BLK_DEV_INITR boot loader (loadlin or lilo) and that is mounted as root before the normal boot procedure. It is typically used to load modules needed to mount the "real" root file system, - etc. See file:Documentation/initrd.txt for details. + etc. See file:Documentation/admin-guide/initrd.rst for details.
If RAM disk support (BLK_DEV_RAM) is also included, this also enables initial RAM disk (initrd) support and adds diff --combined net/batman-adv/translation-table.c index 0dc85eb,447f949..30ecbfb --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@@ -56,7 -56,6 +56,6 @@@ #include "hard-interface.h" #include "hash.h" #include "log.h" - #include "multicast.h" #include "netlink.h" #include "originator.h" #include "packet.h" @@@ -647,6 -646,7 +646,7 @@@ bool batadv_tt_local_add(struct net_dev struct net *net = dev_net(soft_iface); struct batadv_softif_vlan *vlan; struct net_device *in_dev = NULL; + struct batadv_hard_iface *in_hardif = NULL; struct hlist_head *head; struct batadv_tt_orig_list_entry *orig_entry; int hash_added, table_size, packet_size_max; @@@ -658,6 -658,9 +658,9 @@@ if (ifindex != BATADV_NULL_IFINDEX) in_dev = dev_get_by_index(net, ifindex);
+ if (in_dev) + in_hardif = batadv_hardif_get_by_netdev(in_dev); + tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
if (!is_multicast_ether_addr(addr)) @@@ -731,7 -734,7 +734,7 @@@ */ tt_local->common.flags = BATADV_TT_CLIENT_NEW; tt_local->common.vid = vid; - if (batadv_is_wifi_netdev(in_dev)) + if (batadv_is_wifi_hardif(in_hardif)) tt_local->common.flags |= BATADV_TT_CLIENT_WIFI; kref_init(&tt_local->common.refcount); tt_local->last_seen = jiffies; @@@ -791,7 -794,7 +794,7 @@@ check_roaming */ remote_flags = tt_local->common.flags & BATADV_TT_REMOTE_MASK;
- if (batadv_is_wifi_netdev(in_dev)) + if (batadv_is_wifi_hardif(in_hardif)) tt_local->common.flags |= BATADV_TT_CLIENT_WIFI; else tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI; @@@ -815,6 -818,8 +818,8 @@@
ret = true; out: + if (in_hardif) + batadv_hardif_put(in_hardif); if (in_dev) dev_put(in_dev); if (tt_local) @@@ -3282,7 -3287,7 +3287,7 @@@ static bool batadv_send_my_tt_response( &tvlv_tt_data, &tt_change, &tt_len); - if (!tt_len) + if (!tt_len || !tvlv_len) goto unlock;
/* Copy the last orig_node's OGM buffer */ @@@ -3300,7 -3305,7 +3305,7 @@@ &tvlv_tt_data, &tt_change, &tt_len); - if (!tt_len) + if (!tt_len || !tvlv_len) goto out;
/* fill the rest of the tvlv with the real TT entries */ @@@ -3795,9 -3800,6 +3800,6 @@@ static void batadv_tt_local_commit_chan { lockdep_assert_held(&bat_priv->tt.commit_lock);
- /* Update multicast addresses in local translation table */ - batadv_mcast_mla_update(bat_priv); - if (atomic_read(&bat_priv->tt.local_changes) < 1) { if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt)) batadv_tt_tvlv_container_update(bat_priv); @@@ -3835,8 -3837,8 +3837,8 @@@ void batadv_tt_local_commit_changes(str bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst, unsigned short vid) { - struct batadv_tt_local_entry *tt_local_entry = NULL; - struct batadv_tt_global_entry *tt_global_entry = NULL; + struct batadv_tt_local_entry *tt_local_entry; + struct batadv_tt_global_entry *tt_global_entry; struct batadv_softif_vlan *vlan; bool ret = false;
@@@ -3845,27 -3847,24 +3847,24 @@@ return false;
if (!atomic_read(&vlan->ap_isolation)) - goto out; + goto vlan_put;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid); if (!tt_local_entry) - goto out; + goto vlan_put;
tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid); if (!tt_global_entry) - goto out; + goto local_entry_put;
- if (!_batadv_is_ap_isolated(tt_local_entry, tt_global_entry)) - goto out; - - ret = true; + if (_batadv_is_ap_isolated(tt_local_entry, tt_global_entry)) + ret = true;
- out: + batadv_tt_global_entry_put(tt_global_entry); + local_entry_put: + batadv_tt_local_entry_put(tt_local_entry); + vlan_put: batadv_softif_vlan_put(vlan); - if (tt_global_entry) - batadv_tt_global_entry_put(tt_global_entry); - if (tt_local_entry) - batadv_tt_local_entry_put(tt_local_entry); return ret; }
diff --combined net/unix/af_unix.c index 6f72508,1752d6b..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;
linux-merge@lists.open-mesh.org