Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull memremap fix from Dan Williams:
"The new memremap() api introduced in the 4.3 cycle to unify/replace
ioremap_cache() and ioremap_wt() is mishandling the highmem case.
This patch has received a build success notification from a
0day-kbuild-robot run and has received an ack from Ard"
From the commit message:
"The impact of this bug is low for now since the pmem driver is the
only user of memremap(), but this is important to fix before more
conversions to memremap arrive in 4.4"
* 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
memremap: fix highmem support
diff --git a/.mailmap b/.mailmap
index 4b31af5..b1e9a97 100644
--- a/.mailmap
+++ b/.mailmap
@@ -59,6 +59,7 @@
James Bottomley <jejb@titanic.il.steeleye.com>
James E Wilson <wilson@specifix.com>
James Ketrenos <jketreno@io.(none)>
+<javier@osg.samsung.com> <javier.martinez@collabora.co.uk>
Jean Tourrilhes <jt@hpl.hp.com>
Jeff Garzik <jgarzik@pretzel.yyz.us>
Jens Axboe <axboe@suse.de>
diff --git a/Documentation/arm/OMAP/README b/Documentation/arm/OMAP/README
new file mode 100644
index 0000000..75645c4
--- /dev/null
+++ b/Documentation/arm/OMAP/README
@@ -0,0 +1,7 @@
+This file contains documentation for running mainline
+kernel on omaps.
+
+KERNEL NEW DEPENDENCIES
+v4.3+ Update is needed for custom .config files to make sure
+ CONFIG_REGULATOR_PBIAS is enabled for MMC1 to work
+ properly.
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index a9df21a..a2cae4e 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -39,6 +39,7 @@
Optional properties:
- dual_emac_res_vlan : Specifies VID to be used to segregate the ports
- mac-address : See ethernet.txt file in the same directory
+- phy-handle : See ethernet.txt file in the same directory
Note: "ti,hwmods" field is used to fetch the base address and irq
resources from TI, omap hwmod data base during device registration.
diff --git a/Documentation/devicetree/bindings/net/smsc-lan87xx.txt b/Documentation/devicetree/bindings/net/smsc-lan87xx.txt
new file mode 100644
index 0000000..974edd5
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/smsc-lan87xx.txt
@@ -0,0 +1,24 @@
+SMSC LAN87xx Ethernet PHY
+
+Some boards require special tuning values. Configure them
+through an Ethernet OF device node.
+
+Optional properties:
+
+- smsc,disable-energy-detect:
+ If set, do not enable energy detect mode for the SMSC phy.
+ default: enable energy detect mode
+
+Examples:
+smsc phy with disabled energy detect mode on an am335x based board.
+&davinci_mdio {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&davinci_mdio_default>;
+ pinctrl-1 = <&davinci_mdio_sleep>;
+ status = "okay";
+
+ ethernetphy0: ethernet-phy@0 {
+ reg = <0>;
+ smsc,disable-energy-detect;
+ };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 5f46784..747c653 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -894,11 +894,12 @@
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-ARM/Allwinner A1X SoC support
+ARM/Allwinner sunXi SoC support
M: Maxime Ripard <maxime.ripard@free-electrons.com>
+M: Chen-Yu Tsai <wens@csie.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-N: sun[x4567]i
+N: sun[x456789]i
ARM/Allwinner SoC Clock Support
M: Emilio López <emilio@elopez.com.ar>
@@ -3591,6 +3592,13 @@
F: include/drm/i915*
F: include/uapi/drm/i915*
+DRM DRIVERS FOR ATMEL HLCDC
+M: Boris Brezillon <boris.brezillon@free-electrons.com>
+L: dri-devel@lists.freedesktop.org
+S: Supported
+F: drivers/gpu/drm/atmel-hlcdc/
+F: Documentation/devicetree/bindings/drm/atmel/
+
DRM DRIVERS FOR EXYNOS
M: Inki Dae <inki.dae@samsung.com>
M: Joonyoung Shim <jy0922.shim@samsung.com>
@@ -3619,6 +3627,14 @@
F: drivers/gpu/drm/imx/
F: Documentation/devicetree/bindings/drm/imx/
+DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets)
+M: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+L: dri-devel@lists.freedesktop.org
+T: git git://github.com/patjak/drm-gma500
+S: Maintained
+F: drivers/gpu/drm/gma500
+F: include/drm/gma500*
+
DRM DRIVERS FOR NVIDIA TEGRA
M: Thierry Reding <thierry.reding@gmail.com>
M: Terje Bergström <tbergstrom@nvidia.com>
@@ -4412,6 +4428,14 @@
S: Maintained
F: drivers/net/ethernet/freescale/ucc_geth*
+FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
+M: Claudiu Manoil <claudiu.manoil@freescale.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/ethernet/freescale/gianfar*
+X: drivers/net/ethernet/freescale/gianfar_ptp.c
+F: Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
+
FREESCALE QUICC ENGINE UCC UART DRIVER
M: Timur Tabi <timur@tabi.org>
L: linuxppc-dev@lists.ozlabs.org
@@ -6778,7 +6802,6 @@
MELLANOX ETHERNET DRIVER (mlx4_en)
M: Amir Vadai <amirv@mellanox.com>
-M: Ido Shamay <idos@mellanox.com>
L: netdev@vger.kernel.org
S: Supported
W: http://www.mellanox.com
@@ -9101,6 +9124,15 @@
F: Documentation/devicetree/bindings/net/snps,dwc-qos-ethernet.txt
F: drivers/net/ethernet/synopsys/dwc_eth_qos.c
+SYNOPSYS DESIGNWARE I2C DRIVER
+M: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+M: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+M: Mika Westerberg <mika.westerberg@linux.intel.com>
+L: linux-i2c@vger.kernel.org
+S: Maintained
+F: drivers/i2c/busses/i2c-designware-*
+F: include/linux/platform_data/i2c-designware.h
+
SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
M: Seungwon Jeon <tgih.jun@samsung.com>
M: Jaehoon Chung <jh80.chung@samsung.com>
@@ -11651,6 +11683,7 @@
ZSMALLOC COMPRESSED SLAB MEMORY ALLOCATOR
M: Minchan Kim <minchan@kernel.org>
M: Nitin Gupta <ngupta@vflare.org>
+R: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
L: linux-mm@kvack.org
S: Maintained
F: mm/zsmalloc.c
diff --git a/Makefile b/Makefile
index 416660d..431067a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 4
PATCHLEVEL = 3
SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc7
NAME = Blurry Fish Butt
# *DOCUMENTATION*
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 72ad724..639411f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -645,6 +645,7 @@
config ARCH_RPC
bool "RiscPC"
+ depends on MMU
select ARCH_ACORN
select ARCH_MAY_HAVE_PC_FDC
select ARCH_SPARSEMEM_ENABLE
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
index 568adf5..d55e3ea 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
@@ -402,11 +402,12 @@
/* SMPS9 unused */
ldo1_reg: ldo1 {
- /* VDD_SD */
+ /* VDD_SD / VDDSHV8 */
regulator-name = "ldo1";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
+ regulator-always-on;
};
ldo2_reg: ldo2 {
diff --git a/arch/arm/boot/dts/armada-385-db-ap.dts b/arch/arm/boot/dts/armada-385-db-ap.dts
index 89f5a95..4047621 100644
--- a/arch/arm/boot/dts/armada-385-db-ap.dts
+++ b/arch/arm/boot/dts/armada-385-db-ap.dts
@@ -46,7 +46,7 @@
/ {
model = "Marvell Armada 385 Access Point Development Board";
- compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada38x";
+ compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada380";
chosen {
stdout-path = "serial1:115200n8";
diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index 63a4849..d4dbd28 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -152,7 +152,7 @@
};
usb_phy2: phy@a2f400 {
- compatible = "marvell,berlin2-usb-phy";
+ compatible = "marvell,berlin2cd-usb-phy";
reg = <0xa2f400 0x128>;
#phy-cells = <0>;
resets = <&chip_rst 0x104 14>;
@@ -170,7 +170,7 @@
};
usb_phy0: phy@b74000 {
- compatible = "marvell,berlin2-usb-phy";
+ compatible = "marvell,berlin2cd-usb-phy";
reg = <0xb74000 0x128>;
#phy-cells = <0>;
resets = <&chip_rst 0x104 12>;
@@ -178,7 +178,7 @@
};
usb_phy1: phy@b78000 {
- compatible = "marvell,berlin2-usb-phy";
+ compatible = "marvell,berlin2cd-usb-phy";
reg = <0xb78000 0x128>;
#phy-cells = <0>;
resets = <&chip_rst 0x104 13>;
diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts
index 955c24e..8c24975 100644
--- a/arch/arm/boot/dts/emev2-kzm9d.dts
+++ b/arch/arm/boot/dts/emev2-kzm9d.dts
@@ -35,28 +35,28 @@
button@1 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
label = "DSW2-1";
linux,code = <KEY_1>;
gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
};
button@2 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
label = "DSW2-2";
linux,code = <KEY_2>;
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
button@3 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
label = "DSW2-3";
linux,code = <KEY_3>;
gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
};
button@4 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
label = "DSW2-4";
linux,code = <KEY_4>;
gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 8f4d76c..1b95da7 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -915,6 +915,11 @@
};
};
+&pmu_system_controller {
+ assigned-clocks = <&pmu_system_controller 0>;
+ assigned-clock-parents = <&clock CLK_FIN_PLL>;
+};
+
&rtc {
status = "okay";
clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index 7d5b386..8f40c7e 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -878,6 +878,11 @@
};
};
+&pmu_system_controller {
+ assigned-clocks = <&pmu_system_controller 0>;
+ assigned-clock-parents = <&clock CLK_FIN_PLL>;
+};
+
&rtc {
status = "okay";
clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index b738ce0..6e444bb 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -588,10 +588,10 @@
status = "disabled";
};
- uart2: serial@30870000 {
+ uart2: serial@30890000 {
compatible = "fsl,imx7d-uart",
"fsl,imx6q-uart";
- reg = <0x30870000 0x10000>;
+ reg = <0x30890000 0x10000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_UART2_ROOT_CLK>,
<&clks IMX7D_UART2_ROOT_CLK>;
diff --git a/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts b/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
index 91146c3..5b04300 100644
--- a/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
+++ b/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
@@ -12,7 +12,7 @@
/ {
model = "LogicPD Zoom DM3730 Torpedo Development Kit";
- compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap36xx";
+ compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap3630", "ti,omap3";
gpio_keys {
compatible = "gpio-keys";
diff --git a/arch/arm/boot/dts/meson.dtsi b/arch/arm/boot/dts/meson.dtsi
index 5484413..8c77c87 100644
--- a/arch/arm/boot/dts/meson.dtsi
+++ b/arch/arm/boot/dts/meson.dtsi
@@ -67,7 +67,7 @@
timer@c1109940 {
compatible = "amlogic,meson6-timer";
- reg = <0xc1109940 0x14>;
+ reg = <0xc1109940 0x18>;
interrupts = <0 10 1>;
};
@@ -80,36 +80,37 @@
wdt: watchdog@c1109900 {
compatible = "amlogic,meson6-wdt";
reg = <0xc1109900 0x8>;
+ interrupts = <0 0 1>;
};
uart_AO: serial@c81004c0 {
compatible = "amlogic,meson-uart";
- reg = <0xc81004c0 0x14>;
+ reg = <0xc81004c0 0x18>;
interrupts = <0 90 1>;
clocks = <&clk81>;
status = "disabled";
};
- uart_A: serial@c81084c0 {
+ uart_A: serial@c11084c0 {
compatible = "amlogic,meson-uart";
- reg = <0xc81084c0 0x14>;
- interrupts = <0 90 1>;
+ reg = <0xc11084c0 0x18>;
+ interrupts = <0 26 1>;
clocks = <&clk81>;
status = "disabled";
};
- uart_B: serial@c81084dc {
+ uart_B: serial@c11084dc {
compatible = "amlogic,meson-uart";
- reg = <0xc81084dc 0x14>;
- interrupts = <0 90 1>;
+ reg = <0xc11084dc 0x18>;
+ interrupts = <0 75 1>;
clocks = <&clk81>;
status = "disabled";
};
- uart_C: serial@c8108700 {
+ uart_C: serial@c1108700 {
compatible = "amlogic,meson-uart";
- reg = <0xc8108700 0x14>;
- interrupts = <0 90 1>;
+ reg = <0xc1108700 0x18>;
+ interrupts = <0 93 1>;
clocks = <&clk81>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/omap3-evm-37xx.dts b/arch/arm/boot/dts/omap3-evm-37xx.dts
index 16e8ce3..bb339d1 100644
--- a/arch/arm/boot/dts/omap3-evm-37xx.dts
+++ b/arch/arm/boot/dts/omap3-evm-37xx.dts
@@ -13,7 +13,7 @@
/ {
model = "TI OMAP37XX EVM (TMDSEVM3730)";
- compatible = "ti,omap3-evm-37xx", "ti,omap36xx";
+ compatible = "ti,omap3-evm-37xx", "ti,omap3630", "ti,omap3";
memory {
device_type = "memory";
diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dtsi b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
index 810cda7..9c2387b 100644
--- a/arch/arm/boot/dts/ste-hrefv60plus.dtsi
+++ b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
@@ -56,7 +56,7 @@
/* VMMCI level-shifter enable */
default_hrefv60_cfg2 {
pins = "GPIO169_D22";
- ste,config = <&gpio_out_lo>;
+ ste,config = <&gpio_out_hi>;
};
/* VMMCI level-shifter voltage select */
default_hrefv60_cfg3 {
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index 32a5ccb..e80e421 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -47,35 +47,35 @@
button@1 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <2>;
label = "userpb";
gpios = <&gpio1 0 0x4>;
};
button@2 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <3>;
label = "extkb1";
gpios = <&gpio4 23 0x4>;
};
button@3 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <4>;
label = "extkb2";
gpios = <&gpio4 24 0x4>;
};
button@4 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <5>;
label = "extkb3";
gpios = <&gpio5 1 0x4>;
};
button@5 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <6>;
label = "extkb4";
gpios = <&gpio5 2 0x4>;
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 9d4f86e..d845bd1 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -234,7 +234,9 @@
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
+ /*
gpio-ranges = <&pinmux 0 0 246>;
+ */
};
apbmisc@70000800 {
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 1e204a6..819e2ae 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -258,7 +258,9 @@
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
+ /*
gpio-ranges = <&pinmux 0 0 251>;
+ */
};
apbdma: dma@0,60020000 {
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index e058709..969b828 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -244,7 +244,9 @@
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
+ /*
gpio-ranges = <&pinmux 0 0 224>;
+ */
};
apbmisc@70000800 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index fe04fb5..c6938ad 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -349,7 +349,9 @@
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
+ /*
gpio-ranges = <&pinmux 0 0 248>;
+ */
};
apbmisc@70000800 {
diff --git a/arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts b/arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts
index 33963ac..f80f772 100644
--- a/arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts
+++ b/arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts
@@ -85,7 +85,7 @@
};
ðsc {
- interrupts = <0 50 4>;
+ interrupts = <0 52 4>;
};
&serial0 {
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 210ecca..356970f 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -21,6 +21,7 @@
depends on MMU && OF
select PREEMPT_NOTIFIERS
select ANON_INODES
+ select ARM_GIC
select HAVE_KVM_CPU_RELAX_INTERCEPT
select HAVE_KVM_ARCH_TLB_FLUSH_ALL
select KVM_MMIO
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index dc017ad..78b2869 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1080,7 +1080,7 @@
*/
err = kvm_timer_hyp_init();
if (err)
- goto out_free_mappings;
+ goto out_free_context;
#ifndef CONFIG_HOTPLUG_CPU
free_boot_hyp_pgd();
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index 4a87e86..7c21760 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -200,15 +200,15 @@
args.args_count = 0;
child_domain = of_genpd_get_from_provider(&args);
if (IS_ERR(child_domain))
- goto next_pd;
+ continue;
if (of_parse_phandle_with_args(np, "power-domains",
"#power-domain-cells", 0, &args) != 0)
- goto next_pd;
+ continue;
parent_domain = of_genpd_get_from_provider(&args);
if (IS_ERR(parent_domain))
- goto next_pd;
+ continue;
if (pm_genpd_add_subdomain(parent_domain, child_domain))
pr_warn("%s failed to add subdomain: %s\n",
@@ -216,8 +216,6 @@
else
pr_info("%s has as child subdomain: %s.\n",
parent_domain->name, child_domain->name);
-next_pd:
- of_node_put(np);
}
return 0;
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index b3a0dff..33d1460 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -49,6 +49,7 @@
select OMAP_INTERCONNECT
select OMAP_INTERCONNECT_BARRIER
select PM_OPP if PM
+ select ZONE_DMA if ARM_LPAE
config SOC_AM33XX
bool "TI AM33XX"
@@ -78,6 +79,7 @@
select OMAP_INTERCONNECT
select OMAP_INTERCONNECT_BARRIER
select PM_OPP if PM
+ select ZONE_DMA if ARM_LPAE
config ARCH_OMAP2PLUS
bool
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 6133eaa..fb219a3 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -106,6 +106,7 @@
MACHINE_END
static const char *const omap36xx_boards_compat[] __initconst = {
+ "ti,omap3630",
"ti,omap36xx",
NULL,
};
@@ -243,6 +244,9 @@
};
DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+ .dma_zone_size = SZ_2G,
+#endif
.reserve = omap_reserve,
.smp = smp_ops(omap4_smp_ops),
.map_io = omap5_map_io,
@@ -288,6 +292,9 @@
};
DT_MACHINE_START(DRA74X_DT, "Generic DRA74X (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+ .dma_zone_size = SZ_2G,
+#endif
.reserve = omap_reserve,
.smp = smp_ops(omap4_smp_ops),
.map_io = dra7xx_map_io,
@@ -308,6 +315,9 @@
};
DT_MACHINE_START(DRA72X_DT, "Generic DRA72X (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+ .dma_zone_size = SZ_2G,
+#endif
.reserve = omap_reserve,
.map_io = dra7xx_map_io,
.init_early = dra7xx_init_early,
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index ea56397..1dfe346 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -559,7 +559,14 @@
void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
{
- omap_sdrc_init(NULL, NULL);
+ /*
+ * We still need this for omap2420 and omap3 PM to work, others are
+ * using drivers/misc/sram.c already.
+ */
+ if (of_machine_is_compatible("ti,omap2420") ||
+ of_machine_is_compatible("ti,omap3"))
+ omap_sdrc_init(NULL, NULL);
+
pdata_quirks_check(auxdata_quirks);
of_platform_populate(NULL, omap_dt_match_table,
omap_auxdata_lookup, NULL);
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 06005d3..20ce2d3 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,10 +42,6 @@
#define PECR_IS(n) ((1 << ((n) * 2)) << 29)
extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-#ifdef CONFIG_PM
-
-#define ISRAM_START 0x5c000000
-#define ISRAM_SIZE SZ_256K
/*
* NAND NFC: DFI bus arbitration subset
@@ -54,6 +50,11 @@
#define NDCR_ND_ARB_EN (1 << 12)
#define NDCR_ND_ARB_CNTL (1 << 19)
+#ifdef CONFIG_PM
+
+#define ISRAM_START 0x5c000000
+#define ISRAM_SIZE SZ_256K
+
static void __iomem *sram;
static unsigned long wakeup_src;
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 876060b..b8efb8c 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -614,6 +614,7 @@
case BPF_LD | BPF_B | BPF_IND:
load_order = 0;
load_ind:
+ update_on_xread(ctx);
OP_IMM3(ARM_ADD, r_off, r_X, k, ctx);
goto load_common;
case BPF_LDX | BPF_IMM:
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 2235081a..8861c36 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -495,7 +495,7 @@
d->netdev = &orion_ge00.dev;
for (i = 0; i < d->nr_chips; i++)
- d->chip[i].host_dev = &orion_ge00_shared.dev;
+ d->chip[i].host_dev = &orion_ge_mvmdio.dev;
orion_switch_device.dev.platform_data = d;
platform_device_register(&orion_switch_device);
diff --git a/arch/arm/vdso/vdsomunge.c b/arch/arm/vdso/vdsomunge.c
index aedec81..0cebd98 100644
--- a/arch/arm/vdso/vdsomunge.c
+++ b/arch/arm/vdso/vdsomunge.c
@@ -45,7 +45,6 @@
* it does.
*/
-#include <byteswap.h>
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
@@ -59,6 +58,16 @@
#include <sys/types.h>
#include <unistd.h>
+#define swab16(x) \
+ ((((x) & 0x00ff) << 8) | \
+ (((x) & 0xff00) >> 8))
+
+#define swab32(x) \
+ ((((x) & 0x000000ff) << 24) | \
+ (((x) & 0x0000ff00) << 8) | \
+ (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0xff000000) << 24))
+
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define HOST_ORDER ELFDATA2LSB
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
@@ -104,17 +113,17 @@
static Elf32_Word read_elf_word(Elf32_Word word, bool swap)
{
- return swap ? bswap_32(word) : word;
+ return swap ? swab32(word) : word;
}
static Elf32_Half read_elf_half(Elf32_Half half, bool swap)
{
- return swap ? bswap_16(half) : half;
+ return swap ? swab16(half) : half;
}
static void write_elf_word(Elf32_Word val, Elf32_Word *dst, bool swap)
{
- *dst = swap ? bswap_32(val) : val;
+ *dst = swap ? swab32(val) : val;
}
int main(int argc, char **argv)
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index f9914d7..d10b5d4 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -42,7 +42,7 @@
CHECKFLAGS += -D__aarch64__
ifeq ($(CONFIG_ARM64_ERRATUM_843419), y)
-CFLAGS_MODULE += -mcmodel=large
+KBUILD_CFLAGS_MODULE += -mcmodel=large
endif
# Default value
diff --git a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
index 637e046..3c38668 100644
--- a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
@@ -61,42 +61,42 @@
button@1 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <116>;
label = "POWER";
gpios = <&iofpga_gpio0 0 0x4>;
};
button@2 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <102>;
label = "HOME";
gpios = <&iofpga_gpio0 1 0x4>;
};
button@3 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <152>;
label = "RLOCK";
gpios = <&iofpga_gpio0 2 0x4>;
};
button@4 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <115>;
label = "VOL+";
gpios = <&iofpga_gpio0 3 0x4>;
};
button@5 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <114>;
label = "VOL-";
gpios = <&iofpga_gpio0 4 0x4>;
};
button@6 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <99>;
label = "NMI";
gpios = <&iofpga_gpio0 5 0x4>;
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 3bc498c..41e58fe 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -44,7 +44,7 @@
#define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2)
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5)
-#define __NR_compat_syscalls 388
+#define __NR_compat_syscalls 390
#endif
#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index cef934a..5b925b7 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -797,3 +797,12 @@
__SYSCALL(__NR_bpf, sys_bpf)
#define __NR_execveat 387
__SYSCALL(__NR_execveat, compat_sys_execveat)
+#define __NR_userfaultfd 388
+__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
+#define __NR_membarrier 389
+__SYSCALL(__NR_membarrier, sys_membarrier)
+
+/*
+ * Please add new compat syscalls above this comment and update
+ * __NR_compat_syscalls in asm/unistd.h.
+ */
diff --git a/arch/arm64/include/uapi/asm/signal.h b/arch/arm64/include/uapi/asm/signal.h
index 8d1e723..991bf5d 100644
--- a/arch/arm64/include/uapi/asm/signal.h
+++ b/arch/arm64/include/uapi/asm/signal.h
@@ -19,6 +19,9 @@
/* Required for AArch32 compatibility. */
#define SA_RESTORER 0x04000000
+#define MINSIGSTKSZ 5120
+#define SIGSTKSZ 16384
+
#include <asm-generic/signal.h>
#endif
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index bcee7ab..937f5e5 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -284,21 +284,23 @@
__asm__ __volatile__( \
ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
CONFIG_ARM64_PAN) \
- " mov %w2, %w1\n" \
- "0: ldxr"B" %w1, [%3]\n" \
- "1: stxr"B" %w0, %w2, [%3]\n" \
+ "0: ldxr"B" %w2, [%3]\n" \
+ "1: stxr"B" %w0, %w1, [%3]\n" \
" cbz %w0, 2f\n" \
" mov %w0, %w4\n" \
+ " b 3f\n" \
"2:\n" \
+ " mov %w1, %w2\n" \
+ "3:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
- "3: mov %w0, %w5\n" \
- " b 2b\n" \
+ "4: mov %w0, %w5\n" \
+ " b 3b\n" \
" .popsection" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .quad 0b, 3b\n" \
- " .quad 1b, 3b\n" \
+ " .quad 0b, 4b\n" \
+ " .quad 1b, 4b\n" \
" .popsection\n" \
ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
CONFIG_ARM64_PAN) \
diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
index 816120e..78dfbd3 100644
--- a/arch/arm64/kernel/efi-stub.c
+++ b/arch/arm64/kernel/efi-stub.c
@@ -25,10 +25,20 @@
unsigned long kernel_size, kernel_memsize = 0;
unsigned long nr_pages;
void *old_image_addr = (void *)*image_addr;
+ unsigned long preferred_offset;
+
+ /*
+ * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
+ * a 2 MB aligned base, which itself may be lower than dram_base, as
+ * long as the resulting offset equals or exceeds it.
+ */
+ preferred_offset = round_down(dram_base, SZ_2M) + TEXT_OFFSET;
+ if (preferred_offset < dram_base)
+ preferred_offset += SZ_2M;
/* Relocate the image, if required. */
kernel_size = _edata - _text;
- if (*image_addr != (dram_base + TEXT_OFFSET)) {
+ if (*image_addr != preferred_offset) {
kernel_memsize = kernel_size + (_end - _edata);
/*
@@ -42,7 +52,7 @@
* Mustang), we can still place the kernel at the address
* 'dram_base + TEXT_OFFSET'.
*/
- *image_addr = *reserve_addr = dram_base + TEXT_OFFSET;
+ *image_addr = *reserve_addr = preferred_offset;
nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /
EFI_PAGE_SIZE;
status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 407991b..ccb6078 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -48,11 +48,7 @@
frame->sp = fp + 0x10;
frame->fp = *(unsigned long *)(fp);
- /*
- * -4 here because we care about the PC at time of bl,
- * not where the return will go.
- */
- frame->pc = *(unsigned long *)(fp + 8) - 4;
+ frame->pc = *(unsigned long *)(fp + 8);
return 0;
}
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 8297d50..44ca414 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -80,17 +80,21 @@
if (ret == 0) {
/*
* We are resuming from reset with TTBR0_EL1 set to the
- * idmap to enable the MMU; restore the active_mm mappings in
- * TTBR0_EL1 unless the active_mm == &init_mm, in which case
- * the thread entered cpu_suspend with TTBR0_EL1 set to
- * reserved TTBR0 page tables and should be restored as such.
+ * idmap to enable the MMU; set the TTBR0 to the reserved
+ * page tables to prevent speculative TLB allocations, flush
+ * the local tlb and set the default tcr_el1.t0sz so that
+ * the TTBR0 address space set-up is properly restored.
+ * If the current active_mm != &init_mm we entered cpu_suspend
+ * with mappings in TTBR0 that must be restored, so we switch
+ * them back to complete the address space configuration
+ * restoration before returning.
*/
- if (mm == &init_mm)
- cpu_set_reserved_ttbr0();
- else
- cpu_switch_mm(mm->pgd, mm);
-
+ cpu_set_reserved_ttbr0();
flush_tlb_all();
+ cpu_set_default_tcr_t0sz();
+
+ if (mm != &init_mm)
+ cpu_switch_mm(mm->pgd, mm);
/*
* Restore per-cpu offset before any kernel
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index 99c96a5..db73390 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -11,7 +11,7 @@
-#define NR_syscalls 321 /* length of syscall table */
+#define NR_syscalls 322 /* length of syscall table */
/*
* The following defines stop scripts/checksyscalls.sh from complaining about
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h
index 98e94e1..9038726 100644
--- a/arch/ia64/include/uapi/asm/unistd.h
+++ b/arch/ia64/include/uapi/asm/unistd.h
@@ -334,5 +334,6 @@
#define __NR_execveat 1342
#define __NR_userfaultfd 1343
#define __NR_membarrier 1344
+#define __NR_kcmp 1345
#endif /* _UAPI_ASM_IA64_UNISTD_H */
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 37cc7a6..dcd97f8 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1770,5 +1770,6 @@
data8 sys_execveat
data8 sys_userfaultfd
data8 sys_membarrier
+ data8 sys_kcmp // 1345
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 6bc0ee4..2c041b5 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -111,7 +111,7 @@
CONFIG_SCSI_QLA_ISCSI=m
CONFIG_SCSI_LPFC=m
CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_ALUA=m
CONFIG_ATA=y
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 7991f37..36871a4 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -114,7 +114,7 @@
CONFIG_SCSI_QLA_ISCSI=m
CONFIG_SCSI_LPFC=m
CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_ALUA=m
CONFIG_ATA=y
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index 0dc42c5..5f8229e 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -3,7 +3,6 @@
#ifdef __KERNEL__
-#include <asm/reg.h>
/* bytes per L1 cache line */
#if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
@@ -40,12 +39,6 @@
};
extern struct ppc64_caches ppc64_caches;
-
-static inline void logmpp(u64 x)
-{
- asm volatile(PPC_LOGMPP(R1) : : "r" (x));
-}
-
#endif /* __powerpc64__ && ! __ASSEMBLY__ */
#if defined(__ASSEMBLY__)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 827a38d..887c259 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -297,8 +297,6 @@
u32 arch_compat;
ulong pcr;
ulong dpdes; /* doorbell state (POWER8) */
- void *mpp_buffer; /* Micro Partition Prefetch buffer */
- bool mpp_buffer_is_valid;
ulong conferring_threads;
};
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index cab6753..3f191f5 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -61,8 +61,13 @@
unsigned long addr,
unsigned char *hpte_slot_array,
int psize, int ssize, int local);
- /* special for kexec, to be called in real mode, linear mapping is
- * destroyed as well */
+ /*
+ * Special for kexec.
+ * To be called in real mode with interrupts disabled. No locks are
+ * taken as such, concurrent access on pre POWER5 hardware could result
+ * in a deadlock.
+ * The linear mapping is destroyed as well.
+ */
void (*hpte_clear_all)(void);
void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size,
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 790f5d1..7ab04fc 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -141,7 +141,6 @@
#define PPC_INST_ISEL 0x7c00001e
#define PPC_INST_ISEL_MASK 0xfc00003e
#define PPC_INST_LDARX 0x7c0000a8
-#define PPC_INST_LOGMPP 0x7c0007e4
#define PPC_INST_LSWI 0x7c0004aa
#define PPC_INST_LSWX 0x7c00042a
#define PPC_INST_LWARX 0x7c000028
@@ -285,20 +284,6 @@
#define __PPC_EH(eh) 0
#endif
-/* POWER8 Micro Partition Prefetch (MPP) parameters */
-/* Address mask is common for LOGMPP instruction and MPPR SPR */
-#define PPC_MPPE_ADDRESS_MASK 0xffffffffc000ULL
-
-/* Bits 60 and 61 of MPP SPR should be set to one of the following */
-/* Aborting the fetch is indeed setting 00 in the table size bits */
-#define PPC_MPPR_FETCH_ABORT (0x0ULL << 60)
-#define PPC_MPPR_FETCH_WHOLE_TABLE (0x2ULL << 60)
-
-/* Bits 54 and 55 of register for LOGMPP instruction should be set to: */
-#define PPC_LOGMPP_LOG_L2 (0x02ULL << 54)
-#define PPC_LOGMPP_LOG_L2L3 (0x01ULL << 54)
-#define PPC_LOGMPP_LOG_ABORT (0x03ULL << 54)
-
/* Deal with instructions that older assemblers aren't aware of */
#define PPC_DCBAL(a, b) stringify_in_c(.long PPC_INST_DCBAL | \
__PPC_RA(a) | __PPC_RB(b))
@@ -307,8 +292,6 @@
#define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \
___PPC_RT(t) | ___PPC_RA(a) | \
___PPC_RB(b) | __PPC_EH(eh))
-#define PPC_LOGMPP(b) stringify_in_c(.long PPC_INST_LOGMPP | \
- __PPC_RB(b))
#define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \
___PPC_RT(t) | ___PPC_RA(a) | \
___PPC_RB(b) | __PPC_EH(eh))
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index aa1cc5f0..a908ada 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -226,7 +226,6 @@
#define CTRL_TE 0x00c00000 /* thread enable */
#define CTRL_RUNLATCH 0x1
#define SPRN_DAWR 0xB4
-#define SPRN_MPPR 0xB8 /* Micro Partition Prefetch Register */
#define SPRN_RPR 0xBA /* Relative Priority Register */
#define SPRN_CIABR 0xBB
#define CIABR_PRIV 0x3
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 59503ed..3f1472a 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -303,7 +303,7 @@
dev->coherent_dma_mask = mask;
return 0;
}
-EXPORT_SYMBOL_GPL(dma_set_coherent_mask);
+EXPORT_SYMBOL(dma_set_coherent_mask);
#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 84bf934..5a753fa 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -1043,6 +1043,9 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ if (!rtas.entry)
+ return -EINVAL;
+
if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
return -EFAULT;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 2280497..9c26c5a 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -36,7 +36,6 @@
#include <asm/reg.h>
#include <asm/cputable.h>
-#include <asm/cache.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
@@ -75,12 +74,6 @@
static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
-#if defined(CONFIG_PPC_64K_PAGES)
-#define MPP_BUFFER_ORDER 0
-#elif defined(CONFIG_PPC_4K_PAGES)
-#define MPP_BUFFER_ORDER 3
-#endif
-
static int dynamic_mt_modes = 6;
module_param(dynamic_mt_modes, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(dynamic_mt_modes, "Set of allowed dynamic micro-threading modes: 0 (= none), 2, 4, or 6 (= 2 or 4)");
@@ -1455,13 +1448,6 @@
vcore->kvm = kvm;
INIT_LIST_HEAD(&vcore->preempt_list);
- vcore->mpp_buffer_is_valid = false;
-
- if (cpu_has_feature(CPU_FTR_ARCH_207S))
- vcore->mpp_buffer = (void *)__get_free_pages(
- GFP_KERNEL|__GFP_ZERO,
- MPP_BUFFER_ORDER);
-
return vcore;
}
@@ -1894,33 +1880,6 @@
return 1;
}
-static void kvmppc_start_saving_l2_cache(struct kvmppc_vcore *vc)
-{
- phys_addr_t phy_addr, mpp_addr;
-
- phy_addr = (phys_addr_t)virt_to_phys(vc->mpp_buffer);
- mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
-
- mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_ABORT);
- logmpp(mpp_addr | PPC_LOGMPP_LOG_L2);
-
- vc->mpp_buffer_is_valid = true;
-}
-
-static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc)
-{
- phys_addr_t phy_addr, mpp_addr;
-
- phy_addr = virt_to_phys(vc->mpp_buffer);
- mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
-
- /* We must abort any in-progress save operations to ensure
- * the table is valid so that prefetch engine knows when to
- * stop prefetching. */
- logmpp(mpp_addr | PPC_LOGMPP_LOG_ABORT);
- mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
-}
-
/*
* A list of virtual cores for each physical CPU.
* These are vcores that could run but their runner VCPU tasks are
@@ -2471,14 +2430,8 @@
srcu_idx = srcu_read_lock(&vc->kvm->srcu);
- if (vc->mpp_buffer_is_valid)
- kvmppc_start_restoring_l2_cache(vc);
-
__kvmppc_vcore_entry();
- if (vc->mpp_buffer)
- kvmppc_start_saving_l2_cache(vc);
-
srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
spin_lock(&vc->lock);
@@ -3073,14 +3026,8 @@
{
long int i;
- for (i = 0; i < KVM_MAX_VCORES; ++i) {
- if (kvm->arch.vcores[i] && kvm->arch.vcores[i]->mpp_buffer) {
- struct kvmppc_vcore *vc = kvm->arch.vcores[i];
- free_pages((unsigned long)vc->mpp_buffer,
- MPP_BUFFER_ORDER);
- }
+ for (i = 0; i < KVM_MAX_VCORES; ++i)
kfree(kvm->arch.vcores[i]);
- }
kvm->arch.online_vcores = 0;
}
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 13befa35..c8822af 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -582,13 +582,21 @@
* be when they isi), and we are the only one left. We rely on our kernel
* mapping being 0xC0's and the hardware ignoring those two real bits.
*
+ * This must be called with interrupts disabled.
+ *
+ * Taking the native_tlbie_lock is unsafe here due to the possibility of
+ * lockdep being on. On pre POWER5 hardware, not taking the lock could
+ * cause deadlock. POWER5 and newer not taking the lock is fine. This only
+ * gets called during boot before secondary CPUs have come up and during
+ * crashdump and all bets are off anyway.
+ *
* TODO: add batching support when enabled. remember, no dynamic memory here,
* athough there is the control page available...
*/
static void native_hpte_clear(void)
{
unsigned long vpn = 0;
- unsigned long slot, slots, flags;
+ unsigned long slot, slots;
struct hash_pte *hptep = htab_address;
unsigned long hpte_v;
unsigned long pteg_count;
@@ -596,13 +604,6 @@
pteg_count = htab_hash_mask + 1;
- local_irq_save(flags);
-
- /* we take the tlbie lock and hold it. Some hardware will
- * deadlock if we try to tlbie from two processors at once.
- */
- raw_spin_lock(&native_tlbie_lock);
-
slots = pteg_count * HPTES_PER_GROUP;
for (slot = 0; slot < slots; slot++, hptep++) {
@@ -614,8 +615,8 @@
hpte_v = be64_to_cpu(hptep->v);
/*
- * Call __tlbie() here rather than tlbie() since we
- * already hold the native_tlbie_lock.
+ * Call __tlbie() here rather than tlbie() since we can't take the
+ * native_tlbie_lock.
*/
if (hpte_v & HPTE_V_VALID) {
hpte_decode(hptep, slot, &psize, &apsize, &ssize, &vpn);
@@ -625,8 +626,6 @@
}
asm volatile("eieio; tlbsync; ptesync":::"memory");
- raw_spin_unlock(&native_tlbie_lock);
- local_irq_restore(flags);
}
/*
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 230f3a7..4296d55 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -487,9 +487,12 @@
* PRD component would have already got notified about this
* error through other channels.
*
- * In any case, let us just fall through. We anyway heading
- * down to panic path.
+ * If hardware marked this as an unrecoverable MCE, we are
+ * going to panic anyway. Even if it didn't, it's not safe to
+ * continue at this point, so we should explicitly panic.
*/
+
+ panic("PowerNV Unrecovered Machine Check");
return 0;
}
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 8f70ba6..ca26483 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -171,7 +171,26 @@
* so clear LPCR:PECE1. We keep PECE2 enabled.
*/
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+
+ /*
+ * Hard-disable interrupts, and then clear irq_happened flags
+ * that we can safely ignore while off-line, since they
+ * are for things for which we do no processing when off-line
+ * (or in the case of HMI, all the processing we need to do
+ * is done in lower-level real-mode code).
+ */
+ hard_irq_disable();
+ local_paca->irq_happened &= ~(PACA_IRQ_DEC | PACA_IRQ_HMI);
+
while (!generic_check_cpu_restart(cpu)) {
+ /*
+ * Clear IPI flag, since we don't handle IPIs while
+ * offline, except for those when changing micro-threading
+ * mode, which are handled explicitly below, and those
+ * for coming online, which are handled via
+ * generic_check_cpu_restart() calls.
+ */
+ kvmppc_set_host_ipi(cpu, 0);
ppc64_runlatch_off();
@@ -196,20 +215,20 @@
* having finished executing in a KVM guest, then srr1
* contains 0.
*/
- if ((srr1 & wmask) == SRR1_WAKEEE) {
+ if (((srr1 & wmask) == SRR1_WAKEEE) ||
+ (local_paca->irq_happened & PACA_IRQ_EE)) {
icp_native_flush_interrupt();
- local_paca->irq_happened &= PACA_IRQ_HARD_DIS;
- smp_mb();
} else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
- kvmppc_set_host_ipi(cpu, 0);
}
+ local_paca->irq_happened &= ~(PACA_IRQ_EE | PACA_IRQ_DBELL);
+ smp_mb();
if (cpu_core_split_required())
continue;
- if (!generic_check_cpu_restart(cpu))
+ if (srr1 && !generic_check_cpu_restart(cpu))
DBG("CPU%d Unexpected exit while offline !\n", cpu);
}
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 0978713..3db53e8 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -194,11 +194,6 @@
.key = OS_AREA_DB_KEY_RTC_DIFF
};
-static const struct os_area_db_id os_area_db_id_video_mode = {
- .owner = OS_AREA_DB_OWNER_LINUX,
- .key = OS_AREA_DB_KEY_VIDEO_MODE
-};
-
#define SECONDS_FROM_1970_TO_2000 946684800LL
/**
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index fe20d14..ceb5201 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -59,6 +59,7 @@
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
extern void copy_page(void *to, void *from);
+#define copy_user_page(to, from, vaddr, pg) __copy_user(to, from, PAGE_SIZE)
struct page;
struct vm_area_struct;
diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c
index 2e48eb8..c90930d 100644
--- a/arch/sparc/crypto/aes_glue.c
+++ b/arch/sparc/crypto/aes_glue.c
@@ -433,6 +433,7 @@
.blkcipher = {
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
.setkey = aes_set_key,
.encrypt = cbc_encrypt,
.decrypt = cbc_decrypt,
@@ -452,6 +453,7 @@
.blkcipher = {
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
.setkey = aes_set_key,
.encrypt = ctr_crypt,
.decrypt = ctr_crypt,
diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c
index 6bf2479..561a84d 100644
--- a/arch/sparc/crypto/camellia_glue.c
+++ b/arch/sparc/crypto/camellia_glue.c
@@ -274,6 +274,7 @@
.blkcipher = {
.min_keysize = CAMELLIA_MIN_KEY_SIZE,
.max_keysize = CAMELLIA_MAX_KEY_SIZE,
+ .ivsize = CAMELLIA_BLOCK_SIZE,
.setkey = camellia_set_key,
.encrypt = cbc_encrypt,
.decrypt = cbc_decrypt,
diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c
index dd6a34f..61af794 100644
--- a/arch/sparc/crypto/des_glue.c
+++ b/arch/sparc/crypto/des_glue.c
@@ -429,6 +429,7 @@
.blkcipher = {
.min_keysize = DES_KEY_SIZE,
.max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
.setkey = des_set_key,
.encrypt = cbc_encrypt,
.decrypt = cbc_decrypt,
@@ -485,6 +486,7 @@
.blkcipher = {
.min_keysize = DES3_EDE_KEY_SIZE,
.max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
.setkey = des3_ede_set_key,
.encrypt = cbc3_encrypt,
.decrypt = cbc3_decrypt,
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 098ab33..e3abe6f 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -70,8 +70,8 @@
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
$(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \
- -D_FILE_OFFSET_BITS=64 -idirafter include \
- -D__KERNEL__ -D__UM_HOST__
+ -D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
+ -idirafter $(obj)/include -D__KERNEL__ -D__UM_HOST__
#This will adjust *FLAGS accordingly to the platform.
include $(ARCH_DIR)/Makefile-os-$(OS)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index d8a9fce..98783dd 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -220,7 +220,7 @@
show_regs(container_of(regs, struct pt_regs, regs));
panic("Segfault with no mm");
}
- else if (!is_user && address < TASK_SIZE) {
+ else if (!is_user && address > PAGE_SIZE && address < TASK_SIZE) {
show_regs(container_of(regs, struct pt_regs, regs));
panic("Kernel tried to access user memory at addr 0x%lx, ip 0x%lx",
address, ip);
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index e3ee4a5..3f02d42 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -96,7 +96,7 @@
"ret = %d\n", -n);
ret = n;
}
- CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
+ CATCH_EINTR(waitpid(pid, NULL, __WALL));
}
out_free2:
@@ -129,7 +129,7 @@
return err;
}
if (stack_out == NULL) {
- CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
+ CATCH_EINTR(pid = waitpid(pid, &status, __WALL));
if (pid < 0) {
err = -errno;
printk(UM_KERN_ERR "run_helper_thread - wait failed, "
@@ -148,7 +148,7 @@
int helper_wait(int pid)
{
int ret, status;
- int wflags = __WCLONE;
+ int wflags = __WALL;
CATCH_EINTR(ret = waitpid(pid, &status, wflags));
if (ret < 0) {
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index ee1b6d3..db51c1f 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -667,6 +667,7 @@
bool conout_found = false;
void *dummy = NULL;
u32 h = handles[i];
+ u32 current_fb_base;
status = efi_call_early(handle_protocol, h,
proto, (void **)&gop32);
@@ -678,7 +679,7 @@
if (status == EFI_SUCCESS)
conout_found = true;
- status = __gop_query32(gop32, &info, &size, &fb_base);
+ status = __gop_query32(gop32, &info, &size, ¤t_fb_base);
if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
/*
* Systems that use the UEFI Console Splitter may
@@ -692,6 +693,7 @@
pixel_format = info->pixel_format;
pixel_info = info->pixel_information;
pixels_per_scan_line = info->pixels_per_scan_line;
+ fb_base = current_fb_base;
/*
* Once we've found a GOP supporting ConOut,
@@ -770,6 +772,7 @@
bool conout_found = false;
void *dummy = NULL;
u64 h = handles[i];
+ u32 current_fb_base;
status = efi_call_early(handle_protocol, h,
proto, (void **)&gop64);
@@ -781,7 +784,7 @@
if (status == EFI_SUCCESS)
conout_found = true;
- status = __gop_query64(gop64, &info, &size, &fb_base);
+ status = __gop_query64(gop64, &info, &size, ¤t_fb_base);
if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
/*
* Systems that use the UEFI Console Splitter may
@@ -795,6 +798,7 @@
pixel_format = info->pixel_format;
pixel_info = info->pixel_information;
pixels_per_scan_line = info->pixels_per_scan_line;
+ fb_base = current_fb_base;
/*
* Once we've found a GOP supporting ConOut,
diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c
index 80a0e43..bacaa13 100644
--- a/arch/x86/crypto/camellia_aesni_avx_glue.c
+++ b/arch/x86/crypto/camellia_aesni_avx_glue.c
@@ -554,6 +554,11 @@
{
const char *feature_name;
+ if (!cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) {
+ pr_info("AVX or AES-NI instructions are not detected.\n");
+ return -ENODEV;
+ }
+
if (!cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, &feature_name)) {
pr_info("CPU feature '%s' is not supported.\n", feature_name);
return -ENODEV;
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 2beee03..3a36ee7 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1226,10 +1226,8 @@
int kvm_is_in_guest(void);
-int __x86_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region *mem);
-int x86_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region *mem);
+int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size);
+int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size);
bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu);
bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index e466119..ff8b9a1 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -27,12 +27,11 @@
function. */
#define __HAVE_ARCH_MEMCPY 1
+extern void *memcpy(void *to, const void *from, size_t len);
extern void *__memcpy(void *to, const void *from, size_t len);
#ifndef CONFIG_KMEMCHECK
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
-extern void *memcpy(void *to, const void *from, size_t len);
-#else
+#if (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || __GNUC__ < 4
#define memcpy(dst, src, len) \
({ \
size_t __len = (len); \
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 5c60bb1..4f28215 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2547,7 +2547,9 @@
mask = apic->target_cpus();
chip = irq_data_get_irq_chip(idata);
- chip->irq_set_affinity(idata, mask, false);
+ /* Might be lapic_chip for irq 0 */
+ if (chip->irq_set_affinity)
+ chip->irq_set_affinity(idata, mask, false);
}
}
#endif
@@ -2907,6 +2909,7 @@
struct irq_data *irq_data;
struct mp_chip_data *data;
struct irq_alloc_info *info = arg;
+ unsigned long flags;
if (!info || nr_irqs > 1)
return -EINVAL;
@@ -2939,11 +2942,14 @@
cfg = irqd_cfg(irq_data);
add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
+
+ local_irq_save(flags);
if (info->ioapic_entry)
mp_setup_entry(cfg, data, info->ioapic_entry);
mp_register_handler(virq, data->trigger);
if (virq < nr_legacy_irqs())
legacy_pic->mask(virq);
+ local_irq_restore(flags);
apic_printk(APIC_VERBOSE, KERN_DEBUG
"IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n",
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 1b55de1..cd99433 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -131,11 +131,12 @@
bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp)
{
+ if (!*dev)
+ *dev = &x86_dma_fallback_dev;
+
*gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
*gfp = dma_alloc_coherent_gfp_flags(*dev, *gfp);
- if (!*dev)
- *dev = &x86_dma_fallback_dev;
if (!is_device_dma_capable(*dev))
return false;
return true;
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 39e585a..9f7c21c 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -84,6 +84,9 @@
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
memcpy(dst, src, arch_task_struct_size);
+#ifdef CONFIG_VM86
+ dst->thread.vm86 = NULL;
+#endif
return fpu__copy(&dst->thread.fpu, &src->thread.fpu);
}
@@ -550,14 +553,14 @@
if (sp < bottom || sp > top)
return 0;
- fp = READ_ONCE(*(unsigned long *)sp);
+ fp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
do {
if (fp < bottom || fp > top)
return 0;
- ip = READ_ONCE(*(unsigned long *)(fp + sizeof(unsigned long)));
+ ip = READ_ONCE_NOCHECK(*(unsigned long *)(fp + sizeof(unsigned long)));
if (!in_sched_functions(ip))
return ip;
- fp = READ_ONCE(*(unsigned long *)fp);
+ fp = READ_ONCE_NOCHECK(*(unsigned long *)fp);
} while (count++ < 16 && p->state != TASK_RUNNING);
return 0;
}
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index fdb7f2a..a3cccbf 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1173,6 +1173,14 @@
clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
swapper_pg_dir + KERNEL_PGD_BOUNDARY,
KERNEL_PGD_PTRS);
+
+ /*
+ * sync back low identity map too. It is used for example
+ * in the 32-bit EFI stub.
+ */
+ clone_pgd_range(initial_page_table,
+ swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+ KERNEL_PGD_PTRS);
#endif
tboot_probe();
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index e0c198e..892ee2e5 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -509,7 +509,7 @@
*/
#define UDELAY_10MS_DEFAULT 10000
-static unsigned int init_udelay = UDELAY_10MS_DEFAULT;
+static unsigned int init_udelay = INT_MAX;
static int __init cpu_init_udelay(char *str)
{
@@ -522,13 +522,16 @@
static void __init smp_quirk_init_udelay(void)
{
/* if cmdline changed it from default, leave it alone */
- if (init_udelay != UDELAY_10MS_DEFAULT)
+ if (init_udelay != INT_MAX)
return;
/* if modern processor, use no delay */
if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF)))
init_udelay = 0;
+
+ /* else, use legacy delay */
+ init_udelay = UDELAY_10MS_DEFAULT;
}
/*
@@ -657,7 +660,9 @@
/*
* Give the other CPU some time to accept the IPI.
*/
- if (init_udelay)
+ if (init_udelay == 0)
+ udelay(10);
+ else
udelay(300);
pr_debug("Startup point 1\n");
@@ -668,7 +673,9 @@
/*
* Give the other CPU some time to accept the IPI.
*/
- if (init_udelay)
+ if (init_udelay == 0)
+ udelay(10);
+ else
udelay(200);
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b372a75..9da95b9 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2418,7 +2418,7 @@
u64 val, cr0, cr4;
u32 base3;
u16 selector;
- int i;
+ int i, r;
for (i = 0; i < 16; i++)
*reg_write(ctxt, i) = GET_SMSTATE(u64, smbase, 0x7ff8 - i * 8);
@@ -2460,13 +2460,17 @@
dt.address = GET_SMSTATE(u64, smbase, 0x7e68);
ctxt->ops->set_gdt(ctxt, &dt);
+ r = rsm_enter_protected_mode(ctxt, cr0, cr4);
+ if (r != X86EMUL_CONTINUE)
+ return r;
+
for (i = 0; i < 6; i++) {
- int r = rsm_load_seg_64(ctxt, smbase, i);
+ r = rsm_load_seg_64(ctxt, smbase, i);
if (r != X86EMUL_CONTINUE)
return r;
}
- return rsm_enter_protected_mode(ctxt, cr0, cr4);
+ return X86EMUL_CONTINUE;
}
static int em_rsm(struct x86_emulate_ctxt *ctxt)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 06ef490..6a8bc64 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4105,17 +4105,13 @@
static int alloc_apic_access_page(struct kvm *kvm)
{
struct page *page;
- struct kvm_userspace_memory_region kvm_userspace_mem;
int r = 0;
mutex_lock(&kvm->slots_lock);
if (kvm->arch.apic_access_page_done)
goto out;
- kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
- kvm_userspace_mem.flags = 0;
- kvm_userspace_mem.guest_phys_addr = APIC_DEFAULT_PHYS_BASE;
- kvm_userspace_mem.memory_size = PAGE_SIZE;
- r = __x86_set_memory_region(kvm, &kvm_userspace_mem);
+ r = __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
+ APIC_DEFAULT_PHYS_BASE, PAGE_SIZE);
if (r)
goto out;
@@ -4140,17 +4136,12 @@
{
/* Called with kvm->slots_lock held. */
- struct kvm_userspace_memory_region kvm_userspace_mem;
int r = 0;
BUG_ON(kvm->arch.ept_identity_pagetable_done);
- kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
- kvm_userspace_mem.flags = 0;
- kvm_userspace_mem.guest_phys_addr =
- kvm->arch.ept_identity_map_addr;
- kvm_userspace_mem.memory_size = PAGE_SIZE;
- r = __x86_set_memory_region(kvm, &kvm_userspace_mem);
+ r = __x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT,
+ kvm->arch.ept_identity_map_addr, PAGE_SIZE);
return r;
}
@@ -4949,14 +4940,9 @@
static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
{
int ret;
- struct kvm_userspace_memory_region tss_mem = {
- .slot = TSS_PRIVATE_MEMSLOT,
- .guest_phys_addr = addr,
- .memory_size = PAGE_SIZE * 3,
- .flags = 0,
- };
- ret = x86_set_memory_region(kvm, &tss_mem);
+ ret = x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, addr,
+ PAGE_SIZE * 3);
if (ret)
return ret;
kvm->arch.tss_addr = addr;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 92511d4..9a9a198 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6453,6 +6453,12 @@
return 1;
}
+static inline bool kvm_vcpu_running(struct kvm_vcpu *vcpu)
+{
+ return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
+ !vcpu->arch.apf.halted);
+}
+
static int vcpu_run(struct kvm_vcpu *vcpu)
{
int r;
@@ -6461,8 +6467,7 @@
vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
for (;;) {
- if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
- !vcpu->arch.apf.halted)
+ if (kvm_vcpu_running(vcpu))
r = vcpu_enter_guest(vcpu);
else
r = vcpu_block(kvm, vcpu);
@@ -7474,34 +7479,66 @@
kvm_free_pit(kvm);
}
-int __x86_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region *mem)
+int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
{
int i, r;
+ unsigned long hva;
+ struct kvm_memslots *slots = kvm_memslots(kvm);
+ struct kvm_memory_slot *slot, old;
/* Called with kvm->slots_lock held. */
- BUG_ON(mem->slot >= KVM_MEM_SLOTS_NUM);
+ if (WARN_ON(id >= KVM_MEM_SLOTS_NUM))
+ return -EINVAL;
+ slot = id_to_memslot(slots, id);
+ if (size) {
+ if (WARN_ON(slot->npages))
+ return -EEXIST;
+
+ /*
+ * MAP_SHARED to prevent internal slot pages from being moved
+ * by fork()/COW.
+ */
+ hva = vm_mmap(NULL, 0, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, 0);
+ if (IS_ERR((void *)hva))
+ return PTR_ERR((void *)hva);
+ } else {
+ if (!slot->npages)
+ return 0;
+
+ hva = 0;
+ }
+
+ old = *slot;
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
- struct kvm_userspace_memory_region m = *mem;
+ struct kvm_userspace_memory_region m;
- m.slot |= i << 16;
+ m.slot = id | (i << 16);
+ m.flags = 0;
+ m.guest_phys_addr = gpa;
+ m.userspace_addr = hva;
+ m.memory_size = size;
r = __kvm_set_memory_region(kvm, &m);
if (r < 0)
return r;
}
+ if (!size) {
+ r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE);
+ WARN_ON(r < 0);
+ }
+
return 0;
}
EXPORT_SYMBOL_GPL(__x86_set_memory_region);
-int x86_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region *mem)
+int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
{
int r;
mutex_lock(&kvm->slots_lock);
- r = __x86_set_memory_region(kvm, mem);
+ r = __x86_set_memory_region(kvm, id, gpa, size);
mutex_unlock(&kvm->slots_lock);
return r;
@@ -7516,16 +7553,9 @@
* unless the the memory map has changed due to process exit
* or fd copying.
*/
- struct kvm_userspace_memory_region mem;
- memset(&mem, 0, sizeof(mem));
- mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
- x86_set_memory_region(kvm, &mem);
-
- mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
- x86_set_memory_region(kvm, &mem);
-
- mem.slot = TSS_PRIVATE_MEMSLOT;
- x86_set_memory_region(kvm, &mem);
+ x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, 0, 0);
+ x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT, 0, 0);
+ x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, 0, 0);
}
kvm_iommu_unmap_guest(kvm);
kfree(kvm->arch.vpic);
@@ -7628,27 +7658,6 @@
const struct kvm_userspace_memory_region *mem,
enum kvm_mr_change change)
{
- /*
- * Only private memory slots need to be mapped here since
- * KVM_SET_MEMORY_REGION ioctl is no longer supported.
- */
- if ((memslot->id >= KVM_USER_MEM_SLOTS) && (change == KVM_MR_CREATE)) {
- unsigned long userspace_addr;
-
- /*
- * MAP_SHARED to prevent internal slot pages from being moved
- * by fork()/COW.
- */
- userspace_addr = vm_mmap(NULL, 0, memslot->npages * PAGE_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_ANONYMOUS, 0);
-
- if (IS_ERR((void *)userspace_addr))
- return PTR_ERR((void *)userspace_addr);
-
- memslot->userspace_addr = userspace_addr;
- }
-
return 0;
}
@@ -7710,17 +7719,6 @@
{
int nr_mmu_pages = 0;
- if (change == KVM_MR_DELETE && old->id >= KVM_USER_MEM_SLOTS) {
- int ret;
-
- ret = vm_munmap(old->userspace_addr,
- old->npages * PAGE_SIZE);
- if (ret < 0)
- printk(KERN_WARNING
- "kvm_vm_ioctl_set_memory_region: "
- "failed to munmap memory\n");
- }
-
if (!kvm->arch.n_requested_mmu_pages)
nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
@@ -7769,19 +7767,36 @@
kvm_mmu_invalidate_zap_all_pages(kvm);
}
+static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
+{
+ if (!list_empty_careful(&vcpu->async_pf.done))
+ return true;
+
+ if (kvm_apic_has_events(vcpu))
+ return true;
+
+ if (vcpu->arch.pv.pv_unhalted)
+ return true;
+
+ if (atomic_read(&vcpu->arch.nmi_queued))
+ return true;
+
+ if (test_bit(KVM_REQ_SMI, &vcpu->requests))
+ return true;
+
+ if (kvm_arch_interrupt_allowed(vcpu) &&
+ kvm_cpu_has_interrupt(vcpu))
+ return true;
+
+ return false;
+}
+
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events)
kvm_x86_ops->check_nested_events(vcpu, false);
- return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
- !vcpu->arch.apf.halted)
- || !list_empty_careful(&vcpu->async_pf.done)
- || kvm_apic_has_events(vcpu)
- || vcpu->arch.pv.pv_unhalted
- || atomic_read(&vcpu->arch.nmi_queued) ||
- (kvm_arch_interrupt_allowed(vcpu) &&
- kvm_cpu_has_interrupt(vcpu));
+ return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu);
}
int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/um/ldt.c b/arch/x86/um/ldt.c
index 9701a4f..836a1eb 100644
--- a/arch/x86/um/ldt.c
+++ b/arch/x86/um/ldt.c
@@ -12,7 +12,10 @@
#include <skas.h>
#include <sysdep/tls.h>
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
+static inline int modify_ldt (int func, void *ptr, unsigned long bytecount)
+{
+ return syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
static long write_ldt_entry(struct mm_id *mm_idp, int func,
struct user_desc *desc, void **addr, int done)
diff --git a/block/blk-core.c b/block/blk-core.c
index 2eb722d..18e92a6 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -576,7 +576,7 @@
q->queue_lock = &q->__queue_lock;
spin_unlock_irq(lock);
- bdi_destroy(&q->backing_dev_info);
+ bdi_unregister(&q->backing_dev_info);
/* @q is and will stay empty, shutdown and put */
blk_put_queue(q);
diff --git a/block/blk-lib.c b/block/blk-lib.c
index bd40292..9ebf653 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -26,13 +26,6 @@
bio_put(bio);
}
-/*
- * Ensure that max discard sectors doesn't overflow bi_size and hopefully
- * it is of the proper granularity as long as the granularity is a power
- * of two.
- */
-#define MAX_BIO_SECTORS ((1U << 31) >> 9)
-
/**
* blkdev_issue_discard - queue a discard
* @bdev: blockdev to issue discard for
@@ -50,6 +43,8 @@
DECLARE_COMPLETION_ONSTACK(wait);
struct request_queue *q = bdev_get_queue(bdev);
int type = REQ_WRITE | REQ_DISCARD;
+ unsigned int granularity;
+ int alignment;
struct bio_batch bb;
struct bio *bio;
int ret = 0;
@@ -61,6 +56,10 @@
if (!blk_queue_discard(q))
return -EOPNOTSUPP;
+ /* Zero-sector (unknown) and one-sector granularities are the same. */
+ granularity = max(q->limits.discard_granularity >> 9, 1U);
+ alignment = (bdev_discard_alignment(bdev) >> 9) % granularity;
+
if (flags & BLKDEV_DISCARD_SECURE) {
if (!blk_queue_secdiscard(q))
return -EOPNOTSUPP;
@@ -74,7 +73,7 @@
blk_start_plug(&plug);
while (nr_sects) {
unsigned int req_sects;
- sector_t end_sect;
+ sector_t end_sect, tmp;
bio = bio_alloc(gfp_mask, 1);
if (!bio) {
@@ -82,8 +81,22 @@
break;
}
- req_sects = min_t(sector_t, nr_sects, MAX_BIO_SECTORS);
+ /* Make sure bi_size doesn't overflow */
+ req_sects = min_t(sector_t, nr_sects, UINT_MAX >> 9);
+
+ /*
+ * If splitting a request, and the next starting sector would be
+ * misaligned, stop the discard at the previous aligned sector.
+ */
end_sect = sector + req_sects;
+ tmp = end_sect;
+ if (req_sects < nr_sects &&
+ sector_div(tmp, granularity) != alignment) {
+ end_sect = end_sect - alignment;
+ sector_div(end_sect, granularity);
+ end_sect = end_sect * granularity + alignment;
+ req_sects = end_sect - sector;
+ }
bio->bi_iter.bi_sector = sector;
bio->bi_end_io = bio_batch_end_io;
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index ed96474..ec2d119 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -641,6 +641,7 @@
{
bt_free(&tags->bitmap_tags);
bt_free(&tags->breserved_tags);
+ free_cpumask_var(tags->cpumask);
kfree(tags);
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 7785ae9..85f0143 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -2296,10 +2296,8 @@
int i;
for (i = 0; i < set->nr_hw_queues; i++) {
- if (set->tags[i]) {
+ if (set->tags[i])
blk_mq_free_rq_map(set, set->tags[i], i);
- free_cpumask_var(set->tags[i]->cpumask);
- }
}
kfree(set->tags);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 3e44a9d..07b42f5 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -540,6 +540,7 @@
struct request_queue *q =
container_of(kobj, struct request_queue, kobj);
+ bdi_exit(&q->backing_dev_info);
blkcg_exit_queue(q);
if (q->elevator) {
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index b788f16..b4ffc5b 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -706,7 +706,7 @@
err:
if (err != -EAGAIN)
break;
- if (signal_pending(current)) {
+ if (fatal_signal_pending(current)) {
err = -EINTR;
break;
}
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 8acb88603..9c1dc8d 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -544,7 +544,8 @@
struct crypto_alg *base = &alg->halg.base;
if (alg->halg.digestsize > PAGE_SIZE / 8 ||
- alg->halg.statesize > PAGE_SIZE / 8)
+ alg->halg.statesize > PAGE_SIZE / 8 ||
+ alg->halg.statesize == 0)
return -EINVAL;
base->cra_type = &crypto_ahash_type;
diff --git a/crypto/algapi.c b/crypto/algapi.c
index d130b41..59bf491 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -345,7 +345,7 @@
crypto_alg_tested(larval->alg.cra_driver_name, 0);
}
- err = wait_for_completion_interruptible(&larval->completion);
+ err = wait_for_completion_killable(&larval->completion);
WARN_ON(err);
out:
diff --git a/crypto/api.c b/crypto/api.c
index afe4610..bbc147c 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -172,7 +172,7 @@
struct crypto_larval *larval = (void *)alg;
long timeout;
- timeout = wait_for_completion_interruptible_timeout(
+ timeout = wait_for_completion_killable_timeout(
&larval->completion, 60 * HZ);
alg = larval->adult;
@@ -445,7 +445,7 @@
err:
if (err != -EAGAIN)
break;
- if (signal_pending(current)) {
+ if (fatal_signal_pending(current)) {
err = -EINTR;
break;
}
@@ -562,7 +562,7 @@
err:
if (err != -EAGAIN)
break;
- if (signal_pending(current)) {
+ if (fatal_signal_pending(current)) {
err = -EINTR;
break;
}
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index d94d99f..237f379 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -375,7 +375,7 @@
err = PTR_ERR(alg);
if (err != -EAGAIN)
break;
- if (signal_pending(current)) {
+ if (fatal_signal_pending(current)) {
err = -EINTR;
break;
}
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 09f37b5..4dde37c 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -61,6 +61,7 @@
ACPI_INIT_GLOBAL(u32, acpi_gbl_dsdt_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_facs_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_xfacs_index, ACPI_INVALID_TABLE_INDEX);
+ACPI_INIT_GLOBAL(u32, acpi_gbl_fadt_index, ACPI_INVALID_TABLE_INDEX);
#if (!ACPI_REDUCED_HARDWARE)
ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS);
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index f7731f2..591ea95 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -85,7 +85,7 @@
/*
* tbfadt - FADT parse/convert/validate
*/
-void acpi_tb_parse_fadt(u32 table_index);
+void acpi_tb_parse_fadt(void);
void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length);
@@ -138,8 +138,6 @@
*/
acpi_status acpi_tb_initialize_facs(void);
-u8 acpi_tb_tables_loaded(void);
-
void
acpi_tb_print_table_header(acpi_physical_address address,
struct acpi_table_header *header);
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index faad911..10ce48e 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -71,7 +71,7 @@
/* ACPI tables must be present */
- if (!acpi_tb_tables_loaded()) {
+ if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) {
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 455a070..a6454f4 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -298,7 +298,7 @@
*
* FUNCTION: acpi_tb_parse_fadt
*
- * PARAMETERS: table_index - Index for the FADT
+ * PARAMETERS: None
*
* RETURN: None
*
@@ -307,7 +307,7 @@
*
******************************************************************************/
-void acpi_tb_parse_fadt(u32 table_index)
+void acpi_tb_parse_fadt(void)
{
u32 length;
struct acpi_table_header *table;
@@ -319,11 +319,11 @@
* Get a local copy of the FADT and convert it to a common format
* Map entire FADT, assumed to be smaller than one page.
*/
- length = acpi_gbl_root_table_list.tables[table_index].length;
+ length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length;
table =
- acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index].
- address, length);
+ acpi_os_map_memory(acpi_gbl_root_table_list.
+ tables[acpi_gbl_fadt_index].address, length);
if (!table) {
return;
}
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 4337990..d8ddef3 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -99,29 +99,6 @@
/*******************************************************************************
*
- * FUNCTION: acpi_tb_tables_loaded
- *
- * PARAMETERS: None
- *
- * RETURN: TRUE if required ACPI tables are loaded
- *
- * DESCRIPTION: Determine if the minimum required ACPI tables are present
- * (FADT, FACS, DSDT)
- *
- ******************************************************************************/
-
-u8 acpi_tb_tables_loaded(void)
-{
-
- if (acpi_gbl_root_table_list.current_table_count >= 4) {
- return (TRUE);
- }
-
- return (FALSE);
-}
-
-/*******************************************************************************
- *
* FUNCTION: acpi_tb_check_dsdt_header
*
* PARAMETERS: None
@@ -392,7 +369,8 @@
ACPI_COMPARE_NAME(&acpi_gbl_root_table_list.
tables[table_index].signature,
ACPI_SIG_FADT)) {
- acpi_tb_parse_fadt(table_index);
+ acpi_gbl_fadt_index = table_index;
+ acpi_tb_parse_fadt();
}
next_table:
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 950fff9..a12ff98 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -187,7 +187,7 @@
* global one. Requires architecture specific dev_get_cma_area() helper
* function.
*/
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
unsigned int align)
{
if (align > CONFIG_CMA_ALIGNMENT)
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 2a4154a..85e17ba 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -77,13 +77,16 @@
dev_update_qos_constraint);
if (constraint_ns > 0) {
- constraint_ns -= td->start_latency_ns;
+ constraint_ns -= td->save_state_latency_ns +
+ td->stop_latency_ns +
+ td->start_latency_ns +
+ td->restore_state_latency_ns;
if (constraint_ns == 0)
return false;
}
td->effective_constraint_ns = constraint_ns;
- td->cached_stop_ok = constraint_ns > td->stop_latency_ns ||
- constraint_ns == 0;
+ td->cached_stop_ok = constraint_ns >= 0;
+
/*
* The children have been suspended already, so we don't need to take
* their stop latencies into account here.
@@ -126,18 +129,6 @@
off_on_time_ns = genpd->power_off_latency_ns +
genpd->power_on_latency_ns;
- /*
- * It doesn't make sense to remove power from the domain if saving
- * the state of all devices in it and the power off/power on operations
- * take too much time.
- *
- * All devices in this domain have been stopped already at this point.
- */
- list_for_each_entry(pdd, &genpd->dev_list, list_node) {
- if (pdd->dev->driver)
- off_on_time_ns +=
- to_gpd_data(pdd)->td.save_state_latency_ns;
- }
min_off_time_ns = -1;
/*
@@ -193,7 +184,6 @@
* constraint_ns cannot be negative here, because the device has
* been suspended.
*/
- constraint_ns -= td->restore_state_latency_ns;
if (constraint_ns <= off_on_time_ns)
return false;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 293495a..1b87623 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -60,6 +60,7 @@
bool disconnect; /* a disconnect has been requested by user */
struct timer_list timeout_timer;
+ spinlock_t tasks_lock;
struct task_struct *task_recv;
struct task_struct *task_send;
@@ -140,21 +141,23 @@
static void nbd_xmit_timeout(unsigned long arg)
{
struct nbd_device *nbd = (struct nbd_device *)arg;
- struct task_struct *task;
+ unsigned long flags;
if (list_empty(&nbd->queue_head))
return;
nbd->disconnect = true;
- task = READ_ONCE(nbd->task_recv);
- if (task)
- force_sig(SIGKILL, task);
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
- task = READ_ONCE(nbd->task_send);
- if (task)
+ if (nbd->task_recv)
+ force_sig(SIGKILL, nbd->task_recv);
+
+ if (nbd->task_send)
force_sig(SIGKILL, nbd->task_send);
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
}
@@ -403,17 +406,24 @@
{
struct request *req;
int ret;
+ unsigned long flags;
BUG_ON(nbd->magic != NBD_MAGIC);
sk_set_memalloc(nbd->sock->sk);
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_recv = current;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
if (ret) {
dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
+
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_recv = NULL;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
return ret;
}
@@ -429,7 +439,9 @@
device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_recv = NULL;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
if (signal_pending(current)) {
siginfo_t info;
@@ -534,8 +546,11 @@
{
struct nbd_device *nbd = data;
struct request *req;
+ unsigned long flags;
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_send = current;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
set_user_nice(current, MIN_NICE);
while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
@@ -572,7 +587,15 @@
nbd_handle_req(nbd, req);
}
+ spin_lock_irqsave(&nbd->tasks_lock, flags);
nbd->task_send = NULL;
+ spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
+ /* Clear maybe pending signals */
+ if (signal_pending(current)) {
+ siginfo_t info;
+ dequeue_signal_lock(current, ¤t->blocked, &info);
+ }
return 0;
}
@@ -1052,6 +1075,7 @@
nbd_dev[i].magic = NBD_MAGIC;
INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
spin_lock_init(&nbd_dev[i].queue_lock);
+ spin_lock_init(&nbd_dev[i].tasks_lock);
INIT_LIST_HEAD(&nbd_dev[i].queue_head);
mutex_init(&nbd_dev[i].tx_lock);
init_timer(&nbd_dev[i].timeout_timer);
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 6f04771..ccc0c1f 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -603,27 +603,31 @@
struct nvme_iod *iod = ctx;
struct request *req = iod_get_private(iod);
struct nvme_cmd_info *cmd_rq = blk_mq_rq_to_pdu(req);
-
u16 status = le16_to_cpup(&cqe->status) >> 1;
+ bool requeue = false;
+ int error = 0;
if (unlikely(status)) {
if (!(status & NVME_SC_DNR || blk_noretry_request(req))
&& (jiffies - req->start_time) < req->timeout) {
unsigned long flags;
+ requeue = true;
blk_mq_requeue_request(req);
spin_lock_irqsave(req->q->queue_lock, flags);
if (!blk_queue_stopped(req->q))
blk_mq_kick_requeue_list(req->q);
spin_unlock_irqrestore(req->q->queue_lock, flags);
- return;
+ goto release_iod;
}
if (req->cmd_type == REQ_TYPE_DRV_PRIV) {
if (cmd_rq->ctx == CMD_CTX_CANCELLED)
- status = -EINTR;
+ error = -EINTR;
+ else
+ error = status;
} else {
- status = nvme_error_status(status);
+ error = nvme_error_status(status);
}
}
@@ -635,8 +639,9 @@
if (cmd_rq->aborted)
dev_warn(nvmeq->dev->dev,
"completing aborted command with status:%04x\n",
- status);
+ error);
+release_iod:
if (iod->nents) {
dma_unmap_sg(nvmeq->dev->dev, iod->sg, iod->nents,
rq_data_dir(req) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
@@ -649,7 +654,8 @@
}
nvme_free_iod(nvmeq->dev, iod);
- blk_mq_complete_request(req, status);
+ if (likely(!requeue))
+ blk_mq_complete_request(req, error);
}
/* length is in bytes. gfp flags indicates whether we may sleep. */
@@ -1804,7 +1810,7 @@
length = (io.nblocks + 1) << ns->lba_shift;
meta_len = (io.nblocks + 1) * ns->ms;
- metadata = (void __user *)(unsigned long)io.metadata;
+ metadata = (void __user *)(uintptr_t)io.metadata;
write = io.opcode & 1;
if (ns->ext) {
@@ -1844,7 +1850,7 @@
c.rw.metadata = cpu_to_le64(meta_dma);
status = __nvme_submit_sync_cmd(ns->queue, &c, NULL,
- (void __user *)io.addr, length, NULL, 0);
+ (void __user *)(uintptr_t)io.addr, length, NULL, 0);
unmap:
if (meta) {
if (status == NVME_SC_SUCCESS && !write) {
@@ -1886,7 +1892,7 @@
timeout = msecs_to_jiffies(cmd.timeout_ms);
status = __nvme_submit_sync_cmd(ns ? ns->queue : dev->admin_q, &c,
- NULL, (void __user *)cmd.addr, cmd.data_len,
+ NULL, (void __user *)(uintptr_t)cmd.addr, cmd.data_len,
&cmd.result, timeout);
if (status >= 0) {
if (put_user(cmd.result, &ucmd->result))
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index d93a037..128e7df 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -96,6 +96,8 @@
#define RBD_MINORS_PER_MAJOR 256
#define RBD_SINGLE_MAJOR_PART_SHIFT 4
+#define RBD_MAX_PARENT_CHAIN_LEN 16
+
#define RBD_SNAP_DEV_NAME_PREFIX "snap_"
#define RBD_MAX_SNAP_NAME_LEN \
(NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1))
@@ -426,7 +428,7 @@
size_t count);
static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf,
size_t count);
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth);
static void rbd_spec_put(struct rbd_spec *spec);
static int rbd_dev_id_to_minor(int dev_id)
@@ -1863,9 +1865,11 @@
rbd_osd_read_callback(obj_request);
break;
case CEPH_OSD_OP_SETALLOCHINT:
- rbd_assert(osd_req->r_ops[1].op == CEPH_OSD_OP_WRITE);
+ rbd_assert(osd_req->r_ops[1].op == CEPH_OSD_OP_WRITE ||
+ osd_req->r_ops[1].op == CEPH_OSD_OP_WRITEFULL);
/* fall through */
case CEPH_OSD_OP_WRITE:
+ case CEPH_OSD_OP_WRITEFULL:
rbd_osd_write_callback(obj_request);
break;
case CEPH_OSD_OP_STAT:
@@ -2401,7 +2405,10 @@
opcode = CEPH_OSD_OP_ZERO;
}
} else if (op_type == OBJ_OP_WRITE) {
- opcode = CEPH_OSD_OP_WRITE;
+ if (!offset && length == object_size)
+ opcode = CEPH_OSD_OP_WRITEFULL;
+ else
+ opcode = CEPH_OSD_OP_WRITE;
osd_req_op_alloc_hint_init(osd_request, num_ops,
object_size, object_size);
num_ops++;
@@ -3760,6 +3767,7 @@
/* set io sizes to object size */
segment_size = rbd_obj_bytes(&rbd_dev->header);
blk_queue_max_hw_sectors(q, segment_size / SECTOR_SIZE);
+ q->limits.max_sectors = queue_max_hw_sectors(q);
blk_queue_max_segments(q, segment_size / SECTOR_SIZE);
blk_queue_max_segment_size(q, segment_size);
blk_queue_io_min(q, segment_size);
@@ -3772,6 +3780,9 @@
blk_queue_max_discard_sectors(q, segment_size / SECTOR_SIZE);
q->limits.discard_zeroes_data = 1;
+ if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
+ q->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
+
disk->queue = q;
q->queuedata = rbd_dev;
@@ -5125,44 +5136,51 @@
return ret;
}
-static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)
+/*
+ * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() ->
+ * rbd_dev_image_probe() recursion depth, which means it's also the
+ * length of the already discovered part of the parent chain.
+ */
+static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth)
{
struct rbd_device *parent = NULL;
- struct rbd_spec *parent_spec;
- struct rbd_client *rbdc;
int ret;
if (!rbd_dev->parent_spec)
return 0;
- /*
- * We need to pass a reference to the client and the parent
- * spec when creating the parent rbd_dev. Images related by
- * parent/child relationships always share both.
- */
- parent_spec = rbd_spec_get(rbd_dev->parent_spec);
- rbdc = __rbd_get_client(rbd_dev->rbd_client);
- ret = -ENOMEM;
- parent = rbd_dev_create(rbdc, parent_spec, NULL);
- if (!parent)
+ if (++depth > RBD_MAX_PARENT_CHAIN_LEN) {
+ pr_info("parent chain is too long (%d)\n", depth);
+ ret = -EINVAL;
goto out_err;
-
- ret = rbd_dev_image_probe(parent, false);
- if (ret < 0)
- goto out_err;
- rbd_dev->parent = parent;
- atomic_set(&rbd_dev->parent_ref, 1);
-
- return 0;
-out_err:
- if (parent) {
- rbd_dev_unparent(rbd_dev);
- rbd_dev_destroy(parent);
- } else {
- rbd_put_client(rbdc);
- rbd_spec_put(parent_spec);
}
+ parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec,
+ NULL);
+ if (!parent) {
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ /*
+ * Images related by parent/child relationships always share
+ * rbd_client and spec/parent_spec, so bump their refcounts.
+ */
+ __rbd_get_client(rbd_dev->rbd_client);
+ rbd_spec_get(rbd_dev->parent_spec);
+
+ ret = rbd_dev_image_probe(parent, depth);
+ if (ret < 0)
+ goto out_err;
+
+ rbd_dev->parent = parent;
+ atomic_set(&rbd_dev->parent_ref, 1);
+ return 0;
+
+out_err:
+ rbd_dev_unparent(rbd_dev);
+ if (parent)
+ rbd_dev_destroy(parent);
return ret;
}
@@ -5280,7 +5298,7 @@
* parent), initiate a watch on its header object before using that
* object to get detailed information about the rbd image.
*/
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
{
int ret;
@@ -5298,7 +5316,7 @@
if (ret)
goto err_out_format;
- if (mapping) {
+ if (!depth) {
ret = rbd_dev_header_watch_sync(rbd_dev);
if (ret) {
if (ret == -ENOENT)
@@ -5319,7 +5337,7 @@
* Otherwise this is a parent image, identified by pool, image
* and snap ids - need to fill in names for those ids.
*/
- if (mapping)
+ if (!depth)
ret = rbd_spec_fill_snap_id(rbd_dev);
else
ret = rbd_spec_fill_names(rbd_dev);
@@ -5341,12 +5359,12 @@
* Need to warn users if this image is the one being
* mapped and has a parent.
*/
- if (mapping && rbd_dev->parent_spec)
+ if (!depth && rbd_dev->parent_spec)
rbd_warn(rbd_dev,
"WARNING: kernel layering is EXPERIMENTAL!");
}
- ret = rbd_dev_probe_parent(rbd_dev);
+ ret = rbd_dev_probe_parent(rbd_dev, depth);
if (ret)
goto err_out_probe;
@@ -5357,7 +5375,7 @@
err_out_probe:
rbd_dev_unprobe(rbd_dev);
err_out_watch:
- if (mapping)
+ if (!depth)
rbd_dev_header_unwatch_sync(rbd_dev);
out_header_name:
kfree(rbd_dev->header_name);
@@ -5420,7 +5438,7 @@
spec = NULL; /* rbd_dev now owns this */
rbd_opts = NULL; /* rbd_dev now owns this */
- rc = rbd_dev_image_probe(rbd_dev, true);
+ rc = rbd_dev_image_probe(rbd_dev, 0);
if (rc < 0)
goto err_out_rbd_dev;
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 6111708..a69c02d 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -1956,7 +1956,8 @@
break;
/* Missed the backend's Closing state -- fallthrough */
case XenbusStateClosing:
- blkfront_closing(info);
+ if (info)
+ blkfront_closing(info);
break;
}
}
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
index 7d9879e..7082c72 100644
--- a/drivers/bus/arm-ccn.c
+++ b/drivers/bus/arm-ccn.c
@@ -1184,11 +1184,12 @@
if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu))
break;
target = cpumask_any_but(cpu_online_mask, cpu);
- if (target < 0)
+ if (target >= nr_cpu_ids)
break;
perf_pmu_migrate_context(&dt->pmu, cpu, target);
cpumask_set_cpu(target, &dt->cpu);
- WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
+ if (ccn->irq)
+ WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
default:
break;
}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index c0eaf09..779b6ff 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -333,7 +333,8 @@
if (IS_ERR(r))
return PTR_ERR(r);
- l = clkdev_create(r, alias, "%s", alias_dev_name);
+ l = clkdev_create(r, alias, alias_dev_name ? "%s" : NULL,
+ alias_dev_name);
clk_put(r);
return l ? 0 : -ENODEV;
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index 5837eb8..85da8b9 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -197,6 +197,7 @@
for_each_node_by_type(dn, "cpu") {
struct clk_init_data init;
struct clk *clk;
+ struct clk *parent_clk;
char *clk_name = kzalloc(5, GFP_KERNEL);
int cpu, err;
@@ -208,8 +209,9 @@
goto bail_out;
sprintf(clk_name, "cpu%d", cpu);
+ parent_clk = of_clk_get(node, 0);
- cpuclk[cpu].parent_name = of_clk_get_parent_name(node, 0);
+ cpuclk[cpu].parent_name = __clk_get_name(parent_clk);
cpuclk[cpu].clk_name = clk_name;
cpuclk[cpu].cpu = cpu;
cpuclk[cpu].reg_base = clock_complex_base;
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index 29ea50a..a2cb6fa 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -60,7 +60,7 @@
* different to the 32-bit upper value read previously, go back to step 2.
* Otherwise the 64-bit timer counter value is correct.
*/
-static u64 gt_counter_read(void)
+static u64 notrace _gt_counter_read(void)
{
u64 counter;
u32 lower;
@@ -79,6 +79,11 @@
return counter;
}
+static u64 gt_counter_read(void)
+{
+ return _gt_counter_read();
+}
+
/**
* To ensure that updates to comparator value register do not set the
* Interrupt Status Register proceed as follows:
@@ -201,7 +206,7 @@
#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
static u64 notrace gt_sched_clock_read(void)
{
- return gt_counter_read();
+ return _gt_counter_read();
}
#endif
diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c
index ef43469..10202f1 100644
--- a/drivers/clocksource/fsl_ftm_timer.c
+++ b/drivers/clocksource/fsl_ftm_timer.c
@@ -118,7 +118,7 @@
ftm_writel(0x00, base + FTM_CNT);
}
-static u64 ftm_read_sched_clock(void)
+static u64 notrace ftm_read_sched_clock(void)
{
return ftm_readl(priv->clksrc_base + FTM_CNT);
}
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c
index bc90e13..9502bc4 100644
--- a/drivers/clocksource/samsung_pwm_timer.c
+++ b/drivers/clocksource/samsung_pwm_timer.c
@@ -307,7 +307,7 @@
samsung_time_start(pwm.source_id, true);
}
-static cycle_t samsung_clocksource_read(struct clocksource *c)
+static cycle_t notrace samsung_clocksource_read(struct clocksource *c)
{
return ~readl_relaxed(pwm.source_reg);
}
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index f1985da..53aa7e9 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -280,7 +280,9 @@
{
struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced);
- sh_mtu2_disable(ch);
+ if (clockevent_state_periodic(ced))
+ sh_mtu2_disable(ch);
+
return 0;
}
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c
index 18d4266..bba6799 100644
--- a/drivers/clocksource/time-pistachio.c
+++ b/drivers/clocksource/time-pistachio.c
@@ -67,7 +67,8 @@
writel(value, base + 0x20 * gpt_id + offset);
}
-static cycle_t pistachio_clocksource_read_cycles(struct clocksource *cs)
+static cycle_t notrace
+pistachio_clocksource_read_cycles(struct clocksource *cs)
{
struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
u32 counter, overflw;
diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c
index e73947f0f..a536eeb 100644
--- a/drivers/clocksource/timer-digicolor.c
+++ b/drivers/clocksource/timer-digicolor.c
@@ -143,7 +143,7 @@
return IRQ_HANDLED;
}
-static u64 digicolor_timer_sched_read(void)
+static u64 notrace digicolor_timer_sched_read(void)
{
return ~readl(dc_timer_dev.base + COUNT(TIMER_B));
}
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c
index 78de982..2854c66 100644
--- a/drivers/clocksource/timer-prima2.c
+++ b/drivers/clocksource/timer-prima2.c
@@ -73,7 +73,7 @@
}
/* read 64-bit timer counter */
-static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+static cycle_t notrace sirfsoc_timer_read(struct clocksource *cs)
{
u64 cycles;
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c
index f07ba99..a0e6c68 100644
--- a/drivers/clocksource/vf_pit_timer.c
+++ b/drivers/clocksource/vf_pit_timer.c
@@ -52,7 +52,7 @@
__raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
}
-static u64 pit_read_sched_clock(void)
+static u64 notrace pit_read_sched_clock(void)
{
return ~__raw_readl(clksrc_base + PITCVAL);
}
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 3af9dd7..aa33b92 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -776,6 +776,11 @@
local_irq_save(flags);
rdmsrl(MSR_IA32_APERF, aperf);
rdmsrl(MSR_IA32_MPERF, mperf);
+ if (cpu->prev_mperf == mperf) {
+ local_irq_restore(flags);
+ return;
+ }
+
tsc = rdtsc();
local_irq_restore(flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 6647fb2..0d13e63 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1654,6 +1654,7 @@
u8 fan_max_rpm;
/* dpm */
bool dpm_enabled;
+ bool sysfs_initialized;
struct amdgpu_dpm dpm;
const struct firmware *fw; /* SMC firmware */
uint32_t fw_version;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 77f1d7c..9416e0f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -672,8 +672,12 @@
/* disp clock */
adev->clock.default_dispclk =
le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
- if (adev->clock.default_dispclk == 0)
- adev->clock.default_dispclk = 54000; /* 540 Mhz */
+ /* set a reasonable default for DP */
+ if (adev->clock.default_dispclk < 53900) {
+ DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n",
+ adev->clock.default_dispclk / 100);
+ adev->clock.default_dispclk = 60000;
+ }
adev->clock.dp_extclk =
le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
adev->clock.current_dispclk = adev->clock.default_dispclk;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index cb3c274..fd16652 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -177,7 +177,7 @@
/* get chunks */
INIT_LIST_HEAD(&p->validated);
- chunk_array_user = (uint64_t __user *)(cs->in.chunks);
+ chunk_array_user = (uint64_t __user *)(unsigned long)(cs->in.chunks);
if (copy_from_user(chunk_array, chunk_array_user,
sizeof(uint64_t)*cs->in.num_chunks)) {
ret = -EFAULT;
@@ -197,7 +197,7 @@
struct drm_amdgpu_cs_chunk user_chunk;
uint32_t __user *cdata;
- chunk_ptr = (void __user *)chunk_array[i];
+ chunk_ptr = (void __user *)(unsigned long)chunk_array[i];
if (copy_from_user(&user_chunk, chunk_ptr,
sizeof(struct drm_amdgpu_cs_chunk))) {
ret = -EFAULT;
@@ -208,7 +208,7 @@
p->chunks[i].length_dw = user_chunk.length_dw;
size = p->chunks[i].length_dw;
- cdata = (void __user *)user_chunk.chunk_data;
+ cdata = (void __user *)(unsigned long)user_chunk.chunk_data;
p->chunks[i].user_ptr = cdata;
p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t));
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index e3d7077..6c9e090 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -85,8 +85,6 @@
/* We borrow the event spin lock for protecting flip_status */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
- /* set the proper interrupt */
- amdgpu_irq_get(adev, &adev->pageflip_irq, work->crtc_id);
/* do the flip (mmio) */
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
/* set the flip status */
@@ -186,10 +184,6 @@
goto cleanup;
}
- fence_get(work->excl);
- for (i = 0; i < work->shared_count; ++i)
- fence_get(work->shared[i]);
-
amdgpu_bo_get_tiling_flags(new_rbo, &tiling_flags);
amdgpu_bo_unreserve(new_rbo);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index adb4835..b190c2a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -242,11 +242,11 @@
{0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
#endif
/* topaz */
- {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
- {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
- {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
- {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
- {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
+ {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+ {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+ {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+ {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+ {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
/* tonga */
{0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 8a122b1..96290d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -402,3 +402,19 @@
return true;
return false;
}
+
+void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev)
+{
+ struct amdgpu_fbdev *afbdev = adev->mode_info.rfbdev;
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ if (!afbdev)
+ return;
+
+ fb_helper = &afbdev->helper;
+
+ ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+ if (ret)
+ DRM_DEBUG("failed to restore crtc mode\n");
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 8c735f5..5d11e79 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -485,7 +485,7 @@
* Outdated mess for old drm with Xorg being in charge (void function now).
*/
/**
- * amdgpu_driver_firstopen_kms - drm callback for last close
+ * amdgpu_driver_lastclose_kms - drm callback for last close
*
* @dev: drm dev pointer
*
@@ -493,6 +493,9 @@
*/
void amdgpu_driver_lastclose_kms(struct drm_device *dev)
{
+ struct amdgpu_device *adev = dev->dev_private;
+
+ amdgpu_fbdev_restore_mode(adev);
vga_switcheroo_process_delayed_switch();
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 64efe5b..7bd470d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -567,6 +567,7 @@
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state);
int amdgpu_fbdev_total_size(struct amdgpu_device *adev);
bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj);
+void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev);
void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index efed115..22a8c7d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -294,10 +294,14 @@
struct amdgpu_device *adev = dev_get_drvdata(dev);
umode_t effective_mode = attr->mode;
- /* Skip limit attributes if DPM is not enabled */
+ /* Skip attributes if DPM is not enabled */
if (!adev->pm.dpm_enabled &&
(attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
- attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+ attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
return 0;
/* Skip fan attributes if fan is not present */
@@ -691,6 +695,9 @@
{
int ret;
+ if (adev->pm.sysfs_initialized)
+ return 0;
+
if (adev->pm.funcs->get_temperature == NULL)
return 0;
adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev,
@@ -719,6 +726,8 @@
return ret;
}
+ adev->pm.sysfs_initialized = true;
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 1e14531..53d551f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -455,8 +455,10 @@
return -ENOMEM;
r = amdgpu_ib_get(ring, NULL, ndw * 4, ib);
- if (r)
+ if (r) {
+ kfree(ib);
return r;
+ }
ib->length_dw = 0;
/* walk over the address space and update the page directory */
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index 82e8d07..a1a35a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -6185,6 +6185,11 @@
if (!amdgpu_dpm)
return 0;
+ /* init the sysfs and debugfs files late */
+ ret = amdgpu_pm_sysfs_init(adev);
+ if (ret)
+ return ret;
+
ret = ci_set_temperature_range(adev);
if (ret)
return ret;
@@ -6232,9 +6237,6 @@
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);
- ret = amdgpu_pm_sysfs_init(adev);
- if (ret)
- goto dpm_failed;
mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 4b6ce74..484710c 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1567,6 +1567,9 @@
int ret, i;
u16 tmp16;
+ if (pci_is_root_bus(adev->pdev->bus))
+ return;
+
if (amdgpu_pcie_gen2 == 0)
return;
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
index 44fa96a..2e3373e 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -596,6 +596,12 @@
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (amdgpu_dpm) {
+ int ret;
+ /* init the sysfs and debugfs files late */
+ ret = amdgpu_pm_sysfs_init(adev);
+ if (ret)
+ return ret;
+
/* powerdown unused blocks for now */
cz_dpm_powergate_uvd(adev, true);
cz_dpm_powergate_vce(adev, true);
@@ -632,10 +638,6 @@
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);
- ret = amdgpu_pm_sysfs_init(adev);
- if (ret)
- goto dpm_init_failed;
-
mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index e4d101b..d4c82b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -255,6 +255,24 @@
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
}
+static void dce_v10_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Enable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v10_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Disable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
/**
* dce_v10_0_page_flip - pageflip callback.
*
@@ -2663,9 +2681,10 @@
dce_v10_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v10_0_vga_enable(crtc, false);
- /* Make sure VBLANK interrupt is still enabled */
+ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
+ amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v10_0_crtc_load_lut(crtc);
break;
@@ -3025,6 +3044,8 @@
dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v10_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -3039,6 +3060,8 @@
dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v10_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -3050,6 +3073,8 @@
dce_v10_0_hpd_fini(adev);
+ dce_v10_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -3075,6 +3100,8 @@
/* initialize hpd */
dce_v10_0_hpd_init(adev);
+ dce_v10_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -3369,7 +3396,6 @@
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
- amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 6411e82..7e1cf5e 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -233,6 +233,24 @@
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
}
+static void dce_v11_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Enable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v11_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Disable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
/**
* dce_v11_0_page_flip - pageflip callback.
*
@@ -2640,9 +2658,10 @@
dce_v11_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v11_0_vga_enable(crtc, false);
- /* Make sure VBLANK interrupt is still enabled */
+ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
+ amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v11_0_crtc_load_lut(crtc);
break;
@@ -2888,7 +2907,7 @@
switch (adev->asic_type) {
case CHIP_CARRIZO:
- adev->mode_info.num_crtc = 4;
+ adev->mode_info.num_crtc = 3;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 9;
break;
@@ -3000,6 +3019,8 @@
dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v11_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -3014,6 +3035,8 @@
dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v11_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -3025,6 +3048,8 @@
dce_v11_0_hpd_fini(adev);
+ dce_v11_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -3051,6 +3076,8 @@
/* initialize hpd */
dce_v11_0_hpd_init(adev);
+ dce_v11_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -3345,7 +3372,6 @@
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
- amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index c86911c..34b9c2a 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -204,6 +204,24 @@
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
}
+static void dce_v8_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Enable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v8_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+ unsigned i;
+
+ /* Disable pflip interrupts */
+ for (i = 0; i < adev->mode_info.num_crtc; i++)
+ amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
/**
* dce_v8_0_page_flip - pageflip callback.
*
@@ -2575,9 +2593,10 @@
dce_v8_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v8_0_vga_enable(crtc, false);
- /* Make sure VBLANK interrupt is still enabled */
+ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
+ amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v8_0_crtc_load_lut(crtc);
break;
@@ -2933,6 +2952,8 @@
dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v8_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -2947,6 +2968,8 @@
dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
+ dce_v8_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -2958,6 +2981,8 @@
dce_v8_0_hpd_fini(adev);
+ dce_v8_0_pageflip_interrupt_fini(adev);
+
return 0;
}
@@ -2981,6 +3006,8 @@
/* initialize hpd */
dce_v8_0_hpd_init(adev);
+ dce_v8_0_pageflip_interrupt_init(adev);
+
return 0;
}
@@ -3376,7 +3403,6 @@
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
- amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
index 94ec04a..7e9154c 100644
--- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
@@ -2995,6 +2995,15 @@
{
/* powerdown unused blocks for now */
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ if (!amdgpu_dpm)
+ return 0;
+
+ /* init the sysfs and debugfs files late */
+ ret = amdgpu_pm_sysfs_init(adev);
+ if (ret)
+ return ret;
kv_dpm_powergate_acp(adev, true);
kv_dpm_powergate_samu(adev, true);
@@ -3038,9 +3047,6 @@
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);
- ret = amdgpu_pm_sysfs_init(adev);
- if (ret)
- goto dpm_failed;
mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index b55ceb1..0bac870 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -1005,6 +1005,9 @@
u32 mask;
int ret;
+ if (pci_is_root_bus(adev->pdev->bus))
+ return;
+
if (amdgpu_pcie_gen2 == 0)
return;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 33d877c..8328e70 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4105,7 +4105,7 @@
struct drm_property_blob *blob;
int ret;
- if (!length)
+ if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
return ERR_PTR(-EINVAL);
blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
@@ -4454,7 +4454,7 @@
* not associated with any file_priv. */
mutex_lock(&dev->mode_config.blob_lock);
out_resp->blob_id = blob->base.id;
- list_add_tail(&file_priv->blobs, &blob->head_file);
+ list_add_tail(&blob->head_file, &file_priv->blobs);
mutex_unlock(&dev->mode_config.blob_lock);
return 0;
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index bf27a07..809959d 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1194,17 +1194,18 @@
list_for_each_entry(port, &mstb->ports, next) {
if (port->port_num == port_num) {
- if (!port->mstb) {
+ mstb = port->mstb;
+ if (!mstb) {
DRM_ERROR("failed to lookup MSTB with lct %d, rad %02x\n", lct, rad[0]);
- return NULL;
+ goto out;
}
- mstb = port->mstb;
break;
}
}
}
kref_get(&mstb->kref);
+out:
mutex_unlock(&mgr->lock);
return mstb;
}
@@ -2801,12 +2802,13 @@
if (msgs[num - 1].flags & I2C_M_RD)
reading = true;
- if (!reading) {
+ if (!reading || (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)) {
DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n");
ret = -EIO;
goto out;
}
+ memset(&msg, 0, sizeof(msg));
msg.req_type = DP_REMOTE_I2C_READ;
msg.u.i2c_read.num_transactions = num - 1;
msg.u.i2c_read.port_number = port->port_num;
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 0f6cd33..684bd4a 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -235,18 +235,12 @@
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
- struct drm_device *dev = connector->dev;
- uint64_t dpms_status;
- int ret;
+ int dpms;
- ret = drm_object_property_get_value(&connector->base,
- dev->mode_config.dpms_property,
- &dpms_status);
- if (ret)
- return 0;
+ dpms = READ_ONCE(connector->dpms);
return snprintf(buf, PAGE_SIZE, "%s\n",
- drm_get_dpms_name((int)dpms_status));
+ drm_get_dpms_name(dpms));
}
static ssize_t enabled_show(struct device *device,
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index f6ecbda..6743417 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -143,7 +143,7 @@
}
/**
- * i915_gem_shrink - Shrink buffer object caches completely
+ * i915_gem_shrink_all - Shrink buffer object caches completely
* @dev_priv: i915 device
*
* This is a simple wraper around i915_gem_shrink() to aggressively shrink all
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
index 8fd431b..a96b900 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -804,7 +804,10 @@
* Also note, that the object created here is not currently a "first class"
* object, in that several ioctls are banned. These are the CPU access
* ioctls: mmap(), pwrite and pread. In practice, you are expected to use
- * direct access via your pointer rather than use those ioctls.
+ * direct access via your pointer rather than use those ioctls. Another
+ * restriction is that we do not allow userptr surfaces to be pinned to the
+ * hardware and so we reject any attempt to create a framebuffer out of a
+ * userptr.
*
* If you think this is a good interface to use to pass GPU memory between
* drivers, please use dma-buf instead. In fact, wherever possible use
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cf418be..b2270d5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1724,6 +1724,15 @@
I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE);
}
+ /*
+ * Apparently we need to have VGA mode enabled prior to changing
+ * the P1/P2 dividers. Otherwise the DPLL will keep using the old
+ * dividers, even though the register value does change.
+ */
+ I915_WRITE(reg, 0);
+
+ I915_WRITE(reg, dpll);
+
/* Wait for the clocks to stabilize. */
POSTING_READ(reg);
udelay(150);
@@ -14107,6 +14116,11 @@
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
struct drm_i915_gem_object *obj = intel_fb->obj;
+ if (obj->userptr.mm) {
+ DRM_DEBUG("attempting to use a userptr for a framebuffer, denied\n");
+ return -EINVAL;
+ }
+
return drm_gem_handle_create(file, &obj->base, handle);
}
@@ -14897,9 +14911,19 @@
/* restore vblank interrupts to correct state */
drm_crtc_vblank_reset(&crtc->base);
if (crtc->active) {
+ struct intel_plane *plane;
+
drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
update_scanline_offset(crtc);
drm_crtc_vblank_on(&crtc->base);
+
+ /* Disable everything but the primary plane */
+ for_each_intel_plane_on_crtc(dev, crtc, plane) {
+ if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
+ continue;
+
+ plane->disable_plane(&plane->base, &crtc->base);
+ }
}
/* We need to sanitize the plane -> pipe mapping first because this will
@@ -15067,38 +15091,25 @@
i915_redisable_vga_power_on(dev);
}
-static bool primary_get_hw_state(struct intel_crtc *crtc)
+static bool primary_get_hw_state(struct intel_plane *plane)
{
- struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+ struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
- return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE);
+ return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE;
}
-static void readout_plane_state(struct intel_crtc *crtc,
- struct intel_crtc_state *crtc_state)
+/* FIXME read out full plane state for all planes */
+static void readout_plane_state(struct intel_crtc *crtc)
{
- struct intel_plane *p;
- struct intel_plane_state *plane_state;
- bool active = crtc_state->base.active;
+ struct drm_plane *primary = crtc->base.primary;
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(primary->state);
- for_each_intel_plane(crtc->base.dev, p) {
- if (crtc->pipe != p->pipe)
- continue;
+ plane_state->visible =
+ primary_get_hw_state(to_intel_plane(primary));
- plane_state = to_intel_plane_state(p->base.state);
-
- if (p->base.type == DRM_PLANE_TYPE_PRIMARY) {
- plane_state->visible = primary_get_hw_state(crtc);
- if (plane_state->visible)
- crtc->base.state->plane_mask |=
- 1 << drm_plane_index(&p->base);
- } else {
- if (active)
- p->disable_plane(&p->base, &crtc->base);
-
- plane_state->visible = false;
- }
- }
+ if (plane_state->visible)
+ crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
}
static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@ -15121,34 +15132,7 @@
crtc->base.state->active = crtc->active;
crtc->base.enabled = crtc->active;
- memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
- if (crtc->base.state->active) {
- intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
- intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
- WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
-
- /*
- * The initial mode needs to be set in order to keep
- * the atomic core happy. It wants a valid mode if the
- * crtc's enabled, so we do the above call.
- *
- * At this point some state updated by the connectors
- * in their ->detect() callback has not run yet, so
- * no recalculation can be done yet.
- *
- * Even if we could do a recalculation and modeset
- * right now it would cause a double modeset if
- * fbdev or userspace chooses a different initial mode.
- *
- * If that happens, someone indicated they wanted a
- * mode change, which means it's safe to do a full
- * recalculation.
- */
- crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
- }
-
- crtc->base.hwmode = crtc->config->base.adjusted_mode;
- readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));
+ readout_plane_state(crtc);
DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
crtc->base.base.id,
@@ -15207,6 +15191,36 @@
connector->base.name,
connector->base.encoder ? "enabled" : "disabled");
}
+
+ for_each_intel_crtc(dev, crtc) {
+ crtc->base.hwmode = crtc->config->base.adjusted_mode;
+
+ memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
+ if (crtc->base.state->active) {
+ intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
+ intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
+ WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
+
+ /*
+ * The initial mode needs to be set in order to keep
+ * the atomic core happy. It wants a valid mode if the
+ * crtc's enabled, so we do the above call.
+ *
+ * At this point some state updated by the connectors
+ * in their ->detect() callback has not run yet, so
+ * no recalculation can be done yet.
+ *
+ * Even if we could do a recalculation and modeset
+ * right now it would cause a double modeset if
+ * fbdev or userspace chooses a different initial mode.
+ *
+ * If that happens, someone indicated they wanted a
+ * mode change, which means it's safe to do a full
+ * recalculation.
+ */
+ crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
+ }
+ }
}
/* Scan out the current hw modeset state,
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 7412cae..29dd448 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1659,6 +1659,7 @@
if (flush_domains) {
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
}
if (invalidate_domains) {
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6e6b8db..61b451f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -347,6 +347,7 @@
if (flush_domains) {
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
}
if (invalidate_domains) {
flags |= PIPE_CONTROL_TLB_INVALIDATE;
@@ -418,6 +419,7 @@
if (flush_domains) {
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
}
if (invalidate_domains) {
flags |= PIPE_CONTROL_TLB_INVALIDATE;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index cc6c228..e905c00 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -469,9 +469,13 @@
if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
dev->mode_config.max_width = 4096;
dev->mode_config.max_height = 4096;
- } else {
+ } else
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) {
dev->mode_config.max_width = 8192;
dev->mode_config.max_height = 8192;
+ } else {
+ dev->mode_config.max_width = 16384;
+ dev->mode_config.max_height = 16384;
}
dev->mode_config.preferred_depth = 24;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 2791701..59f27e7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -178,8 +178,30 @@
return 0;
}
+static int
+nouveau_fbcon_open(struct fb_info *info, int user)
+{
+ struct nouveau_fbdev *fbcon = info->par;
+ struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ int ret = pm_runtime_get_sync(drm->dev->dev);
+ if (ret < 0 && ret != -EACCES)
+ return ret;
+ return 0;
+}
+
+static int
+nouveau_fbcon_release(struct fb_info *info, int user)
+{
+ struct nouveau_fbdev *fbcon = info->par;
+ struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+ pm_runtime_put(drm->dev->dev);
+ return 0;
+}
+
static struct fb_ops nouveau_fbcon_ops = {
.owner = THIS_MODULE,
+ .fb_open = nouveau_fbcon_open,
+ .fb_release = nouveau_fbcon_release,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = nouveau_fbcon_fillrect,
@@ -195,6 +217,8 @@
static struct fb_ops nouveau_fbcon_sw_ops = {
.owner = THIS_MODULE,
+ .fb_open = nouveau_fbcon_open,
+ .fb_release = nouveau_fbcon_release,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 2c99815..41be584 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -227,11 +227,12 @@
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
struct nvkm_vma *vma;
- if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+ if (is_power_of_2(nvbo->valid_domains))
+ rep->domain = nvbo->valid_domains;
+ else if (nvbo->bo.mem.mem_type == TTM_PL_TT)
rep->domain = NOUVEAU_GEM_DOMAIN_GART;
else
rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
-
rep->offset = nvbo->bo.offset;
if (cli->vm) {
vma = nouveau_bo_vma_find(nvbo, cli->vm);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
index 65af314..a7d69ce 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
@@ -267,6 +267,12 @@
index = NVKM_I2C_BUS_PRI;
if (init->outp && init->outp->i2c_upper_default)
index = NVKM_I2C_BUS_SEC;
+ } else
+ if (index == 0x80) {
+ index = NVKM_I2C_BUS_PRI;
+ } else
+ if (index == 0x81) {
+ index = NVKM_I2C_BUS_SEC;
}
bus = nvkm_i2c_bus_find(i2c, index);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
index e0ec2a6..212800e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
@@ -8,7 +8,10 @@
void *(*init)(struct nvkm_bios *, const char *);
void (*fini)(void *);
u32 (*read)(void *, u32 offset, u32 length, struct nvkm_bios *);
+ u32 (*size)(void *);
bool rw;
+ bool ignore_checksum;
+ bool no_pcir;
};
int nvbios_extend(struct nvkm_bios *, u32 length);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
index 792f017..b2557e8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
@@ -45,7 +45,7 @@
u32 read = mthd->func->read(data, start, limit - start, bios);
bios->size = start + read;
}
- return bios->size >= limit;
+ return bios->size >= upto;
}
static int
@@ -55,14 +55,22 @@
struct nvbios_image image;
int score = 1;
- if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
- nvkm_debug(subdev, "%08x: header fetch failed\n", offset);
- return 0;
- }
+ if (mthd->func->no_pcir) {
+ image.base = 0;
+ image.type = 0;
+ image.size = mthd->func->size(mthd->data);
+ image.last = 1;
+ } else {
+ if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
+ nvkm_debug(subdev, "%08x: header fetch failed\n",
+ offset);
+ return 0;
+ }
- if (!nvbios_image(bios, idx, &image)) {
- nvkm_debug(subdev, "image %d invalid\n", idx);
- return 0;
+ if (!nvbios_image(bios, idx, &image)) {
+ nvkm_debug(subdev, "image %d invalid\n", idx);
+ return 0;
+ }
}
nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
image.base, image.type, image.size);
@@ -74,7 +82,8 @@
switch (image.type) {
case 0x00:
- if (nvbios_checksum(&bios->data[image.base], image.size)) {
+ if (!mthd->func->ignore_checksum &&
+ nvbios_checksum(&bios->data[image.base], image.size)) {
nvkm_debug(subdev, "%08x: checksum failed\n",
image.base);
if (mthd->func->rw)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
index bd60d7d..4bf486b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
@@ -21,6 +21,7 @@
*
*/
#include "priv.h"
+
#include <core/pci.h>
#if defined(__powerpc__)
@@ -33,17 +34,26 @@
of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{
struct priv *priv = data;
- if (offset + length <= priv->size) {
+ if (offset < priv->size) {
+ length = min_t(u32, length, priv->size - offset);
memcpy_fromio(bios->data + offset, priv->data + offset, length);
return length;
}
return 0;
}
+static u32
+of_size(void *data)
+{
+ struct priv *priv = data;
+ return priv->size;
+}
+
static void *
of_init(struct nvkm_bios *bios, const char *name)
{
- struct pci_dev *pdev = bios->subdev.device->func->pci(bios->subdev.device)->pdev;
+ struct nvkm_device *device = bios->subdev.device;
+ struct pci_dev *pdev = device->func->pci(device)->pdev;
struct device_node *dn;
struct priv *priv;
if (!(dn = pci_device_to_OF_node(pdev)))
@@ -62,7 +72,10 @@
.init = of_init,
.fini = (void(*)(void *))kfree,
.read = of_read,
+ .size = of_size,
.rw = false,
+ .ignore_checksum = true,
+ .no_pcir = true,
};
#else
const struct nvbios_source
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c
index 814cb51..385a90f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c
@@ -35,6 +35,8 @@
nvkm_device_agp_quirks[] = {
/* VIA Apollo PRO133x / GeForce FX 5600 Ultra - fdo#20341 */
{ PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 },
+ /* SiS 761 does not support AGP cards, use PCI mode */
+ { PCI_VENDOR_ID_SI, 0x0761, PCI_ANY_ID, PCI_ANY_ID, 0 },
{},
};
@@ -137,8 +139,10 @@
while (quirk->hostbridge_vendor) {
if (info.device->vendor == quirk->hostbridge_vendor &&
info.device->device == quirk->hostbridge_device &&
- pci->pdev->vendor == quirk->chip_vendor &&
- pci->pdev->device == quirk->chip_device) {
+ (quirk->chip_vendor == (u16)PCI_ANY_ID ||
+ pci->pdev->vendor == quirk->chip_vendor) &&
+ (quirk->chip_device == (u16)PCI_ANY_ID ||
+ pci->pdev->device == quirk->chip_device)) {
nvkm_info(subdev, "forcing default agp mode to %dX, "
"use NvAGP=<mode> to override\n",
quirk->mode);
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 4649bd2..183aea1 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -244,6 +244,10 @@
ret = qxl_bo_reserve(bo, false);
if (ret)
return ret;
+ ret = qxl_bo_pin(bo, bo->type, NULL);
+ qxl_bo_unreserve(bo);
+ if (ret)
+ return ret;
qxl_draw_dirty_fb(qdev, qfb_src, bo, 0, 0,
&norect, one_clip_rect, inc);
@@ -257,7 +261,11 @@
}
drm_vblank_put(dev, qcrtc->index);
- qxl_bo_unreserve(bo);
+ ret = qxl_bo_reserve(bo, false);
+ if (!ret) {
+ qxl_bo_unpin(bo);
+ qxl_bo_unreserve(bo);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index 41c422f..c4a5526 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -144,14 +144,17 @@
spin_lock_irqsave(&qfbdev->dirty.lock, flags);
- if (qfbdev->dirty.y1 < y)
- y = qfbdev->dirty.y1;
- if (qfbdev->dirty.y2 > y2)
- y2 = qfbdev->dirty.y2;
- if (qfbdev->dirty.x1 < x)
- x = qfbdev->dirty.x1;
- if (qfbdev->dirty.x2 > x2)
- x2 = qfbdev->dirty.x2;
+ if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) &&
+ (qfbdev->dirty.x2 - qfbdev->dirty.x1)) {
+ if (qfbdev->dirty.y1 < y)
+ y = qfbdev->dirty.y1;
+ if (qfbdev->dirty.y2 > y2)
+ y2 = qfbdev->dirty.y2;
+ if (qfbdev->dirty.x1 < x)
+ x = qfbdev->dirty.x1;
+ if (qfbdev->dirty.x2 > x2)
+ x2 = qfbdev->dirty.x2;
+ }
qfbdev->dirty.x1 = x;
qfbdev->dirty.x2 = x2;
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index b66ec33..4efa8e2 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -307,7 +307,7 @@
idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release);
if (idr_ret < 0)
return idr_ret;
- bo = qxl_bo_ref(to_qxl_bo(entry->tv.bo));
+ bo = to_qxl_bo(entry->tv.bo);
(*release)->release_offset = create_rel->release_offset + 64;
@@ -316,8 +316,6 @@
info = qxl_release_map(qdev, *release);
info->id = idr_ret;
qxl_release_unmap(qdev, *release, info);
-
- qxl_bo_unref(&bo);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 65adb9c..bb29214 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -237,6 +237,7 @@
backlight_update_status(bd);
DRM_INFO("radeon atom DIG backlight initialized\n");
+ rdev->mode_info.bl_encoder = radeon_encoder;
return;
@@ -1624,9 +1625,14 @@
} else
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
- struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+ if (rdev->mode_info.bl_encoder) {
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
- atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+ atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+ } else {
+ args.ucAction = ATOM_LCD_BLON;
+ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+ }
}
break;
case DRM_MODE_DPMS_STANDBY:
@@ -1706,8 +1712,13 @@
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
}
- if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
- atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+ if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+ if (rdev->mode_info.bl_encoder)
+ atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+ else
+ atombios_dig_transmitter_setup(encoder,
+ ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+ }
if (ext_encoder)
atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
break;
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index f03b7eb..b6cbd81 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1658,6 +1658,7 @@
u8 fan_max_rpm;
/* dpm */
bool dpm_enabled;
+ bool sysfs_initialized;
struct radeon_dpm dpm;
};
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index d2e9e9e..6743174 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1633,18 +1633,8 @@
radeon_fbdev_init(rdev);
drm_kms_helper_poll_init(rdev->ddev);
- if (rdev->pm.dpm_enabled) {
- /* do dpm late init */
- ret = radeon_pm_late_init(rdev);
- if (ret) {
- rdev->pm.dpm_enabled = false;
- DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
- }
- /* set the dpm state for PX since there won't be
- * a modeset to call this.
- */
- radeon_pm_compute_clocks(rdev);
- }
+ /* do pm late init */
+ ret = radeon_pm_late_init(rdev);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index 6cddae4..744f5c4 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -283,6 +283,7 @@
radeon_connector->mst_encoder = radeon_dp_create_fake_mst_encoder(master);
drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
+ drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
drm_mode_connector_set_path_property(connector, pathprop);
return connector;
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index ef99917..c6ee802 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -194,7 +194,6 @@
radeon_atom_backlight_init(radeon_encoder, connector);
else
radeon_legacy_backlight_init(radeon_encoder, connector);
- rdev->mode_info.bl_encoder = radeon_encoder;
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 1aa657f..26da2f4 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -397,3 +397,19 @@
{
drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector);
}
+
+void radeon_fbdev_restore_mode(struct radeon_device *rdev)
+{
+ struct radeon_fbdev *rfbdev = rdev->mode_info.rfbdev;
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ if (!rfbdev)
+ return;
+
+ fb_helper = &rfbdev->helper;
+
+ ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+ if (ret)
+ DRM_DEBUG("failed to restore crtc mode\n");
+}
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 4a119c2..0e932bf 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -598,7 +598,7 @@
* Outdated mess for old drm with Xorg being in charge (void function now).
*/
/**
- * radeon_driver_firstopen_kms - drm callback for last close
+ * radeon_driver_lastclose_kms - drm callback for last close
*
* @dev: drm dev pointer
*
@@ -606,6 +606,9 @@
*/
void radeon_driver_lastclose_kms(struct drm_device *dev)
{
+ struct radeon_device *rdev = dev->dev_private;
+
+ radeon_fbdev_restore_mode(rdev);
vga_switcheroo_process_delayed_switch();
}
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 4571530..30de433 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -441,6 +441,7 @@
backlight_update_status(bd);
DRM_INFO("radeon legacy LVDS backlight initialized\n");
+ rdev->mode_info.bl_encoder = radeon_encoder;
return;
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index aecc3e3..457b026 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -980,6 +980,7 @@
void radeon_fbdev_fini(struct radeon_device *rdev);
void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
+void radeon_fbdev_restore_mode(struct radeon_device *rdev);
void radeon_fb_output_poll_changed(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 05751f3..5feee3b 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -717,10 +717,14 @@
struct radeon_device *rdev = dev_get_drvdata(dev);
umode_t effective_mode = attr->mode;
- /* Skip limit attributes if DPM is not enabled */
+ /* Skip attributes if DPM is not enabled */
if (rdev->pm.pm_method != PM_METHOD_DPM &&
(attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
- attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+ attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+ attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
return 0;
/* Skip fan attributes if fan is not present */
@@ -1326,14 +1330,6 @@
INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
if (rdev->pm.num_power_states > 1) {
- /* where's the best place to put these? */
- ret = device_create_file(rdev->dev, &dev_attr_power_profile);
- if (ret)
- DRM_ERROR("failed to create device file for power profile\n");
- ret = device_create_file(rdev->dev, &dev_attr_power_method);
- if (ret)
- DRM_ERROR("failed to create device file for power method\n");
-
if (radeon_debugfs_pm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for PM!\n");
}
@@ -1391,20 +1387,6 @@
goto dpm_failed;
rdev->pm.dpm_enabled = true;
- ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
- if (ret)
- DRM_ERROR("failed to create device file for dpm state\n");
- ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
- if (ret)
- DRM_ERROR("failed to create device file for dpm state\n");
- /* XXX: these are noops for dpm but are here for backwards compat */
- ret = device_create_file(rdev->dev, &dev_attr_power_profile);
- if (ret)
- DRM_ERROR("failed to create device file for power profile\n");
- ret = device_create_file(rdev->dev, &dev_attr_power_method);
- if (ret)
- DRM_ERROR("failed to create device file for power method\n");
-
if (radeon_debugfs_pm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for dpm!\n");
}
@@ -1545,9 +1527,51 @@
int ret = 0;
if (rdev->pm.pm_method == PM_METHOD_DPM) {
- mutex_lock(&rdev->pm.mutex);
- ret = radeon_dpm_late_enable(rdev);
- mutex_unlock(&rdev->pm.mutex);
+ if (rdev->pm.dpm_enabled) {
+ if (!rdev->pm.sysfs_initialized) {
+ ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
+ if (ret)
+ DRM_ERROR("failed to create device file for dpm state\n");
+ ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
+ if (ret)
+ DRM_ERROR("failed to create device file for dpm state\n");
+ /* XXX: these are noops for dpm but are here for backwards compat */
+ ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+ if (ret)
+ DRM_ERROR("failed to create device file for power profile\n");
+ ret = device_create_file(rdev->dev, &dev_attr_power_method);
+ if (ret)
+ DRM_ERROR("failed to create device file for power method\n");
+ if (!ret)
+ rdev->pm.sysfs_initialized = true;
+ }
+
+ mutex_lock(&rdev->pm.mutex);
+ ret = radeon_dpm_late_enable(rdev);
+ mutex_unlock(&rdev->pm.mutex);
+ if (ret) {
+ rdev->pm.dpm_enabled = false;
+ DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+ } else {
+ /* set the dpm state for PX since there won't be
+ * a modeset to call this.
+ */
+ radeon_pm_compute_clocks(rdev);
+ }
+ }
+ } else {
+ if ((rdev->pm.num_power_states > 1) &&
+ (!rdev->pm.sysfs_initialized)) {
+ /* where's the best place to put these? */
+ ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+ if (ret)
+ DRM_ERROR("failed to create device file for power profile\n");
+ ret = device_create_file(rdev->dev, &dev_attr_power_method);
+ if (ret)
+ DRM_ERROR("failed to create device file for power method\n");
+ if (!ret)
+ rdev->pm.sysfs_initialized = true;
+ }
}
return ret;
}
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index e9115d3..e72bf46 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -2928,6 +2928,7 @@
{ PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
{ PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
{ PCI_VENDOR_ID_ATI, 0x6811, 0x1762, 0x2015, 0, 120000 },
+ { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
{ 0, 0, 0, 0 },
};
diff --git a/drivers/gpu/drm/virtio/virtgpu_debugfs.c b/drivers/gpu/drm/virtio/virtgpu_debugfs.c
index db8b491..5122639 100644
--- a/drivers/gpu/drm/virtio/virtgpu_debugfs.c
+++ b/drivers/gpu/drm/virtio/virtgpu_debugfs.c
@@ -34,8 +34,8 @@
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct virtio_gpu_device *vgdev = node->minor->dev->dev_private;
- seq_printf(m, "fence %ld %lld\n",
- atomic64_read(&vgdev->fence_drv.last_seq),
+ seq_printf(m, "fence %llu %lld\n",
+ (u64)atomic64_read(&vgdev->fence_drv.last_seq),
vgdev->fence_drv.sync_seq);
return 0;
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c
index 1da6326..67097c9 100644
--- a/drivers/gpu/drm/virtio/virtgpu_fence.c
+++ b/drivers/gpu/drm/virtio/virtgpu_fence.c
@@ -61,7 +61,7 @@
{
struct virtio_gpu_fence *fence = to_virtio_fence(f);
- snprintf(str, size, "%lu", atomic64_read(&fence->drv->last_seq));
+ snprintf(str, size, "%llu", (u64)atomic64_read(&fence->drv->last_seq));
}
static const struct fence_ops virtio_fence_ops = {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
index 8a76821..6377e81 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
@@ -415,16 +415,16 @@
*
* Calls vmw_cmdbuf_ctx_process() on all contexts. If any context has
* command buffers left that are not submitted to hardware, Make sure
- * IRQ handling is turned on. Otherwise, make sure it's turned off. This
- * function may return -EAGAIN to indicate it should be rerun due to
- * possibly missed IRQs if IRQs has just been turned on.
+ * IRQ handling is turned on. Otherwise, make sure it's turned off.
*/
-static int vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
+static void vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
{
- int notempty = 0;
+ int notempty;
struct vmw_cmdbuf_context *ctx;
int i;
+retry:
+ notempty = 0;
for_each_cmdbuf_ctx(man, i, ctx)
vmw_cmdbuf_ctx_process(man, ctx, ¬empty);
@@ -440,10 +440,8 @@
man->irq_on = true;
/* Rerun in case we just missed an irq. */
- return -EAGAIN;
+ goto retry;
}
-
- return 0;
}
/**
@@ -468,8 +466,7 @@
header->cb_context = cb_context;
list_add_tail(&header->list, &man->ctx[cb_context].submitted);
- if (vmw_cmdbuf_man_process(man) == -EAGAIN)
- vmw_cmdbuf_man_process(man);
+ vmw_cmdbuf_man_process(man);
}
/**
@@ -488,8 +485,7 @@
struct vmw_cmdbuf_man *man = (struct vmw_cmdbuf_man *) data;
spin_lock(&man->lock);
- if (vmw_cmdbuf_man_process(man) == -EAGAIN)
- (void) vmw_cmdbuf_man_process(man);
+ vmw_cmdbuf_man_process(man);
spin_unlock(&man->lock);
}
@@ -507,6 +503,7 @@
struct vmw_cmdbuf_man *man =
container_of(work, struct vmw_cmdbuf_man, work);
struct vmw_cmdbuf_header *entry, *next;
+ uint32_t dummy;
bool restart = false;
spin_lock_bh(&man->lock);
@@ -523,6 +520,8 @@
if (restart && vmw_cmdbuf_startstop(man, true))
DRM_ERROR("Failed restarting command buffer context 0.\n");
+ /* Send a new fence in case one was removed */
+ vmw_fifo_send_fence(man->dev_priv, &dummy);
}
/**
@@ -682,7 +681,7 @@
DRM_MM_SEARCH_DEFAULT,
DRM_MM_CREATE_DEFAULT);
if (ret) {
- (void) vmw_cmdbuf_man_process(man);
+ vmw_cmdbuf_man_process(man);
ret = drm_mm_insert_node_generic(&man->mm, info->node,
info->page_size, 0, 0,
DRM_MM_SEARCH_DEFAULT,
@@ -1168,7 +1167,14 @@
drm_mm_init(&man->mm, 0, size >> PAGE_SHIFT);
man->has_pool = true;
- man->default_size = default_size;
+
+ /*
+ * For now, set the default size to VMW_CMDBUF_INLINE_SIZE to
+ * prevent deadlocks from happening when vmw_cmdbuf_space_pool()
+ * needs to wait for space and we block on further command
+ * submissions to be able to free up space.
+ */
+ man->default_size = VMW_CMDBUF_INLINE_SIZE;
DRM_INFO("Using command buffers with %s pool.\n",
(man->using_mob) ? "MOB" : "DMA");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index 64b5040..03f63c7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -657,7 +657,8 @@
struct vmw_resource *res = &user_srf->srf.res;
*p_base = NULL;
- ttm_base_object_unref(&user_srf->backup_base);
+ if (user_srf->backup_base)
+ ttm_base_object_unref(&user_srf->backup_base);
vmw_resource_unreference(&res);
}
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 3dd2de3..472b882 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
@@ -51,6 +52,22 @@
}
#ifdef CONFIG_ACPI
+/*
+ * The HCNT/LCNT information coming from ACPI should be the most accurate
+ * for given platform. However, some systems get it wrong. On such systems
+ * we get better results by calculating those based on the input clock.
+ */
+static const struct dmi_system_id dw_i2c_no_acpi_params[] = {
+ {
+ .ident = "Dell Inspiron 7348",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7348"),
+ },
+ },
+ { }
+};
+
static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
u16 *hcnt, u16 *lcnt, u32 *sda_hold)
{
@@ -58,6 +75,9 @@
acpi_handle handle = ACPI_HANDLE(&pdev->dev);
union acpi_object *obj;
+ if (dmi_check_system(dw_i2c_no_acpi_params))
+ return;
+
if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
return;
@@ -253,12 +273,6 @@
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
- r = i2c_add_numbered_adapter(adap);
- if (r) {
- dev_err(&pdev->dev, "failure adding adapter\n");
- return r;
- }
-
if (dev->pm_runtime_disabled) {
pm_runtime_forbid(&pdev->dev);
} else {
@@ -268,6 +282,13 @@
pm_runtime_enable(&pdev->dev);
}
+ r = i2c_add_numbered_adapter(adap);
+ if (r) {
+ dev_err(&pdev->dev, "failure adding adapter\n");
+ pm_runtime_disable(&pdev->dev);
+ return r;
+ }
+
return 0;
}
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 30059c1..5801227 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -669,8 +669,6 @@
struct i2c_msg *msgs = drv_data->msgs;
int num = drv_data->num_msgs;
- return false;
-
if (!drv_data->offload_enabled)
return false;
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index e814a36..6f8b446 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -600,7 +600,7 @@
{
struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
- clk_disable(alg_data->clk);
+ clk_disable_unprepare(alg_data->clk);
return 0;
}
@@ -609,7 +609,7 @@
{
struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
- return clk_enable(alg_data->clk);
+ return clk_prepare_enable(alg_data->clk);
}
static SIMPLE_DEV_PM_OPS(i2c_pnx_pm,
@@ -672,7 +672,7 @@
if (IS_ERR(alg_data->ioaddr))
return PTR_ERR(alg_data->ioaddr);
- ret = clk_enable(alg_data->clk);
+ ret = clk_prepare_enable(alg_data->clk);
if (ret)
return ret;
@@ -726,7 +726,7 @@
return 0;
out_clock:
- clk_disable(alg_data->clk);
+ clk_disable_unprepare(alg_data->clk);
return ret;
}
@@ -735,7 +735,7 @@
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
i2c_del_adapter(&alg_data->adapter);
- clk_disable(alg_data->clk);
+ clk_disable_unprepare(alg_data->clk);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index d8361da..d8b5a8f 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -690,15 +690,16 @@
return ret;
}
+ pm_runtime_enable(dev);
+ platform_set_drvdata(pdev, priv);
+
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
dev_err(dev, "reg adap failed: %d\n", ret);
+ pm_runtime_disable(dev);
return ret;
}
- pm_runtime_enable(dev);
- platform_set_drvdata(pdev, priv);
-
dev_info(dev, "probed\n");
return 0;
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 50bfd8c..5df8196 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1243,17 +1243,19 @@
i2c->adap.nr = i2c->pdata->bus_num;
i2c->adap.dev.of_node = pdev->dev.of_node;
+ platform_set_drvdata(pdev, i2c);
+
+ pm_runtime_enable(&pdev->dev);
+
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+ pm_runtime_disable(&pdev->dev);
s3c24xx_i2c_deregister_cpufreq(i2c);
clk_unprepare(i2c->clk);
return ret;
}
- platform_set_drvdata(pdev, i2c);
-
- pm_runtime_enable(&pdev->dev);
pm_runtime_enable(&i2c->adap.dev);
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 5f89f1e..a59c311 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -694,12 +694,12 @@
goto err_clear_wakeup_irq;
status = dev_pm_domain_attach(&client->dev, true);
- if (status != -EPROBE_DEFER) {
- status = driver->probe(client, i2c_match_id(driver->id_table,
- client));
- if (status)
- goto err_detach_pm_domain;
- }
+ if (status == -EPROBE_DEFER)
+ goto err_clear_wakeup_irq;
+
+ status = driver->probe(client, i2c_match_id(driver->id_table, client));
+ if (status)
+ goto err_detach_pm_domain;
return 0;
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index ff30f88..fb93111 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -149,8 +149,6 @@
#define ST_ACCEL_4_BDU_MASK 0x40
#define ST_ACCEL_4_DRDY_IRQ_ADDR 0x21
#define ST_ACCEL_4_DRDY_IRQ_INT1_MASK 0x04
-#define ST_ACCEL_4_IG1_EN_ADDR 0x21
-#define ST_ACCEL_4_IG1_EN_MASK 0x08
#define ST_ACCEL_4_MULTIREAD_BIT true
/* CUSTOM VALUES FOR SENSOR 5 */
@@ -489,10 +487,6 @@
.drdy_irq = {
.addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
- .ig1 = {
- .en_addr = ST_ACCEL_4_IG1_EN_ADDR,
- .en_mask = ST_ACCEL_4_IG1_EN_MASK,
- },
},
.multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
.bootime = 2, /* guess */
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index ebe415f..0c74869 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -45,13 +45,18 @@
#include <linux/types.h>
#include <linux/gfp.h>
#include <linux/err.h>
+#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
+#define TWL4030_USB_SEL_MADC_MCPC (1<<3)
+#define TWL4030_USB_CARKIT_ANA_CTRL 0xBB
+
/**
* struct twl4030_madc_data - a container for madc info
* @dev: Pointer to device structure for madc
* @lock: Mutex protecting this data structure
+ * @regulator: Pointer to bias regulator for madc
* @requests: Array of request struct corresponding to SW1, SW2 and RT
* @use_second_irq: IRQ selection (main or co-processor)
* @imr: Interrupt mask register of MADC
@@ -60,6 +65,7 @@
struct twl4030_madc_data {
struct device *dev;
struct mutex lock; /* mutex protecting this data structure */
+ struct regulator *usb3v1;
struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
bool use_second_irq;
u8 imr;
@@ -841,6 +847,32 @@
}
twl4030_madc = madc;
+ /* Configure MADC[3:6] */
+ ret = twl_i2c_read_u8(TWL_MODULE_USB, ®val,
+ TWL4030_USB_CARKIT_ANA_CTRL);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to read reg CARKIT_ANA_CTRL 0x%X\n",
+ TWL4030_USB_CARKIT_ANA_CTRL);
+ goto err_i2c;
+ }
+ regval |= TWL4030_USB_SEL_MADC_MCPC;
+ ret = twl_i2c_write_u8(TWL_MODULE_USB, regval,
+ TWL4030_USB_CARKIT_ANA_CTRL);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to write reg CARKIT_ANA_CTRL 0x%X\n",
+ TWL4030_USB_CARKIT_ANA_CTRL);
+ goto err_i2c;
+ }
+
+ /* Enable 3v1 bias regulator for MADC[3:6] */
+ madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1");
+ if (IS_ERR(madc->usb3v1))
+ return -ENODEV;
+
+ ret = regulator_enable(madc->usb3v1);
+ if (ret)
+ dev_err(madc->dev, "could not enable 3v1 bias regulator\n");
+
ret = iio_device_register(iio_dev);
if (ret) {
dev_err(&pdev->dev, "could not register iio device\n");
@@ -866,6 +898,8 @@
twl4030_madc_set_current_generator(madc, 0, 0);
twl4030_madc_set_power(madc, 0);
+ regulator_disable(madc->usb3v1);
+
return 0;
}
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 8f66c67..87471ef 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -508,12 +508,12 @@
memset(&gid_attr, 0, sizeof(gid_attr));
gid_attr.ndev = ndev;
+ mutex_lock(&table->lock);
ix = find_gid(table, NULL, NULL, true, GID_ATTR_FIND_MASK_DEFAULT);
/* Coudn't find default GID location */
WARN_ON(ix < 0);
- mutex_lock(&table->lock);
if (!__ib_cache_gid_get(ib_dev, port, ix,
¤t_gid, ¤t_gid_attr) &&
mode == IB_CACHE_GID_DEFAULT_MODE_SET &&
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index ea4db9c..4f918b9 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -835,6 +835,11 @@
case IB_CM_SIDR_REQ_RCVD:
spin_unlock_irq(&cm_id_priv->lock);
cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
+ spin_lock_irq(&cm.lock);
+ if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
+ rb_erase(&cm_id_priv->sidr_id_node,
+ &cm.remote_sidr_table);
+ spin_unlock_irq(&cm.lock);
break;
case IB_CM_REQ_SENT:
case IB_CM_MRA_REQ_RCVD:
@@ -3172,7 +3177,10 @@
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
spin_lock_irqsave(&cm.lock, flags);
- rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+ if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
+ rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+ RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
+ }
spin_unlock_irqrestore(&cm.lock, flags);
return 0;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index b1ab13f..36b12d5 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1067,14 +1067,14 @@
sizeof(req->local_gid));
req->has_gid = true;
req->service_id = req_param->primary_path->service_id;
- req->pkey = req_param->bth_pkey;
+ req->pkey = be16_to_cpu(req_param->primary_path->pkey);
break;
case IB_CM_SIDR_REQ_RECEIVED:
req->device = sidr_param->listen_id->device;
req->port = sidr_param->port;
req->has_gid = false;
req->service_id = sidr_param->service_id;
- req->pkey = sidr_param->bth_pkey;
+ req->pkey = sidr_param->pkey;
break;
default:
return -EINVAL;
@@ -1232,14 +1232,32 @@
return true;
}
+static bool cma_protocol_roce_dev_port(struct ib_device *device, int port_num)
+{
+ enum rdma_link_layer ll = rdma_port_get_link_layer(device, port_num);
+ enum rdma_transport_type transport =
+ rdma_node_get_transport(device->node_type);
+
+ return ll == IB_LINK_LAYER_ETHERNET && transport == RDMA_TRANSPORT_IB;
+}
+
+static bool cma_protocol_roce(const struct rdma_cm_id *id)
+{
+ struct ib_device *device = id->device;
+ const int port_num = id->port_num ?: rdma_start_port(device);
+
+ return cma_protocol_roce_dev_port(device, port_num);
+}
+
static bool cma_match_net_dev(const struct rdma_id_private *id_priv,
const struct net_device *net_dev)
{
const struct rdma_addr *addr = &id_priv->id.route.addr;
if (!net_dev)
- /* This request is an AF_IB request */
- return addr->src_addr.ss_family == AF_IB;
+ /* This request is an AF_IB request or a RoCE request */
+ return addr->src_addr.ss_family == AF_IB ||
+ cma_protocol_roce(&id_priv->id);
return !addr->dev_addr.bound_dev_if ||
(net_eq(dev_net(net_dev), &init_net) &&
@@ -1294,6 +1312,10 @@
if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) {
/* Assuming the protocol is AF_IB */
*net_dev = NULL;
+ } else if (cma_protocol_roce_dev_port(req.device, req.port)) {
+ /* TODO find the net dev matching the request parameters
+ * through the RoCE GID table */
+ *net_dev = NULL;
} else {
return ERR_CAST(*net_dev);
}
@@ -1302,7 +1324,7 @@
bind_list = cma_ps_find(rdma_ps_from_service_id(req.service_id),
cma_port_from_service_id(req.service_id));
id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev);
- if (IS_ERR(id_priv)) {
+ if (IS_ERR(id_priv) && *net_dev) {
dev_put(*net_dev);
*net_dev = NULL;
}
@@ -1593,11 +1615,16 @@
if (ret)
goto err;
} else {
- /* An AF_IB connection */
- WARN_ON_ONCE(ss_family != AF_IB);
-
- cma_translate_ib((struct sockaddr_ib *)cma_src_addr(id_priv),
- &rt->addr.dev_addr);
+ if (!cma_protocol_roce(listen_id) &&
+ cma_any_addr(cma_src_addr(id_priv))) {
+ rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND;
+ rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
+ ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey));
+ } else if (!cma_any_addr(cma_src_addr(id_priv))) {
+ ret = cma_translate_addr(cma_src_addr(id_priv), &rt->addr.dev_addr);
+ if (ret)
+ goto err;
+ }
}
rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
@@ -1635,13 +1662,12 @@
if (ret)
goto err;
} else {
- /* An AF_IB connection */
- WARN_ON_ONCE(ss_family != AF_IB);
-
- if (!cma_any_addr(cma_src_addr(id_priv)))
- cma_translate_ib((struct sockaddr_ib *)
- cma_src_addr(id_priv),
- &id->route.addr.dev_addr);
+ if (!cma_any_addr(cma_src_addr(id_priv))) {
+ ret = cma_translate_addr(cma_src_addr(id_priv),
+ &id->route.addr.dev_addr);
+ if (ret)
+ goto err;
+ }
}
id_priv->state = RDMA_CM_CONNECT;
diff --git a/drivers/infiniband/core/roce_gid_mgmt.c b/drivers/infiniband/core/roce_gid_mgmt.c
index 6b24cba..178f984 100644
--- a/drivers/infiniband/core/roce_gid_mgmt.c
+++ b/drivers/infiniband/core/roce_gid_mgmt.c
@@ -250,25 +250,44 @@
u8 port, struct net_device *ndev)
{
struct in_device *in_dev;
+ struct sin_list {
+ struct list_head list;
+ struct sockaddr_in ip;
+ };
+ struct sin_list *sin_iter;
+ struct sin_list *sin_temp;
+ LIST_HEAD(sin_list);
if (ndev->reg_state >= NETREG_UNREGISTERING)
return;
- in_dev = in_dev_get(ndev);
- if (!in_dev)
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(ndev);
+ if (!in_dev) {
+ rcu_read_unlock();
return;
+ }
for_ifa(in_dev) {
- struct sockaddr_in ip;
+ struct sin_list *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
- ip.sin_family = AF_INET;
- ip.sin_addr.s_addr = ifa->ifa_address;
- update_gid_ip(GID_ADD, ib_dev, port, ndev,
- (struct sockaddr *)&ip);
+ if (!entry) {
+ pr_warn("roce_gid_mgmt: couldn't allocate entry for IPv4 update\n");
+ continue;
+ }
+ entry->ip.sin_family = AF_INET;
+ entry->ip.sin_addr.s_addr = ifa->ifa_address;
+ list_add_tail(&entry->list, &sin_list);
}
endfor_ifa(in_dev);
+ rcu_read_unlock();
- in_dev_put(in_dev);
+ list_for_each_entry_safe(sin_iter, sin_temp, &sin_list, list) {
+ update_gid_ip(GID_ADD, ib_dev, port, ndev,
+ (struct sockaddr *)&sin_iter->ip);
+ list_del(&sin_iter->list);
+ kfree(sin_iter);
+ }
}
static void enum_netdev_ipv6_ips(struct ib_device *ib_dev,
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index a53fc9b..30467d1 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -1624,11 +1624,16 @@
if (!file)
return -ENOMEM;
+ file->close_wq = create_singlethread_workqueue("ucma_close_id");
+ if (!file->close_wq) {
+ kfree(file);
+ return -ENOMEM;
+ }
+
INIT_LIST_HEAD(&file->event_list);
INIT_LIST_HEAD(&file->ctx_list);
init_waitqueue_head(&file->poll_wait);
mutex_init(&file->mut);
- file->close_wq = create_singlethread_workqueue("ucma_close_id");
filp->private_data = file;
file->filp = filp;
diff --git a/drivers/infiniband/hw/usnic/usnic.h b/drivers/infiniband/hw/usnic/usnic.h
index 5be13d8..f903502 100644
--- a/drivers/infiniband/hw/usnic/usnic.h
+++ b/drivers/infiniband/hw/usnic/usnic.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_abi.h b/drivers/infiniband/hw/usnic/usnic_abi.h
index 04a6622..7fe9502 100644
--- a/drivers/infiniband/hw/usnic/usnic_abi.h
+++ b/drivers/infiniband/hw/usnic/usnic_abi.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h b/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h
index 3935672..596e0ed 100644
--- a/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h
+++ b/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_common_util.h b/drivers/infiniband/hw/usnic/usnic_common_util.h
index 9d737ed..b54986d 100644
--- a/drivers/infiniband/hw/usnic/usnic_common_util.h
+++ b/drivers/infiniband/hw/usnic/usnic_common_util.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_debugfs.c b/drivers/infiniband/hw/usnic/usnic_debugfs.c
index 5d13860..5e55b8b 100644
--- a/drivers/infiniband/hw/usnic/usnic_debugfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_debugfs.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_debugfs.h b/drivers/infiniband/hw/usnic/usnic_debugfs.h
index 4087d24..98453e9 100644
--- a/drivers/infiniband/hw/usnic/usnic_debugfs.h
+++ b/drivers/infiniband/hw/usnic/usnic_debugfs.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.c b/drivers/infiniband/hw/usnic/usnic_fwd.c
index e3c9bd9..3c37dd5 100644
--- a/drivers/infiniband/hw/usnic/usnic_fwd.c
+++ b/drivers/infiniband/hw/usnic/usnic_fwd.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.h b/drivers/infiniband/hw/usnic/usnic_fwd.h
index 93713a2..3a8add9 100644
--- a/drivers/infiniband/hw/usnic/usnic_fwd.h
+++ b/drivers/infiniband/hw/usnic/usnic_fwd.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_ib.h b/drivers/infiniband/hw/usnic/usnic_ib.h
index e5a9297..525bf27 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
index 34c49b8..0c15bd8 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
index db3588d..85dc3f9 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
index b0aafe8..b1458be 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
index 27dc67c..3412ea0 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h
index 0d09b49..3d98e16 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 7df4382..f8e3211 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
index 0bd04ef..414eaa5 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_log.h b/drivers/infiniband/hw/usnic/usnic_log.h
index 75777a6..183fcb6 100644
--- a/drivers/infiniband/hw/usnic/usnic_log.h
+++ b/drivers/infiniband/hw/usnic/usnic_log.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_transport.c b/drivers/infiniband/hw/usnic/usnic_transport.c
index ddef6f7..de31838 100644
--- a/drivers/infiniband/hw/usnic/usnic_transport.c
+++ b/drivers/infiniband/hw/usnic/usnic_transport.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_transport.h b/drivers/infiniband/hw/usnic/usnic_transport.h
index 7e5dc6d..9a7a2d9 100644
--- a/drivers/infiniband/hw/usnic/usnic_transport.h
+++ b/drivers/infiniband/hw/usnic/usnic_transport.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c
index cb2337f..645a5f6 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.c
@@ -7,7 +7,7 @@
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
+ * BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.h b/drivers/infiniband/hw/usnic/usnic_uiom.h
index 7044099..45ca7c1 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.h
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
index 3a4288e..42b4b4c 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2014, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h
index d4f752e..c0b0b87 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h
+++ b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_vnic.c b/drivers/infiniband/hw/usnic/usnic_vnic.c
index 656b88c..66de93f 100644
--- a/drivers/infiniband/hw/usnic/usnic_vnic.c
+++ b/drivers/infiniband/hw/usnic/usnic_vnic.c
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/hw/usnic/usnic_vnic.h b/drivers/infiniband/hw/usnic/usnic_vnic.h
index 14d931a..a08423e 100644
--- a/drivers/infiniband/hw/usnic/usnic_vnic.h
+++ b/drivers/infiniband/hw/usnic/usnic_vnic.h
@@ -1,9 +1,24 @@
/*
* Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
*
- * This program is free software; you may 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 software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 4cd5428..edc5b85 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -495,6 +495,7 @@
void ipoib_mcast_join_task(struct work_struct *work);
void ipoib_mcast_carrier_on_task(struct work_struct *work);
void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb);
+void ipoib_mcast_free(struct ipoib_mcast *mc);
void ipoib_mcast_restart_task(struct work_struct *work);
int ipoib_mcast_start_thread(struct net_device *dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index f74316e..babba05 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1207,8 +1207,10 @@
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
- list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
+ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
ipoib_mcast_leave(dev, mcast);
+ ipoib_mcast_free(mcast);
+ }
}
static void ipoib_reap_neigh(struct work_struct *work)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 136cbef..d750a86 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -106,7 +106,7 @@
queue_delayed_work(priv->wq, &priv->mcast_task, 0);
}
-static void ipoib_mcast_free(struct ipoib_mcast *mcast)
+void ipoib_mcast_free(struct ipoib_mcast *mcast)
{
struct net_device *dev = mcast->dev;
int tx_dropped = 0;
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4d24686..41e6cb5 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -100,7 +100,7 @@
#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
6-byte ALPS packet */
-#define ALPS_DELL 0x100 /* device is a Dell laptop */
+#define ALPS_STICK_BITS 0x100 /* separate stick button bits */
#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
static const struct alps_model_info alps_model_data[] = {
@@ -159,6 +159,43 @@
ALPS_PROTO_V8, 0x18, 0x18, 0
};
+/*
+ * Some v2 models report the stick buttons in separate bits
+ */
+static const struct dmi_system_id alps_dmi_has_separate_stick_buttons[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+ {
+ /* Extrapolated from other entries */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D420"),
+ },
+ },
+ {
+ /* Reported-by: Hans de Bruin <jmdebruin@xmsnet.nl> */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D430"),
+ },
+ },
+ {
+ /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D620"),
+ },
+ },
+ {
+ /* Extrapolated from other entries */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D630"),
+ },
+ },
+#endif
+ { }
+};
+
static void alps_set_abs_params_st(struct alps_data *priv,
struct input_dev *dev1);
static void alps_set_abs_params_semi_mt(struct alps_data *priv,
@@ -253,9 +290,8 @@
return;
}
- /* Dell non interleaved V2 dualpoint has separate stick button bits */
- if (priv->proto_version == ALPS_PROTO_V2 &&
- priv->flags == (ALPS_DELL | ALPS_PASS | ALPS_DUALPOINT)) {
+ /* Some models have separate stick button bits */
+ if (priv->flags & ALPS_STICK_BITS) {
left |= packet[0] & 1;
right |= packet[0] & 2;
middle |= packet[0] & 4;
@@ -2552,8 +2588,6 @@
priv->byte0 = protocol->byte0;
priv->mask0 = protocol->mask0;
priv->flags = protocol->flags;
- if (dmi_name_in_vendors("Dell"))
- priv->flags |= ALPS_DELL;
priv->x_max = 2000;
priv->y_max = 1400;
@@ -2568,6 +2602,8 @@
priv->set_abs_params = alps_set_abs_params_st;
priv->x_max = 1023;
priv->y_max = 767;
+ if (dmi_check_system(alps_dmi_has_separate_stick_buttons))
+ priv->flags |= ALPS_STICK_BITS;
break;
case ALPS_PROTO_V3:
diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c
index 5f19107..e4eb048 100644
--- a/drivers/input/mouse/cyapa_gen6.c
+++ b/drivers/input/mouse/cyapa_gen6.c
@@ -241,14 +241,10 @@
memcpy(&cyapa->product_id[13], &resp_data[62], 2);
cyapa->product_id[15] = '\0';
+ /* Get the number of Rx electrodes. */
rotat_align = resp_data[68];
- if (rotat_align) {
- cyapa->electrodes_rx = cyapa->electrodes_y;
- cyapa->electrodes_rx = cyapa->electrodes_y;
- } else {
- cyapa->electrodes_rx = cyapa->electrodes_x;
- cyapa->electrodes_rx = cyapa->electrodes_y;
- }
+ cyapa->electrodes_rx =
+ rotat_align ? cyapa->electrodes_y : cyapa->electrodes_x;
cyapa->aligned_electrodes_rx = (cyapa->electrodes_rx + 3) & ~3u;
if (!cyapa->electrodes_x || !cyapa->electrodes_y ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 600dccef..deb14c1 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1006,6 +1006,7 @@
config TOUCHSCREEN_SUR40
tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
depends on USB && MEDIA_USB_SUPPORT && HAS_DMA
+ depends on VIDEO_V4L2
select INPUT_POLLDEV
select VIDEOBUF2_DMA_SG
help
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 0f5f968..04edc8f 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -668,18 +668,22 @@
static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)
{
+ int value;
struct spi_transfer *t =
list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
if (ts->model == 7845) {
- return be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
+ value = be16_to_cpup((__be16 *)&(((char *)t->rx_buf)[1]));
} else {
/*
* adjust: on-wire is a must-ignore bit, a BE12 value, then
* padding; built from two 8 bit values written msb-first.
*/
- return be16_to_cpup((__be16 *)t->rx_buf) >> 3;
+ value = be16_to_cpup((__be16 *)t->rx_buf);
}
+
+ /* enforce ADC output is 12 bits width */
+ return (value >> 3) & 0xfff;
}
static void ads7846_update_value(struct spi_message *m, int val)
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
index 24d704c..7fbb3b0 100644
--- a/drivers/input/touchscreen/lpc32xx_ts.c
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -139,14 +139,14 @@
tsc_readl(tsc, LPC32XX_TSC_CON) &
~LPC32XX_TSC_ADCCON_AUTO_EN);
- clk_disable(tsc->clk);
+ clk_disable_unprepare(tsc->clk);
}
static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
{
u32 tmp;
- clk_enable(tsc->clk);
+ clk_prepare_enable(tsc->clk);
tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d9da766..cbe6a89 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -23,8 +23,7 @@
config IOMMU_IO_PGTABLE_LPAE
bool "ARMv7/v8 Long Descriptor Format"
select IOMMU_IO_PGTABLE
- # SWIOTLB guarantees a dma_to_phys() implementation
- depends on ARM || ARM64 || (COMPILE_TEST && SWIOTLB)
+ depends on HAS_DMA && (ARM || ARM64 || COMPILE_TEST)
help
Enable support for the ARM long descriptor pagetable format.
This allocator supports 4K/2M/1G, 16K/32M and 64K/512M page
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index f82060e7..532e2a2 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1974,8 +1974,8 @@
static void clear_dte_entry(u16 devid)
{
/* remove entry from the device table seen by the hardware */
- amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
- amd_iommu_dev_table[devid].data[1] = 0;
+ amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
+ amd_iommu_dev_table[devid].data[1] &= DTE_FLAG_MASK;
amd_iommu_apply_erratum_63(devid);
}
@@ -2006,6 +2006,15 @@
{
struct amd_iommu *iommu;
+ /*
+ * First check if the device is still attached. It might already
+ * be detached from its domain because the generic
+ * iommu_detach_group code detached it and we try again here in
+ * our alias handling.
+ */
+ if (!dev_data->domain)
+ return;
+
iommu = amd_iommu_rlookup_table[dev_data->devid];
/* decrease reference counters */
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 5ef347a..1b066e7 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -1256,6 +1256,9 @@
if (!iommu->dev)
return -ENODEV;
+ /* Prevent binding other PCI device drivers to IOMMU devices */
+ iommu->dev->match_driver = false;
+
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
&iommu->cap);
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET,
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index f659088..c9b6472 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -295,6 +295,7 @@
#define IOMMU_PTE_IR (1ULL << 61)
#define IOMMU_PTE_IW (1ULL << 62)
+#define DTE_FLAG_MASK (0x3ffULL << 32)
#define DTE_FLAG_IOTLB (0x01UL << 32)
#define DTE_FLAG_GV (0x01ULL << 55)
#define DTE_GLX_SHIFT (56)
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 1131664..d21d4ed 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -516,6 +516,13 @@
goto out;
}
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
+ /* handle_mm_fault would BUG_ON() */
+ up_read(&mm->mmap_sem);
+ handle_fault_error(fault);
+ goto out;
+ }
+
ret = handle_mm_fault(mm, vma, address, write);
if (ret & VM_FAULT_ERROR) {
/* failed to service fault */
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index dafaf59..286e890 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -56,6 +56,7 @@
#define IDR0_TTF_SHIFT 2
#define IDR0_TTF_MASK 0x3
#define IDR0_TTF_AARCH64 (2 << IDR0_TTF_SHIFT)
+#define IDR0_TTF_AARCH32_64 (3 << IDR0_TTF_SHIFT)
#define IDR0_S1P (1 << 1)
#define IDR0_S2P (1 << 0)
@@ -342,7 +343,8 @@
#define CMDQ_TLBI_0_VMID_SHIFT 32
#define CMDQ_TLBI_0_ASID_SHIFT 48
#define CMDQ_TLBI_1_LEAF (1UL << 0)
-#define CMDQ_TLBI_1_ADDR_MASK ~0xfffUL
+#define CMDQ_TLBI_1_VA_MASK ~0xfffUL
+#define CMDQ_TLBI_1_IPA_MASK 0xfffffffff000UL
#define CMDQ_PRI_0_SSID_SHIFT 12
#define CMDQ_PRI_0_SSID_MASK 0xfffffUL
@@ -770,11 +772,13 @@
break;
case CMDQ_OP_TLBI_NH_VA:
cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
- /* Fallthrough */
+ cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
+ cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK;
+ break;
case CMDQ_OP_TLBI_S2_IPA:
cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT;
cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
- cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_ADDR_MASK;
+ cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_IPA_MASK;
break;
case CMDQ_OP_TLBI_NH_ASID:
cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
@@ -2460,7 +2464,13 @@
}
/* We only support the AArch64 table format at present */
- if ((reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) < IDR0_TTF_AARCH64) {
+ switch (reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) {
+ case IDR0_TTF_AARCH32_64:
+ smmu->ias = 40;
+ /* Fallthrough */
+ case IDR0_TTF_AARCH64:
+ break;
+ default:
dev_err(smmu->dev, "AArch64 table format not supported!\n");
return -ENXIO;
}
@@ -2541,8 +2551,7 @@
dev_warn(smmu->dev,
"failed to set DMA mask for table walker\n");
- if (!smmu->ias)
- smmu->ias = smmu->oas;
+ smmu->ias = max(smmu->ias, smmu->oas);
dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n",
smmu->ias, smmu->oas, smmu->features);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 041bc18..d65cf42 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2115,15 +2115,19 @@
return -ENOMEM;
/* It is large page*/
if (largepage_lvl > 1) {
+ unsigned long nr_superpages, end_pfn;
+
pteval |= DMA_PTE_LARGE_PAGE;
lvl_pages = lvl_to_nr_pages(largepage_lvl);
+
+ nr_superpages = sg_res / lvl_pages;
+ end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
+
/*
* Ensure that old small page tables are
- * removed to make room for superpage,
- * if they exist.
+ * removed to make room for superpage(s).
*/
- dma_pte_free_pagetable(domain, iov_pfn,
- iov_pfn + lvl_pages - 1);
+ dma_pte_free_pagetable(domain, iov_pfn, end_pfn);
} else {
pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
}
@@ -2301,6 +2305,7 @@
if (ret) {
spin_unlock_irqrestore(&device_domain_lock, flags);
+ free_devinfo_mem(info);
return NULL;
}
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 73c0748..7df9777 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -202,9 +202,9 @@
static bool selftest_running = false;
-static dma_addr_t __arm_lpae_dma_addr(struct device *dev, void *pages)
+static dma_addr_t __arm_lpae_dma_addr(void *pages)
{
- return phys_to_dma(dev, virt_to_phys(pages));
+ return (dma_addr_t)virt_to_phys(pages);
}
static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
@@ -223,10 +223,10 @@
goto out_free;
/*
* We depend on the IOMMU being able to work with any physical
- * address directly, so if the DMA layer suggests it can't by
- * giving us back some translation, that bodes very badly...
+ * address directly, so if the DMA layer suggests otherwise by
+ * translating or truncating them, that bodes very badly...
*/
- if (dma != __arm_lpae_dma_addr(dev, pages))
+ if (dma != virt_to_phys(pages))
goto out_unmap;
}
@@ -243,10 +243,8 @@
static void __arm_lpae_free_pages(void *pages, size_t size,
struct io_pgtable_cfg *cfg)
{
- struct device *dev = cfg->iommu_dev;
-
if (!selftest_running)
- dma_unmap_single(dev, __arm_lpae_dma_addr(dev, pages),
+ dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages),
size, DMA_TO_DEVICE);
free_pages_exact(pages, size);
}
@@ -254,12 +252,11 @@
static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
struct io_pgtable_cfg *cfg)
{
- struct device *dev = cfg->iommu_dev;
-
*ptep = pte;
if (!selftest_running)
- dma_sync_single_for_device(dev, __arm_lpae_dma_addr(dev, ptep),
+ dma_sync_single_for_device(cfg->iommu_dev,
+ __arm_lpae_dma_addr(ptep),
sizeof(pte), DMA_TO_DEVICE);
}
@@ -629,6 +626,11 @@
if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS)
return NULL;
+ if (!selftest_running && cfg->iommu_dev->dma_pfn_offset) {
+ dev_err(cfg->iommu_dev, "Cannot accommodate DMA offset for IOMMU page tables\n");
+ return NULL;
+ }
+
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return NULL;
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 655cb96..389318a 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -317,6 +317,7 @@
handle_level_irq);
}
irq_set_probe(virq);
+ irq_clear_status_flags(virq, IRQ_NOAUTOEN);
return 0;
}
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index 2fd89eb..fd88e68 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -214,6 +214,7 @@
.irq_unmask = tegra_unmask,
.irq_retrigger = tegra_retrigger,
.irq_set_wake = tegra_set_wake,
+ .irq_set_type = irq_chip_set_type_parent,
.flags = IRQCHIP_MASK_ON_SUSPEND,
#ifdef CONFIG_SMP
.irq_set_affinity = irq_chip_set_affinity_parent,
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index 18accb0..c53a53f 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -1247,7 +1247,7 @@
l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct sk_buff *skb;
+ struct sk_buff *skb, *nskb;
struct Layer2 *l2 = &st->l2;
u_char header[MAX_HEADER_LEN];
int i, hdr_space_needed;
@@ -1262,14 +1262,10 @@
return;
hdr_space_needed = l2headersize(l2, 0);
- if (hdr_space_needed > skb_headroom(skb)) {
- struct sk_buff *orig_skb = skb;
-
- skb = skb_realloc_headroom(skb, hdr_space_needed);
- if (!skb) {
- dev_kfree_skb(orig_skb);
- return;
- }
+ nskb = skb_realloc_headroom(skb, hdr_space_needed);
+ if (!nskb) {
+ skb_queue_head(&l2->i_queue, skb);
+ return;
}
spin_lock_irqsave(&l2->lock, flags);
if (test_bit(FLG_MOD128, &l2->flag))
@@ -1282,7 +1278,7 @@
p1);
dev_kfree_skb(l2->windowar[p1]);
}
- l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
+ l2->windowar[p1] = skb;
i = sethdraddr(&st->l2, header, CMD);
@@ -1295,8 +1291,8 @@
l2->vs = (l2->vs + 1) % 8;
}
spin_unlock_irqrestore(&l2->lock, flags);
- memcpy(skb_push(skb, i), header, i);
- st->l2.l2l1(st, PH_PULL | INDICATION, skb);
+ memcpy(skb_push(nskb, i), header, i);
+ st->l2.l2l1(st, PH_PULL | INDICATION, nskb);
test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
FsmDelTimer(&st->l2.t203, 13);
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index 949cabb..5eb380a 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -1476,7 +1476,7 @@
l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
{
struct layer2 *l2 = fi->userdata;
- struct sk_buff *skb, *nskb, *oskb;
+ struct sk_buff *skb, *nskb;
u_char header[MAX_L2HEADER_LEN];
u_int i, p1;
@@ -1486,11 +1486,26 @@
skb = skb_dequeue(&l2->i_queue);
if (!skb)
return;
-
- if (test_bit(FLG_MOD128, &l2->flag))
+ i = sethdraddr(l2, header, CMD);
+ if (test_bit(FLG_MOD128, &l2->flag)) {
+ header[i++] = l2->vs << 1;
+ header[i++] = l2->vr << 1;
+ } else
+ header[i++] = (l2->vr << 5) | (l2->vs << 1);
+ nskb = skb_realloc_headroom(skb, i);
+ if (!nskb) {
+ printk(KERN_WARNING "%s: no headroom(%d) copy for IFrame\n",
+ mISDNDevName4ch(&l2->ch), i);
+ skb_queue_head(&l2->i_queue, skb);
+ return;
+ }
+ if (test_bit(FLG_MOD128, &l2->flag)) {
p1 = (l2->vs - l2->va) % 128;
- else
+ l2->vs = (l2->vs + 1) % 128;
+ } else {
p1 = (l2->vs - l2->va) % 8;
+ l2->vs = (l2->vs + 1) % 8;
+ }
p1 = (p1 + l2->sow) % l2->window;
if (l2->windowar[p1]) {
printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
@@ -1498,36 +1513,7 @@
dev_kfree_skb(l2->windowar[p1]);
}
l2->windowar[p1] = skb;
- i = sethdraddr(l2, header, CMD);
- if (test_bit(FLG_MOD128, &l2->flag)) {
- header[i++] = l2->vs << 1;
- header[i++] = l2->vr << 1;
- l2->vs = (l2->vs + 1) % 128;
- } else {
- header[i++] = (l2->vr << 5) | (l2->vs << 1);
- l2->vs = (l2->vs + 1) % 8;
- }
-
- nskb = skb_clone(skb, GFP_ATOMIC);
- p1 = skb_headroom(nskb);
- if (p1 >= i)
- memcpy(skb_push(nskb, i), header, i);
- else {
- printk(KERN_WARNING
- "%s: L2 pull_iqueue skb header(%d/%d) too short\n",
- mISDNDevName4ch(&l2->ch), i, p1);
- oskb = nskb;
- nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC);
- if (!nskb) {
- dev_kfree_skb(oskb);
- printk(KERN_WARNING "%s: no skb mem in %s\n",
- mISDNDevName4ch(&l2->ch), __func__);
- return;
- }
- memcpy(skb_put(nskb, i), header, i);
- memcpy(skb_put(nskb, oskb->len), oskb->data, oskb->len);
- dev_kfree_skb(oskb);
- }
+ memcpy(skb_push(nskb, i), header, i);
l2down(l2, PH_DATA_REQ, l2_newid(l2), nskb);
test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) {
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 20cc36b..0a17d1b 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -634,10 +634,10 @@
disk_super = dm_block_data(sblock);
+ disk_super->flags = cpu_to_le32(cmd->flags);
if (mutator)
update_flags(disk_super, mutator);
- disk_super->flags = cpu_to_le32(cmd->flags);
disk_super->mapping_root = cpu_to_le64(cmd->root);
disk_super->hint_root = cpu_to_le64(cmd->hint_root);
disk_super->discard_root = cpu_to_le64(cmd->discard_root);
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index aeacad9..117a05e 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -847,6 +847,7 @@
static int persistent_ctr(struct dm_exception_store *store, char *options)
{
struct pstore *ps;
+ int r;
/* allocate the pstore */
ps = kzalloc(sizeof(*ps), GFP_KERNEL);
@@ -868,9 +869,9 @@
ps->metadata_wq = alloc_workqueue("ksnaphd", WQ_MEM_RECLAIM, 0);
if (!ps->metadata_wq) {
- kfree(ps);
DMERR("couldn't start header metadata update thread");
- return -ENOMEM;
+ r = -ENOMEM;
+ goto err_workqueue;
}
if (options) {
@@ -879,13 +880,21 @@
store->userspace_supports_overflow = true;
else {
DMERR("Unsupported persistent store option: %s", options);
- return -EINVAL;
+ r = -EINVAL;
+ goto err_options;
}
}
store->context = ps;
return 0;
+
+err_options:
+ destroy_workqueue(ps->metadata_wq);
+err_workqueue:
+ kfree(ps);
+
+ return r;
}
static unsigned persistent_status(struct dm_exception_store *store,
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 6fcbfb0..3897b90 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -3201,7 +3201,7 @@
metadata_low_callback,
pool);
if (r)
- goto out_free_pt;
+ goto out_flags_changed;
pt->callbacks.congested_fn = pool_is_congested;
dm_table_add_target_callbacks(ti->table, &pt->callbacks);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c702de1..3fe3d04 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -8040,8 +8040,7 @@
!test_bit(Bitmap_sync, &rdev->flags)))
continue;
- if (rdev->saved_raid_disk < 0)
- rdev->recovery_offset = 0;
+ rdev->recovery_offset = 0;
if (mddev->pers->
hot_add_disk(mddev, rdev) == 0) {
if (sysfs_link_rdev(mddev, rdev))
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
index 421a36c..2e4c4cb 100644
--- a/drivers/md/persistent-data/dm-btree-remove.c
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -301,11 +301,16 @@
{
int s;
uint32_t max_entries = le32_to_cpu(left->header.max_entries);
- unsigned target = (nr_left + nr_center + nr_right) / 3;
- BUG_ON(target > max_entries);
+ unsigned total = nr_left + nr_center + nr_right;
+ unsigned target_right = total / 3;
+ unsigned remainder = (target_right * 3) != total;
+ unsigned target_left = target_right + remainder;
+
+ BUG_ON(target_left > max_entries);
+ BUG_ON(target_right > max_entries);
if (nr_left < nr_right) {
- s = nr_left - target;
+ s = nr_left - target_left;
if (s < 0 && nr_center < -s) {
/* not enough in central node */
@@ -316,10 +321,10 @@
} else
shift(left, center, s);
- shift(center, right, target - nr_right);
+ shift(center, right, target_right - nr_right);
} else {
- s = target - nr_right;
+ s = target_right - nr_right;
if (s > 0 && nr_center < s) {
/* not enough in central node */
shift(center, right, nr_center);
@@ -329,7 +334,7 @@
} else
shift(center, right, s);
- shift(left, center, nr_left - target);
+ shift(left, center, nr_left - target_left);
}
*key_ptr(parent, c->index) = center->keys[0];
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index b6cec25..0e09aef 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -523,7 +523,7 @@
r = new_block(s->info, &right);
if (r < 0) {
- /* FIXME: put left */
+ unlock_block(s->info, left);
return r;
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ddd8a5f..d9d031e 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2195,7 +2195,7 @@
bio_trim(wbio, sector - r1_bio->sector, sectors);
wbio->bi_iter.bi_sector += rdev->data_offset;
wbio->bi_bdev = rdev->bdev;
- if (submit_bio_wait(WRITE, wbio) == 0)
+ if (submit_bio_wait(WRITE, wbio) < 0)
/* failure! */
ok = rdev_set_badblocks(rdev, sector,
sectors, 0)
@@ -2258,15 +2258,16 @@
rdev_dec_pending(conf->mirrors[m].rdev,
conf->mddev);
}
- if (test_bit(R1BIO_WriteError, &r1_bio->state))
- close_write(r1_bio);
if (fail) {
spin_lock_irq(&conf->device_lock);
list_add(&r1_bio->retry_list, &conf->bio_end_io_list);
spin_unlock_irq(&conf->device_lock);
md_wakeup_thread(conf->mddev->thread);
- } else
+ } else {
+ if (test_bit(R1BIO_WriteError, &r1_bio->state))
+ close_write(r1_bio);
raid_end_bio_io(r1_bio);
+ }
}
static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
@@ -2385,6 +2386,10 @@
r1_bio = list_first_entry(&tmp, struct r1bio,
retry_list);
list_del(&r1_bio->retry_list);
+ if (mddev->degraded)
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+ if (test_bit(R1BIO_WriteError, &r1_bio->state))
+ close_write(r1_bio);
raid_end_bio_io(r1_bio);
}
}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9f69dc5..96f3659 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -39,6 +39,7 @@
* far_copies (stored in second byte of layout)
* far_offset (stored in bit 16 of layout )
* use_far_sets (stored in bit 17 of layout )
+ * use_far_sets_bugfixed (stored in bit 18 of layout )
*
* The data to be stored is divided into chunks using chunksize. Each device
* is divided into far_copies sections. In each section, chunks are laid out
@@ -1497,6 +1498,8 @@
seq_printf(seq, " %d offset-copies", conf->geo.far_copies);
else
seq_printf(seq, " %d far-copies", conf->geo.far_copies);
+ if (conf->geo.far_set_size != conf->geo.raid_disks)
+ seq_printf(seq, " %d devices per set", conf->geo.far_set_size);
}
seq_printf(seq, " [%d/%d] [", conf->geo.raid_disks,
conf->geo.raid_disks - mddev->degraded);
@@ -2467,7 +2470,7 @@
choose_data_offset(r10_bio, rdev) +
(sector - r10_bio->sector));
wbio->bi_bdev = rdev->bdev;
- if (submit_bio_wait(WRITE, wbio) == 0)
+ if (submit_bio_wait(WRITE, wbio) < 0)
/* Failure! */
ok = rdev_set_badblocks(rdev, sector,
sectors, 0)
@@ -2654,16 +2657,17 @@
rdev_dec_pending(rdev, conf->mddev);
}
}
- if (test_bit(R10BIO_WriteError,
- &r10_bio->state))
- close_write(r10_bio);
if (fail) {
spin_lock_irq(&conf->device_lock);
list_add(&r10_bio->retry_list, &conf->bio_end_io_list);
spin_unlock_irq(&conf->device_lock);
md_wakeup_thread(conf->mddev->thread);
- } else
+ } else {
+ if (test_bit(R10BIO_WriteError,
+ &r10_bio->state))
+ close_write(r10_bio);
raid_end_bio_io(r10_bio);
+ }
}
}
@@ -2691,6 +2695,12 @@
r10_bio = list_first_entry(&tmp, struct r10bio,
retry_list);
list_del(&r10_bio->retry_list);
+ if (mddev->degraded)
+ set_bit(R10BIO_Degraded, &r10_bio->state);
+
+ if (test_bit(R10BIO_WriteError,
+ &r10_bio->state))
+ close_write(r10_bio);
raid_end_bio_io(r10_bio);
}
}
@@ -3387,7 +3397,7 @@
disks = mddev->raid_disks + mddev->delta_disks;
break;
}
- if (layout >> 18)
+ if (layout >> 19)
return -1;
if (chunk < (PAGE_SIZE >> 9) ||
!is_power_of_2(chunk))
@@ -3399,7 +3409,22 @@
geo->near_copies = nc;
geo->far_copies = fc;
geo->far_offset = fo;
- geo->far_set_size = (layout & (1<<17)) ? disks / fc : disks;
+ switch (layout >> 17) {
+ case 0: /* original layout. simple but not always optimal */
+ geo->far_set_size = disks;
+ break;
+ case 1: /* "improved" layout which was buggy. Hopefully no-one is
+ * actually using this, but leave code here just in case.*/
+ geo->far_set_size = disks/fc;
+ WARN(geo->far_set_size < fc,
+ "This RAID10 layout does not provide data safety - please backup and create new array\n");
+ break;
+ case 2: /* "improved" layout fixed to match documentation */
+ geo->far_set_size = fc * nc;
+ break;
+ default: /* Not a valid layout */
+ return -1;
+ }
geo->chunk_mask = chunk - 1;
geo->chunk_shift = ffz(~chunk);
return nc*fc;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 49bb8d3..45933c1 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3499,6 +3499,7 @@
}
if (!discard_pending &&
test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) {
+ int hash;
clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags);
clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
if (sh->qd_idx >= 0) {
@@ -3512,16 +3513,17 @@
* no updated data, so remove it from hash list and the stripe
* will be reinitialized
*/
- spin_lock_irq(&conf->device_lock);
unhash:
+ hash = sh->hash_lock_index;
+ spin_lock_irq(conf->hash_locks + hash);
remove_hash(sh);
+ spin_unlock_irq(conf->hash_locks + hash);
if (head_sh->batch_head) {
sh = list_first_entry(&sh->batch_list,
struct stripe_head, batch_list);
if (sh != head_sh)
goto unhash;
}
- spin_unlock_irq(&conf->device_lock);
sh = head_sh;
if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
diff --git a/drivers/media/dvb-frontends/horus3a.h b/drivers/media/dvb-frontends/horus3a.h
index b055319..c1e2d18 100644
--- a/drivers/media/dvb-frontends/horus3a.h
+++ b/drivers/media/dvb-frontends/horus3a.h
@@ -46,8 +46,8 @@
const struct horus3a_config *config,
struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend *horus3a_attach(
- const struct cxd2820r_config *config,
+static inline struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe,
+ const struct horus3a_config *config,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
diff --git a/drivers/media/dvb-frontends/lnbh25.h b/drivers/media/dvb-frontends/lnbh25.h
index 69f30e2..1f329ef 100644
--- a/drivers/media/dvb-frontends/lnbh25.h
+++ b/drivers/media/dvb-frontends/lnbh25.h
@@ -43,7 +43,7 @@
struct lnbh25_config *cfg,
struct i2c_adapter *i2c);
#else
-static inline dvb_frontend *lnbh25_attach(
+static inline struct dvb_frontend *lnbh25_attach(
struct dvb_frontend *fe,
struct lnbh25_config *cfg,
struct i2c_adapter *i2c)
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index ff31e7a..feeeb70 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -18,6 +18,27 @@
static struct dvb_frontend_ops m88ds3103_ops;
+/* write single register with mask */
+static int m88ds3103_update_bits(struct m88ds3103_dev *dev,
+ u8 reg, u8 mask, u8 val)
+{
+ int ret;
+ u8 tmp;
+
+ /* no need for read if whole reg is written */
+ if (mask != 0xff) {
+ ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ val &= mask;
+ tmp &= ~mask;
+ val |= tmp;
+ }
+
+ return regmap_bulk_write(dev->regmap, reg, &val, 1);
+}
+
/* write reg val table using reg addr auto increment */
static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev,
const struct m88ds3103_reg_val *tab, int tab_len)
@@ -394,10 +415,10 @@
u8tmp2 = 0x00; /* 0b00 */
break;
}
- ret = regmap_update_bits(dev->regmap, 0x22, 0xc0, u8tmp1 << 6);
+ ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x24, 0xc0, u8tmp2 << 6);
+ ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6);
if (ret)
goto err;
}
@@ -455,13 +476,13 @@
if (ret)
goto err;
}
- ret = regmap_update_bits(dev->regmap, 0x9d, 0x08, 0x08);
+ ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08);
if (ret)
goto err;
ret = regmap_write(dev->regmap, 0xf1, 0x01);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x30, 0x80, 0x80);
+ ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
if (ret)
goto err;
}
@@ -498,7 +519,7 @@
switch (dev->cfg->ts_mode) {
case M88DS3103_TS_SERIAL:
case M88DS3103_TS_SERIAL_D7:
- ret = regmap_update_bits(dev->regmap, 0x29, 0x20, u8tmp1);
+ ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1);
if (ret)
goto err;
u8tmp1 = 0;
@@ -567,11 +588,11 @@
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x4d, 0x02, dev->cfg->spec_inv << 1);
+ ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x30, 0x10, dev->cfg->agc_inv << 4);
+ ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4);
if (ret)
goto err;
@@ -625,13 +646,13 @@
dev->warm = false;
/* wake up device from sleep */
- ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x01);
+ ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x01);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x00);
+ ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x00);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x00);
+ ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x00);
if (ret)
goto err;
@@ -749,18 +770,18 @@
utmp = 0x29;
else
utmp = 0x27;
- ret = regmap_update_bits(dev->regmap, utmp, 0x01, 0x00);
+ ret = m88ds3103_update_bits(dev, utmp, 0x01, 0x00);
if (ret)
goto err;
/* sleep */
- ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+ ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+ ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
if (ret)
goto err;
- ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+ ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
if (ret)
goto err;
@@ -992,12 +1013,12 @@
}
utmp = tone << 7 | dev->cfg->envelope_mode << 5;
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
if (ret)
goto err;
utmp = 1 << 2;
- ret = regmap_update_bits(dev->regmap, 0xa1, reg_a1_mask, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa1, reg_a1_mask, utmp);
if (ret)
goto err;
@@ -1047,7 +1068,7 @@
voltage_dis ^= dev->cfg->lnb_en_pol;
utmp = voltage_dis << 1 | voltage_sel << 0;
- ret = regmap_update_bits(dev->regmap, 0xa2, 0x03, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0x03, utmp);
if (ret)
goto err;
@@ -1080,7 +1101,7 @@
}
utmp = dev->cfg->envelope_mode << 5;
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
if (ret)
goto err;
@@ -1115,12 +1136,12 @@
} else {
dev_dbg(&client->dev, "diseqc tx timeout\n");
- ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+ ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
if (ret)
goto err;
}
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
if (ret)
goto err;
@@ -1152,7 +1173,7 @@
}
utmp = dev->cfg->envelope_mode << 5;
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
if (ret)
goto err;
@@ -1194,12 +1215,12 @@
} else {
dev_dbg(&client->dev, "diseqc tx timeout\n");
- ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+ ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
if (ret)
goto err;
}
- ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+ ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
if (ret)
goto err;
@@ -1435,13 +1456,13 @@
goto err_kfree;
/* sleep */
- ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+ ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
if (ret)
goto err_kfree;
- ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+ ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
if (ret)
goto err_kfree;
- ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+ ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
if (ret)
goto err_kfree;
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index 81788c5..821a8f4 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -502,6 +502,10 @@
/* firmware is in the new format */
for (remaining = fw->size; remaining > 0; remaining -= 17) {
len = fw->data[fw->size - remaining];
+ if (len > SI2168_ARGLEN) {
+ ret = -EINVAL;
+ break;
+ }
memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
cmd.wlen = len;
cmd.rlen = 1;
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
index f55b327..56773f3 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
@@ -80,11 +80,9 @@
u16 reg;
unsigned long flags;
- if (!spi) {
- dev_dbg(&spi->master->dev,
- "%s(): SPI not initialized\n", __func__);
+ if (!spi)
return IRQ_NONE;
- }
+
spin_lock_irqsave(&spi->lock, flags);
reg = readw(&spi->regs->control_stat);
if (!(reg & NETUP_SPI_CTRL_IRQ)) {
@@ -234,11 +232,9 @@
unsigned long flags;
struct netup_spi *spi = ndev->spi;
- if (!spi) {
- dev_dbg(&spi->master->dev,
- "%s(): SPI not initialized\n", __func__);
+ if (!spi)
return;
- }
+
spin_lock_irqsave(&spi->lock, flags);
reg = readw(&spi->regs->control_stat);
writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
index 486aef5..f922f2e 100644
--- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
+++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
@@ -1097,7 +1097,7 @@
Elf32_Ehdr *ehdr;
Elf32_Phdr *phdr;
u8 __iomem *dst;
- int err, i;
+ int err = 0, i;
if (!fw || !context)
return -EINVAL;
@@ -1106,7 +1106,7 @@
phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff);
/* go through the available ELF segments */
- for (i = 0; i < ehdr->e_phnum && !err; i++, phdr++) {
+ for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
/* Only consider LOAD segments */
if (phdr->p_type != PT_LOAD)
@@ -1192,7 +1192,6 @@
static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei)
{
- int ret;
int err;
dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
@@ -1207,7 +1206,7 @@
if (err) {
dev_err(fei->dev, "request_firmware_nowait err: %d.\n", err);
complete_all(&fei->fw_ack);
- return ret;
+ return err;
}
return 0;
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index 1c087cb..d0549fb 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -257,7 +257,7 @@
goto clkerr;
if (devm_request_irq(dev, priv->irq, hix5hd2_ir_rx_interrupt,
- IRQF_NO_SUSPEND, pdev->name, priv) < 0) {
+ 0, pdev->name, priv) < 0) {
dev_err(dev, "IRQ %d register failed\n", priv->irq);
ret = -EINVAL;
goto regerr;
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 5073821..ce157ed 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -166,6 +166,10 @@
for (remaining = fw->size; remaining > 0; remaining -= 17) {
len = fw->data[fw->size - remaining];
+ if (len > SI2157_ARGLEN) {
+ dev_err(&client->dev, "Bad firmware length\n");
+ goto err_release_firmware;
+ }
memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
cmd.wlen = len;
cmd.rlen = 1;
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index c3cac4c..197a4f2 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -34,6 +34,14 @@
unsigned int pipe;
u8 requesttype;
+ mutex_lock(&d->usb_mutex);
+
+ if (req->size > sizeof(dev->buf)) {
+ dev_err(&d->intf->dev, "too large message %u\n", req->size);
+ ret = -EINVAL;
+ goto err_mutex_unlock;
+ }
+
if (req->index & CMD_WR_FLAG) {
/* write */
memcpy(dev->buf, req->data, req->size);
@@ -50,14 +58,17 @@
dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value,
req->index, dev->buf, req->size);
if (ret < 0)
- goto err;
+ goto err_mutex_unlock;
/* read request, copy returned data to return buf */
if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
memcpy(req->data, dev->buf, req->size);
+ mutex_unlock(&d->usb_mutex);
+
return 0;
-err:
+err_mutex_unlock:
+ mutex_unlock(&d->usb_mutex);
dev_dbg(&d->intf->dev, "failed=%d\n", ret);
return ret;
}
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 9f6115a..1380629 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -71,7 +71,7 @@
struct rtl28xxu_dev {
- u8 buf[28];
+ u8 buf[128];
u8 chip_id;
u8 tuner;
char *tuner_name;
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 82876a6..9beece0 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -47,7 +47,7 @@
# Used by LED subsystem flash drivers
config V4L2_FLASH_LED_CLASS
tristate "V4L2 flash API for LED flash class devices"
- depends on VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on LEDS_CLASS_FLASH
---help---
Say Y here to enable V4L2 flash API support for LED flash
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index c6a644b..6f31546 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -58,12 +58,18 @@
memory drives like NOR, NAND, OneNAND, SRAM.
config OMAP_GPMC_DEBUG
- bool
+ bool "Enable GPMC debug output and skip reset of GPMC during init"
depends on OMAP_GPMC
help
Enables verbose debugging mostly to decode the bootloader provided
- timings. Enable this during development to configure devices
- connected to the GPMC bus.
+ timings. To preserve the bootloader provided timings, the reset
+ of GPMC is skipped during init. Enable this during development to
+ configure devices connected to the GPMC bus.
+
+ NOTE: In addition to matching the register setup with the bootloader
+ you also need to match the GPMC FCLK frequency used by the
+ bootloader or else the GPMC timings won't be identical with the
+ bootloader timings.
config MVEBU_DEVBUS
bool "Marvell EBU Device Bus Controller"
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 32ac049..6515dfc 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -696,7 +696,6 @@
int div;
u32 l;
- gpmc_cs_show_timings(cs, "before gpmc_cs_set_timings");
div = gpmc_calc_divider(t->sync_clk);
if (div < 0)
return div;
@@ -1988,6 +1987,7 @@
if (ret < 0)
goto err;
+ gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings");
ret = gpmc_cs_program_settings(cs, &gpmc_s);
if (ret < 0)
goto err;
diff --git a/drivers/mfd/intel-lpss.h b/drivers/mfd/intel-lpss.h
index f28cb28..2c7f8d7 100644
--- a/drivers/mfd/intel-lpss.h
+++ b/drivers/mfd/intel-lpss.h
@@ -42,6 +42,8 @@
.thaw = intel_lpss_resume, \
.poweroff = intel_lpss_suspend, \
.restore = intel_lpss_resume,
+#else
+#define INTEL_LPSS_SLEEP_PM_OPS
#endif
#define INTEL_LPSS_RUNTIME_PM_OPS \
diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c
index c52162e..586098f 100644
--- a/drivers/mfd/max77843.c
+++ b/drivers/mfd/max77843.c
@@ -80,7 +80,7 @@
if (!max77843->i2c_chg) {
dev_err(&max77843->i2c->dev,
"Cannot allocate I2C device for Charger\n");
- return PTR_ERR(max77843->i2c_chg);
+ return -ENODEV;
}
i2c_set_clientdata(max77843->i2c_chg, max77843);
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index 8af12c8..103baf0 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -105,6 +105,7 @@
void cxl_free_afu_irqs(struct cxl_context *ctx)
{
+ afu_irq_name_free(ctx);
cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
}
EXPORT_SYMBOL_GPL(cxl_free_afu_irqs);
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index e762f85..2faa127 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -275,6 +275,9 @@
if (ctx->kernelapi)
kfree(ctx->mapping);
+ if (ctx->irq_bitmap)
+ kfree(ctx->irq_bitmap);
+
kfree(ctx);
}
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 1c30ef7..0cfb9c1 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -677,6 +677,7 @@
void cxl_release_serr_irq(struct cxl_afu *afu);
int afu_register_irqs(struct cxl_context *ctx, u32 count);
void afu_release_irqs(struct cxl_context *ctx, void *cookie);
+void afu_irq_name_free(struct cxl_context *ctx);
irqreturn_t cxl_slice_irq_err(int irq, void *data);
int cxl_debugfs_init(void);
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index a30bf28..7ccd299 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -120,9 +120,16 @@
__func__, ctx->pe);
cxl_context_detach(ctx);
- mutex_lock(&ctx->mapping_lock);
- ctx->mapping = NULL;
- mutex_unlock(&ctx->mapping_lock);
+
+ /*
+ * Delete the context's mapping pointer, unless it's created by the
+ * kernel API, in which case leave it so it can be freed by reclaim_ctx()
+ */
+ if (!ctx->kernelapi) {
+ mutex_lock(&ctx->mapping_lock);
+ ctx->mapping = NULL;
+ mutex_unlock(&ctx->mapping_lock);
+ }
put_device(&ctx->afu->dev);
diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c
index 583b42a..09a4060 100644
--- a/drivers/misc/cxl/irq.c
+++ b/drivers/misc/cxl/irq.c
@@ -414,7 +414,7 @@
kfree(afu->psl_irq_name);
}
-static void afu_irq_name_free(struct cxl_context *ctx)
+void afu_irq_name_free(struct cxl_context *ctx)
{
struct cxl_irq_name *irq_name, *tmp;
@@ -524,7 +524,5 @@
afu_irq_name_free(ctx);
cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
- kfree(ctx->irq_bitmap);
- ctx->irq_bitmap = NULL;
ctx->irq_count = 0;
}
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index b37f2e8..d2e75c8 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -457,6 +457,7 @@
dev_info(&afu->dev, "Activating AFU directed mode\n");
+ afu->num_procs = afu->max_procs_virtualised;
if (afu->spa == NULL) {
if (cxl_alloc_spa(afu))
return -ENOMEM;
@@ -468,7 +469,6 @@
cxl_p1n_write(afu, CXL_PSL_ID_An, CXL_PSL_ID_An_F | CXL_PSL_ID_An_L);
afu->current_mode = CXL_MODE_DIRECTED;
- afu->num_procs = afu->max_procs_virtualised;
if ((rc = cxl_chardev_m_afu_add(afu)))
return rc;
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index a5e9771..85761d7 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -1035,6 +1035,32 @@
return 0;
}
+/*
+ * Workaround a PCIe Host Bridge defect on some cards, that can cause
+ * malformed Transaction Layer Packet (TLP) errors to be erroneously
+ * reported. Mask this error in the Uncorrectable Error Mask Register.
+ *
+ * The upper nibble of the PSL revision is used to distinguish between
+ * different cards. The affected ones have it set to 0.
+ */
+static void cxl_fixup_malformed_tlp(struct cxl *adapter, struct pci_dev *dev)
+{
+ int aer;
+ u32 data;
+
+ if (adapter->psl_rev & 0xf000)
+ return;
+ if (!(aer = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)))
+ return;
+ pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, &data);
+ if (data & PCI_ERR_UNC_MALF_TLP)
+ if (data & PCI_ERR_UNC_INTN)
+ return;
+ data |= PCI_ERR_UNC_MALF_TLP;
+ data |= PCI_ERR_UNC_INTN;
+ pci_write_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, data);
+}
+
static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev)
{
if (adapter->vsec_status & CXL_STATUS_SECOND_PORT)
@@ -1134,6 +1160,8 @@
if ((rc = cxl_vsec_looks_ok(adapter, dev)))
return rc;
+ cxl_fixup_malformed_tlp(adapter, dev);
+
if ((rc = setup_cxl_bars(dev)))
return rc;
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index b78cf5d..7fc9174 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -2263,15 +2263,12 @@
/*
* eMMC hardware reset.
*/
-static int mmc_test_hw_reset(struct mmc_test_card *test)
+static int mmc_test_reset(struct mmc_test_card *test)
{
struct mmc_card *card = test->card;
struct mmc_host *host = card->host;
int err;
- if (!mmc_card_mmc(card) || !mmc_can_reset(card))
- return RESULT_UNSUP_CARD;
-
err = mmc_hw_reset(host);
if (!err)
return RESULT_OK;
@@ -2605,8 +2602,8 @@
},
{
- .name = "eMMC hardware reset",
- .run = mmc_test_hw_reset,
+ .name = "Reset test",
+ .run = mmc_test_reset,
},
};
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index e726903..f6cd995 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1924,7 +1924,6 @@
static int mmc_reset(struct mmc_host *host)
{
struct mmc_card *card = host->card;
- u32 status;
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
return -EOPNOTSUPP;
@@ -1937,12 +1936,6 @@
host->ops->hw_reset(host);
- /* If the reset has happened, then a status command will fail */
- if (!mmc_send_status(card, &status)) {
- mmc_host_clk_release(host);
- return -ENOSYS;
- }
-
/* Set initial state and call mmc_set_ios */
mmc_set_initial_state(host);
mmc_host_clk_release(host);
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index e5fac36..131026f 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -87,6 +87,7 @@
{PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,},
#ifdef CONFIG_CAN_PEAK_PCIEC
{PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index 48ce83e..8d50314 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -847,21 +847,25 @@
if (ndev->irq == -ENXIO) {
netdev_err(ndev, "No irq resource\n");
ret = ndev->irq;
- goto out;
+ goto out_iounmap;
}
db->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(db->clk)) {
ret = PTR_ERR(db->clk);
- goto out;
+ goto out_iounmap;
}
- clk_prepare_enable(db->clk);
+ ret = clk_prepare_enable(db->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
+ goto out_iounmap;
+ }
ret = sunxi_sram_claim(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
- goto out;
+ goto out_clk_disable_unprepare;
}
db->phy_node = of_parse_phandle(np, "phy", 0);
@@ -910,6 +914,10 @@
out_release_sram:
sunxi_sram_release(&pdev->dev);
+out_clk_disable_unprepare:
+ clk_disable_unprepare(db->clk);
+out_iounmap:
+ iounmap(db->membase);
out:
dev_err(db->dev, "not found (%d).\n", ret);
@@ -921,8 +929,12 @@
static int emac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
+ struct emac_board_info *db = netdev_priv(ndev);
unregister_netdev(ndev);
+ sunxi_sram_release(&pdev->dev);
+ clk_disable_unprepare(db->clk);
+ iounmap(db->membase);
free_netdev(ndev);
dev_dbg(&pdev->dev, "released and freed device\n");
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index 2c063b6..96f485a 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -327,9 +327,13 @@
pdata->debugfs_xpcs_reg = 0;
buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
+ if (!buf)
+ return;
+
pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL);
if (!pdata->xgbe_debugfs) {
netdev_err(pdata->netdev, "debugfs_create_dir failed\n");
+ kfree(buf);
return;
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index a4473d8..f672dba 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1595,7 +1595,7 @@
packet->rdesc_count, 1);
/* Make sure ownership is written to the descriptor */
- dma_wmb();
+ smp_wmb();
ring->cur = cur_index + 1;
if (!packet->skb->xmit_more ||
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index aae9d5e..dde0486 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1807,6 +1807,7 @@
struct netdev_queue *txq;
int processed = 0;
unsigned int tx_packets = 0, tx_bytes = 0;
+ unsigned int cur;
DBGPR("-->xgbe_tx_poll\n");
@@ -1814,10 +1815,15 @@
if (!ring)
return 0;
+ cur = ring->cur;
+
+ /* Be sure we get ring->cur before accessing descriptor data */
+ smp_rmb();
+
txq = netdev_get_tx_queue(netdev, channel->queue_index);
while ((processed < XGBE_TX_DESC_MAX_PROC) &&
- (ring->dirty != ring->cur)) {
+ (ring->dirty != cur)) {
rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
rdesc = rdata->rdesc;
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index a7f2cc3..4183c2a 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -2049,7 +2049,7 @@
for (i = 0; i < priv->num_ports; i++) {
struct bcm63xx_enetsw_port *port;
- int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
+ int val, j, up, advertise, lpa, speed, duplex, media;
int external_phy = bcm_enet_port_is_rgmii(i);
u8 override;
@@ -2092,22 +2092,27 @@
lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
MII_LPA);
- lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
- MII_STAT1000);
-
/* figure out media and duplex from advertise and LPA values */
media = mii_nway_result(lpa & advertise);
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
- if (lpa2 & LPA_1000FULL)
- duplex = 1;
- if (lpa2 & (LPA_1000FULL | LPA_1000HALF))
- speed = 1000;
- else {
- if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
- speed = 100;
- else
- speed = 10;
+ if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+ speed = 100;
+ else
+ speed = 10;
+
+ if (val & BMSR_ESTATEN) {
+ advertise = bcmenet_sw_mdio_read(priv, external_phy,
+ port->phy_id, MII_CTRL1000);
+
+ lpa = bcmenet_sw_mdio_read(priv, external_phy,
+ port->phy_id, MII_STAT1000);
+
+ if (advertise & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)
+ && lpa & (LPA_1000FULL | LPA_1000HALF)) {
+ speed = 1000;
+ duplex = (lpa & LPA_1000FULL);
+ }
}
dev_info(&priv->pdev->dev,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index aeb7ce6..be628bd 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -3351,6 +3351,13 @@
udp_rss_requested = 0;
else
return -EINVAL;
+
+ if (CHIP_IS_E1x(bp) && udp_rss_requested) {
+ DP(BNX2X_MSG_ETHTOOL,
+ "57710, 57711 boards don't support RSS according to UDP 4-tuple\n");
+ return -EINVAL;
+ }
+
if ((info->flow_type == UDP_V4_FLOW) &&
(bp->rss_conf_obj.udp_rss_v4 != udp_rss_requested)) {
bp->rss_conf_obj.udp_rss_v4 = udp_rss_requested;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 3bc701e..1805541 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1683,6 +1683,24 @@
bcmgenet_intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
}
+static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)
+{
+ u32 int0_enable = 0;
+
+ /* Monitor cable plug/unplugged event for internal PHY, external PHY
+ * and MoCA PHY
+ */
+ if (priv->internal_phy) {
+ int0_enable |= UMAC_IRQ_LINK_EVENT;
+ } else if (priv->ext_phy) {
+ int0_enable |= UMAC_IRQ_LINK_EVENT;
+ } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
+ if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
+ int0_enable |= UMAC_IRQ_LINK_EVENT;
+ }
+ bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
+}
+
static int init_umac(struct bcmgenet_priv *priv)
{
struct device *kdev = &priv->pdev->dev;
@@ -1723,15 +1741,8 @@
/* Enable Tx default queue 16 interrupts */
int0_enable |= UMAC_IRQ_TXDMA_DONE;
- /* Monitor cable plug/unplugged event for internal PHY */
- if (priv->internal_phy) {
- int0_enable |= UMAC_IRQ_LINK_EVENT;
- } else if (priv->ext_phy) {
- int0_enable |= UMAC_IRQ_LINK_EVENT;
- } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
- if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
- int0_enable |= UMAC_IRQ_LINK_EVENT;
-
+ /* Configure backpressure vectors for MoCA */
+ if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
reg = bcmgenet_bp_mc_get(priv);
reg |= BIT(priv->hw_params->bp_in_en_shift);
@@ -2645,6 +2656,9 @@
netif_tx_start_all_queues(dev);
+ /* Monitor link interrupts now */
+ bcmgenet_link_intr_enable(priv);
+
phy_start(priv->phydev);
}
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 9b35d14..8fb84e6 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -3,7 +3,7 @@
#
config NET_VENDOR_CAVIUM
- tristate "Cavium ethernet drivers"
+ bool "Cavium ethernet drivers"
depends on PCI
default y
---help---
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index b3a5947..c561fdc 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -22,7 +22,6 @@
struct nicpf {
struct pci_dev *pdev;
- u8 rev_id;
u8 node;
unsigned int flags;
u8 num_vf_en; /* No of VF enabled */
@@ -44,6 +43,7 @@
u8 duplex[MAX_LMAC];
u32 speed[MAX_LMAC];
u16 cpi_base[MAX_NUM_VFS_SUPPORTED];
+ u16 rssi_base[MAX_NUM_VFS_SUPPORTED];
u16 rss_ind_tbl_size;
bool mbx_lock[MAX_NUM_VFS_SUPPORTED];
@@ -54,6 +54,11 @@
bool irq_allocated[NIC_PF_MSIX_VECTORS];
};
+static inline bool pass1_silicon(struct nicpf *nic)
+{
+ return nic->pdev->revision < 8;
+}
+
/* Supported devices */
static const struct pci_device_id nic_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_NIC_PF) },
@@ -117,7 +122,7 @@
* when PF writes to MBOX(1), in next revisions when
* PF writes to MBOX(0)
*/
- if (nic->rev_id == 0) {
+ if (pass1_silicon(nic)) {
/* see the comment for nic_reg_write()/nic_reg_read()
* functions above
*/
@@ -305,9 +310,6 @@
{
int i;
- /* Reset NIC, in case the driver is repeatedly inserted and removed */
- nic_reg_write(nic, NIC_PF_SOFT_RESET, 1);
-
/* Enable NIC HW block */
nic_reg_write(nic, NIC_PF_CFG, 0x3);
@@ -395,8 +397,18 @@
padd = cpi % 8; /* 3 bits CS out of 6bits DSCP */
/* Leave RSS_SIZE as '0' to disable RSS */
- nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
- (vnic << 24) | (padd << 16) | (rssi_base + rssi));
+ if (pass1_silicon(nic)) {
+ nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
+ (vnic << 24) | (padd << 16) |
+ (rssi_base + rssi));
+ } else {
+ /* Set MPI_ALG to '0' to disable MCAM parsing */
+ nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
+ (padd << 16));
+ /* MPI index is same as CPI if MPI_ALG is not enabled */
+ nic_reg_write(nic, NIC_PF_MPI_0_2047_CFG | (cpi << 3),
+ (vnic << 24) | (rssi_base + rssi));
+ }
if ((rssi + 1) >= cfg->rq_cnt)
continue;
@@ -409,6 +421,7 @@
rssi = ((cpi - cpi_base) & 0x38) >> 3;
}
nic->cpi_base[cfg->vf_id] = cpi_base;
+ nic->rssi_base[cfg->vf_id] = rssi_base;
}
/* Responsds to VF with its RSS indirection table size */
@@ -434,10 +447,9 @@
{
u8 qset, idx = 0;
u64 cpi_cfg, cpi_base, rssi_base, rssi;
+ u64 idx_addr;
- cpi_base = nic->cpi_base[cfg->vf_id];
- cpi_cfg = nic_reg_read(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3));
- rssi_base = (cpi_cfg & 0x0FFF) + cfg->tbl_offset;
+ rssi_base = nic->rssi_base[cfg->vf_id] + cfg->tbl_offset;
rssi = rssi_base;
qset = cfg->vf_id;
@@ -454,9 +466,15 @@
idx++;
}
+ cpi_base = nic->cpi_base[cfg->vf_id];
+ if (pass1_silicon(nic))
+ idx_addr = NIC_PF_CPI_0_2047_CFG;
+ else
+ idx_addr = NIC_PF_MPI_0_2047_CFG;
+ cpi_cfg = nic_reg_read(nic, idx_addr | (cpi_base << 3));
cpi_cfg &= ~(0xFULL << 20);
cpi_cfg |= (cfg->hash_bits << 20);
- nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3), cpi_cfg);
+ nic_reg_write(nic, idx_addr | (cpi_base << 3), cpi_cfg);
}
/* 4 level transmit side scheduler configutation
@@ -1001,8 +1019,6 @@
goto err_release_regions;
}
- pci_read_config_byte(pdev, PCI_REVISION_ID, &nic->rev_id);
-
nic->node = nic_get_node_id(pdev);
nic_set_lmac_vf_mapping(nic);
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index 58197bb..dd536be 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -85,7 +85,11 @@
#define NIC_PF_ECC3_DBE_INT_W1S (0x2708)
#define NIC_PF_ECC3_DBE_ENA_W1C (0x2710)
#define NIC_PF_ECC3_DBE_ENA_W1S (0x2718)
+#define NIC_PF_MCAM_0_191_ENA (0x100000)
+#define NIC_PF_MCAM_0_191_M_0_5_DATA (0x110000)
+#define NIC_PF_MCAM_CTRL (0x120000)
#define NIC_PF_CPI_0_2047_CFG (0x200000)
+#define NIC_PF_MPI_0_2047_CFG (0x210000)
#define NIC_PF_RSSI_0_4097_RQ (0x220000)
#define NIC_PF_LMAC_0_7_CFG (0x240000)
#define NIC_PF_LMAC_0_7_SW_XOFF (0x242000)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index b63e579..a937772 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -29,7 +29,7 @@
static const struct pci_device_id nicvf_id_table[] = {
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM,
PCI_DEVICE_ID_THUNDER_NIC_VF,
- PCI_VENDOR_ID_CAVIUM, 0xA11E) },
+ PCI_VENDOR_ID_CAVIUM, 0xA134) },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM,
PCI_DEVICE_ID_THUNDER_PASS1_NIC_VF,
PCI_VENDOR_ID_CAVIUM, 0xA11E) },
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 574c492..180aa9f 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -977,8 +977,10 @@
SET_NETDEV_DEV(&bgx->lmac[lmac].netdev, &bgx->pdev->dev);
bgx->lmac[lmac].lmacid = lmac;
lmac++;
- if (lmac == MAX_LMAC_PER_BGX)
+ if (lmac == MAX_LMAC_PER_BGX) {
+ of_node_put(np_child);
break;
+ }
}
return 0;
}
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 8215409..d463563 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -592,6 +592,7 @@
int be_get_temp_freq;
struct be_hwmon hwmon_info;
u8 pf_number;
+ u8 pci_func_num;
struct rss_info rss_info;
/* Filters for packets that need to be sent to BMC */
u32 bmc_filt_mask;
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index eb32391..1795c93 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -851,8 +851,10 @@
return status;
dest_wrb = be_cmd_copy(adapter, wrb);
- if (!dest_wrb)
- return -EBUSY;
+ if (!dest_wrb) {
+ status = -EBUSY;
+ goto unlock;
+ }
if (use_mcc(adapter))
status = be_mcc_notify_wait(adapter);
@@ -862,6 +864,7 @@
if (!status)
memcpy(wrb, dest_wrb, sizeof(*wrb));
+unlock:
be_cmd_unlock(adapter);
return status;
}
@@ -1984,6 +1987,8 @@
be_if_cap_flags(adapter));
}
flags &= be_if_cap_flags(adapter);
+ if (!flags)
+ return -ENOTSUPP;
return __be_cmd_rx_filter(adapter, flags, value);
}
@@ -2887,6 +2892,7 @@
if (!status) {
attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
adapter->hba_port_num = attribs->hba_attribs.phy_port;
+ adapter->pci_func_num = attribs->pci_func_num;
serial_num = attribs->hba_attribs.controller_serial_number;
for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++)
adapter->serial_num[i] = le32_to_cpu(serial_num[i]) &
@@ -3709,7 +3715,6 @@
status = -EINVAL;
goto err;
}
-
adapter->pf_number = desc->pf_num;
be_copy_nic_desc(res, desc);
}
@@ -3721,7 +3726,10 @@
return status;
}
-/* Will use MBOX only if MCCQ has not been created */
+/* Will use MBOX only if MCCQ has not been created
+ * non-zero domain => a PF is querying this on behalf of a VF
+ * zero domain => a PF or a VF is querying this for itself
+ */
int be_cmd_get_profile_config(struct be_adapter *adapter,
struct be_resources *res, u8 query, u8 domain)
{
@@ -3748,10 +3756,15 @@
OPCODE_COMMON_GET_PROFILE_CONFIG,
cmd.size, &wrb, &cmd);
- req->hdr.domain = domain;
if (!lancer_chip(adapter))
req->hdr.version = 1;
req->type = ACTIVE_PROFILE_TYPE;
+ /* When a function is querying profile information relating to
+ * itself hdr.pf_number must be set to it's pci_func_num + 1
+ */
+ req->hdr.domain = domain;
+ if (domain == 0)
+ req->hdr.pf_num = adapter->pci_func_num + 1;
/* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
* descriptors with all bits set to "1" for the fields which can be
@@ -3921,12 +3934,16 @@
vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS |
BE_IF_FLAGS_DEFQ_RSS);
}
-
- nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
} else {
num_vf_qs = 1;
}
+ if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
+ nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
+ vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
+ }
+
+ nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
nic_vft->rq_count = cpu_to_le16(num_vf_qs);
nic_vft->txq_count = cpu_to_le16(num_vf_qs);
nic_vft->rssq_count = cpu_to_le16(num_vf_qs);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 7d178bd..91155ea 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -289,7 +289,9 @@
u32 timeout; /* dword 1 */
u32 request_length; /* dword 2 */
u8 version; /* dword 3 */
- u8 rsvd[3]; /* dword 3 */
+ u8 rsvd1; /* dword 3 */
+ u8 pf_num; /* dword 3 */
+ u8 rsvd2; /* dword 3 */
};
#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */
@@ -1652,7 +1654,11 @@
struct mgmt_controller_attrib {
struct mgmt_hba_attribs hba_attribs;
- u32 rsvd0[10];
+ u32 rsvd0[2];
+ u16 rsvd1;
+ u8 pci_func_num;
+ u8 rsvd2;
+ u32 rsvd3[7];
} __packed;
struct be_cmd_req_cntl_attribs {
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 7bf51a1..eb48a97 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1123,11 +1123,12 @@
struct sk_buff *skb,
struct be_wrb_params *wrb_params)
{
- /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or
- * less may cause a transmit stall on that port. So the work-around is
- * to pad short packets (<= 32 bytes) to a 36-byte length.
+ /* Lancer, SH and BE3 in SRIOV mode have a bug wherein
+ * packets that are 32b or less may cause a transmit stall
+ * on that port. The workaround is to pad such packets
+ * (len <= 32 bytes) to a minimum length of 36b.
*/
- if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
+ if (skb->len <= 32) {
if (skb_put_padto(skb, 36))
return NULL;
}
@@ -4205,10 +4206,6 @@
int status, level;
u16 profile_id;
- status = be_cmd_get_cntl_attributes(adapter);
- if (status)
- return status;
-
status = be_cmd_query_fw_cfg(adapter);
if (status)
return status;
@@ -4407,6 +4404,11 @@
if (!lancer_chip(adapter))
be_cmd_req_native_mode(adapter);
+ /* Need to invoke this cmd first to get the PCI Function Number */
+ status = be_cmd_get_cntl_attributes(adapter);
+ if (status)
+ return status;
+
if (!BE2_chip(adapter) && be_physfn(adapter))
be_alloc_sriov_res(adapter);
@@ -4999,7 +5001,15 @@
return false;
}
- return (fhdr->asic_type_rev >= adapter->asic_rev);
+ /* In BE3 FW images the "asic_type_rev" field doesn't track the
+ * asic_rev of the chips it is compatible with.
+ * When asic_type_rev is 0 the image is compatible only with
+ * pre-BE3-R chips (asic_rev < 0x10)
+ */
+ if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
+ return adapter->asic_rev < 0x10;
+ else
+ return (fhdr->asic_type_rev >= adapter->asic_rev);
}
static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 3c40f6b..55c3623 100644
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@ -198,11 +198,13 @@
#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
/*
+ * Return the TBIPA address, starting from the address
+ * of the mapped GFAR MDIO registers (struct gfar)
* This is mildly evil, but so is our hardware for doing this.
* Also, we have to cast back to struct gfar because of
* definition weirdness done in gianfar.h.
*/
-static uint32_t __iomem *get_gfar_tbipa(void __iomem *p)
+static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p)
{
struct gfar __iomem *enet_regs = p;
@@ -210,6 +212,15 @@
}
/*
+ * Return the TBIPA address, starting from the address
+ * of the mapped GFAR MII registers (gfar_mii_regs[] within struct gfar)
+ */
+static uint32_t __iomem *get_gfar_tbipa_from_mii(void __iomem *p)
+{
+ return get_gfar_tbipa_from_mdio(container_of(p, struct gfar, gfar_mii_regs));
+}
+
+/*
* Return the TBIPAR address for an eTSEC2 node
*/
static uint32_t __iomem *get_etsec_tbipa(void __iomem *p)
@@ -220,11 +231,12 @@
#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
/*
- * Return the TBIPAR address for a QE MDIO node
+ * Return the TBIPAR address for a QE MDIO node, starting from the address
+ * of the mapped MII registers (struct fsl_pq_mii)
*/
static uint32_t __iomem *get_ucc_tbipa(void __iomem *p)
{
- struct fsl_pq_mdio __iomem *mdio = p;
+ struct fsl_pq_mdio __iomem *mdio = container_of(p, struct fsl_pq_mdio, mii);
return &mdio->utbipar;
}
@@ -300,14 +312,14 @@
.compatible = "fsl,gianfar-tbi",
.data = &(struct fsl_pq_mdio_data) {
.mii_offset = 0,
- .get_tbipa = get_gfar_tbipa,
+ .get_tbipa = get_gfar_tbipa_from_mii,
},
},
{
.compatible = "fsl,gianfar-mdio",
.data = &(struct fsl_pq_mdio_data) {
.mii_offset = 0,
- .get_tbipa = get_gfar_tbipa,
+ .get_tbipa = get_gfar_tbipa_from_mii,
},
},
{
@@ -315,7 +327,7 @@
.compatible = "gianfar",
.data = &(struct fsl_pq_mdio_data) {
.mii_offset = offsetof(struct fsl_pq_mdio, mii),
- .get_tbipa = get_gfar_tbipa,
+ .get_tbipa = get_gfar_tbipa_from_mdio,
},
},
{
@@ -445,6 +457,16 @@
tbipa = data->get_tbipa(priv->map);
+ /*
+ * Add consistency check to make sure TBI is contained
+ * within the mapped range (not because we would get a
+ * segfault, rather to catch bugs in computing TBI
+ * address). Print error message but continue anyway.
+ */
+ if ((void *)tbipa > priv->map + resource_size(&res) - 4)
+ dev_err(&pdev->dev, "invalid register map (should be at least 0x%04x to contain TBI address)\n",
+ ((void *)tbipa - priv->map) + 4);
+
iowrite32be(be32_to_cpup(prop), tbipa);
}
}
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 710715f..ce38d26 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -341,7 +341,7 @@
if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX))
priv->uses_rxfcb = 1;
- if (priv->hwts_rx_en)
+ if (priv->hwts_rx_en || priv->rx_filer_enable)
priv->uses_rxfcb = 1;
}
@@ -351,7 +351,7 @@
u32 rctrl = 0;
if (priv->rx_filer_enable) {
- rctrl |= RCTRL_FILREN;
+ rctrl |= RCTRL_FILREN | RCTRL_PRSDEP_INIT;
/* Program the RIR0 reg with the required distribution */
if (priv->poll_mode == GFAR_SQ_POLLING)
gfar_write(®s->rir0, DEFAULT_2RXQ_RIR0);
@@ -3462,11 +3462,9 @@
netif_dbg(priv, tx_err, dev, "Transmit Error\n");
}
if (events & IEVENT_BSY) {
- dev->stats.rx_errors++;
+ dev->stats.rx_over_errors++;
atomic64_inc(&priv->extra_stats.rx_bsy);
- gfar_receive(irq, grp_id);
-
netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n",
gfar_read(®s->rstat));
}
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 6bdc891..a33e4a8 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -676,14 +676,14 @@
u32 fcr = 0x0, fpr = FPR_FILER_MASK;
if (ethflow & RXH_L2DA) {
- fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH |
+ fcr = RQFCR_PID_DAH | RQFCR_CMP_NOMATCH |
RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
priv->cur_filer_idx = priv->cur_filer_idx - 1;
- fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH |
+ fcr = RQFCR_PID_DAL | RQFCR_CMP_NOMATCH |
RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index 62488a6..c0e943a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -386,7 +386,6 @@
hw->aq.asq.next_to_use = 0;
hw->aq.asq.next_to_clean = 0;
- hw->aq.asq.count = hw->aq.num_asq_entries;
/* allocate the ring memory */
ret_code = i40e_alloc_adminq_asq_ring(hw);
@@ -404,6 +403,7 @@
goto init_adminq_free_rings;
/* success! */
+ hw->aq.asq.count = hw->aq.num_asq_entries;
goto init_adminq_exit;
init_adminq_free_rings:
@@ -445,7 +445,6 @@
hw->aq.arq.next_to_use = 0;
hw->aq.arq.next_to_clean = 0;
- hw->aq.arq.count = hw->aq.num_arq_entries;
/* allocate the ring memory */
ret_code = i40e_alloc_adminq_arq_ring(hw);
@@ -463,6 +462,7 @@
goto init_adminq_free_rings;
/* success! */
+ hw->aq.arq.count = hw->aq.num_arq_entries;
goto init_adminq_exit;
init_adminq_free_rings:
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index e972b5e..13a5d4c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -1344,6 +1344,12 @@
data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
+ for (j = 0; j < I40E_MAX_TRAFFIC_CLASS; j++) {
+ data[i++] = veb->tc_stats.tc_tx_packets[j];
+ data[i++] = veb->tc_stats.tc_tx_bytes[j];
+ data[i++] = veb->tc_stats.tc_rx_packets[j];
+ data[i++] = veb->tc_stats.tc_rx_bytes[j];
+ }
}
for (j = 0; j < I40E_GLOBAL_STATS_LEN; j++) {
p = (char *)pf + i40e_gstrings_stats[j].stat_offset;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 2fdf978..3dd26cd 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -7911,6 +7911,7 @@
if (pf->hw.func_caps.vmdq) {
pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI;
pf->flags |= I40E_FLAG_VMDQ_ENABLED;
+ pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf);
}
#ifdef I40E_FCOE
@@ -8389,6 +8390,7 @@
netdev->hw_enc_features |= NETIF_F_IP_CSUM |
NETIF_F_GSO_UDP_TUNNEL |
+ NETIF_F_GSO_GRE |
NETIF_F_TSO;
netdev->features = NETIF_F_SG |
@@ -8396,6 +8398,7 @@
NETIF_F_SCTP_CSUM |
NETIF_F_HIGHDMA |
NETIF_F_GSO_UDP_TUNNEL |
+ NETIF_F_GSO_GRE |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER |
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
index 929d471..a23ebfd 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
@@ -373,7 +373,6 @@
hw->aq.asq.next_to_use = 0;
hw->aq.asq.next_to_clean = 0;
- hw->aq.asq.count = hw->aq.num_asq_entries;
/* allocate the ring memory */
ret_code = i40e_alloc_adminq_asq_ring(hw);
@@ -391,6 +390,7 @@
goto init_adminq_free_rings;
/* success! */
+ hw->aq.asq.count = hw->aq.num_asq_entries;
goto init_adminq_exit;
init_adminq_free_rings:
@@ -432,7 +432,6 @@
hw->aq.arq.next_to_use = 0;
hw->aq.arq.next_to_clean = 0;
- hw->aq.arq.count = hw->aq.num_arq_entries;
/* allocate the ring memory */
ret_code = i40e_alloc_adminq_arq_ring(hw);
@@ -450,6 +449,7 @@
goto init_adminq_free_rings;
/* success! */
+ hw->aq.arq.count = hw->aq.num_arq_entries;
goto init_adminq_exit;
init_adminq_free_rings:
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 960169e..dfb6d5f 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -759,11 +759,23 @@
desc->l4i_chk = 0;
desc->byte_cnt = length;
- desc->buf_ptr = dma_map_single(dev->dev.parent, data,
- length, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(dev->dev.parent, desc->buf_ptr))) {
- WARN(1, "dma_map_single failed!\n");
- return -ENOMEM;
+
+ if (length <= 8 && (uintptr_t)data & 0x7) {
+ /* Copy unaligned small data fragment to TSO header data area */
+ memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE,
+ data, length);
+ desc->buf_ptr = txq->tso_hdrs_dma
+ + txq->tx_curr_desc * TSO_HEADER_SIZE;
+ } else {
+ /* Alignment is okay, map buffer and hand off to hardware */
+ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
+ desc->buf_ptr = dma_map_single(dev->dev.parent, data,
+ length, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev->dev.parent,
+ desc->buf_ptr))) {
+ WARN(1, "dma_map_single failed!\n");
+ return -ENOMEM;
+ }
}
cmd_sts = BUFFER_OWNED_BY_DMA;
@@ -779,7 +791,8 @@
}
static inline void
-txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
+txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length,
+ u32 *first_cmd_sts, bool first_desc)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -788,6 +801,7 @@
int ret;
u32 cmd_csum = 0;
u16 l4i_chk = 0;
+ u32 cmd_sts;
tx_index = txq->tx_curr_desc;
desc = &txq->tx_desc_area[tx_index];
@@ -803,9 +817,17 @@
desc->byte_cnt = hdr_len;
desc->buf_ptr = txq->tso_hdrs_dma +
txq->tx_curr_desc * TSO_HEADER_SIZE;
- desc->cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC |
+ cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC |
GEN_CRC;
+ /* Defer updating the first command descriptor until all
+ * following descriptors have been written.
+ */
+ if (first_desc)
+ *first_cmd_sts = cmd_sts;
+ else
+ desc->cmd_sts = cmd_sts;
+
txq->tx_curr_desc++;
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
@@ -819,6 +841,8 @@
int desc_count = 0;
struct tso_t tso;
int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ struct tx_desc *first_tx_desc;
+ u32 first_cmd_sts = 0;
/* Count needed descriptors */
if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) {
@@ -826,11 +850,14 @@
return -EBUSY;
}
+ first_tx_desc = &txq->tx_desc_area[txq->tx_curr_desc];
+
/* Initialize the TSO handler, and prepare the first payload */
tso_start(skb, &tso);
total_len = skb->len - hdr_len;
while (total_len > 0) {
+ bool first_desc = (desc_count == 0);
char *hdr;
data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
@@ -840,7 +867,8 @@
/* prepare packet headers: MAC + IP + TCP */
hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE;
tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
- txq_put_hdr_tso(skb, txq, data_left);
+ txq_put_hdr_tso(skb, txq, data_left, &first_cmd_sts,
+ first_desc);
while (data_left > 0) {
int size;
@@ -860,6 +888,10 @@
__skb_queue_tail(&txq->tx_skb, skb);
skb_tx_timestamp(skb);
+ /* ensure all other descriptors are written before first cmd_sts */
+ wmb();
+ first_tx_desc->cmd_sts = first_cmd_sts;
+
/* clear TX_END status */
mp->work_tx_end &= ~(1 << txq->index);
@@ -2785,8 +2817,10 @@
for_each_available_child_of_node(np, pnp) {
ret = mv643xx_eth_shared_of_add_port(pdev, pnp);
- if (ret)
+ if (ret) {
+ of_node_put(pnp);
return ret;
+ }
}
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 0a32020..2177e56 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -2398,7 +2398,7 @@
}
}
- memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
+ memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe));
priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
INIT_WORK(&priv->mfunc.master.comm_work,
mlx4_master_comm_channel);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 494e776..4421bf5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -964,6 +964,8 @@
tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_SVLAN;
else if (vlan_proto == ETH_P_8021Q)
tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_CVLAN;
+ else
+ tx_desc->ctrl.ins_vlan = 0;
tx_desc->ctrl.fence_size = real_size;
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 8e81e53..603d1c3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -196,7 +196,7 @@
return;
}
- memcpy(s_eqe, eqe, dev->caps.eqe_size - 1);
+ memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1);
s_eqe->slave_id = slave;
/* ensure all information is written before setting the ownersip bit */
dma_wmb();
@@ -1364,6 +1364,10 @@
* and performing a NOP command
*/
for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
+ /* Make sure request_irq was called */
+ if (!priv->eq_table.eq[i].have_irq)
+ continue;
+
/* Temporary use polling for command completions */
mlx4_cmd_use_polling(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 006757f..cc3a989 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -2669,14 +2669,11 @@
if (msi_x) {
int nreq = dev->caps.num_ports * num_online_cpus() + 1;
- bool shared_ports = false;
nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
nreq);
- if (nreq > MAX_MSIX) {
+ if (nreq > MAX_MSIX)
nreq = MAX_MSIX;
- shared_ports = true;
- }
entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
if (!entries)
@@ -2699,9 +2696,6 @@
bitmap_zero(priv->eq_table.eq[MLX4_EQ_ASYNC].actv_ports.ports,
dev->caps.num_ports);
- if (MLX4_IS_LEGACY_EQ_MODE(dev->caps))
- shared_ports = true;
-
for (i = 0; i < dev->caps.num_comp_vectors + 1; i++) {
if (i == MLX4_EQ_ASYNC)
continue;
@@ -2709,7 +2703,7 @@
priv->eq_table.eq[i].irq =
entries[i + 1 - !!(i > MLX4_EQ_ASYNC)].vector;
- if (shared_ports) {
+ if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) {
bitmap_fill(priv->eq_table.eq[i].actv_ports.ports,
dev->caps.num_ports);
/* We don't set affinity hint when there
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c b/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
index e71563c..22d603f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
@@ -598,6 +598,8 @@
return;
priv->vlan.filter_disabled = false;
+ if (priv->netdev->flags & IFF_PROMISC)
+ return;
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
}
@@ -607,6 +609,8 @@
return;
priv->vlan.filter_disabled = true;
+ if (priv->netdev->flags & IFF_PROMISC)
+ return;
mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
}
@@ -717,8 +721,12 @@
bool enable_broadcast = !ea->broadcast_enabled && broadcast_enabled;
bool disable_broadcast = ea->broadcast_enabled && !broadcast_enabled;
- if (enable_promisc)
+ if (enable_promisc) {
mlx5e_add_eth_addr_rule(priv, &ea->promisc, MLX5E_PROMISC);
+ if (!priv->vlan.filter_disabled)
+ mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
+ 0);
+ }
if (enable_allmulti)
mlx5e_add_eth_addr_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
if (enable_broadcast)
@@ -730,8 +738,12 @@
mlx5e_del_eth_addr_from_flow_table(priv, &ea->broadcast);
if (disable_allmulti)
mlx5e_del_eth_addr_from_flow_table(priv, &ea->allmulti);
- if (disable_promisc)
+ if (disable_promisc) {
+ if (!priv->vlan.filter_disabled)
+ mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
+ 0);
mlx5e_del_eth_addr_from_flow_table(priv, &ea->promisc);
+ }
ea->promisc_enabled = promisc_enabled;
ea->allmulti_enabled = allmulti_enabled;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index 821caaa..3b9480f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -311,7 +311,7 @@
int err;
memset(in, 0, sizeof(in));
- MLX5_SET(ptys_reg, in, local_port, local_port);
+ MLX5_SET(pvlc_reg, in, local_port, local_port);
err = mlx5_core_access_reg(dev, in, sizeof(in), pvlc,
pvlc_size, MLX5_REG_PVLC, 0, 0);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index dbcaf5d..28c19cc 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -374,26 +374,31 @@
int err;
int ret;
+ mlxsw_core->emad.trans_active = true;
+
err = mlxsw_core_skb_transmit(mlxsw_core->driver_priv, skb, tx_info);
if (err) {
dev_err(mlxsw_core->bus_info->dev, "Failed to transmit EMAD (tid=%llx)\n",
mlxsw_core->emad.tid);
dev_kfree_skb(skb);
- return err;
+ goto trans_inactive_out;
}
- mlxsw_core->emad.trans_active = true;
ret = wait_event_timeout(mlxsw_core->emad.wait,
!(mlxsw_core->emad.trans_active),
msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS));
if (!ret) {
dev_warn(mlxsw_core->bus_info->dev, "EMAD timed-out (tid=%llx)\n",
mlxsw_core->emad.tid);
- mlxsw_core->emad.trans_active = false;
- return -EIO;
+ err = -EIO;
+ goto trans_inactive_out;
}
return 0;
+
+trans_inactive_out:
+ mlxsw_core->emad.trans_active = false;
+ return err;
}
static int mlxsw_emad_process_status(struct mlxsw_core *mlxsw_core,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/item.h b/drivers/net/ethernet/mellanox/mlxsw/item.h
index ffd55d0..36fb1ce 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/item.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/item.h
@@ -187,6 +187,7 @@
{
u16 max_index, be_index;
u16 offset; /* byte offset inside the array */
+ u8 in_byte_index;
BUG_ON(index && !item->element_size);
if (item->offset % sizeof(u32) != 0 ||
@@ -199,7 +200,8 @@
max_index = (item->size.bytes << 3) / item->element_size - 1;
be_index = max_index - index;
offset = be_index * item->element_size >> 3;
- *shift = index % (BITS_PER_BYTE / item->element_size) << 1;
+ in_byte_index = index % (BITS_PER_BYTE / item->element_size);
+ *shift = in_byte_index * item->element_size;
return item->offset + offset;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index 462cea3..cef866c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -1582,11 +1582,11 @@
if (in_mbox)
memcpy(mlxsw_pci->cmd.in_mbox.buf, in_mbox, in_mbox_size);
- mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, in_mapaddr >> 32);
- mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, in_mapaddr);
+ mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, upper_32_bits(in_mapaddr));
+ mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, lower_32_bits(in_mapaddr));
- mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, out_mapaddr >> 32);
- mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, out_mapaddr);
+ mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, upper_32_bits(out_mapaddr));
+ mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, lower_32_bits(out_mapaddr));
mlxsw_pci_write32(mlxsw_pci, CIR_IN_MODIFIER, in_mod);
mlxsw_pci_write32(mlxsw_pci, CIR_TOKEN, 0);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index 3e52ee9..62cbbd1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -1069,9 +1069,9 @@
return 0;
err_register_netdev:
-err_port_admin_status_set:
err_port_mac_learning_mode_set:
err_port_stp_state_set:
+err_port_admin_status_set:
err_port_mtu_set:
err_port_speed_set:
err_port_swid_set:
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index a41bb5e..75e88f4 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4076,6 +4076,8 @@
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 mask = 0;
+ unsigned long flags;
+ unsigned int irq = 0;
/*
* First disable irq(s) and then
@@ -4085,25 +4087,27 @@
if (!using_multi_irqs(dev)) {
if (np->msi_flags & NV_MSI_X_ENABLED)
- disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ irq = np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector;
else
- disable_irq_lockdep(np->pci_dev->irq);
+ irq = np->pci_dev->irq;
mask = np->irqmask;
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
- disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ irq = np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector;
mask |= NVREG_IRQ_RX_ALL;
}
if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
- disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+ irq = np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector;
mask |= NVREG_IRQ_TX_ALL;
}
if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
- disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+ irq = np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector;
mask |= NVREG_IRQ_OTHER;
}
}
- /* disable_irq() contains synchronize_irq, thus no irq handler can run now */
+
+ disable_irq_nosync_lockdep_irqsave(irq, &flags);
+ synchronize_irq(irq);
if (np->recover_error) {
np->recover_error = 0;
@@ -4156,28 +4160,22 @@
nv_nic_irq_optimized(0, dev);
else
nv_nic_irq(0, dev);
- if (np->msi_flags & NV_MSI_X_ENABLED)
- enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
- else
- enable_irq_lockdep(np->pci_dev->irq);
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
np->nic_poll_irq &= ~NVREG_IRQ_RX_ALL;
nv_nic_irq_rx(0, dev);
- enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
np->nic_poll_irq &= ~NVREG_IRQ_TX_ALL;
nv_nic_irq_tx(0, dev);
- enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
}
if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
np->nic_poll_irq &= ~NVREG_IRQ_OTHER;
nv_nic_irq_other(0, dev);
- enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
}
}
+ enable_irq_lockdep_irqrestore(irq, &flags);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index 66fd868..b159ef8 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -476,13 +476,12 @@
mac[5] = tmp >> 8;
}
-static void __lpc_eth_clock_enable(struct netdata_local *pldat,
- bool enable)
+static void __lpc_eth_clock_enable(struct netdata_local *pldat, bool enable)
{
if (enable)
- clk_enable(pldat->clk);
+ clk_prepare_enable(pldat->clk);
else
- clk_disable(pldat->clk);
+ clk_disable_unprepare(pldat->clk);
}
static void __lpc_params_setup(struct netdata_local *pldat)
@@ -1494,7 +1493,7 @@
err_out_iounmap:
iounmap(pldat->net_base);
err_out_disable_clocks:
- clk_disable(pldat->clk);
+ clk_disable_unprepare(pldat->clk);
clk_put(pldat->clk);
err_out_free_dev:
free_netdev(ndev);
@@ -1519,7 +1518,7 @@
iounmap(pldat->net_base);
mdiobus_unregister(pldat->mii_bus);
mdiobus_free(pldat->mii_bus);
- clk_disable(pldat->clk);
+ clk_disable_unprepare(pldat->clk);
clk_put(pldat->clk);
free_netdev(ndev);
@@ -1540,7 +1539,7 @@
if (netif_running(ndev)) {
netif_device_detach(ndev);
__lpc_eth_shutdown(pldat);
- clk_disable(pldat->clk);
+ clk_disable_unprepare(pldat->clk);
/*
* Reset again now clock is disable to be sure
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 257ea71..a484d8b 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1127,7 +1127,7 @@
struct sh_eth_txdesc *txdesc = NULL;
int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
- int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
+ int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
dma_addr_t dma_addr;
mdp->cur_rx = 0;
@@ -1148,8 +1148,8 @@
/* RX descriptor */
rxdesc = &mdp->rx_ring[i];
- /* The size of the buffer is a multiple of 16 bytes. */
- rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+ /* The size of the buffer is a multiple of 32 bytes. */
+ rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
dma_addr = dma_map_single(&ndev->dev, skb->data,
rxdesc->buffer_length,
DMA_FROM_DEVICE);
@@ -1450,7 +1450,7 @@
struct sk_buff *skb;
u16 pkt_len = 0;
u32 desc_status;
- int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
+ int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
dma_addr_t dma_addr;
boguscnt = min(boguscnt, *quota);
@@ -1506,7 +1506,7 @@
if (mdp->cd->rpadir)
skb_reserve(skb, NET_IP_ALIGN);
dma_unmap_single(&ndev->dev, rxdesc->addr,
- ALIGN(mdp->rx_buf_sz, 16),
+ ALIGN(mdp->rx_buf_sz, 32),
DMA_FROM_DEVICE);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, ndev);
@@ -1524,8 +1524,8 @@
for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
entry = mdp->dirty_rx % mdp->num_rx_ring;
rxdesc = &mdp->rx_ring[entry];
- /* The size of the buffer is 16 byte boundary. */
- rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+ /* The size of the buffer is 32 byte boundary. */
+ rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
if (mdp->rx_skbuff[entry] == NULL) {
skb = netdev_alloc_skb(ndev, skbuff_size);
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8fc90f1..874fb29 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
+#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_device.h>
#include <linux/if_vlan.h>
@@ -365,6 +366,7 @@
spinlock_t lock;
struct platform_device *pdev;
struct net_device *ndev;
+ struct device_node *phy_node;
struct napi_struct napi_rx;
struct napi_struct napi_tx;
struct device *dev;
@@ -1145,7 +1147,11 @@
cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
- slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
+ if (priv->phy_node)
+ slave->phy = of_phy_connect(priv->ndev, priv->phy_node,
+ &cpsw_adjust_link, 0, slave->data->phy_if);
+ else
+ slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
&cpsw_adjust_link, slave->data->phy_if);
if (IS_ERR(slave->phy)) {
dev_err(priv->dev, "phy %s not found on slave %d\n",
@@ -1934,11 +1940,12 @@
slave->port_vlan = data->dual_emac_res_vlan;
}
-static int cpsw_probe_dt(struct cpsw_platform_data *data,
+static int cpsw_probe_dt(struct cpsw_priv *priv,
struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct device_node *slave_node;
+ struct cpsw_platform_data *data = &priv->data;
int i = 0, ret;
u32 prop;
@@ -2029,6 +2036,7 @@
if (strcmp(slave_node->name, "slave"))
continue;
+ priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0);
parp = of_get_property(slave_node, "phy_id", &lenp);
if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i);
@@ -2044,7 +2052,6 @@
}
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
PHY_ID_FMT, mdio->name, phyid);
-
slave_data->phy_if = of_get_phy_mode(slave_node);
if (slave_data->phy_if < 0) {
dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n",
@@ -2240,7 +2247,7 @@
/* Select default pin state */
pinctrl_pm_select_default_state(&pdev->dev);
- if (cpsw_probe_dt(&priv->data, pdev)) {
+ if (cpsw_probe_dt(priv, pdev)) {
dev_err(&pdev->dev, "cpsw: platform data missing\n");
ret = -ENODEV;
goto clean_runtime_disable_ret;
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
index 6bff8d8..4e70e75 100644
--- a/drivers/net/ethernet/ti/netcp_ethss.c
+++ b/drivers/net/ethernet/ti/netcp_ethss.c
@@ -2637,8 +2637,10 @@
mac_phy_link = true;
slave->open = true;
- if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
+ if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) {
+ of_node_put(port);
break;
+ }
}
/* of_phy_connect() is needed only for MAC-PHY interface */
@@ -3137,8 +3139,10 @@
continue;
}
gbe_dev->num_slaves++;
- if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
+ if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) {
+ of_node_put(interface);
break;
+ }
}
of_node_put(interfaces);
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index a832637..2b7550c 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -2134,10 +2134,11 @@
}
skb_put(skb, pkt_len);
- skb->protocol = eth_type_trans(skb, dev);
rhine_rx_vlan_tag(skb, desc, data_size);
+ skb->protocol = eth_type_trans(skb, dev);
+
netif_receive_skb(skb);
u64_stats_update_begin(&rp->rx_stats.syncp);
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 8f5c02e..445071c 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -594,14 +594,12 @@
rt = ip_route_output_key(geneve->net, fl4);
if (IS_ERR(rt)) {
netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr);
- dev->stats.tx_carrier_errors++;
- return rt;
+ return ERR_PTR(-ENETUNREACH);
}
if (rt->dst.dev == dev) { /* is this necessary? */
netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr);
- dev->stats.collisions++;
ip_rt_put(rt);
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ELOOP);
}
return rt;
}
@@ -627,12 +625,12 @@
struct ip_tunnel_info *info = NULL;
struct rtable *rt = NULL;
const struct iphdr *iip; /* interior IP header */
+ int err = -EINVAL;
struct flowi4 fl4;
__u8 tos, ttl;
__be16 sport;
bool udp_csum;
__be16 df;
- int err;
if (geneve->collect_md) {
info = skb_tunnel_info(skb);
@@ -647,7 +645,7 @@
rt = geneve_get_rt(skb, dev, &fl4, info);
if (IS_ERR(rt)) {
netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr);
- dev->stats.tx_carrier_errors++;
+ err = PTR_ERR(rt);
goto tx_error;
}
@@ -699,10 +697,37 @@
tx_error:
dev_kfree_skb(skb);
err:
- dev->stats.tx_errors++;
+ if (err == -ELOOP)
+ dev->stats.collisions++;
+ else if (err == -ENETUNREACH)
+ dev->stats.tx_carrier_errors++;
+ else
+ dev->stats.tx_errors++;
return NETDEV_TX_OK;
}
+static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+ struct ip_tunnel_info *info = skb_tunnel_info(skb);
+ struct geneve_dev *geneve = netdev_priv(dev);
+ struct rtable *rt;
+ struct flowi4 fl4;
+
+ if (ip_tunnel_info_af(info) != AF_INET)
+ return -EINVAL;
+
+ rt = geneve_get_rt(skb, dev, &fl4, info);
+ if (IS_ERR(rt))
+ return PTR_ERR(rt);
+
+ ip_rt_put(rt);
+ info->key.u.ipv4.src = fl4.saddr;
+ info->key.tp_src = udp_flow_src_port(geneve->net, skb,
+ 1, USHRT_MAX, true);
+ info->key.tp_dst = geneve->dst_port;
+ return 0;
+}
+
static const struct net_device_ops geneve_netdev_ops = {
.ndo_init = geneve_init,
.ndo_uninit = geneve_uninit,
@@ -713,6 +738,7 @@
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
+ .ndo_fill_metadata_dst = geneve_fill_metadata_dst,
};
static void geneve_get_drvinfo(struct net_device *dev,
@@ -870,14 +896,14 @@
__be16 dst_port = htons(GENEVE_UDP_PORT);
__u8 ttl = 0, tos = 0;
bool metadata = false;
- __be32 rem_addr;
- __u32 vni;
+ __be32 rem_addr = 0;
+ __u32 vni = 0;
- if (!data[IFLA_GENEVE_ID] || !data[IFLA_GENEVE_REMOTE])
- return -EINVAL;
+ if (data[IFLA_GENEVE_ID])
+ vni = nla_get_u32(data[IFLA_GENEVE_ID]);
- vni = nla_get_u32(data[IFLA_GENEVE_ID]);
- rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
+ if (data[IFLA_GENEVE_REMOTE])
+ rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
if (data[IFLA_GENEVE_TTL])
ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 248478c..197c939 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -137,7 +137,7 @@
#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
NETIF_F_TSO6 | NETIF_F_UFO)
#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
-#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
+#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST)
static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev)
{
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index c5ad98a..436972b 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -122,6 +122,11 @@
---help---
Supports the KSZ9021, VSC8201, KS8001 PHYs.
+config DP83848_PHY
+ tristate "Driver for Texas Instruments DP83848 PHY"
+ ---help---
+ Supports the DP83848 PHY.
+
config DP83867_PHY
tristate "Drivers for Texas Instruments DP83867 Gigabit PHY"
---help---
@@ -168,8 +173,6 @@
busses. It is required by the Octeon and ThunderX ethernet device
drivers.
- If in doubt, say Y.
-
config MDIO_SUN4I
tristate "Allwinner sun4i MDIO interface support"
depends on ARCH_SUNXI
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 87f079c..b748224 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -24,6 +24,7 @@
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_DP83640_PHY) += dp83640.o
+obj-$(CONFIG_DP83848_PHY) += dp83848.o
obj-$(CONFIG_DP83867_PHY) += dp83867.o
obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c
new file mode 100644
index 0000000..5ce9bef
--- /dev/null
+++ b/drivers/net/phy/dp83848.c
@@ -0,0 +1,99 @@
+/*
+ * Driver for the Texas Instruments DP83848 PHY
+ *
+ * Copyright (C) 2015 Texas Instruments Inc.
+ *
+ * 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; either 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.
+ */
+
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define DP83848_PHY_ID 0x20005c90
+
+/* Registers */
+#define DP83848_MICR 0x11
+#define DP83848_MISR 0x12
+
+/* MICR Register Fields */
+#define DP83848_MICR_INT_OE BIT(0) /* Interrupt Output Enable */
+#define DP83848_MICR_INTEN BIT(1) /* Interrupt Enable */
+
+/* MISR Register Fields */
+#define DP83848_MISR_RHF_INT_EN BIT(0) /* Receive Error Counter */
+#define DP83848_MISR_FHF_INT_EN BIT(1) /* False Carrier Counter */
+#define DP83848_MISR_ANC_INT_EN BIT(2) /* Auto-negotiation complete */
+#define DP83848_MISR_DUP_INT_EN BIT(3) /* Duplex Status */
+#define DP83848_MISR_SPD_INT_EN BIT(4) /* Speed status */
+#define DP83848_MISR_LINK_INT_EN BIT(5) /* Link status */
+#define DP83848_MISR_ED_INT_EN BIT(6) /* Energy detect */
+#define DP83848_MISR_LQM_INT_EN BIT(7) /* Link Quality Monitor */
+
+static int dp83848_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, DP83848_MISR);
+
+ return err < 0 ? err : 0;
+}
+
+static int dp83848_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+ err = phy_write(phydev, DP83848_MICR,
+ DP83848_MICR_INT_OE |
+ DP83848_MICR_INTEN);
+ if (err < 0)
+ return err;
+
+ return phy_write(phydev, DP83848_MISR,
+ DP83848_MISR_ANC_INT_EN |
+ DP83848_MISR_DUP_INT_EN |
+ DP83848_MISR_SPD_INT_EN |
+ DP83848_MISR_LINK_INT_EN);
+ }
+
+ return phy_write(phydev, DP83848_MICR, 0x0);
+}
+
+static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
+ { DP83848_PHY_ID, 0xfffffff0 },
+ { }
+};
+MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
+
+static struct phy_driver dp83848_driver[] = {
+ {
+ .phy_id = DP83848_PHY_ID,
+ .phy_id_mask = 0xfffffff0,
+ .name = "TI DP83848",
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+
+ .soft_reset = genphy_soft_reset,
+ .config_init = genphy_config_init,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+
+ /* IRQ related */
+ .ack_interrupt = dp83848_ack_interrupt,
+ .config_intr = dp83848_config_intr,
+
+ .driver = { .owner = THIS_MODULE, },
+ },
+};
+module_phy_driver(dp83848_driver);
+
+MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver");
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
index 2377c13..7fde454 100644
--- a/drivers/net/phy/mdio-mux-mmioreg.c
+++ b/drivers/net/phy/mdio-mux-mmioreg.c
@@ -113,12 +113,14 @@
if (!iprop || len != sizeof(uint32_t)) {
dev_err(&pdev->dev, "mdio-mux child node %s is "
"missing a 'reg' property\n", np2->full_name);
+ of_node_put(np2);
return -ENODEV;
}
if (be32_to_cpup(iprop) & ~s->mask) {
dev_err(&pdev->dev, "mdio-mux child node %s has "
"a 'reg' value with unmasked bits\n",
np2->full_name);
+ of_node_put(np2);
return -ENODEV;
}
}
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
index 280c7c3..908e8d4 100644
--- a/drivers/net/phy/mdio-mux.c
+++ b/drivers/net/phy/mdio-mux.c
@@ -144,6 +144,7 @@
dev_err(dev,
"Error: Failed to allocate memory for child\n");
ret_val = -ENOMEM;
+ of_node_put(child_bus_node);
break;
}
cb->bus_number = v;
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 499185e..cf6312f 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -514,6 +514,27 @@
return 0;
}
+static int ksz9031_read_status(struct phy_device *phydev)
+{
+ int err;
+ int regval;
+
+ err = genphy_read_status(phydev);
+ if (err)
+ return err;
+
+ /* Make sure the PHY is not broken. Read idle error count,
+ * and reset the PHY if it is maxed out.
+ */
+ regval = phy_read(phydev, MII_STAT1000);
+ if ((regval & 0xFF) == 0xFF) {
+ phy_init_hw(phydev);
+ phydev->link = 0;
+ }
+
+ return 0;
+}
+
static int ksz8873mll_config_aneg(struct phy_device *phydev)
{
return 0;
@@ -772,7 +793,7 @@
.driver_data = &ksz9021_type,
.config_init = ksz9031_config_init,
.config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
+ .read_status = ksz9031_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
.suspend = genphy_suspend,
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 70b0895..dc2da87 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -43,16 +43,25 @@
static int smsc_phy_config_init(struct phy_device *phydev)
{
+ int __maybe_unused len;
+ struct device *dev __maybe_unused = &phydev->dev;
+ struct device_node *of_node __maybe_unused = dev->of_node;
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ int enable_energy = 1;
if (rc < 0)
return rc;
- /* Enable energy detect mode for this SMSC Transceivers */
- rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
- rc | MII_LAN83C185_EDPWRDOWN);
- if (rc < 0)
- return rc;
+ if (of_find_property(of_node, "smsc,disable-energy-detect", &len))
+ enable_energy = 0;
+
+ if (enable_energy) {
+ /* Enable energy detect mode for this SMSC Transceivers */
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+ rc | MII_LAN83C185_EDPWRDOWN);
+ if (rc < 0)
+ return rc;
+ }
return smsc_phy_ack_interrupt(phydev);
}
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 3837ae3..5e0b432 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -313,7 +313,6 @@
if (po->pppoe_dev == dev &&
sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
pppox_unbind_sock(sk);
- sk->sk_state = PPPOX_ZOMBIE;
sk->sk_state_change(sk);
po->pppoe_dev = NULL;
dev_put(dev);
@@ -590,7 +589,7 @@
po = pppox_sk(sk);
- if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+ if (po->pppoe_dev) {
dev_put(po->pppoe_dev);
po->pppoe_dev = NULL;
}
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index fbb9325..e66805e 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -164,6 +164,7 @@
* Aten UC210T
* ASIX AX88172
* Billionton Systems, USB2AR
+ * Billionton Systems, GUSB2AM-1G-B
* Buffalo LUA-U2-KTX
* Corega FEther USB2-TX
* D-Link DUB-E100
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 75d6f26..079069a 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -91,8 +91,10 @@
}
rx->ax_skb = netdev_alloc_skb_ip_align(dev->net,
rx->size);
- if (!rx->ax_skb)
+ if (!rx->ax_skb) {
+ rx->size = 0;
return 0;
+ }
}
if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 1173a24..5cabefc 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -959,6 +959,10 @@
USB_DEVICE (0x08dd, 0x90ff),
.driver_info = (unsigned long) &ax8817x_info,
}, {
+ // Billionton Systems, GUSB2AM-1G-B
+ USB_DEVICE(0x08dd, 0x0114),
+ .driver_info = (unsigned long) &ax88178_info,
+}, {
// ATEN UC210T
USB_DEVICE (0x0557, 0x2009),
.driver_info = (unsigned long) &ax8817x_info,
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 355842b..2a7c1be 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -765,6 +765,10 @@
{QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */
{QMI_FIXED_INTF(0x1199, 0x9057, 8)},
{QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */
+ {QMI_FIXED_INTF(0x1199, 0x9070, 8)}, /* Sierra Wireless MC74xx/EM74xx */
+ {QMI_FIXED_INTF(0x1199, 0x9070, 10)}, /* Sierra Wireless MC74xx/EM74xx */
+ {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx/EM74xx */
+ {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx/EM74xx */
{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
{QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */
{QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index bbac1d3..c1587ec 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2337,6 +2337,46 @@
return 0;
}
+static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
+ struct ip_tunnel_info *info,
+ __be16 sport, __be16 dport)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct rtable *rt;
+ struct flowi4 fl4;
+
+ memset(&fl4, 0, sizeof(fl4));
+ fl4.flowi4_tos = RT_TOS(info->key.tos);
+ fl4.flowi4_mark = skb->mark;
+ fl4.flowi4_proto = IPPROTO_UDP;
+ fl4.daddr = info->key.u.ipv4.dst;
+
+ rt = ip_route_output_key(vxlan->net, &fl4);
+ if (IS_ERR(rt))
+ return PTR_ERR(rt);
+ ip_rt_put(rt);
+
+ info->key.u.ipv4.src = fl4.saddr;
+ info->key.tp_src = sport;
+ info->key.tp_dst = dport;
+ return 0;
+}
+
+static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct ip_tunnel_info *info = skb_tunnel_info(skb);
+ __be16 sport, dport;
+
+ sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
+ vxlan->cfg.port_max, true);
+ dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
+
+ if (ip_tunnel_info_af(info) == AF_INET)
+ return egress_ipv4_tun_info(dev, skb, info, sport, dport);
+ return -EINVAL;
+}
+
static const struct net_device_ops vxlan_netdev_ops = {
.ndo_init = vxlan_init,
.ndo_uninit = vxlan_uninit,
@@ -2351,6 +2391,7 @@
.ndo_fdb_add = vxlan_fdb_add,
.ndo_fdb_del = vxlan_fdb_delete,
.ndo_fdb_dump = vxlan_fdb_dump,
+ .ndo_fill_metadata_dst = vxlan_fill_metadata_dst,
};
/* Info for udev, that this is a virtual tunnel endpoint */
@@ -2745,11 +2786,10 @@
struct vxlan_config conf;
int err;
- if (!data[IFLA_VXLAN_ID])
- return -EINVAL;
-
memset(&conf, 0, sizeof(conf));
- conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]);
+
+ if (data[IFLA_VXLAN_ID])
+ conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]);
if (data[IFLA_VXLAN_GROUP]) {
conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]);
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 23afcda..678d72a 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -337,7 +337,7 @@
#define TARGET_10X_MAX_FRAG_ENTRIES 0
/* 10.2 parameters */
-#define TARGET_10_2_DMA_BURST_SIZE 1
+#define TARGET_10_2_DMA_BURST_SIZE 0
/* Target specific defines for WMI-TLV firmware */
#define TARGET_TLV_NUM_VDEVS 4
@@ -391,7 +391,7 @@
#define TARGET_10_4_TX_DBG_LOG_SIZE 1024
#define TARGET_10_4_NUM_WDS_ENTRIES 32
-#define TARGET_10_4_DMA_BURST_SIZE 1
+#define TARGET_10_4_DMA_BURST_SIZE 0
#define TARGET_10_4_MAC_AGGR_DELIM 0
#define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
#define TARGET_10_4_VOW_CONFIG 0
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 6e473fa..12241b1 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -715,6 +715,7 @@
board_filename, ret);
continue;
}
+ of_node_put(node);
return true;
}
return false;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 57f95f2..90eb750 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -880,6 +880,7 @@
hw->max_rate_tries = 10;
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
+ hw->extra_tx_headroom = 4;
hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 2849070..71d3e9a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -120,6 +120,7 @@
#ifdef CONFIG_B43_BCMA
static const struct bcma_device_id b43_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x15, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1C, BCMA_ANY_CLASS),
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index ab45819..e18629a 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -1020,7 +1020,7 @@
u8 *pn = seq.ccmp.pn;
ieee80211_get_key_rx_seq(key, i, &seq);
- aes_sc->pn = cpu_to_le64(
+ aes_sc[i].pn = cpu_to_le64(
(u64)pn[5] |
((u64)pn[4] << 8) |
((u64)pn[3] << 16) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index 6951aba..3fb327d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -348,6 +348,6 @@
};
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
+MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 04264e4..5761876 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -274,18 +274,13 @@
break;
case WLAN_CIPHER_SUITE_CCMP:
if (sta) {
- u8 *pn = seq.ccmp.pn;
+ u64 pn64;
aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
- ieee80211_get_key_tx_seq(key, &seq);
- aes_tx_sc->pn = cpu_to_le64((u64)pn[5] |
- ((u64)pn[4] << 8) |
- ((u64)pn[3] << 16) |
- ((u64)pn[2] << 24) |
- ((u64)pn[1] << 32) |
- ((u64)pn[0] << 40));
+ pn64 = atomic64_read(&key->tx_pn);
+ aes_tx_sc->pn = cpu_to_le64(pn64);
} else {
aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
}
@@ -298,12 +293,12 @@
u8 *pn = seq.ccmp.pn;
ieee80211_get_key_rx_seq(key, i, &seq);
- aes_sc->pn = cpu_to_le64((u64)pn[5] |
- ((u64)pn[4] << 8) |
- ((u64)pn[3] << 16) |
- ((u64)pn[2] << 24) |
- ((u64)pn[1] << 32) |
- ((u64)pn[0] << 40));
+ aes_sc[i].pn = cpu_to_le64((u64)pn[5] |
+ ((u64)pn[4] << 8) |
+ ((u64)pn[3] << 16) |
+ ((u64)pn[2] << 24) |
+ ((u64)pn[1] << 32) |
+ ((u64)pn[0] << 40));
}
data->use_rsc_tsc = true;
break;
@@ -1453,15 +1448,15 @@
switch (key->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
- iwl_mvm_aes_sc_to_seq(&sc->aes.tsc, &seq);
iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key);
+ atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn));
break;
case WLAN_CIPHER_SUITE_TKIP:
iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
+ ieee80211_set_key_tx_seq(key, &seq);
break;
}
- ieee80211_set_key_tx_seq(key, &seq);
/* that's it for this key */
return;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 4a0ce83..5c7f7cc 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -703,7 +703,7 @@
* abort after reading the nvm in case RF Kill is on, we will complete
* the init seq later when RF kill will switch to off
*/
- if (iwl_mvm_is_radio_killed(mvm)) {
+ if (iwl_mvm_is_radio_hw_killed(mvm)) {
IWL_DEBUG_RF_KILL(mvm,
"jump over all phy activities due to RF kill\n");
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
@@ -736,7 +736,7 @@
ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
MVM_UCODE_CALIB_TIMEOUT);
- if (ret && iwl_mvm_is_radio_killed(mvm)) {
+ if (ret && iwl_mvm_is_radio_hw_killed(mvm)) {
IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
ret = 1;
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index aa8c2b7..7c2944a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -2388,6 +2388,7 @@
iwl_mvm_remove_time_event(mvm, mvmvif,
&mvmvif->time_event_data);
RCU_INIT_POINTER(mvm->csa_vif, NULL);
+ mvmvif->csa_countdown = false;
}
if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index b95a07e..c754051 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -860,6 +860,11 @@
test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
}
+static inline bool iwl_mvm_is_radio_hw_killed(struct iwl_mvm *mvm)
+{
+ return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
+}
+
/* Must be called with rcu_read_lock() held and it can only be
* released when mvmsta is not needed anymore.
*/
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index a37de3f..f0cb092 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -590,6 +590,7 @@
ieee80211_unregister_hw(mvm->hw);
iwl_mvm_leds_exit(mvm);
out_free:
+ flush_delayed_work(&mvm->fw_dump_wk);
iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd);
if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name)
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index b0825c4..644b58b 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -414,6 +414,11 @@
{IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5F10, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5212, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x520A, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9000, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9400, iwl7265_2ac_cfg)},
/* 8000 Series */
{IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 5932306..bf9afbf 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1114,6 +1114,7 @@
{ USB_DEVICE(0x0db0, 0x871c) },
{ USB_DEVICE(0x0db0, 0x899a) },
/* Ovislink */
+ { USB_DEVICE(0x1b75, 0x3070) },
{ USB_DEVICE(0x1b75, 0x3071) },
{ USB_DEVICE(0x1b75, 0x3072) },
{ USB_DEVICE(0x1b75, 0xa200) },
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index d4567d1..5da6703 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -247,6 +247,8 @@
/* MSI support */
bool msi_support;
bool using_msi;
+ /* interrupt clear before set */
+ bool int_clear;
};
struct mp_adapter {
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
index b7f18e21..6e9418e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
@@ -2253,11 +2253,28 @@
}
}
+static void rtl8821ae_clear_interrupt(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ u32 tmp = rtl_read_dword(rtlpriv, REG_HISR);
+
+ rtl_write_dword(rtlpriv, REG_HISR, tmp);
+
+ tmp = rtl_read_dword(rtlpriv, REG_HISRE);
+ rtl_write_dword(rtlpriv, REG_HISRE, tmp);
+
+ tmp = rtl_read_dword(rtlpriv, REG_HSISR);
+ rtl_write_dword(rtlpriv, REG_HSISR, tmp);
+}
+
void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ if (!rtlpci->int_clear)
+ rtl8821ae_clear_interrupt(hw);/*clear it here first*/
+
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
rtlpci->irq_enabled = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
index a4988121..8ee141a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
@@ -96,6 +96,7 @@
rtl8821ae_bt_reg_init(hw);
rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+ rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
rtlpriv->dm.dm_initialgain_enable = 1;
@@ -167,6 +168,7 @@
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+ rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
@@ -308,6 +310,7 @@
.swctrl_lps = false,
.fwctrl_lps = true,
.msi_support = true,
+ .int_clear = true,
.debug = DBG_EMERG,
.disable_watchdog = 0,
};
@@ -437,6 +440,7 @@
module_param_named(msi, rtl8821ae_mod_params.msi_support, bool, 0444);
module_param_named(disable_watchdog, rtl8821ae_mod_params.disable_watchdog,
bool, 0444);
+module_param_named(int_clear, rtl8821ae_mod_params.int_clear, bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
@@ -444,6 +448,7 @@
MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n");
+MODULE_PARM_DESC(int_clear, "Set to 1 to disable interrupt clear before set (default 0)\n");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index b90ca61..4544752 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -2249,6 +2249,9 @@
/* default 0: 1 means disable */
bool disable_watchdog;
+
+ /* default 0: 1 means do not disable interrupts */
+ bool int_clear;
};
struct rtl_hal_usbint_cfg {
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 929a6e7..56ebd82 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -788,6 +788,12 @@
/* Use the number of queues requested by the frontend */
be->vif->queues = vzalloc(requested_num_queues *
sizeof(struct xenvif_queue));
+ if (!be->vif->queues) {
+ xenbus_dev_fatal(dev, -ENOMEM,
+ "allocating queues");
+ return;
+ }
+
be->vif->num_queues = requested_num_queues;
be->vif->stalled_queues = requested_num_queues;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index f821a97..6febc05 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1706,19 +1706,19 @@
}
static int xennet_create_queues(struct netfront_info *info,
- unsigned int num_queues)
+ unsigned int *num_queues)
{
unsigned int i;
int ret;
- info->queues = kcalloc(num_queues, sizeof(struct netfront_queue),
+ info->queues = kcalloc(*num_queues, sizeof(struct netfront_queue),
GFP_KERNEL);
if (!info->queues)
return -ENOMEM;
rtnl_lock();
- for (i = 0; i < num_queues; i++) {
+ for (i = 0; i < *num_queues; i++) {
struct netfront_queue *queue = &info->queues[i];
queue->id = i;
@@ -1728,7 +1728,7 @@
if (ret < 0) {
dev_warn(&info->netdev->dev,
"only created %d queues\n", i);
- num_queues = i;
+ *num_queues = i;
break;
}
@@ -1738,11 +1738,11 @@
napi_enable(&queue->napi);
}
- netif_set_real_num_tx_queues(info->netdev, num_queues);
+ netif_set_real_num_tx_queues(info->netdev, *num_queues);
rtnl_unlock();
- if (num_queues == 0) {
+ if (*num_queues == 0) {
dev_err(&info->netdev->dev, "no queues\n");
return -EINVAL;
}
@@ -1788,7 +1788,7 @@
if (info->queues)
xennet_destroy_queues(info);
- err = xennet_create_queues(info, num_queues);
+ err = xennet_create_queues(info, &num_queues);
if (err < 0)
goto destroy_ring;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d449714..4a7da3c 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1243,6 +1243,10 @@
BUG_ON(!chip);
if (!chip->irq_write_msi_msg)
chip->irq_write_msi_msg = pci_msi_domain_write_msg;
+ if (!chip->irq_mask)
+ chip->irq_mask = pci_msi_mask_irq;
+ if (!chip->irq_unmask)
+ chip->irq_unmask = pci_msi_unmask_irq;
}
/**
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 312f23a..9261868 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -216,7 +216,7 @@
if (ret)
return ret;
- if (!node_online(node))
+ if (node >= MAX_NUMNODES || !node_online(node))
return -EINVAL;
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 2365a32..be3755c 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -823,9 +823,15 @@
}
/* Now look up the logical CPU number */
- for_each_possible_cpu(cpu)
- if (dn == of_cpu_device_node_get(cpu))
+ for_each_possible_cpu(cpu) {
+ struct device_node *cpu_dn;
+
+ cpu_dn = of_cpu_device_node_get(cpu);
+ of_node_put(cpu_dn);
+
+ if (dn == cpu_dn)
break;
+ }
if (cpu >= nr_cpu_ids) {
pr_warn("Failed to find logical CPU for %s\n",
diff --git a/drivers/pinctrl/freescale/pinctrl-imx25.c b/drivers/pinctrl/freescale/pinctrl-imx25.c
index faf6356..293ed43 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx25.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx25.c
@@ -26,7 +26,8 @@
#include "pinctrl-imx.h"
enum imx25_pads {
- MX25_PAD_RESERVE0 = 1,
+ MX25_PAD_RESERVE0 = 0,
+ MX25_PAD_RESERVE1 = 1,
MX25_PAD_A10 = 2,
MX25_PAD_A13 = 3,
MX25_PAD_A14 = 4,
@@ -169,6 +170,7 @@
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc imx25_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX25_PAD_RESERVE0),
+ IMX_PINCTRL_PIN(MX25_PAD_RESERVE1),
IMX_PINCTRL_PIN(MX25_PAD_A10),
IMX_PINCTRL_PIN(MX25_PAD_A13),
IMX_PINCTRL_PIN(MX25_PAD_A14),
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
index 6367661..f9a3f8f 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
@@ -653,7 +653,7 @@
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* CS1 */
- SUNXI_FUNCTION(0x3, "uart3"), /* PWM1 */
+ SUNXI_FUNCTION(0x3, "pwm"), /* PWM1 */
SUNXI_FUNCTION(0x5, "uart2"), /* CTS */
SUNXI_FUNCTION_IRQ(0x6, 13)), /* EINT13 */
};
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c b/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
index 7e9dae5..2df8bbe 100644
--- a/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
@@ -22,49 +22,49 @@
#define DRIVER_NAME "ph1-sld8-pinctrl"
static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
- UNIPHIER_PINCTRL_PIN(0, "PCA00", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(0, "PCA00", 0,
15, UNIPHIER_PIN_DRV_4_8,
15, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(1, "PCA01", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(1, "PCA01", 0,
16, UNIPHIER_PIN_DRV_4_8,
16, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(2, "PCA02", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(2, "PCA02", 0,
17, UNIPHIER_PIN_DRV_4_8,
17, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(3, "PCA03", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(3, "PCA03", 0,
18, UNIPHIER_PIN_DRV_4_8,
18, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(4, "PCA04", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(4, "PCA04", 0,
19, UNIPHIER_PIN_DRV_4_8,
19, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(5, "PCA05", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(5, "PCA05", 0,
20, UNIPHIER_PIN_DRV_4_8,
20, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(6, "PCA06", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(6, "PCA06", 0,
21, UNIPHIER_PIN_DRV_4_8,
21, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(7, "PCA07", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(7, "PCA07", 0,
22, UNIPHIER_PIN_DRV_4_8,
22, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(8, "PCA08", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(8, "PCA08", 0,
23, UNIPHIER_PIN_DRV_4_8,
23, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(9, "PCA09", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(9, "PCA09", 0,
24, UNIPHIER_PIN_DRV_4_8,
24, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(10, "PCA10", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(10, "PCA10", 0,
25, UNIPHIER_PIN_DRV_4_8,
25, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(11, "PCA11", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(11, "PCA11", 0,
26, UNIPHIER_PIN_DRV_4_8,
26, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(12, "PCA12", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(12, "PCA12", 0,
27, UNIPHIER_PIN_DRV_4_8,
27, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(13, "PCA13", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(13, "PCA13", 0,
28, UNIPHIER_PIN_DRV_4_8,
28, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(14, "PCA14", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(14, "PCA14", 0,
29, UNIPHIER_PIN_DRV_4_8,
29, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(15, "XNFRE_GB", UNIPHIER_PIN_IECTRL_NONE,
@@ -118,199 +118,199 @@
UNIPHIER_PINCTRL_PIN(31, "NFD7_GB", UNIPHIER_PIN_IECTRL_NONE,
36, UNIPHIER_PIN_DRV_8_12_16_20,
128, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(32, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(32, "SDCLK", 8,
40, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(33, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(33, "SDCMD", 8,
44, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(34, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(34, "SDDAT0", 8,
48, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(35, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(35, "SDDAT1", 8,
52, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(36, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(36, "SDDAT2", 8,
56, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(37, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(37, "SDDAT3", 8,
60, UNIPHIER_PIN_DRV_8_12_16_20,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(38, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(38, "SDCD", 8,
-1, UNIPHIER_PIN_DRV_FIXED_4,
129, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(39, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(39, "SDWP", 8,
-1, UNIPHIER_PIN_DRV_FIXED_4,
130, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(40, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(40, "SDVOLC", 9,
-1, UNIPHIER_PIN_DRV_FIXED_4,
131, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", 0,
37, UNIPHIER_PIN_DRV_4_8,
37, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(42, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(42, "USB0OD", 0,
38, UNIPHIER_PIN_DRV_4_8,
38, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", 0,
39, UNIPHIER_PIN_DRV_4_8,
39, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(44, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(44, "USB1OD", 0,
40, UNIPHIER_PIN_DRV_4_8,
40, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(45, "PCRESET", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(45, "PCRESET", 0,
41, UNIPHIER_PIN_DRV_4_8,
41, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(46, "PCREG", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(46, "PCREG", 0,
42, UNIPHIER_PIN_DRV_4_8,
42, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(47, "PCCE2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(47, "PCCE2", 0,
43, UNIPHIER_PIN_DRV_4_8,
43, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(48, "PCVS1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(48, "PCVS1", 0,
44, UNIPHIER_PIN_DRV_4_8,
44, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(49, "PCCD2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(49, "PCCD2", 0,
45, UNIPHIER_PIN_DRV_4_8,
45, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(50, "PCCD1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(50, "PCCD1", 0,
46, UNIPHIER_PIN_DRV_4_8,
46, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(51, "PCREADY", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(51, "PCREADY", 0,
47, UNIPHIER_PIN_DRV_4_8,
47, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(52, "PCDOE", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(52, "PCDOE", 0,
48, UNIPHIER_PIN_DRV_4_8,
48, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(53, "PCCE1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(53, "PCCE1", 0,
49, UNIPHIER_PIN_DRV_4_8,
49, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(54, "PCWE", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(54, "PCWE", 0,
50, UNIPHIER_PIN_DRV_4_8,
50, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(55, "PCOE", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(55, "PCOE", 0,
51, UNIPHIER_PIN_DRV_4_8,
51, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(56, "PCWAIT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(56, "PCWAIT", 0,
52, UNIPHIER_PIN_DRV_4_8,
52, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(57, "PCIOWR", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(57, "PCIOWR", 0,
53, UNIPHIER_PIN_DRV_4_8,
53, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(58, "PCIORD", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(58, "PCIORD", 0,
54, UNIPHIER_PIN_DRV_4_8,
54, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", 0,
55, UNIPHIER_PIN_DRV_4_8,
55, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", 0,
56, UNIPHIER_PIN_DRV_4_8,
56, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", 0,
57, UNIPHIER_PIN_DRV_4_8,
57, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", 0,
58, UNIPHIER_PIN_DRV_4_8,
58, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", 0,
59, UNIPHIER_PIN_DRV_4_8,
59, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", 0,
60, UNIPHIER_PIN_DRV_4_8,
60, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", 0,
61, UNIPHIER_PIN_DRV_4_8,
61, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", 0,
62, UNIPHIER_PIN_DRV_4_8,
62, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", 0,
63, UNIPHIER_PIN_DRV_4_8,
63, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", 0,
64, UNIPHIER_PIN_DRV_4_8,
64, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", 0,
65, UNIPHIER_PIN_DRV_4_8,
65, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", 0,
66, UNIPHIER_PIN_DRV_4_8,
66, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", 0,
67, UNIPHIER_PIN_DRV_4_8,
67, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", 0,
68, UNIPHIER_PIN_DRV_4_8,
68, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", 0,
69, UNIPHIER_PIN_DRV_4_8,
69, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", 0,
70, UNIPHIER_PIN_DRV_4_8,
70, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", 0,
71, UNIPHIER_PIN_DRV_4_8,
71, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", 0,
72, UNIPHIER_PIN_DRV_4_8,
72, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", 0,
73, UNIPHIER_PIN_DRV_4_8,
73, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", 0,
74, UNIPHIER_PIN_DRV_4_8,
74, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", 0,
75, UNIPHIER_PIN_DRV_4_8,
75, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", 0,
76, UNIPHIER_PIN_DRV_4_8,
76, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", 0,
77, UNIPHIER_PIN_DRV_4_8,
77, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", 0,
78, UNIPHIER_PIN_DRV_4_8,
78, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", 0,
79, UNIPHIER_PIN_DRV_4_8,
79, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", 0,
80, UNIPHIER_PIN_DRV_4_8,
80, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", 0,
81, UNIPHIER_PIN_DRV_4_8,
81, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", 0,
82, UNIPHIER_PIN_DRV_4_8,
82, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", 0,
83, UNIPHIER_PIN_DRV_4_8,
83, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", 0,
84, UNIPHIER_PIN_DRV_4_8,
84, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", 0,
85, UNIPHIER_PIN_DRV_4_8,
85, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", 0,
86, UNIPHIER_PIN_DRV_4_8,
86, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", 0,
87, UNIPHIER_PIN_DRV_4_8,
87, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(92, "AGCI", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(92, "AGCI", 3,
-1, UNIPHIER_PIN_DRV_FIXED_4,
132, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(93, "AGCR", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(93, "AGCR", 4,
-1, UNIPHIER_PIN_DRV_FIXED_4,
133, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(94, "AGCBS", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(94, "AGCBS", 5,
-1, UNIPHIER_PIN_DRV_FIXED_4,
134, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(95, "IECOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(95, "IECOUT", 0,
88, UNIPHIER_PIN_DRV_4_8,
88, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(96, "ASMCK", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(96, "ASMCK", 0,
89, UNIPHIER_PIN_DRV_4_8,
89, UNIPHIER_PIN_PULL_DOWN),
UNIPHIER_PINCTRL_PIN(97, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
@@ -325,31 +325,31 @@
UNIPHIER_PINCTRL_PIN(100, "ASDOUT1", UNIPHIER_PIN_IECTRL_NONE,
93, UNIPHIER_PIN_DRV_4_8,
93, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(101, "ARCOUT", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(101, "ARCOUT", 0,
94, UNIPHIER_PIN_DRV_4_8,
94, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(102, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(102, "SDA0", 10,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(103, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(103, "SCL0", 10,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(104, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(104, "SDA1", 11,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(105, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(105, "SCL1", 11,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", 12,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", 12,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", 13,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", 13,
-1, UNIPHIER_PIN_DRV_FIXED_4,
-1, UNIPHIER_PIN_PULL_NONE),
UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
@@ -358,76 +358,76 @@
UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
96, UNIPHIER_PIN_DRV_4_8,
96, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(112, "SBO1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(112, "SBO1", 0,
97, UNIPHIER_PIN_DRV_4_8,
97, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(113, "SBI1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(113, "SBI1", 0,
98, UNIPHIER_PIN_DRV_4_8,
98, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(114, "TXD1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(114, "TXD1", 0,
99, UNIPHIER_PIN_DRV_4_8,
99, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(115, "RXD1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(115, "RXD1", 0,
100, UNIPHIER_PIN_DRV_4_8,
100, UNIPHIER_PIN_PULL_UP),
- UNIPHIER_PINCTRL_PIN(116, "HIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(116, "HIN", 1,
-1, UNIPHIER_PIN_DRV_FIXED_5,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(117, "VIN", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(117, "VIN", 2,
-1, UNIPHIER_PIN_DRV_FIXED_5,
-1, UNIPHIER_PIN_PULL_NONE),
- UNIPHIER_PINCTRL_PIN(118, "TCON0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(118, "TCON0", 0,
101, UNIPHIER_PIN_DRV_4_8,
101, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(119, "TCON1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(119, "TCON1", 0,
102, UNIPHIER_PIN_DRV_4_8,
102, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(120, "TCON2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(120, "TCON2", 0,
103, UNIPHIER_PIN_DRV_4_8,
103, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(121, "TCON3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(121, "TCON3", 0,
104, UNIPHIER_PIN_DRV_4_8,
104, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(122, "TCON4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(122, "TCON4", 0,
105, UNIPHIER_PIN_DRV_4_8,
105, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(123, "TCON5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(123, "TCON5", 0,
106, UNIPHIER_PIN_DRV_4_8,
106, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(124, "TCON6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(124, "TCON6", 0,
107, UNIPHIER_PIN_DRV_4_8,
107, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(125, "TCON7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(125, "TCON7", 0,
108, UNIPHIER_PIN_DRV_4_8,
108, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(126, "TCON8", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(126, "TCON8", 0,
109, UNIPHIER_PIN_DRV_4_8,
109, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(127, "PWMA", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(127, "PWMA", 0,
110, UNIPHIER_PIN_DRV_4_8,
110, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(128, "XIRQ0", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(128, "XIRQ0", 0,
111, UNIPHIER_PIN_DRV_4_8,
111, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(129, "XIRQ1", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(129, "XIRQ1", 0,
112, UNIPHIER_PIN_DRV_4_8,
112, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(130, "XIRQ2", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(130, "XIRQ2", 0,
113, UNIPHIER_PIN_DRV_4_8,
113, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(131, "XIRQ3", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(131, "XIRQ3", 0,
114, UNIPHIER_PIN_DRV_4_8,
114, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(132, "XIRQ4", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(132, "XIRQ4", 0,
115, UNIPHIER_PIN_DRV_4_8,
115, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(133, "XIRQ5", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(133, "XIRQ5", 0,
116, UNIPHIER_PIN_DRV_4_8,
116, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(134, "XIRQ6", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(134, "XIRQ6", 0,
117, UNIPHIER_PIN_DRV_4_8,
117, UNIPHIER_PIN_PULL_DOWN),
- UNIPHIER_PINCTRL_PIN(135, "XIRQ7", UNIPHIER_PIN_IECTRL_NONE,
+ UNIPHIER_PINCTRL_PIN(135, "XIRQ7", 0,
118, UNIPHIER_PIN_DRV_4_8,
118, UNIPHIER_PIN_PULL_DOWN),
};
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 454536c..9c78074 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -887,6 +887,8 @@
static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
struct mvs_slot_info *slot, u32 slot_idx)
{
+ if (!slot)
+ return;
if (!slot->task)
return;
if (!sas_protocol_ata(task->task_proto))
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index 0a2168e..e7649ed 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -226,16 +226,20 @@
drv = scsi_dh_find_driver(sdev);
if (drv)
- devinfo = scsi_dh_lookup(drv);
+ devinfo = __scsi_dh_lookup(drv);
if (devinfo)
err = scsi_dh_handler_attach(sdev, devinfo);
return err;
}
-void scsi_dh_remove_device(struct scsi_device *sdev)
+void scsi_dh_release_device(struct scsi_device *sdev)
{
if (sdev->handler)
scsi_dh_handler_detach(sdev);
+}
+
+void scsi_dh_remove_device(struct scsi_device *sdev)
+{
device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
}
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 644bb73..4d01cdb 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -173,9 +173,11 @@
/* scsi_dh.c */
#ifdef CONFIG_SCSI_DH
int scsi_dh_add_device(struct scsi_device *sdev);
+void scsi_dh_release_device(struct scsi_device *sdev);
void scsi_dh_remove_device(struct scsi_device *sdev);
#else
static inline int scsi_dh_add_device(struct scsi_device *sdev) { return 0; }
+static inline void scsi_dh_release_device(struct scsi_device *sdev) { }
static inline void scsi_dh_remove_device(struct scsi_device *sdev) { }
#endif
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index b333389..dff8faf 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -399,6 +399,8 @@
sdev = container_of(work, struct scsi_device, ew.work);
+ scsi_dh_release_device(sdev);
+
parent = sdev->sdev_gendev.parent;
spin_lock_irqsave(sdev->host->host_lock, flags);
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 23685e7..bd2c69f 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -116,7 +116,7 @@
if (ret)
goto error_ret;
- for (i = 0; i < num_read; i++)
+ for (i = 0; i < num_read / sizeof(u16); i++)
*(((u16 *)rx) + i) = be16_to_cpup((__be16 *)rx + i);
if (copy_to_user(buf, rx, num_read))
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 3f7715c..47fc00a 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -915,11 +915,12 @@
case IIO_CHAN_INFO_OFFSET:
if (chan->type == IIO_TEMP) {
/* The calculated value from the ADC is in Kelvin, we
- * want Celsius for hwmon so the offset is
- * -272.15 * scale
+ * want Celsius for hwmon so the offset is -273.15
+ * The offset is applied before scaling so it is
+ * actually -213.15 * 4 / 1.012 = -1079.644268
*/
- *val = -1075;
- *val2 = 691699;
+ *val = -1079;
+ *val2 = 644268;
return IIO_VAL_INT_PLUS_MICRO;
}
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index 769b611..a9bc6e2 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -224,7 +224,7 @@
prefetchw(&page->flags);
ret = add_to_page_cache_lru(page, inode->i_mapping, offset,
- GFP_KERNEL);
+ GFP_NOFS);
if (ret == 0) {
unlock_page(page);
} else {
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 0bae8cc..ca920b0 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -932,7 +932,7 @@
if (data->soc == SOC_ARCH_EXYNOS5260)
emul_con = EXYNOS5260_EMUL_CON;
- if (data->soc == SOC_ARCH_EXYNOS5433)
+ else if (data->soc == SOC_ARCH_EXYNOS5433)
emul_con = EXYNOS5433_TMU_EMUL_CON;
else if (data->soc == SOC_ARCH_EXYNOS7)
emul_con = EXYNOS7_TMU_REG_EMUL_CON;
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 21d01a4..e508939 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -80,10 +80,6 @@
return 0;
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
- if (dma->tx_size < p->port.fifosize) {
- ret = -EINVAL;
- goto err;
- }
desc = dmaengine_prep_slave_single(dma->txchan,
dma->tx_addr + xmit->tail,
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index c79d336..c47d3e4 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -147,6 +147,7 @@
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+ xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 43291f9..97ffe39 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2191,6 +2191,10 @@
}
/* Fast path - was this the last TRB in the TD for this URB? */
} else if (event_trb == td->last_trb) {
+ if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
+ return finish_td(xhci, td, event_trb, event, ep,
+ status, false);
+
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length =
td->urb->transfer_buffer_length -
@@ -2242,6 +2246,12 @@
td->urb->actual_length +=
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+ if (trb_comp_code == COMP_SHORT_TX) {
+ xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
+ td->urb_length_set = true;
+ return 0;
+ }
}
return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2274,6 +2284,7 @@
u32 trb_comp_code;
int ret = 0;
int td_num = 0;
+ bool handling_skipped_tds = false;
slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id];
@@ -2410,6 +2421,10 @@
ep->skip = true;
xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
goto cleanup;
+ case COMP_PING_ERR:
+ ep->skip = true;
+ xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
+ goto cleanup;
default:
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
status = 0;
@@ -2546,13 +2561,18 @@
ep, &status);
cleanup:
+
+
+ handling_skipped_tds = ep->skip &&
+ trb_comp_code != COMP_MISSED_INT &&
+ trb_comp_code != COMP_PING_ERR;
+
/*
- * Do not update event ring dequeue pointer if ep->skip is set.
- * Will roll back to continue process missed tds.
+ * Do not update event ring dequeue pointer if we're in a loop
+ * processing missed tds.
*/
- if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
+ if (!handling_skipped_tds)
inc_deq(xhci, xhci->event_ring);
- }
if (ret) {
urb = td->urb;
@@ -2587,7 +2607,7 @@
* Process them as short transfer until reach the td pointed by
* the event.
*/
- } while (ep->skip && trb_comp_code != COMP_MISSED_INT);
+ } while (handling_skipped_tds);
return 0;
}
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 70f2b8a..1bd9232 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -391,9 +391,20 @@
}
musb->isr = omap2430_musb_interrupt;
+ /*
+ * Enable runtime PM for musb parent (this driver). We can't
+ * do it earlier as struct musb is not yet allocated and we
+ * need to touch the musb registers for runtime PM.
+ */
+ pm_runtime_enable(glue->dev);
+ status = pm_runtime_get_sync(glue->dev);
+ if (status < 0)
+ goto err1;
+
status = pm_runtime_get_sync(dev);
if (status < 0) {
dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
+ pm_runtime_put_sync(glue->dev);
goto err1;
}
@@ -426,6 +437,7 @@
phy_power_on(musb->phy);
pm_runtime_put_noidle(musb->controller);
+ pm_runtime_put_noidle(glue->dev);
return 0;
err1:
@@ -626,7 +638,11 @@
goto err2;
}
- pm_runtime_enable(&pdev->dev);
+ /*
+ * Note that we cannot enable PM runtime yet for this
+ * driver as we need struct musb initialized first.
+ * See omap2430_musb_init above.
+ */
ret = platform_device_add(musb);
if (ret) {
@@ -675,11 +691,12 @@
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
- if (musb) {
- omap2430_low_level_init(musb);
- musb_writel(musb->mregs, OTG_INTERFSEL,
- musb->context.otg_interfsel);
- }
+ if (!musb)
+ return -EPROBE_DEFER;
+
+ omap2430_low_level_init(musb);
+ musb_writel(musb->mregs, OTG_INTERFSEL,
+ musb->context.otg_interfsel);
return 0;
}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 4772862..d3f7674 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -183,10 +183,17 @@
return vq->acked_features & (1ULL << bit);
}
+#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
{
return vq->is_le;
}
+#else
+static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
+{
+ return virtio_legacy_is_little_endian() || vq->is_le;
+}
+#endif
/* Memory accessors */
static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 1aaf893..92f3949 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -1093,6 +1093,7 @@
con_copy_unimap(vc, svc);
ops = info->fbcon_par;
+ ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
p->con_rotate = initial_rotation;
set_blitting_type(vc, info);
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index ecbc63d..9a2ec79 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1828,7 +1828,6 @@
int found = 0;
struct extent_buffer *eb;
struct btrfs_inode_extref *extref;
- struct extent_buffer *leaf;
u32 item_size;
u32 cur_offset;
unsigned long ptr;
@@ -1856,9 +1855,8 @@
btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
btrfs_release_path(path);
- leaf = path->nodes[0];
- item_size = btrfs_item_size_nr(leaf, slot);
- ptr = btrfs_item_ptr_offset(leaf, slot);
+ item_size = btrfs_item_size_nr(eb, slot);
+ ptr = btrfs_item_ptr_offset(eb, slot);
cur_offset = 0;
while (cur_offset < item_size) {
@@ -1872,7 +1870,7 @@
if (ret)
break;
- cur_offset += btrfs_inode_extref_name_len(leaf, extref);
+ cur_offset += btrfs_inode_extref_name_len(eb, extref);
cur_offset += sizeof(*extref);
}
btrfs_tree_read_unlock_blocking(eb);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index b823fac..8c6f247 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2584,7 +2584,7 @@
alloc_start);
if (ret)
goto out;
- } else {
+ } else if (offset + len > inode->i_size) {
/*
* If we are fallocating from the end of the file onward we
* need to zero out the end of the page if i_size lands in the
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0adf542..8d20f3b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4639,6 +4639,11 @@
bctl->flags |= BTRFS_BALANCE_TYPE_MASK;
}
+ if (bctl->flags & ~(BTRFS_BALANCE_ARGS_MASK | BTRFS_BALANCE_TYPE_MASK)) {
+ ret = -EINVAL;
+ goto out_bctl;
+ }
+
do_balance:
/*
* Ownership of bctl and mutually_exclusive_operation_running
@@ -4650,12 +4655,15 @@
need_unlock = false;
ret = btrfs_balance(bctl, bargs);
+ bctl = NULL;
if (arg) {
if (copy_to_user(arg, bargs, sizeof(*bargs)))
ret = -EFAULT;
}
+out_bctl:
+ kfree(bctl);
out_bargs:
kfree(bargs);
out_unlock:
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 2ca784a..595279a 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -376,6 +376,14 @@
#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4)
#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5)
+#define BTRFS_BALANCE_ARGS_MASK \
+ (BTRFS_BALANCE_ARGS_PROFILES | \
+ BTRFS_BALANCE_ARGS_USAGE | \
+ BTRFS_BALANCE_ARGS_DEVID | \
+ BTRFS_BALANCE_ARGS_DRANGE | \
+ BTRFS_BALANCE_ARGS_VRANGE | \
+ BTRFS_BALANCE_ARGS_LIMIT)
+
/*
* Profile changing flags. When SOFT is set we won't relocate chunk if
* it already has the target profile (even though it may be
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index e2a6af1..62203c3 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3380,6 +3380,7 @@
struct page *page, *tpage;
unsigned int expected_index;
int rc;
+ gfp_t gfp = GFP_KERNEL & mapping_gfp_mask(mapping);
INIT_LIST_HEAD(tmplist);
@@ -3392,7 +3393,7 @@
*/
__set_page_locked(page);
rc = add_to_page_cache_locked(page, mapping,
- page->index, GFP_KERNEL);
+ page->index, gfp);
/* give up if we can't stick it in the cache */
if (rc) {
@@ -3418,8 +3419,7 @@
break;
__set_page_locked(page);
- if (add_to_page_cache_locked(page, mapping, page->index,
- GFP_KERNEL)) {
+ if (add_to_page_cache_locked(page, mapping, page->index, gfp)) {
__clear_page_locked(page);
break;
}
diff --git a/fs/dax.c b/fs/dax.c
index bcfb14b..a86d3cc 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -285,6 +285,7 @@
static int dax_insert_mapping(struct inode *inode, struct buffer_head *bh,
struct vm_area_struct *vma, struct vm_fault *vmf)
{
+ struct address_space *mapping = inode->i_mapping;
sector_t sector = bh->b_blocknr << (inode->i_blkbits - 9);
unsigned long vaddr = (unsigned long)vmf->virtual_address;
void __pmem *addr;
@@ -292,6 +293,8 @@
pgoff_t size;
int error;
+ i_mmap_lock_read(mapping);
+
/*
* Check truncate didn't happen while we were allocating a block.
* If it did, this block may or may not be still allocated to the
@@ -321,6 +324,8 @@
error = vm_insert_mixed(vma, vaddr, pfn);
out:
+ i_mmap_unlock_read(mapping);
+
return error;
}
@@ -382,17 +387,15 @@
* from a read fault and we've raced with a truncate
*/
error = -EIO;
- goto unlock;
+ goto unlock_page;
}
- } else {
- i_mmap_lock_write(mapping);
}
error = get_block(inode, block, &bh, 0);
if (!error && (bh.b_size < PAGE_SIZE))
error = -EIO; /* fs corruption? */
if (error)
- goto unlock;
+ goto unlock_page;
if (!buffer_mapped(&bh) && !buffer_unwritten(&bh) && !vmf->cow_page) {
if (vmf->flags & FAULT_FLAG_WRITE) {
@@ -403,9 +406,8 @@
if (!error && (bh.b_size < PAGE_SIZE))
error = -EIO;
if (error)
- goto unlock;
+ goto unlock_page;
} else {
- i_mmap_unlock_write(mapping);
return dax_load_hole(mapping, page, vmf);
}
}
@@ -417,15 +419,17 @@
else
clear_user_highpage(new_page, vaddr);
if (error)
- goto unlock;
+ goto unlock_page;
vmf->page = page;
if (!page) {
+ i_mmap_lock_read(mapping);
/* Check we didn't race with truncate */
size = (i_size_read(inode) + PAGE_SIZE - 1) >>
PAGE_SHIFT;
if (vmf->pgoff >= size) {
+ i_mmap_unlock_read(mapping);
error = -EIO;
- goto unlock;
+ goto out;
}
}
return VM_FAULT_LOCKED;
@@ -461,8 +465,6 @@
WARN_ON_ONCE(!(vmf->flags & FAULT_FLAG_WRITE));
}
- if (!page)
- i_mmap_unlock_write(mapping);
out:
if (error == -ENOMEM)
return VM_FAULT_OOM | major;
@@ -471,14 +473,11 @@
return VM_FAULT_SIGBUS | major;
return VM_FAULT_NOPAGE | major;
- unlock:
+ unlock_page:
if (page) {
unlock_page(page);
page_cache_release(page);
- } else {
- i_mmap_unlock_write(mapping);
}
-
goto out;
}
EXPORT_SYMBOL(__dax_fault);
@@ -556,10 +555,10 @@
block = (sector_t)pgoff << (PAGE_SHIFT - blkbits);
bh.b_size = PMD_SIZE;
- i_mmap_lock_write(mapping);
length = get_block(inode, block, &bh, write);
if (length)
return VM_FAULT_SIGBUS;
+ i_mmap_lock_read(mapping);
/*
* If the filesystem isn't willing to tell us the length of a hole,
@@ -569,36 +568,14 @@
if (!buffer_size_valid(&bh) || bh.b_size < PMD_SIZE)
goto fallback;
- sector = bh.b_blocknr << (blkbits - 9);
-
- if (buffer_unwritten(&bh) || buffer_new(&bh)) {
- int i;
-
- length = bdev_direct_access(bh.b_bdev, sector, &kaddr, &pfn,
- bh.b_size);
- if (length < 0) {
- result = VM_FAULT_SIGBUS;
- goto out;
- }
- if ((length < PMD_SIZE) || (pfn & PG_PMD_COLOUR))
- goto fallback;
-
- for (i = 0; i < PTRS_PER_PMD; i++)
- clear_pmem(kaddr + i * PAGE_SIZE, PAGE_SIZE);
- wmb_pmem();
- count_vm_event(PGMAJFAULT);
- mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
- result |= VM_FAULT_MAJOR;
- }
-
/*
* If we allocated new storage, make sure no process has any
* zero pages covering this hole
*/
if (buffer_new(&bh)) {
- i_mmap_unlock_write(mapping);
+ i_mmap_unlock_read(mapping);
unmap_mapping_range(mapping, pgoff << PAGE_SHIFT, PMD_SIZE, 0);
- i_mmap_lock_write(mapping);
+ i_mmap_lock_read(mapping);
}
/*
@@ -635,6 +612,7 @@
result = VM_FAULT_NOPAGE;
spin_unlock(ptl);
} else {
+ sector = bh.b_blocknr << (blkbits - 9);
length = bdev_direct_access(bh.b_bdev, sector, &kaddr, &pfn,
bh.b_size);
if (length < 0) {
@@ -644,15 +622,25 @@
if ((length < PMD_SIZE) || (pfn & PG_PMD_COLOUR))
goto fallback;
+ if (buffer_unwritten(&bh) || buffer_new(&bh)) {
+ int i;
+ for (i = 0; i < PTRS_PER_PMD; i++)
+ clear_pmem(kaddr + i * PAGE_SIZE, PAGE_SIZE);
+ wmb_pmem();
+ count_vm_event(PGMAJFAULT);
+ mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
+ result |= VM_FAULT_MAJOR;
+ }
+
result |= vmf_insert_pfn_pmd(vma, address, pmd, pfn, write);
}
out:
+ i_mmap_unlock_read(mapping);
+
if (buffer_unwritten(&bh))
complete_unwritten(&bh, !(result & VM_FAULT_ERROR));
- i_mmap_unlock_write(mapping);
-
return result;
fallback:
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index 47728da..b46e9fc 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -63,7 +63,7 @@
If unsure, say N.
config EXT4_USE_FOR_EXT2
- bool "Use ext4 for ext2/ext3 file systems"
+ bool "Use ext4 for ext2 file systems"
depends on EXT4_FS
depends on EXT2_FS=n
default y
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index e26803f..560af04 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -165,8 +165,8 @@
if (pages) {
page = list_entry(pages->prev, struct page, lru);
list_del(&page->lru);
- if (add_to_page_cache_lru(page, mapping,
- page->index, GFP_KERNEL))
+ if (add_to_page_cache_lru(page, mapping, page->index,
+ GFP_KERNEL & mapping_gfp_mask(mapping)))
goto next_page;
}
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 091a364..29e4599 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -778,19 +778,24 @@
struct wb_writeback_work *base_work,
bool skip_if_busy)
{
- int next_memcg_id = 0;
- struct bdi_writeback *wb;
- struct wb_iter iter;
+ struct bdi_writeback *last_wb = NULL;
+ struct bdi_writeback *wb = list_entry_rcu(&bdi->wb_list,
+ struct bdi_writeback, bdi_node);
might_sleep();
restart:
rcu_read_lock();
- bdi_for_each_wb(wb, bdi, &iter, next_memcg_id) {
+ list_for_each_entry_continue_rcu(wb, &bdi->wb_list, bdi_node) {
DEFINE_WB_COMPLETION_ONSTACK(fallback_work_done);
struct wb_writeback_work fallback_work;
struct wb_writeback_work *work;
long nr_pages;
+ if (last_wb) {
+ wb_put(last_wb);
+ last_wb = NULL;
+ }
+
/* SYNC_ALL writes out I_DIRTY_TIME too */
if (!wb_has_dirty_io(wb) &&
(base_work->sync_mode == WB_SYNC_NONE ||
@@ -819,12 +824,22 @@
wb_queue_work(wb, work);
- next_memcg_id = wb->memcg_css->id + 1;
+ /*
+ * Pin @wb so that it stays on @bdi->wb_list. This allows
+ * continuing iteration from @wb after dropping and
+ * regrabbing rcu read lock.
+ */
+ wb_get(wb);
+ last_wb = wb;
+
rcu_read_unlock();
wb_wait_for_completion(bdi, &fallback_work_done);
goto restart;
}
rcu_read_unlock();
+
+ if (last_wb)
+ wb_put(last_wb);
}
#else /* CONFIG_CGROUP_WRITEBACK */
@@ -1857,12 +1872,11 @@
rcu_read_lock();
list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
struct bdi_writeback *wb;
- struct wb_iter iter;
if (!bdi_has_dirty_io(bdi))
continue;
- bdi_for_each_wb(wb, bdi, &iter, 0)
+ list_for_each_entry_rcu(wb, &bdi->wb_list, bdi_node)
wb_start_writeback(wb, wb_split_bdi_pages(wb, nr_pages),
false, reason);
}
@@ -1894,11 +1908,10 @@
rcu_read_lock();
list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
struct bdi_writeback *wb;
- struct wb_iter iter;
- bdi_for_each_wb(wb, bdi, &iter, 0)
- if (!list_empty(&bdi->wb.b_dirty_time))
- wb_wakeup(&bdi->wb);
+ list_for_each_entry_rcu(wb, &bdi->wb_list, bdi_node)
+ if (!list_empty(&wb->b_dirty_time))
+ wb_wakeup(wb);
}
rcu_read_unlock();
schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
diff --git a/fs/mpage.c b/fs/mpage.c
index 778a4dd..a7c3427 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -139,7 +139,8 @@
static struct bio *
do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
sector_t *last_block_in_bio, struct buffer_head *map_bh,
- unsigned long *first_logical_block, get_block_t get_block)
+ unsigned long *first_logical_block, get_block_t get_block,
+ gfp_t gfp)
{
struct inode *inode = page->mapping->host;
const unsigned blkbits = inode->i_blkbits;
@@ -277,8 +278,7 @@
goto out;
}
bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9),
- min_t(int, nr_pages, BIO_MAX_PAGES),
- GFP_KERNEL);
+ min_t(int, nr_pages, BIO_MAX_PAGES), gfp);
if (bio == NULL)
goto confused;
}
@@ -361,6 +361,7 @@
sector_t last_block_in_bio = 0;
struct buffer_head map_bh;
unsigned long first_logical_block = 0;
+ gfp_t gfp = GFP_KERNEL & mapping_gfp_mask(mapping);
map_bh.b_state = 0;
map_bh.b_size = 0;
@@ -370,12 +371,13 @@
prefetchw(&page->flags);
list_del(&page->lru);
if (!add_to_page_cache_lru(page, mapping,
- page->index, GFP_KERNEL)) {
+ page->index,
+ gfp)) {
bio = do_mpage_readpage(bio, page,
nr_pages - page_idx,
&last_block_in_bio, &map_bh,
&first_logical_block,
- get_block);
+ get_block, gfp);
}
page_cache_release(page);
}
@@ -395,11 +397,12 @@
sector_t last_block_in_bio = 0;
struct buffer_head map_bh;
unsigned long first_logical_block = 0;
+ gfp_t gfp = GFP_KERNEL & mapping_gfp_mask(page->mapping);
map_bh.b_state = 0;
map_bh.b_size = 0;
bio = do_mpage_readpage(bio, page, 1, &last_block_in_bio,
- &map_bh, &first_logical_block, get_block);
+ &map_bh, &first_logical_block, get_block, gfp);
if (bio)
mpage_bio_submit(READ, bio);
return 0;
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index cdefaa3..c29d942 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -56,14 +56,6 @@
u32 device_generation = 0;
int error;
- /*
- * We do not attempt to support I/O smaller than the fs block size,
- * or not aligned to it.
- */
- if (args->lg_minlength < block_size) {
- dprintk("pnfsd: I/O too small\n");
- goto out_layoutunavailable;
- }
if (seg->offset & (block_size - 1)) {
dprintk("pnfsd: I/O misaligned\n");
goto out_layoutunavailable;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index ee5aa4d..ce38b4c 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -1658,12 +1658,13 @@
if (ret < 0) {
mlog(ML_ERROR, "failed to dispatch assert master work\n");
response = DLM_MASTER_RESP_ERROR;
+ spin_unlock(&res->spinlock);
dlm_lockres_put(res);
} else {
dispatched = 1;
__dlm_lockres_grab_inflight_worker(dlm, res);
+ spin_unlock(&res->spinlock);
}
- spin_unlock(&res->spinlock);
} else {
if (res)
dlm_lockres_put(res);
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 3d90ad7..58eaa5c 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -1723,8 +1723,8 @@
} else {
dispatched = 1;
__dlm_lockres_grab_inflight_worker(dlm, res);
+ spin_unlock(&res->spinlock);
}
- spin_unlock(&res->spinlock);
} else {
/* put.. incase we are not the master */
spin_unlock(&res->spinlock);
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 84d693d..871fcb6 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -81,11 +81,11 @@
if (len == 0)
return 0;
- old_file = ovl_path_open(old, O_RDONLY);
+ old_file = ovl_path_open(old, O_LARGEFILE | O_RDONLY);
if (IS_ERR(old_file))
return PTR_ERR(old_file);
- new_file = ovl_path_open(new, O_WRONLY);
+ new_file = ovl_path_open(new, O_LARGEFILE | O_WRONLY);
if (IS_ERR(new_file)) {
error = PTR_ERR(new_file);
goto out_fput;
@@ -267,7 +267,7 @@
out_cleanup:
ovl_cleanup(wdir, newdentry);
- goto out;
+ goto out2;
}
/*
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index d9da5a4..ec0c2a050 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -363,6 +363,9 @@
ovl_path_upper(dentry, &realpath);
}
+ if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE)
+ return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
+
return d_backing_inode(realpath.dentry);
}
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 79073d6..e38ee0f 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -544,6 +544,7 @@
mntput(ufs->upper_mnt);
for (i = 0; i < ufs->numlower; i++)
mntput(ufs->lower_mnt[i]);
+ kfree(ufs->lower_mnt);
kfree(ufs->config.lowerdir);
kfree(ufs->config.upperdir);
@@ -1048,6 +1049,7 @@
oe->lowerstack[i].dentry = stack[i].dentry;
oe->lowerstack[i].mnt = ufs->lower_mnt[i];
}
+ kfree(stack);
root_dentry->d_fsdata = oe;
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index ba1323a..a586467 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -70,6 +70,7 @@
unsigned order;
void *data;
int ret;
+ gfp_t gfp = mapping_gfp_mask(inode->i_mapping);
/* make various checks */
order = get_order(newsize);
@@ -84,7 +85,7 @@
/* allocate enough contiguous pages to be able to satisfy the
* request */
- pages = alloc_pages(mapping_gfp_mask(inode->i_mapping), order);
+ pages = alloc_pages(gfp, order);
if (!pages)
return -ENOMEM;
@@ -108,7 +109,7 @@
struct page *page = pages + loop;
ret = add_to_page_cache_lru(page, inode->i_mapping, loop,
- GFP_KERNEL);
+ gfp);
if (ret < 0)
goto add_error;
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 0f408b0..5340099 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -253,6 +253,7 @@
u8 *bytes;
};
+#define DP_REMOTE_I2C_READ_MAX_TRANSACTIONS 4
struct drm_dp_remote_i2c_read {
u8 num_transactions;
u8 port_number;
@@ -262,7 +263,7 @@
u8 *bytes;
u8 no_stop_bit;
u8 i2c_transaction_delay;
- } transactions[4];
+ } transactions[DP_REMOTE_I2C_READ_MAX_TRANSACTIONS];
u8 read_i2c_device_id;
u8 num_bytes_read;
};
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index a23209b..1b4d69f 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -116,6 +116,8 @@
struct list_head work_list;
struct delayed_work dwork; /* work item used for writeback */
+ struct list_head bdi_node; /* anchored at bdi->wb_list */
+
#ifdef CONFIG_CGROUP_WRITEBACK
struct percpu_ref refcnt; /* used only for !root wb's */
struct fprop_local_percpu memcg_completions;
@@ -150,6 +152,7 @@
atomic_long_t tot_write_bandwidth;
struct bdi_writeback wb; /* the root writeback info for this bdi */
+ struct list_head wb_list; /* list of all wbs */
#ifdef CONFIG_CGROUP_WRITEBACK
struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
struct rb_root cgwb_congested_tree; /* their congested states */
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index d5eb4ad1..c85f749 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -19,13 +19,17 @@
#include <linux/slab.h>
int __must_check bdi_init(struct backing_dev_info *bdi);
-void bdi_destroy(struct backing_dev_info *bdi);
+void bdi_exit(struct backing_dev_info *bdi);
__printf(3, 4)
int bdi_register(struct backing_dev_info *bdi, struct device *parent,
const char *fmt, ...);
int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
+void bdi_unregister(struct backing_dev_info *bdi);
+
int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
+void bdi_destroy(struct backing_dev_info *bdi);
+
void wb_start_writeback(struct bdi_writeback *wb, long nr_pages,
bool range_cyclic, enum wb_reason reason);
void wb_start_background_writeback(struct bdi_writeback *wb);
@@ -408,61 +412,6 @@
rcu_read_unlock();
}
-struct wb_iter {
- int start_memcg_id;
- struct radix_tree_iter tree_iter;
- void **slot;
-};
-
-static inline struct bdi_writeback *__wb_iter_next(struct wb_iter *iter,
- struct backing_dev_info *bdi)
-{
- struct radix_tree_iter *titer = &iter->tree_iter;
-
- WARN_ON_ONCE(!rcu_read_lock_held());
-
- if (iter->start_memcg_id >= 0) {
- iter->slot = radix_tree_iter_init(titer, iter->start_memcg_id);
- iter->start_memcg_id = -1;
- } else {
- iter->slot = radix_tree_next_slot(iter->slot, titer, 0);
- }
-
- if (!iter->slot)
- iter->slot = radix_tree_next_chunk(&bdi->cgwb_tree, titer, 0);
- if (iter->slot)
- return *iter->slot;
- return NULL;
-}
-
-static inline struct bdi_writeback *__wb_iter_init(struct wb_iter *iter,
- struct backing_dev_info *bdi,
- int start_memcg_id)
-{
- iter->start_memcg_id = start_memcg_id;
-
- if (start_memcg_id)
- return __wb_iter_next(iter, bdi);
- else
- return &bdi->wb;
-}
-
-/**
- * bdi_for_each_wb - walk all wb's of a bdi in ascending memcg ID order
- * @wb_cur: cursor struct bdi_writeback pointer
- * @bdi: bdi to walk wb's of
- * @iter: pointer to struct wb_iter to be used as iteration buffer
- * @start_memcg_id: memcg ID to start iteration from
- *
- * Iterate @wb_cur through the wb's (bdi_writeback's) of @bdi in ascending
- * memcg ID order starting from @start_memcg_id. @iter is struct wb_iter
- * to be used as temp storage during iteration. rcu_read_lock() must be
- * held throughout iteration.
- */
-#define bdi_for_each_wb(wb_cur, bdi, iter, start_memcg_id) \
- for ((wb_cur) = __wb_iter_init(iter, bdi, start_memcg_id); \
- (wb_cur); (wb_cur) = __wb_iter_next(iter, bdi))
-
#else /* CONFIG_CGROUP_WRITEBACK */
static inline bool inode_cgwb_enabled(struct inode *inode)
@@ -522,14 +471,6 @@
{
}
-struct wb_iter {
- int next_id;
-};
-
-#define bdi_for_each_wb(wb_cur, bdi, iter, start_blkcg_id) \
- for ((iter)->next_id = (start_blkcg_id); \
- ({ (wb_cur) = !(iter)->next_id++ ? &(bdi)->wb : NULL; }); )
-
static inline int inode_congested(struct inode *inode, int cong_bits)
{
return wb_congested(&inode_to_bdi(inode)->wb, cong_bits);
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index 0a5cc7a..c02e669 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -713,9 +713,9 @@
if (!throtl) {
blkg = blkg ?: q->root_blkg;
- blkg_rwstat_add(&blkg->stat_bytes, bio->bi_flags,
+ blkg_rwstat_add(&blkg->stat_bytes, bio->bi_rw,
bio->bi_iter.bi_size);
- blkg_rwstat_add(&blkg->stat_ios, bio->bi_flags, 1);
+ blkg_rwstat_add(&blkg->stat_ios, bio->bi_rw, 1);
}
rcu_read_unlock();
diff --git a/include/linux/cma.h b/include/linux/cma.h
index f7ef093..29f9e77 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -26,6 +26,6 @@
extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
unsigned int order_per_bit,
struct cma **res_cma);
-extern struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align);
+extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align);
extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);
#endif
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index dfaa7b3..8efb40e 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -237,12 +237,25 @@
#define KASAN_ABI_VERSION 3
#endif
+#if GCC_VERSION >= 40902
+/*
+ * Tell the compiler that address safety instrumentation (KASAN)
+ * should not be applied to that function.
+ * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ */
+#define __no_sanitize_address __attribute__((no_sanitize_address))
+#endif
+
#endif /* gcc version >= 40000 specific checks */
#if !defined(__noclone)
#define __noclone /* not needed */
#endif
+#if !defined(__no_sanitize_address)
+#define __no_sanitize_address
+#endif
+
/*
* A trick to suppress uninitialized variable warning without generating any
* code
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index c836eb2..3d78103 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -198,20 +198,46 @@
#include <uapi/linux/types.h>
-static __always_inline void __read_once_size(const volatile void *p, void *res, int size)
+#define __READ_ONCE_SIZE \
+({ \
+ switch (size) { \
+ case 1: *(__u8 *)res = *(volatile __u8 *)p; break; \
+ case 2: *(__u16 *)res = *(volatile __u16 *)p; break; \
+ case 4: *(__u32 *)res = *(volatile __u32 *)p; break; \
+ case 8: *(__u64 *)res = *(volatile __u64 *)p; break; \
+ default: \
+ barrier(); \
+ __builtin_memcpy((void *)res, (const void *)p, size); \
+ barrier(); \
+ } \
+})
+
+static __always_inline
+void __read_once_size(const volatile void *p, void *res, int size)
{
- switch (size) {
- case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
- case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
- case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
- case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
- default:
- barrier();
- __builtin_memcpy((void *)res, (const void *)p, size);
- barrier();
- }
+ __READ_ONCE_SIZE;
}
+#ifdef CONFIG_KASAN
+/*
+ * This function is not 'inline' because __no_sanitize_address confilcts
+ * with inlining. Attempt to inline it may cause a build failure.
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ * '__maybe_unused' allows us to avoid defined-but-not-used warnings.
+ */
+static __no_sanitize_address __maybe_unused
+void __read_once_size_nocheck(const volatile void *p, void *res, int size)
+{
+ __READ_ONCE_SIZE;
+}
+#else
+static __always_inline
+void __read_once_size_nocheck(const volatile void *p, void *res, int size)
+{
+ __READ_ONCE_SIZE;
+}
+#endif
+
static __always_inline void __write_once_size(volatile void *p, void *res, int size)
{
switch (size) {
@@ -248,8 +274,22 @@
* required ordering.
*/
-#define READ_ONCE(x) \
- ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
+#define __READ_ONCE(x, check) \
+({ \
+ union { typeof(x) __val; char __c[1]; } __u; \
+ if (check) \
+ __read_once_size(&(x), __u.__c, sizeof(x)); \
+ else \
+ __read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \
+ __u.__val; \
+})
+#define READ_ONCE(x) __READ_ONCE(x, 1)
+
+/*
+ * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need
+ * to hide memory access from KASAN.
+ */
+#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
#define WRITE_ONCE(x, val) \
({ \
diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h
index 569bbd0..fec734d 100644
--- a/include/linux/dma-contiguous.h
+++ b/include/linux/dma-contiguous.h
@@ -111,7 +111,7 @@
return ret;
}
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
unsigned int order);
bool dma_release_from_contiguous(struct device *dev, struct page *pages,
int count);
@@ -144,7 +144,7 @@
}
static inline
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
unsigned int order)
{
return NULL;
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 6452ff4..3e3318dd 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -676,8 +676,9 @@
struct list_head *mem_cgroup_cgwb_list(struct mem_cgroup *memcg);
struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb);
-void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pavail,
- unsigned long *pdirty, unsigned long *pwriteback);
+void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
+ unsigned long *pheadroom, unsigned long *pdirty,
+ unsigned long *pwriteback);
#else /* CONFIG_CGROUP_WRITEBACK */
@@ -687,7 +688,8 @@
}
static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
- unsigned long *pavail,
+ unsigned long *pfilepages,
+ unsigned long *pheadroom,
unsigned long *pdirty,
unsigned long *pwriteback)
{
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2d15e38..210d11a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1054,6 +1054,10 @@
* This function is used to pass protocol port error state information
* to the switch driver. The switch driver can react to the proto_down
* by doing a phys down on the associated switch port.
+ * int (*ndo_fill_metadata_dst)(struct net_device *dev, struct sk_buff *skb);
+ * This function is used to get egress tunnel information for given skb.
+ * This is useful for retrieving outer tunnel header parameters while
+ * sampling packet.
*
*/
struct net_device_ops {
@@ -1227,6 +1231,8 @@
int (*ndo_get_iflink)(const struct net_device *dev);
int (*ndo_change_proto_down)(struct net_device *dev,
bool proto_down);
+ int (*ndo_fill_metadata_dst)(struct net_device *dev,
+ struct sk_buff *skb);
};
/**
@@ -2203,6 +2209,7 @@
void dev_remove_offload(struct packet_offload *po);
int dev_get_iflink(const struct net_device *dev);
+int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
unsigned short mask);
struct net_device *dev_get_by_name(struct net *net, const char *name);
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index e5a7013..88fa8af 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -17,7 +17,7 @@
#include <linux/platform_device.h>
-#define INT_DMA_LCD 25
+#define INT_DMA_LCD (NR_IRQS_LEGACY + 25)
#define OMAP1_DMA_TOUT_IRQ (1 << 0)
#define OMAP_DMA_DROP_IRQ (1 << 1)
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index cb1b9bb..b36d837 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -64,7 +64,7 @@
struct socket_wq peer_wq;
};
-static inline struct unix_sock *unix_sk(struct sock *sk)
+static inline struct unix_sock *unix_sk(const struct sock *sk)
{
return (struct unix_sock *)sk;
}
diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h
index af9d538..ce00971 100644
--- a/include/net/dst_metadata.h
+++ b/include/net/dst_metadata.h
@@ -60,6 +60,38 @@
return tun_dst;
}
+static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb)
+{
+ struct metadata_dst *md_dst = skb_metadata_dst(skb);
+ int md_size = md_dst->u.tun_info.options_len;
+ struct metadata_dst *new_md;
+
+ if (!md_dst)
+ return ERR_PTR(-EINVAL);
+
+ new_md = metadata_dst_alloc(md_size, GFP_ATOMIC);
+ if (!new_md)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(&new_md->u.tun_info, &md_dst->u.tun_info,
+ sizeof(struct ip_tunnel_info) + md_size);
+ skb_dst_drop(skb);
+ dst_hold(&new_md->dst);
+ skb_dst_set(skb, &new_md->dst);
+ return new_md;
+}
+
+static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb)
+{
+ struct metadata_dst *dst;
+
+ dst = tun_dst_unclone(skb);
+ if (IS_ERR(dst))
+ return NULL;
+
+ return &dst->u.tun_info;
+}
+
static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
__be16 flags,
__be64 tunnel_id,
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 186f3a1e..fc19376 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -113,12 +113,12 @@
void __inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo,
bool rearm);
-static void inline inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo)
+static inline void inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo)
{
__inet_twsk_schedule(tw, timeo, false);
}
-static void inline inet_twsk_reschedule(struct inet_timewait_sock *tw, int timeo)
+static inline void inet_twsk_reschedule(struct inet_timewait_sock *tw, int timeo)
{
__inet_twsk_schedule(tw, timeo, true);
}
diff --git a/include/net/sock.h b/include/net/sock.h
index 7aa7844..e237170 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -828,6 +828,14 @@
if (sk_rcvqueues_full(sk, limit))
return -ENOBUFS;
+ /*
+ * If the skb was allocated from pfmemalloc reserves, only
+ * allow SOCK_MEMALLOC sockets to use it as this socket is
+ * helping free memory
+ */
+ if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC))
+ return -ENOMEM;
+
__sk_add_backlog(sk, skb);
sk->sk_backlog.len += skb->truesize;
return 0;
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 884e728..26ede14 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -86,7 +86,7 @@
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array),\
- .info = snd_soc_info_volsw, \
+ .info = snd_soc_info_volsw_sx, \
.get = snd_soc_get_volsw_sx,\
.put = snd_soc_put_volsw_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
@@ -156,7 +156,7 @@
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, \
+ .info = snd_soc_info_volsw_sx, \
.get = snd_soc_get_volsw_sx, \
.put = snd_soc_put_volsw_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
@@ -574,6 +574,8 @@
struct snd_ctl_elem_value *ucontrol);
int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
+int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
diff --git a/include/sound/wm8904.h b/include/sound/wm8904.h
index 898be3a..6d8f8fb 100644
--- a/include/sound/wm8904.h
+++ b/include/sound/wm8904.h
@@ -119,7 +119,7 @@
#define WM8904_MIC_REGS 2
#define WM8904_GPIO_REGS 4
#define WM8904_DRC_REGS 4
-#define WM8904_EQ_REGS 25
+#define WM8904_EQ_REGS 24
/**
* DRC configurations are specified with a label and a set of register
diff --git a/include/uapi/asm-generic/signal.h b/include/uapi/asm-generic/signal.h
index 9df61f1..3094618 100644
--- a/include/uapi/asm-generic/signal.h
+++ b/include/uapi/asm-generic/signal.h
@@ -80,8 +80,10 @@
* SA_RESTORER 0x04000000
*/
+#if !defined MINSIGSTKSZ || !defined SIGSTKSZ
#define MINSIGSTKSZ 2048
#define SIGSTKSZ 8192
+#endif
#ifndef __ASSEMBLY__
typedef struct {
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 32e07d8..e663627 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -323,10 +323,10 @@
OVS_KEY_ATTR_MPLS, /* array of struct ovs_key_mpls.
* The implementation may restrict
* the accepted length of the array. */
- OVS_KEY_ATTR_CT_STATE, /* u8 bitmask of OVS_CS_F_* */
+ OVS_KEY_ATTR_CT_STATE, /* u32 bitmask of OVS_CS_F_* */
OVS_KEY_ATTR_CT_ZONE, /* u16 connection tracking zone. */
OVS_KEY_ATTR_CT_MARK, /* u32 connection tracking mark */
- OVS_KEY_ATTR_CT_LABEL, /* 16-octet connection tracking label */
+ OVS_KEY_ATTR_CT_LABELS, /* 16-octet connection tracking label */
#ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO, /* struct ip_tunnel_info */
@@ -439,9 +439,9 @@
__u8 nd_tll[ETH_ALEN];
};
-#define OVS_CT_LABEL_LEN 16
-struct ovs_key_ct_label {
- __u8 ct_label[OVS_CT_LABEL_LEN];
+#define OVS_CT_LABELS_LEN 16
+struct ovs_key_ct_labels {
+ __u8 ct_labels[OVS_CT_LABELS_LEN];
};
/* OVS_KEY_ATTR_CT_STATE flags */
@@ -449,9 +449,9 @@
#define OVS_CS_F_ESTABLISHED 0x02 /* Part of an existing connection. */
#define OVS_CS_F_RELATED 0x04 /* Related to an established
* connection. */
-#define OVS_CS_F_INVALID 0x20 /* Could not track connection. */
-#define OVS_CS_F_REPLY_DIR 0x40 /* Flow is in the reply direction. */
-#define OVS_CS_F_TRACKED 0x80 /* Conntrack has occurred. */
+#define OVS_CS_F_REPLY_DIR 0x08 /* Flow is in the reply direction. */
+#define OVS_CS_F_INVALID 0x10 /* Could not track connection. */
+#define OVS_CS_F_TRACKED 0x20 /* Conntrack has occurred. */
/**
* enum ovs_flow_attr - attributes for %OVS_FLOW_* commands.
@@ -618,22 +618,25 @@
/**
* enum ovs_ct_attr - Attributes for %OVS_ACTION_ATTR_CT action.
- * @OVS_CT_ATTR_FLAGS: u32 connection tracking flags.
+ * @OVS_CT_ATTR_COMMIT: If present, commits the connection to the conntrack
+ * table. This allows future packets for the same connection to be identified
+ * as 'established' or 'related'. The flow key for the current packet will
+ * retain the pre-commit connection state.
* @OVS_CT_ATTR_ZONE: u16 connection tracking zone.
* @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the
* mask, the corresponding bit in the value is copied to the connection
* tracking mark field in the connection.
- * @OVS_CT_ATTR_LABEL: %OVS_CT_LABEL_LEN value followed by %OVS_CT_LABEL_LEN
+ * @OVS_CT_ATTR_LABEL: %OVS_CT_LABELS_LEN value followed by %OVS_CT_LABELS_LEN
* mask. For each bit set in the mask, the corresponding bit in the value is
* copied to the connection tracking label field in the connection.
* @OVS_CT_ATTR_HELPER: variable length string defining conntrack ALG.
*/
enum ovs_ct_attr {
OVS_CT_ATTR_UNSPEC,
- OVS_CT_ATTR_FLAGS, /* u8 bitmask of OVS_CT_F_*. */
+ OVS_CT_ATTR_COMMIT, /* No argument, commits connection. */
OVS_CT_ATTR_ZONE, /* u16 zone id. */
OVS_CT_ATTR_MARK, /* mark to associate with this connection. */
- OVS_CT_ATTR_LABEL, /* label to associate with this connection. */
+ OVS_CT_ATTR_LABELS, /* labels to associate with this connection. */
OVS_CT_ATTR_HELPER, /* netlink helper to assist detection of
related connections. */
__OVS_CT_ATTR_MAX
@@ -641,14 +644,6 @@
#define OVS_CT_ATTR_MAX (__OVS_CT_ATTR_MAX - 1)
-/*
- * OVS_CT_ATTR_FLAGS flags - bitmask of %OVS_CT_F_*
- * @OVS_CT_F_COMMIT: Commits the flow to the conntrack table. This allows
- * future packets for the same connection to be identified as 'established'
- * or 'related'.
- */
-#define OVS_CT_F_COMMIT 0x01
-
/**
* enum ovs_action_attr - Action types.
*
@@ -705,7 +700,7 @@
* data immediately followed by a mask.
* The data must be zero for the unmasked
* bits. */
- OVS_ACTION_ATTR_CT, /* One nested OVS_CT_ATTR_* . */
+ OVS_ACTION_ATTR_CT, /* Nested OVS_CT_ATTR_* . */
__OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
* from userspace. */
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 7020247..9d8f5d1 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -160,7 +160,7 @@
/* Macros to handle rtattributes */
-#define RTA_ALIGNTO 4
+#define RTA_ALIGNTO 4U
#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
(rta)->rta_len >= sizeof(struct rtattr) && \
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 7e6512b..be9149f 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -228,11 +228,7 @@
{
struct irq_chip *chip = info->chip;
- BUG_ON(!chip);
- if (!chip->irq_mask)
- chip->irq_mask = pci_msi_mask_irq;
- if (!chip->irq_unmask)
- chip->irq_unmask = pci_msi_unmask_irq;
+ BUG_ON(!chip || !chip->irq_mask || !chip->irq_unmask);
if (!chip->irq_set_affinity)
chip->irq_set_affinity = msi_domain_set_affinity;
}
diff --git a/kernel/kmod.c b/kernel/kmod.c
index da98d05..0277d12 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -327,9 +327,13 @@
call_usermodehelper_exec_sync(sub_info);
} else {
pid_t pid;
-
+ /*
+ * Use CLONE_PARENT to reparent it to kthreadd; we do not
+ * want to pollute current->children, and we need a parent
+ * that always ignores SIGCHLD to ensure auto-reaping.
+ */
pid = kernel_thread(call_usermodehelper_exec_async, sub_info,
- SIGCHLD);
+ CLONE_PARENT | SIGCHLD);
if (pid < 0) {
sub_info->retval = pid;
umh_complete(sub_info);
diff --git a/kernel/module.c b/kernel/module.c
index b86b7bf..8f051a1 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1063,11 +1063,15 @@
if (core_kernel_text(a))
return;
- /* module_text_address is safe here: we're supposed to have reference
- * to module from symbol_get, so it can't go away. */
+ /*
+ * Even though we hold a reference on the module; we still need to
+ * disable preemption in order to safely traverse the data structure.
+ */
+ preempt_disable();
modaddr = __module_text_address(a);
BUG_ON(!modaddr);
module_put(modaddr);
+ preempt_enable();
}
EXPORT_SYMBOL_GPL(symbol_put_addr);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 10a8faa..bcd214e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2366,8 +2366,15 @@
trace_sched_wakeup_new(p);
check_preempt_curr(rq, p, WF_FORK);
#ifdef CONFIG_SMP
- if (p->sched_class->task_woken)
+ if (p->sched_class->task_woken) {
+ /*
+ * Nothing relies on rq->lock after this, so its fine to
+ * drop it.
+ */
+ lockdep_unpin_lock(&rq->lock);
p->sched_class->task_woken(rq, p);
+ lockdep_pin_lock(&rq->lock);
+ }
#endif
task_rq_unlock(rq, p, &flags);
}
@@ -7238,9 +7245,6 @@
alloc_cpumask_var(&non_isolated_cpus, GFP_KERNEL);
alloc_cpumask_var(&fallback_doms, GFP_KERNEL);
- /* nohz_full won't take effect without isolating the cpus. */
- tick_nohz_full_add_cpus_to(cpu_isolated_map);
-
sched_init_numa();
/*
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index fc8f010..8b0a15e 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -668,8 +668,15 @@
* Queueing this task back might have overloaded rq, check if we need
* to kick someone away.
*/
- if (has_pushable_dl_tasks(rq))
+ if (has_pushable_dl_tasks(rq)) {
+ /*
+ * Nothing relies on rq->lock after this, so its safe to drop
+ * rq->lock.
+ */
+ lockdep_unpin_lock(&rq->lock);
push_dl_task(rq);
+ lockdep_pin_lock(&rq->lock);
+ }
#endif
unlock:
@@ -1066,8 +1073,9 @@
int target = find_later_rq(p);
if (target != -1 &&
- dl_time_before(p->dl.deadline,
- cpu_rq(target)->dl.earliest_dl.curr))
+ (dl_time_before(p->dl.deadline,
+ cpu_rq(target)->dl.earliest_dl.curr) ||
+ (cpu_rq(target)->dl.dl_nr_running == 0)))
cpu = target;
}
rcu_read_unlock();
@@ -1417,7 +1425,8 @@
later_rq = cpu_rq(cpu);
- if (!dl_time_before(task->dl.deadline,
+ if (later_rq->dl.dl_nr_running &&
+ !dl_time_before(task->dl.deadline,
later_rq->dl.earliest_dl.curr)) {
/*
* Target rq has tasks of equal or earlier deadline,
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6e2e348..9a5e60f 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2363,7 +2363,7 @@
*/
tg_weight = atomic_long_read(&tg->load_avg);
tg_weight -= cfs_rq->tg_load_avg_contrib;
- tg_weight += cfs_rq_load_avg(cfs_rq);
+ tg_weight += cfs_rq->load.weight;
return tg_weight;
}
@@ -2373,7 +2373,7 @@
long tg_weight, load, shares;
tg_weight = calc_tg_weight(tg, cfs_rq);
- load = cfs_rq_load_avg(cfs_rq);
+ load = cfs_rq->load.weight;
shares = (tg->shares * load);
if (tg_weight)
@@ -2664,13 +2664,14 @@
/* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */
static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
{
- int decayed;
struct sched_avg *sa = &cfs_rq->avg;
+ int decayed, removed = 0;
if (atomic_long_read(&cfs_rq->removed_load_avg)) {
long r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
sa->load_avg = max_t(long, sa->load_avg - r, 0);
sa->load_sum = max_t(s64, sa->load_sum - r * LOAD_AVG_MAX, 0);
+ removed = 1;
}
if (atomic_long_read(&cfs_rq->removed_util_avg)) {
@@ -2688,7 +2689,7 @@
cfs_rq->load_last_update_time_copy = sa->last_update_time;
#endif
- return decayed;
+ return decayed || removed;
}
/* Update task and its cfs_rq load average */
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index 8f177c7..4a2ef5a 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -57,9 +57,11 @@
rcu_idle_enter();
trace_cpu_idle_rcuidle(0, smp_processor_id());
local_irq_enable();
+ stop_critical_timings();
while (!tif_need_resched() &&
(cpu_idle_force_poll || tick_check_broadcast_expired()))
cpu_relax();
+ start_critical_timings();
trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
rcu_idle_exit();
return 1;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 3739ac6..44d2cc0 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1251,7 +1251,7 @@
set_normalized_timespec64(&tmp, -boot.tv_sec, -boot.tv_nsec);
tk_set_wall_to_mono(tk, tmp);
- timekeeping_update(tk, TK_MIRROR);
+ timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index b746399..8abf1ba 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -85,9 +85,19 @@
if (!object_is_on_stack(stack))
return;
+ /* Can't do this from NMI context (can cause deadlocks) */
+ if (in_nmi())
+ return;
+
local_irq_save(flags);
arch_spin_lock(&max_stack_lock);
+ /*
+ * RCU may not be watching, make it see us.
+ * The stack trace code uses rcu_sched.
+ */
+ rcu_irq_enter();
+
/* In case another CPU set the tracer_frame on us */
if (unlikely(!frame_size))
this_size -= tracer_frame;
@@ -169,6 +179,7 @@
}
out:
+ rcu_irq_exit();
arch_spin_unlock(&max_stack_lock);
local_irq_restore(flags);
}
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index ca71582..bcb14ca 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1458,13 +1458,13 @@
timer_stats_timer_set_start_info(&dwork->timer);
dwork->wq = wq;
+ /* timer isn't guaranteed to run in this cpu, record earlier */
+ if (cpu == WORK_CPU_UNBOUND)
+ cpu = raw_smp_processor_id();
dwork->cpu = cpu;
timer->expires = jiffies + delay;
- if (unlikely(cpu != WORK_CPU_UNBOUND))
- add_timer_on(timer, cpu);
- else
- add_timer(timer);
+ add_timer_on(timer, cpu);
}
/**
diff --git a/lib/Kconfig b/lib/Kconfig
index 2e491ac..f0df318 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -220,6 +220,7 @@
config ZLIB_DEFLATE
tristate
+ select BITREVERSE
config LZO_COMPRESS
tristate
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ab76b99..1d1521c 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -197,6 +197,7 @@
config FRAME_WARN
int "Warn for stack frames larger than (needs gcc 4.4)"
range 0 8192
+ default 0 if KASAN
default 1024 if !64BIT
default 2048 if 64BIT
help
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index f1cdeb0..6a823a5 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -44,7 +44,7 @@
printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure.\n"
"name %pd, interval %lu, probability %lu, "
"space %d, times %d\n", attr->dname,
- attr->probability, attr->interval,
+ attr->interval, attr->probability,
atomic_read(&attr->space),
atomic_read(&attr->times));
if (attr->verbose > 1)
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 2df8ddc..619984f 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -480,6 +480,10 @@
release_work);
struct backing_dev_info *bdi = wb->bdi;
+ spin_lock_irq(&cgwb_lock);
+ list_del_rcu(&wb->bdi_node);
+ spin_unlock_irq(&cgwb_lock);
+
wb_shutdown(wb);
css_put(wb->memcg_css);
@@ -575,6 +579,7 @@
ret = radix_tree_insert(&bdi->cgwb_tree, memcg_css->id, wb);
if (!ret) {
atomic_inc(&bdi->usage_cnt);
+ list_add_tail_rcu(&wb->bdi_node, &bdi->wb_list);
list_add(&wb->memcg_node, memcg_cgwb_list);
list_add(&wb->blkcg_node, blkcg_cgwb_list);
css_get(memcg_css);
@@ -676,7 +681,7 @@
static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
{
struct radix_tree_iter iter;
- struct bdi_writeback_congested *congested, *congested_n;
+ struct rb_node *rbn;
void **slot;
WARN_ON(test_bit(WB_registered, &bdi->wb.state));
@@ -686,9 +691,11 @@
radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0)
cgwb_kill(*slot);
- rbtree_postorder_for_each_entry_safe(congested, congested_n,
- &bdi->cgwb_congested_tree, rb_node) {
- rb_erase(&congested->rb_node, &bdi->cgwb_congested_tree);
+ while ((rbn = rb_first(&bdi->cgwb_congested_tree))) {
+ struct bdi_writeback_congested *congested =
+ rb_entry(rbn, struct bdi_writeback_congested, rb_node);
+
+ rb_erase(rbn, &bdi->cgwb_congested_tree);
congested->bdi = NULL; /* mark @congested unlinked */
}
@@ -764,15 +771,22 @@
int bdi_init(struct backing_dev_info *bdi)
{
+ int ret;
+
bdi->dev = NULL;
bdi->min_ratio = 0;
bdi->max_ratio = 100;
bdi->max_prop_frac = FPROP_FRAC_BASE;
INIT_LIST_HEAD(&bdi->bdi_list);
+ INIT_LIST_HEAD(&bdi->wb_list);
init_waitqueue_head(&bdi->wb_waitq);
- return cgwb_bdi_init(bdi);
+ ret = cgwb_bdi_init(bdi);
+
+ list_add_tail_rcu(&bdi->wb.bdi_node, &bdi->wb_list);
+
+ return ret;
}
EXPORT_SYMBOL(bdi_init);
@@ -823,7 +837,7 @@
synchronize_rcu_expedited();
}
-void bdi_destroy(struct backing_dev_info *bdi)
+void bdi_unregister(struct backing_dev_info *bdi)
{
/* make sure nobody finds us on the bdi_list anymore */
bdi_remove_from_list(bdi);
@@ -835,9 +849,19 @@
device_unregister(bdi->dev);
bdi->dev = NULL;
}
+}
+void bdi_exit(struct backing_dev_info *bdi)
+{
+ WARN_ON_ONCE(bdi->dev);
wb_exit(&bdi->wb);
}
+
+void bdi_destroy(struct backing_dev_info *bdi)
+{
+ bdi_unregister(bdi);
+ bdi_exit(bdi);
+}
EXPORT_SYMBOL(bdi_destroy);
/*
diff --git a/mm/cma.c b/mm/cma.c
index e7d1db5..4eb56ba 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -361,7 +361,7 @@
* This function allocates part of contiguous memory on specific
* contiguous memory area.
*/
-struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align)
+struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align)
{
unsigned long mask, offset, pfn, start = 0;
unsigned long bitmap_maxno, bitmap_no, bitmap_count;
@@ -371,7 +371,7 @@
if (!cma || !cma->count)
return NULL;
- pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
+ pr_debug("%s(cma %p, count %zu, align %d)\n", __func__, (void *)cma,
count, align);
if (!count)
diff --git a/mm/filemap.c b/mm/filemap.c
index 1cc5467..327910c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2488,6 +2488,11 @@
break;
}
+ if (fatal_signal_pending(current)) {
+ status = -EINTR;
+ break;
+ }
+
status = a_ops->write_begin(file, mapping, pos, bytes, flags,
&page, &fsdata);
if (unlikely(status < 0))
@@ -2525,10 +2530,6 @@
written += copied;
balance_dirty_pages_ratelimited(mapping);
- if (fatal_signal_pending(current)) {
- status = -EINTR;
- break;
- }
} while (iov_iter_count(i));
return written ? written : status;
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 4b06b8d..bbac913 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2206,7 +2206,8 @@
for (_pte = pte; _pte < pte+HPAGE_PMD_NR;
_pte++, address += PAGE_SIZE) {
pte_t pteval = *_pte;
- if (pte_none(pteval) || is_zero_pfn(pte_pfn(pteval))) {
+ if (pte_none(pteval) || (pte_present(pteval) &&
+ is_zero_pfn(pte_pfn(pteval)))) {
if (!userfaultfd_armed(vma) &&
++none_or_zero <= khugepaged_max_ptes_none)
continue;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 1fedbde..c57c442 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3387,6 +3387,7 @@
ret = page_counter_memparse(args, "-1", &threshold);
if (ret)
return ret;
+ threshold <<= PAGE_SHIFT;
mutex_lock(&memcg->thresholds_lock);
@@ -3740,44 +3741,43 @@
/**
* mem_cgroup_wb_stats - retrieve writeback related stats from its memcg
* @wb: bdi_writeback in question
- * @pavail: out parameter for number of available pages
+ * @pfilepages: out parameter for number of file pages
+ * @pheadroom: out parameter for number of allocatable pages according to memcg
* @pdirty: out parameter for number of dirty pages
* @pwriteback: out parameter for number of pages under writeback
*
- * Determine the numbers of available, dirty, and writeback pages in @wb's
- * memcg. Dirty and writeback are self-explanatory. Available is a bit
- * more involved.
+ * Determine the numbers of file, headroom, dirty, and writeback pages in
+ * @wb's memcg. File, dirty and writeback are self-explanatory. Headroom
+ * is a bit more involved.
*
- * A memcg's headroom is "min(max, high) - used". The available memory is
- * calculated as the lowest headroom of itself and the ancestors plus the
- * number of pages already being used for file pages. Note that this
- * doesn't consider the actual amount of available memory in the system.
- * The caller should further cap *@pavail accordingly.
+ * A memcg's headroom is "min(max, high) - used". In the hierarchy, the
+ * headroom is calculated as the lowest headroom of itself and the
+ * ancestors. Note that this doesn't consider the actual amount of
+ * available memory in the system. The caller should further cap
+ * *@pheadroom accordingly.
*/
-void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pavail,
- unsigned long *pdirty, unsigned long *pwriteback)
+void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
+ unsigned long *pheadroom, unsigned long *pdirty,
+ unsigned long *pwriteback)
{
struct mem_cgroup *memcg = mem_cgroup_from_css(wb->memcg_css);
struct mem_cgroup *parent;
- unsigned long head_room = PAGE_COUNTER_MAX;
- unsigned long file_pages;
*pdirty = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_DIRTY);
/* this should eventually include NR_UNSTABLE_NFS */
*pwriteback = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_WRITEBACK);
+ *pfilepages = mem_cgroup_nr_lru_pages(memcg, (1 << LRU_INACTIVE_FILE) |
+ (1 << LRU_ACTIVE_FILE));
+ *pheadroom = PAGE_COUNTER_MAX;
- file_pages = mem_cgroup_nr_lru_pages(memcg, (1 << LRU_INACTIVE_FILE) |
- (1 << LRU_ACTIVE_FILE));
while ((parent = parent_mem_cgroup(memcg))) {
unsigned long ceiling = min(memcg->memory.limit, memcg->high);
unsigned long used = page_counter_read(&memcg->memory);
- head_room = min(head_room, ceiling - min(ceiling, used));
+ *pheadroom = min(*pheadroom, ceiling - min(ceiling, used));
memcg = parent;
}
-
- *pavail = file_pages + head_room;
}
#else /* CONFIG_CGROUP_WRITEBACK */
diff --git a/mm/memory.c b/mm/memory.c
index 9cb2747..deb679c 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2426,6 +2426,8 @@
if (details.last_index < details.first_index)
details.last_index = ULONG_MAX;
+
+ /* DAX uses i_mmap_lock to serialise file truncate vs page fault */
i_mmap_lock_write(mapping);
if (unlikely(!RB_EMPTY_ROOT(&mapping->i_mmap)))
unmap_mapping_range_tree(&mapping->i_mmap, &details);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 0a931cd..2c90357 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -145,9 +145,6 @@
unsigned long pos_ratio;
};
-#define DTC_INIT_COMMON(__wb) .wb = (__wb), \
- .wb_completions = &(__wb)->completions
-
/*
* Length of period for aging writeout fractions of bdis. This is an
* arbitrarily chosen number. The longer the period, the slower fractions will
@@ -157,12 +154,16 @@
#ifdef CONFIG_CGROUP_WRITEBACK
-#define GDTC_INIT(__wb) .dom = &global_wb_domain, \
- DTC_INIT_COMMON(__wb)
+#define GDTC_INIT(__wb) .wb = (__wb), \
+ .dom = &global_wb_domain, \
+ .wb_completions = &(__wb)->completions
+
#define GDTC_INIT_NO_WB .dom = &global_wb_domain
-#define MDTC_INIT(__wb, __gdtc) .dom = mem_cgroup_wb_domain(__wb), \
- .gdtc = __gdtc, \
- DTC_INIT_COMMON(__wb)
+
+#define MDTC_INIT(__wb, __gdtc) .wb = (__wb), \
+ .dom = mem_cgroup_wb_domain(__wb), \
+ .wb_completions = &(__wb)->memcg_completions, \
+ .gdtc = __gdtc
static bool mdtc_valid(struct dirty_throttle_control *dtc)
{
@@ -213,7 +214,8 @@
#else /* CONFIG_CGROUP_WRITEBACK */
-#define GDTC_INIT(__wb) DTC_INIT_COMMON(__wb)
+#define GDTC_INIT(__wb) .wb = (__wb), \
+ .wb_completions = &(__wb)->completions
#define GDTC_INIT_NO_WB
#define MDTC_INIT(__wb, __gdtc)
@@ -682,13 +684,19 @@
return max(thresh, dom->dirty_limit);
}
-/* memory available to a memcg domain is capped by system-wide clean memory */
-static void mdtc_cap_avail(struct dirty_throttle_control *mdtc)
+/*
+ * Memory which can be further allocated to a memcg domain is capped by
+ * system-wide clean memory excluding the amount being used in the domain.
+ */
+static void mdtc_calc_avail(struct dirty_throttle_control *mdtc,
+ unsigned long filepages, unsigned long headroom)
{
struct dirty_throttle_control *gdtc = mdtc_gdtc(mdtc);
- unsigned long clean = gdtc->avail - min(gdtc->avail, gdtc->dirty);
+ unsigned long clean = filepages - min(filepages, mdtc->dirty);
+ unsigned long global_clean = gdtc->avail - min(gdtc->avail, gdtc->dirty);
+ unsigned long other_clean = global_clean - min(global_clean, clean);
- mdtc->avail = min(mdtc->avail, clean);
+ mdtc->avail = filepages + min(headroom, other_clean);
}
/**
@@ -1562,16 +1570,16 @@
}
if (mdtc) {
- unsigned long writeback;
+ unsigned long filepages, headroom, writeback;
/*
* If @wb belongs to !root memcg, repeat the same
* basic calculations for the memcg domain.
*/
- mem_cgroup_wb_stats(wb, &mdtc->avail, &mdtc->dirty,
- &writeback);
- mdtc_cap_avail(mdtc);
+ mem_cgroup_wb_stats(wb, &filepages, &headroom,
+ &mdtc->dirty, &writeback);
mdtc->dirty += writeback;
+ mdtc_calc_avail(mdtc, filepages, headroom);
domain_dirty_limits(mdtc);
@@ -1893,10 +1901,11 @@
return true;
if (mdtc) {
- unsigned long writeback;
+ unsigned long filepages, headroom, writeback;
- mem_cgroup_wb_stats(wb, &mdtc->avail, &mdtc->dirty, &writeback);
- mdtc_cap_avail(mdtc);
+ mem_cgroup_wb_stats(wb, &filepages, &headroom, &mdtc->dirty,
+ &writeback);
+ mdtc_calc_avail(mdtc, filepages, headroom);
domain_dirty_limits(mdtc); /* ditto, ignore writeback */
if (mdtc->dirty > mdtc->bg_thresh)
@@ -1956,7 +1965,6 @@
int nr_pages = global_page_state(NR_FILE_DIRTY) +
global_page_state(NR_UNSTABLE_NFS);
struct bdi_writeback *wb;
- struct wb_iter iter;
/*
* We want to write everything out, not just down to the dirty
@@ -1965,10 +1973,12 @@
if (!bdi_has_dirty_io(&q->backing_dev_info))
return;
- bdi_for_each_wb(wb, &q->backing_dev_info, &iter, 0)
+ rcu_read_lock();
+ list_for_each_entry_rcu(wb, &q->backing_dev_info.wb_list, bdi_node)
if (wb_has_dirty_io(wb))
wb_start_writeback(wb, nr_pages, true,
WB_REASON_LAPTOP_TIMER);
+ rcu_read_unlock();
}
/*
diff --git a/mm/readahead.c b/mm/readahead.c
index 60cd846..24682f6 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -89,8 +89,8 @@
while (!list_empty(pages)) {
page = list_to_page(pages);
list_del(&page->lru);
- if (add_to_page_cache_lru(page, mapping,
- page->index, GFP_KERNEL)) {
+ if (add_to_page_cache_lru(page, mapping, page->index,
+ GFP_KERNEL & mapping_gfp_mask(mapping))) {
read_cache_pages_invalidate_page(mapping, page);
continue;
}
@@ -127,8 +127,8 @@
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_to_page(pages);
list_del(&page->lru);
- if (!add_to_page_cache_lru(page, mapping,
- page->index, GFP_KERNEL)) {
+ if (!add_to_page_cache_lru(page, mapping, page->index,
+ GFP_KERNEL & mapping_gfp_mask(mapping))) {
mapping->a_ops->readpage(filp, page);
}
page_cache_release(page);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 4f5cd97..fbf1448 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1363,15 +1363,16 @@
static void vmstat_update(struct work_struct *w)
{
- if (refresh_cpu_vm_stats())
+ if (refresh_cpu_vm_stats()) {
/*
* Counters were updated so we expect more updates
* to occur in the future. Keep on running the
* update worker thread.
*/
- schedule_delayed_work(this_cpu_ptr(&vmstat_work),
+ schedule_delayed_work_on(smp_processor_id(),
+ this_cpu_ptr(&vmstat_work),
round_jiffies_relative(sysctl_stat_interval));
- else {
+ } else {
/*
* We did not update any counters so the app may be in
* a mode where it does not cause counter updates.
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b4548c73..2dda439 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -91,10 +91,50 @@
* autoconnect action, remove them completely. If they are, just unmark
* them as waiting for connection, by clearing explicit_connect field.
*/
- if (params->auto_connect == HCI_AUTO_CONN_EXPLICIT)
+ params->explicit_connect = false;
+
+ list_del_init(¶ms->action);
+
+ switch (params->auto_connect) {
+ case HCI_AUTO_CONN_EXPLICIT:
hci_conn_params_del(conn->hdev, bdaddr, bdaddr_type);
- else
- params->explicit_connect = false;
+ /* return instead of break to avoid duplicate scan update */
+ return;
+ case HCI_AUTO_CONN_DIRECT:
+ case HCI_AUTO_CONN_ALWAYS:
+ list_add(¶ms->action, &conn->hdev->pend_le_conns);
+ break;
+ case HCI_AUTO_CONN_REPORT:
+ list_add(¶ms->action, &conn->hdev->pend_le_reports);
+ break;
+ default:
+ break;
+ }
+
+ hci_update_background_scan(conn->hdev);
+}
+
+static void hci_conn_cleanup(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
+ hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
+
+ hci_chan_list_flush(conn);
+
+ hci_conn_hash_del(hdev, conn);
+
+ if (hdev->notify)
+ hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
+
+ hci_conn_del_sysfs(conn);
+
+ debugfs_remove_recursive(conn->debugfs);
+
+ hci_dev_put(hdev);
+
+ hci_conn_put(conn);
}
/* This function requires the caller holds hdev->lock */
@@ -102,8 +142,13 @@
{
hci_connect_le_scan_cleanup(conn);
- hci_conn_hash_del(conn->hdev, conn);
- hci_update_background_scan(conn->hdev);
+ /* We can't call hci_conn_del here since that would deadlock
+ * with trying to call cancel_delayed_work_sync(&conn->disc_work).
+ * Instead, call just hci_conn_cleanup() which contains the bare
+ * minimum cleanup operations needed for a connection in this
+ * state.
+ */
+ hci_conn_cleanup(conn);
}
static void hci_acl_create_connection(struct hci_conn *conn)
@@ -581,27 +626,17 @@
}
}
- hci_chan_list_flush(conn);
-
if (conn->amp_mgr)
amp_mgr_put(conn->amp_mgr);
- hci_conn_hash_del(hdev, conn);
- if (hdev->notify)
- hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
-
skb_queue_purge(&conn->data_q);
- hci_conn_del_sysfs(conn);
-
- debugfs_remove_recursive(conn->debugfs);
-
- if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
- hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
-
- hci_dev_put(hdev);
-
- hci_conn_put(conn);
+ /* Remove the connection from the list and cleanup its remaining
+ * state. This is a separate function since for some cases like
+ * BT_CONNECT_SCAN we *only* want the cleanup part without the
+ * rest of hci_conn_del.
+ */
+ hci_conn_cleanup(conn);
return 0;
}
@@ -973,15 +1008,23 @@
if (is_connected(hdev, addr, addr_type))
return -EISCONN;
- params = hci_conn_params_add(hdev, addr, addr_type);
- if (!params)
- return -EIO;
+ params = hci_conn_params_lookup(hdev, addr, addr_type);
+ if (!params) {
+ params = hci_conn_params_add(hdev, addr, addr_type);
+ if (!params)
+ return -ENOMEM;
- /* If we created new params, or existing params were marked as disabled,
- * mark them to be used just once to connect.
- */
- if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
+ /* If we created new params, mark them to be deleted in
+ * hci_connect_le_scan_cleanup. It's different case than
+ * existing disabled params, those will stay after cleanup.
+ */
params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
+ }
+
+ /* We're trying to connect, so make sure params are at pend_le_conns */
+ if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
+ params->auto_connect == HCI_AUTO_CONN_REPORT ||
+ params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
list_del_init(¶ms->action);
list_add(¶ms->action, &hdev->pend_le_conns);
}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index adcbc74..e837539 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2861,13 +2861,6 @@
return param;
}
- list_for_each_entry(param, &hdev->pend_le_reports, action) {
- if (bacmp(¶m->addr, addr) == 0 &&
- param->addr_type == addr_type &&
- param->explicit_connect)
- return param;
- }
-
return NULL;
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 1860418..bc31099 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -55,7 +55,12 @@
wake_up_bit(&hdev->flags, HCI_INQUIRY);
hci_dev_lock(hdev);
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ /* Set discovery state to stopped if we're not doing LE active
+ * scanning.
+ */
+ if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
+ hdev->le_scan_type != LE_SCAN_ACTIVE)
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hci_dev_unlock(hdev);
hci_conn_check_pending(hdev);
@@ -4648,8 +4653,8 @@
/* If we're not connectable only connect devices that we have in
* our pend_le_conns list.
*/
- params = hci_explicit_connect_lookup(hdev, addr, addr_type);
-
+ params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr,
+ addr_type);
if (!params)
return NULL;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ccaf5a4..c4fe2fe 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3545,6 +3545,7 @@
auth_type);
} else {
u8 addr_type;
+ struct hci_conn_params *p;
/* Convert from L2CAP channel address type to HCI address type
*/
@@ -3562,7 +3563,10 @@
* If connection parameters already exist, then they
* will be kept and this function does nothing.
*/
- hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
+ p = hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
+
+ if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
+ p->auto_connect = HCI_AUTO_CONN_DISABLED;
conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr,
addr_type, sec_level,
@@ -6117,14 +6121,21 @@
__hci_update_background_scan(req);
break;
case HCI_AUTO_CONN_REPORT:
- list_add(¶ms->action, &hdev->pend_le_reports);
+ if (params->explicit_connect)
+ list_add(¶ms->action, &hdev->pend_le_conns);
+ else
+ list_add(¶ms->action, &hdev->pend_le_reports);
__hci_update_background_scan(req);
break;
case HCI_AUTO_CONN_DIRECT:
case HCI_AUTO_CONN_ALWAYS:
if (!is_connected(hdev, addr, addr_type)) {
list_add(¶ms->action, &hdev->pend_le_conns);
- __hci_update_background_scan(req);
+ /* If we are in scan phase of connecting, we were
+ * already added to pend_le_conns and scanning.
+ */
+ if (params->auto_connect != HCI_AUTO_CONN_EXPLICIT)
+ __hci_update_background_scan(req);
}
break;
}
@@ -6379,7 +6390,8 @@
goto unlock;
}
- if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
+ if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
+ params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
err = cmd->cmd_complete(cmd,
MGMT_STATUS_INVALID_PARAMS);
mgmt_pending_remove(cmd);
@@ -6415,6 +6427,10 @@
if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
continue;
device_removed(sk, hdev, &p->addr, p->addr_type);
+ if (p->explicit_connect) {
+ p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
+ continue;
+ }
list_del(&p->action);
list_del(&p->list);
kfree(p);
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 80b94e3..f79ccac 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -285,6 +285,7 @@
switch (op->op) {
case CEPH_OSD_OP_READ:
case CEPH_OSD_OP_WRITE:
+ case CEPH_OSD_OP_WRITEFULL:
ceph_osd_data_release(&op->extent.osd_data);
break;
case CEPH_OSD_OP_CALL:
@@ -485,13 +486,14 @@
size_t payload_len = 0;
BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE &&
- opcode != CEPH_OSD_OP_ZERO && opcode != CEPH_OSD_OP_TRUNCATE);
+ opcode != CEPH_OSD_OP_WRITEFULL && opcode != CEPH_OSD_OP_ZERO &&
+ opcode != CEPH_OSD_OP_TRUNCATE);
op->extent.offset = offset;
op->extent.length = length;
op->extent.truncate_size = truncate_size;
op->extent.truncate_seq = truncate_seq;
- if (opcode == CEPH_OSD_OP_WRITE)
+ if (opcode == CEPH_OSD_OP_WRITE || opcode == CEPH_OSD_OP_WRITEFULL)
payload_len += length;
op->payload_len = payload_len;
@@ -670,9 +672,11 @@
break;
case CEPH_OSD_OP_READ:
case CEPH_OSD_OP_WRITE:
+ case CEPH_OSD_OP_WRITEFULL:
case CEPH_OSD_OP_ZERO:
case CEPH_OSD_OP_TRUNCATE:
- if (src->op == CEPH_OSD_OP_WRITE)
+ if (src->op == CEPH_OSD_OP_WRITE ||
+ src->op == CEPH_OSD_OP_WRITEFULL)
request_data_len = src->extent.length;
dst->extent.offset = cpu_to_le64(src->extent.offset);
dst->extent.length = cpu_to_le64(src->extent.length);
@@ -681,7 +685,8 @@
dst->extent.truncate_seq =
cpu_to_le32(src->extent.truncate_seq);
osd_data = &src->extent.osd_data;
- if (src->op == CEPH_OSD_OP_WRITE)
+ if (src->op == CEPH_OSD_OP_WRITE ||
+ src->op == CEPH_OSD_OP_WRITEFULL)
ceph_osdc_msg_data_add(req->r_request, osd_data);
else
ceph_osdc_msg_data_add(req->r_reply, osd_data);
diff --git a/net/core/dev.c b/net/core/dev.c
index 6bb6470..c14748d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -99,6 +99,7 @@
#include <linux/rtnetlink.h>
#include <linux/stat.h>
#include <net/dst.h>
+#include <net/dst_metadata.h>
#include <net/pkt_sched.h>
#include <net/checksum.h>
#include <net/xfrm.h>
@@ -682,6 +683,32 @@
EXPORT_SYMBOL(dev_get_iflink);
/**
+ * dev_fill_metadata_dst - Retrieve tunnel egress information.
+ * @dev: targeted interface
+ * @skb: The packet.
+ *
+ * For better visibility of tunnel traffic OVS needs to retrieve
+ * egress tunnel information for a packet. Following API allows
+ * user to get this info.
+ */
+int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+ struct ip_tunnel_info *info;
+
+ if (!dev->netdev_ops || !dev->netdev_ops->ndo_fill_metadata_dst)
+ return -EINVAL;
+
+ info = skb_tunnel_info_unclone(skb);
+ if (!info)
+ return -ENOMEM;
+ if (unlikely(!(info->mode & IP_TUNNEL_INFO_TX)))
+ return -EINVAL;
+
+ return dev->netdev_ops->ndo_fill_metadata_dst(dev, skb);
+}
+EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
+
+/**
* __dev_get_by_name - find a device by its name
* @net: the applicable net namespace
* @name: name to find
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index b495ab1..29edf74 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1284,7 +1284,7 @@
gstrings.len = ret;
- data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
+ data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER);
if (!data)
return -ENOMEM;
diff --git a/net/core/filter.c b/net/core/filter.c
index 05a04ea..bb18c36 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -1415,6 +1415,7 @@
return dev_forward_skb(dev, skb2);
skb2->dev = dev;
+ skb_sender_cpu_clear(skb2);
return dev_queue_xmit(skb2);
}
@@ -1854,9 +1855,13 @@
goto out;
/* We're copying the filter that has been originally attached,
- * so no conversion/decode needed anymore.
+ * so no conversion/decode needed anymore. eBPF programs that
+ * have no original program cannot be dumped through this.
*/
+ ret = -EACCES;
fprog = filter->prog->orig_prog;
+ if (!fprog)
+ goto out;
ret = fprog->len;
if (!len)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index c59fa5d..adb5325 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -22,6 +22,7 @@
#include <linux/of_platform.h>
#include <linux/of_net.h>
#include <linux/sysfs.h>
+#include <linux/phy_fixed.h>
#include "dsa_priv.h"
char dsa_driver_version[] = "0.1";
@@ -305,7 +306,7 @@
if (ret < 0)
goto out;
- ds->slave_mii_bus = mdiobus_alloc();
+ ds->slave_mii_bus = devm_mdiobus_alloc(parent);
if (ds->slave_mii_bus == NULL) {
ret = -ENOMEM;
goto out;
@@ -314,7 +315,7 @@
ret = mdiobus_register(ds->slave_mii_bus);
if (ret < 0)
- goto out_free;
+ goto out;
/*
@@ -367,10 +368,7 @@
return ret;
-out_free:
- mdiobus_free(ds->slave_mii_bus);
out:
- kfree(ds);
return ret;
}
@@ -400,7 +398,7 @@
/*
* Allocate and initialise switch state.
*/
- ds = kzalloc(sizeof(*ds) + drv->priv_size, GFP_KERNEL);
+ ds = devm_kzalloc(parent, sizeof(*ds) + drv->priv_size, GFP_KERNEL);
if (ds == NULL)
return ERR_PTR(-ENOMEM);
@@ -420,10 +418,47 @@
static void dsa_switch_destroy(struct dsa_switch *ds)
{
+ struct device_node *port_dn;
+ struct phy_device *phydev;
+ struct dsa_chip_data *cd = ds->pd;
+ int port;
+
#ifdef CONFIG_NET_DSA_HWMON
if (ds->hwmon_dev)
hwmon_device_unregister(ds->hwmon_dev);
#endif
+
+ /* Disable configuration of the CPU and DSA ports */
+ for (port = 0; port < DSA_MAX_PORTS; port++) {
+ if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
+ continue;
+
+ port_dn = cd->port_dn[port];
+ if (of_phy_is_fixed_link(port_dn)) {
+ phydev = of_phy_find_device(port_dn);
+ if (phydev) {
+ int addr = phydev->addr;
+
+ phy_device_free(phydev);
+ of_node_put(port_dn);
+ fixed_phy_del(addr);
+ }
+ }
+ }
+
+ /* Destroy network devices for physical switch ports. */
+ for (port = 0; port < DSA_MAX_PORTS; port++) {
+ if (!(ds->phys_port_mask & (1 << port)))
+ continue;
+
+ if (!ds->ports[port])
+ continue;
+
+ unregister_netdev(ds->ports[port]);
+ free_netdev(ds->ports[port]);
+ }
+
+ mdiobus_unregister(ds->slave_mii_bus);
}
#ifdef CONFIG_PM_SLEEP
@@ -802,10 +837,11 @@
}
#endif
-static void dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
- struct device *parent, struct dsa_platform_data *pd)
+static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
+ struct device *parent, struct dsa_platform_data *pd)
{
int i;
+ unsigned configured = 0;
dst->pd = pd;
dst->master_netdev = dev;
@@ -825,9 +861,17 @@
dst->ds[i] = ds;
if (ds->drv->poll_link != NULL)
dst->link_poll_needed = 1;
+
+ ++configured;
}
/*
+ * If no switch was found, exit cleanly
+ */
+ if (!configured)
+ return -EPROBE_DEFER;
+
+ /*
* If we use a tagging format that doesn't have an ethertype
* field, make sure that all packets from this point on get
* sent to the tag format's receive function.
@@ -843,6 +887,8 @@
dst->link_poll_timer.expires = round_jiffies(jiffies + HZ);
add_timer(&dst->link_poll_timer);
}
+
+ return 0;
}
static int dsa_probe(struct platform_device *pdev)
@@ -883,7 +929,7 @@
goto out;
}
- dst = kzalloc(sizeof(*dst), GFP_KERNEL);
+ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
if (dst == NULL) {
dev_put(dev);
ret = -ENOMEM;
@@ -892,7 +938,9 @@
platform_set_drvdata(pdev, dst);
- dsa_setup_dst(dst, dev, &pdev->dev, pd);
+ ret = dsa_setup_dst(dst, dev, &pdev->dev, pd);
+ if (ret)
+ goto out;
return 0;
@@ -914,7 +962,7 @@
for (i = 0; i < dst->pd->nr_chips; i++) {
struct dsa_switch *ds = dst->ds[i];
- if (ds != NULL)
+ if (ds)
dsa_switch_destroy(ds);
}
}
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index f03db8b..0c9c348 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -312,7 +312,7 @@
if (!skb)
return;
- skb_dst_set(skb, dst);
+ skb_dst_set(skb, dst_clone(dst));
arp_xmit(skb);
}
@@ -384,7 +384,7 @@
}
if (skb && !(dev->priv_flags & IFF_XMIT_DST_RELEASE))
- dst = dst_clone(skb_dst(skb));
+ dst = skb_dst(skb);
arp_send_dst(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
dst_hw, dev->dev_addr, NULL, dst);
}
@@ -811,7 +811,7 @@
} else {
pneigh_enqueue(&arp_tbl,
in_dev->arp_parms, skb);
- return 0;
+ goto out_free_dst;
}
goto out;
}
@@ -865,6 +865,8 @@
out:
consume_skb(skb);
+out_free_dst:
+ dst_release(reply_dst);
return 0;
}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 6c2af79..744e593 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1569,7 +1569,7 @@
do {
/* record parent and next child index */
pn = n;
- cindex = key ? get_index(key, pn) : 0;
+ cindex = (key > pn->key) ? get_index(key, pn) : 0;
if (cindex >> pn->bits)
break;
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 5aa46d4..5a8ee32 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -36,7 +36,8 @@
SKB_GSO_TCP_ECN |
SKB_GSO_GRE |
SKB_GSO_GRE_CSUM |
- SKB_GSO_IPIP)))
+ SKB_GSO_IPIP |
+ SKB_GSO_SIT)))
goto out;
if (!skb->encapsulation)
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 7bb9c39..61b45a1 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -577,21 +577,22 @@
static bool reqsk_queue_unlink(struct request_sock_queue *queue,
struct request_sock *req)
{
- struct listen_sock *lopt = queue->listen_opt;
struct request_sock **prev;
+ struct listen_sock *lopt;
bool found = false;
spin_lock(&queue->syn_wait_lock);
-
- for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
- prev = &(*prev)->dl_next) {
- if (*prev == req) {
- *prev = req->dl_next;
- found = true;
- break;
+ lopt = queue->listen_opt;
+ if (lopt) {
+ for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
+ prev = &(*prev)->dl_next) {
+ if (*prev == req) {
+ *prev = req->dl_next;
+ found = true;
+ break;
+ }
}
}
-
spin_unlock(&queue->syn_wait_lock);
if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer))
reqsk_put(req);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index bd0679d..6145214 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -498,10 +498,26 @@
csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
}
+static struct rtable *gre_get_rt(struct sk_buff *skb,
+ struct net_device *dev,
+ struct flowi4 *fl,
+ const struct ip_tunnel_key *key)
+{
+ struct net *net = dev_net(dev);
+
+ memset(fl, 0, sizeof(*fl));
+ fl->daddr = key->u.ipv4.dst;
+ fl->saddr = key->u.ipv4.src;
+ fl->flowi4_tos = RT_TOS(key->tos);
+ fl->flowi4_mark = skb->mark;
+ fl->flowi4_proto = IPPROTO_GRE;
+
+ return ip_route_output_key(net, fl);
+}
+
static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip_tunnel_info *tun_info;
- struct net *net = dev_net(dev);
const struct ip_tunnel_key *key;
struct flowi4 fl;
struct rtable *rt;
@@ -516,14 +532,7 @@
goto err_free_skb;
key = &tun_info->key;
- memset(&fl, 0, sizeof(fl));
- fl.daddr = key->u.ipv4.dst;
- fl.saddr = key->u.ipv4.src;
- fl.flowi4_tos = RT_TOS(key->tos);
- fl.flowi4_mark = skb->mark;
- fl.flowi4_proto = IPPROTO_GRE;
-
- rt = ip_route_output_key(net, &fl);
+ rt = gre_get_rt(skb, dev, &fl, key);
if (IS_ERR(rt))
goto err_free_skb;
@@ -566,6 +575,24 @@
dev->stats.tx_dropped++;
}
+static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+ struct ip_tunnel_info *info = skb_tunnel_info(skb);
+ struct rtable *rt;
+ struct flowi4 fl4;
+
+ if (ip_tunnel_info_af(info) != AF_INET)
+ return -EINVAL;
+
+ rt = gre_get_rt(skb, dev, &fl4, &info->key);
+ if (IS_ERR(rt))
+ return PTR_ERR(rt);
+
+ ip_rt_put(rt);
+ info->key.u.ipv4.src = fl4.saddr;
+ return 0;
+}
+
static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
struct net_device *dev)
{
@@ -1023,6 +1050,7 @@
.ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip_tunnel_get_iflink,
+ .ndo_fill_metadata_dst = gre_fill_metadata_dst,
};
static void ipgre_tap_setup(struct net_device *dev)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 690d27d..a355841 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -75,6 +75,7 @@
config NF_DUP_IPV4
tristate "Netfilter IPv4 packet duplication to alternate destination"
+ depends on !NF_CONNTRACK || NF_CONNTRACK
help
This option enables the nf_dup_ipv4 core, which duplicates an IPv4
packet to be rerouted to another destination.
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c
index 8618fd1..c4ffc9d 100644
--- a/net/ipv4/netfilter/ipt_rpfilter.c
+++ b/net/ipv4/netfilter/ipt_rpfilter.c
@@ -61,9 +61,7 @@
if (FIB_RES_DEV(res) == dev)
dev_match = true;
#endif
- if (dev_match || flags & XT_RPFILTER_LOOSE)
- return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST;
- return dev_match;
+ return dev_match || flags & XT_RPFILTER_LOOSE;
}
static bool rpfilter_is_local(const struct sk_buff *skb)
diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c
index 7092a61..7e538f7 100644
--- a/net/ipv4/tcp_dctcp.c
+++ b/net/ipv4/tcp_dctcp.c
@@ -209,7 +209,7 @@
/* alpha = (1 - g) * alpha + g * F */
- alpha -= alpha >> dctcp_shift_g;
+ alpha -= min_not_zero(alpha, alpha >> dctcp_shift_g);
if (bytes_ecn) {
/* If dctcp_shift_g == 1, a 32bit value would overflow
* after 8 Mbytes.
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 1100ffe..3dbee0d 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3405,7 +3405,7 @@
*/
tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPHDR_ACK);
skb_mstamp_get(&skb->skb_mstamp);
- NET_INC_STATS_BH(sock_net(sk), mib);
+ NET_INC_STATS(sock_net(sk), mib);
return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC);
}
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 2878dbf..41a2613 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -30,6 +30,8 @@
mtu = dst_mtu(skb_dst(skb));
if (skb->len > mtu) {
+ skb->protocol = htons(ETH_P_IP);
+
if (skb->sk)
xfrm_local_error(skb, mtu);
else
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 9001133..36b85bd 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3119,6 +3119,8 @@
}
addrconf_addr_gen(idev, true);
+ if (dev->flags & IFF_POINTOPOINT)
+ addrconf_add_mroute(dev);
}
#endif
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 9f777ec..ed33abf 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -32,6 +32,7 @@
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
int flags, pol_lookup_t lookup)
{
+ struct rt6_info *rt;
struct fib_lookup_arg arg = {
.lookup_ptr = lookup,
.flags = FIB_LOOKUP_NOREF,
@@ -40,11 +41,21 @@
fib_rules_lookup(net->ipv6.fib6_rules_ops,
flowi6_to_flowi(fl6), flags, &arg);
- if (arg.result)
- return arg.result;
+ rt = arg.result;
- dst_hold(&net->ipv6.ip6_null_entry->dst);
- return &net->ipv6.ip6_null_entry->dst;
+ if (!rt) {
+ dst_hold(&net->ipv6.ip6_null_entry->dst);
+ return &net->ipv6.ip6_null_entry->dst;
+ }
+
+ if (rt->rt6i_flags & RTF_REJECT &&
+ rt->dst.error == -EAGAIN) {
+ ip6_rt_put(rt);
+ rt = net->ipv6.ip6_null_entry;
+ dst_hold(&rt->dst);
+ }
+
+ return &rt->dst;
}
static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 7d2e002..6cedc62 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -285,7 +285,17 @@
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
int flags, pol_lookup_t lookup)
{
- return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
+ struct rt6_info *rt;
+
+ rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
+ if (rt->rt6i_flags & RTF_REJECT &&
+ rt->dst.error == -EAGAIN) {
+ ip6_rt_put(rt);
+ rt = net->ipv6.ip6_null_entry;
+ dst_hold(&rt->dst);
+ }
+
+ return &rt->dst;
}
static void __net_init fib6_tables_init(struct net *net)
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 92b1aa3..f84ec4e 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -376,6 +376,9 @@
if (skb->pkt_type != PACKET_HOST)
goto drop;
+ if (unlikely(skb->sk))
+ goto drop;
+
if (skb_warn_if_lro(skb))
goto drop;
@@ -581,6 +584,8 @@
if (np->frag_size)
mtu = np->frag_size;
}
+ if (mtu < hlen + sizeof(struct frag_hdr) + 8)
+ goto fail_toobig;
mtu -= hlen + sizeof(struct frag_hdr);
frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr,
@@ -874,7 +879,8 @@
#ifdef CONFIG_IPV6_SUBTREES
ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) ||
#endif
- (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) {
+ (!(fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) &&
+ (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex))) {
dst_release(dst);
dst = NULL;
}
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 96833e4..f6a024e 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -58,6 +58,7 @@
config NF_DUP_IPV6
tristate "Netfilter IPv6 packet duplication to alternate destination"
+ depends on !NF_CONNTRACK || NF_CONNTRACK
help
This option enables the nf_dup_ipv6 core, which duplicates an IPv6
packet to be rerouted to another destination.
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 701cd2b..c7196ad 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -646,6 +646,7 @@
s = s2;
}
}
+EXPORT_SYMBOL_GPL(nf_ct_frag6_consume_orig);
static int nf_ct_net_init(struct net *net)
{
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index cb32ce2..946880a 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -142,6 +142,9 @@
struct net_device *loopback_dev = net->loopback_dev;
int cpu;
+ if (dev == loopback_dev)
+ return;
+
for_each_possible_cpu(cpu) {
struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu);
struct rt6_info *rt;
@@ -151,14 +154,12 @@
struct inet6_dev *rt_idev = rt->rt6i_idev;
struct net_device *rt_dev = rt->dst.dev;
- if (rt_idev && (rt_idev->dev == dev || !dev) &&
- rt_idev->dev != loopback_dev) {
+ if (rt_idev->dev == dev) {
rt->rt6i_idev = in6_dev_get(loopback_dev);
in6_dev_put(rt_idev);
}
- if (rt_dev && (rt_dev == dev || !dev) &&
- rt_dev != loopback_dev) {
+ if (rt_dev == dev) {
rt->dst.dev = loopback_dev;
dev_hold(rt->dst.dev);
dev_put(rt_dev);
@@ -247,12 +248,6 @@
{
}
-static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst,
- unsigned long old)
-{
- return NULL;
-}
-
static struct dst_ops ip6_dst_blackhole_ops = {
.family = AF_INET6,
.destroy = ip6_dst_destroy,
@@ -261,7 +256,7 @@
.default_advmss = ip6_default_advmss,
.update_pmtu = ip6_rt_blackhole_update_pmtu,
.redirect = ip6_rt_blackhole_redirect,
- .cow_metrics = ip6_rt_blackhole_cow_metrics,
+ .cow_metrics = dst_cow_metrics_generic,
.neigh_lookup = ip6_neigh_lookup,
};
@@ -318,6 +313,15 @@
#endif
+static void rt6_info_init(struct rt6_info *rt)
+{
+ struct dst_entry *dst = &rt->dst;
+
+ memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
+ INIT_LIST_HEAD(&rt->rt6i_siblings);
+ INIT_LIST_HEAD(&rt->rt6i_uncached);
+}
+
/* allocate dst with ip6_dst_ops */
static struct rt6_info *__ip6_dst_alloc(struct net *net,
struct net_device *dev,
@@ -326,13 +330,9 @@
struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
0, DST_OBSOLETE_FORCE_CHK, flags);
- if (rt) {
- struct dst_entry *dst = &rt->dst;
+ if (rt)
+ rt6_info_init(rt);
- memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
- INIT_LIST_HEAD(&rt->rt6i_siblings);
- INIT_LIST_HEAD(&rt->rt6i_uncached);
- }
return rt;
}
@@ -1068,6 +1068,9 @@
fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
saved_fn = fn;
+ if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
+ oif = 0;
+
redo_rt6_select:
rt = rt6_select(fn, oif, strict);
if (rt->rt6i_nsiblings)
@@ -1190,14 +1193,16 @@
struct flowi6 *fl6)
{
int flags = 0;
+ bool any_src;
fl6->flowi6_iif = LOOPBACK_IFINDEX;
+ any_src = ipv6_addr_any(&fl6->saddr);
if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) ||
- fl6->flowi6_oif)
+ (fl6->flowi6_oif && any_src))
flags |= RT6_LOOKUP_F_IFACE;
- if (!ipv6_addr_any(&fl6->saddr))
+ if (!any_src)
flags |= RT6_LOOKUP_F_HAS_SADDR;
else if (sk)
flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
@@ -1213,24 +1218,20 @@
rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0);
if (rt) {
+ rt6_info_init(rt);
+
new = &rt->dst;
-
- memset(new + 1, 0, sizeof(*rt) - sizeof(*new));
-
new->__use = 1;
new->input = dst_discard;
new->output = dst_discard_sk;
- if (dst_metrics_read_only(&ort->dst))
- new->_metrics = ort->dst._metrics;
- else
- dst_copy_metrics(new, &ort->dst);
+ dst_copy_metrics(new, &ort->dst);
rt->rt6i_idev = ort->rt6i_idev;
if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev);
rt->rt6i_gateway = ort->rt6i_gateway;
- rt->rt6i_flags = ort->rt6i_flags;
+ rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU;
rt->rt6i_metric = 0;
memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
@@ -2622,7 +2623,8 @@
fib6_clean_all(net, fib6_ifdown, &adn);
icmp6_clean_all(fib6_ifdown, &adn);
- rt6_uncached_list_flush_dev(net, dev);
+ if (dev)
+ rt6_uncached_list_flush_dev(net, dev);
}
struct rt6_mtu_change_arg {
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 09c76a7..e15feb7 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -79,6 +79,7 @@
if (!skb->ignore_df && skb->len > mtu) {
skb->dev = dst->dev;
+ skb->protocol = htons(ETH_P_IPV6);
if (xfrm6_local_dontfrag(skb))
xfrm6_local_rxpmtu(skb, mtu);
@@ -136,6 +137,7 @@
struct dst_entry *dst = skb_dst(skb);
struct xfrm_state *x = dst->xfrm;
int mtu;
+ bool toobig;
#ifdef CONFIG_NETFILTER
if (!x) {
@@ -144,25 +146,29 @@
}
#endif
+ if (x->props.mode != XFRM_MODE_TUNNEL)
+ goto skip_frag;
+
if (skb->protocol == htons(ETH_P_IPV6))
mtu = ip6_skb_dst_mtu(skb);
else
mtu = dst_mtu(skb_dst(skb));
- if (skb->len > mtu && xfrm6_local_dontfrag(skb)) {
+ toobig = skb->len > mtu && !skb_is_gso(skb);
+
+ if (toobig && xfrm6_local_dontfrag(skb)) {
xfrm6_local_rxpmtu(skb, mtu);
return -EMSGSIZE;
- } else if (!skb->ignore_df && skb->len > mtu && skb->sk) {
+ } else if (!skb->ignore_df && toobig && skb->sk) {
xfrm_local_error(skb, mtu);
return -EMSGSIZE;
}
- if (x->props.mode == XFRM_MODE_TUNNEL &&
- ((skb->len > mtu && !skb_is_gso(skb)) ||
- dst_allfrag(skb_dst(skb)))) {
+ if (toobig || dst_allfrag(skb_dst(skb)))
return ip6_fragment(sk, skb,
x->outer_mode->afinfo->output_finish);
- }
+
+skip_frag:
return x->outer_mode->afinfo->output_finish(sk, skb);
}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 30caa28..da55e0c 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -37,6 +37,7 @@
memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_oif = oif;
+ fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
if (saddr)
memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
@@ -178,7 +179,8 @@
return;
case IPPROTO_ICMPV6:
- if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) {
+ if (!onlyproto && (nh + offset + 2 < skb->data ||
+ pskb_may_pull(skb, nh + offset + 2 - skb->data))) {
u8 *icmp;
nh = skb_network_header(skb);
@@ -192,7 +194,8 @@
#if IS_ENABLED(CONFIG_IPV6_MIP6)
case IPPROTO_MH:
offset += ipv6_optlen(exthdr);
- if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
+ if (!onlyproto && (nh + offset + 3 < skb->data ||
+ pskb_may_pull(skb, nh + offset + 3 - skb->data))) {
struct ip6_mh *mh;
nh = skb_network_header(skb);
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index a26c401..4396459 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -1839,7 +1839,7 @@
for (element = hashbin_get_first(iter->hashbin);
element != NULL;
element = hashbin_get_next(iter->hashbin)) {
- if (!off || *off-- == 0) {
+ if (!off || (*off)-- == 0) {
/* NB: hashbin left locked */
return element;
}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 83a7068..f9c9ecb 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -261,7 +261,7 @@
err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
- /* Error is cleare after succecful sending to at least one
+ /* Error is cleared after successful sending to at least one
* registered KM */
if ((broadcast_flags & BROADCAST_REGISTERED) && err)
err = err2;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index ced6bf3..1560c84 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -149,7 +149,7 @@
for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
if (test_bit(i, local->hw.flags))
- pos += scnprintf(pos, end - pos, "%s",
+ pos += scnprintf(pos, end - pos, "%s\n",
hw_flag_names[i]);
}
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 8ba5832..3ed7ddf 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -101,6 +101,7 @@
* when it wakes up for the next time.
*/
set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
+ ieee80211_clear_fast_xmit(sta);
/*
* This code races in the following way:
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 84e0e8c..7892eb8 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1218,8 +1218,10 @@
if (!tx->sta)
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
- else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
+ else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) {
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+ ieee80211_check_fast_xmit(tx->sta);
+ }
info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
@@ -2451,7 +2453,8 @@
if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
- test_sta_flag(sta, WLAN_STA_PS_DELIVER))
+ test_sta_flag(sta, WLAN_STA_PS_DELIVER) ||
+ test_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT))
goto out;
if (sdata->noack_map)
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 8e47f81..21a0856 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -152,6 +152,8 @@
#endif
synchronize_net();
nf_queue_nf_hook_drop(net, &entry->ops);
+ /* other cpu might still process nfqueue verdict that used reg */
+ synchronize_net();
kfree(entry);
}
EXPORT_SYMBOL(nf_unregister_net_hook);
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index a1fe537..5a30ce6 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -297,7 +297,7 @@
ip_set_timeout_expired(ext_timeout(n, set))))
n = NULL;
- e = kzalloc(set->dsize, GFP_KERNEL);
+ e = kzalloc(set->dsize, GFP_ATOMIC);
if (!e)
return -ENOMEM;
e->id = d->id;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 8f060d7..fafe33b 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2371,7 +2371,7 @@
int pos, idx, shift;
err = 0;
- netlink_table_grab();
+ netlink_lock_table();
for (pos = 0; pos * 8 < nlk->ngroups; pos += sizeof(u32)) {
if (len - pos < sizeof(u32))
break;
@@ -2386,7 +2386,7 @@
}
if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen))
err = -EFAULT;
- netlink_table_ungrab();
+ netlink_unlock_table();
break;
}
case NETLINK_CAP_ACK:
@@ -2785,6 +2785,7 @@
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh;
int len, err = -ENOBUFS;
+ int alloc_min_size;
int alloc_size;
mutex_lock(nlk->cb_mutex);
@@ -2793,9 +2794,6 @@
goto errout_skb;
}
- cb = &nlk->cb;
- alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
-
if (!netlink_rx_is_mmaped(sk) &&
atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
goto errout_skb;
@@ -2805,23 +2803,35 @@
* to reduce number of system calls on dump operations, if user
* ever provided a big enough buffer.
*/
- if (alloc_size < nlk->max_recvmsg_len) {
- skb = netlink_alloc_skb(sk,
- nlk->max_recvmsg_len,
- nlk->portid,
+ cb = &nlk->cb;
+ alloc_min_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
+
+ if (alloc_min_size < nlk->max_recvmsg_len) {
+ alloc_size = nlk->max_recvmsg_len;
+ skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
GFP_KERNEL |
__GFP_NOWARN |
__GFP_NORETRY);
- /* available room should be exact amount to avoid MSG_TRUNC */
- if (skb)
- skb_reserve(skb, skb_tailroom(skb) -
- nlk->max_recvmsg_len);
}
- if (!skb)
+ if (!skb) {
+ alloc_size = alloc_min_size;
skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
GFP_KERNEL);
+ }
if (!skb)
goto errout_skb;
+
+ /* Trim skb to allocated size. User is expected to provide buffer as
+ * large as max(min_dump_alloc, 16KiB (mac_recvmsg_len capped at
+ * netlink_recvmsg())). dump will pack as many smaller messages as
+ * could fit within the allocated skb. skb is typically allocated
+ * with larger space than required (could be as much as near 2x the
+ * requested size with align to next power of 2 approach). Allowing
+ * dump to use the excess space makes it difficult for a user to have a
+ * reasonable static buffer based on the expected largest dump of a
+ * single netdev. The outcome is MSG_TRUNC error.
+ */
+ skb_reserve(skb, skb_tailroom(skb) - alloc_size);
netlink_skb_set_owner_r(skb, sk);
len = cb->dump(skb, cb);
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 315f533..dba635d 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -684,7 +684,7 @@
{
if (skb_network_offset(skb) > MAX_L2_LEN) {
OVS_NLERR(1, "L2 header too long to fragment");
- return;
+ goto err;
}
if (ethertype == htons(ETH_P_IP)) {
@@ -708,8 +708,7 @@
struct rt6_info ovs_rt;
if (!v6ops) {
- kfree_skb(skb);
- return;
+ goto err;
}
prepare_frag(vport, skb);
@@ -728,8 +727,12 @@
WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
ovs_vport_name(vport), ntohs(ethertype), mru,
vport->dev->mtu);
- kfree_skb(skb);
+ goto err;
}
+
+ return;
+err:
+ kfree_skb(skb);
}
static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
@@ -765,7 +768,6 @@
struct sw_flow_key *key, const struct nlattr *attr,
const struct nlattr *actions, int actions_len)
{
- struct ip_tunnel_info info;
struct dp_upcall_info upcall;
const struct nlattr *a;
int rem;
@@ -793,11 +795,9 @@
if (vport) {
int err;
- upcall.egress_tun_info = &info;
- err = ovs_vport_get_egress_tun_info(vport, skb,
- &upcall);
- if (err)
- upcall.egress_tun_info = NULL;
+ err = dev_fill_metadata_dst(vport->dev, skb);
+ if (!err)
+ upcall.egress_tun_info = skb_tunnel_info(skb);
}
break;
@@ -968,7 +968,7 @@
case OVS_KEY_ATTR_CT_STATE:
case OVS_KEY_ATTR_CT_ZONE:
case OVS_KEY_ATTR_CT_MARK:
- case OVS_KEY_ATTR_CT_LABEL:
+ case OVS_KEY_ATTR_CT_LABELS:
err = -EINVAL;
break;
}
@@ -1099,12 +1099,18 @@
break;
case OVS_ACTION_ATTR_CT:
+ if (!is_flow_key_valid(key)) {
+ err = ovs_flow_key_update(skb, key);
+ if (err)
+ return err;
+ }
+
err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key,
nla_data(a));
/* Hide stolen IP fragments from user space. */
- if (err == -EINPROGRESS)
- return 0;
+ if (err)
+ return err == -EINPROGRESS ? 0 : err;
break;
}
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 002a755..5009582 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -37,9 +37,9 @@
};
/* Metadata label for masked write to conntrack label. */
-struct md_label {
- struct ovs_key_ct_label value;
- struct ovs_key_ct_label mask;
+struct md_labels {
+ struct ovs_key_ct_labels value;
+ struct ovs_key_ct_labels mask;
};
/* Conntrack action context for execution. */
@@ -47,10 +47,10 @@
struct nf_conntrack_helper *helper;
struct nf_conntrack_zone zone;
struct nf_conn *ct;
- u32 flags;
+ u8 commit : 1;
u16 family;
struct md_mark mark;
- struct md_label label;
+ struct md_labels labels;
};
static u16 key_to_nfproto(const struct sw_flow_key *key)
@@ -109,21 +109,21 @@
#endif
}
-static void ovs_ct_get_label(const struct nf_conn *ct,
- struct ovs_key_ct_label *label)
+static void ovs_ct_get_labels(const struct nf_conn *ct,
+ struct ovs_key_ct_labels *labels)
{
struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
if (cl) {
size_t len = cl->words * sizeof(long);
- if (len > OVS_CT_LABEL_LEN)
- len = OVS_CT_LABEL_LEN;
- else if (len < OVS_CT_LABEL_LEN)
- memset(label, 0, OVS_CT_LABEL_LEN);
- memcpy(label, cl->bits, len);
+ if (len > OVS_CT_LABELS_LEN)
+ len = OVS_CT_LABELS_LEN;
+ else if (len < OVS_CT_LABELS_LEN)
+ memset(labels, 0, OVS_CT_LABELS_LEN);
+ memcpy(labels, cl->bits, len);
} else {
- memset(label, 0, OVS_CT_LABEL_LEN);
+ memset(labels, 0, OVS_CT_LABELS_LEN);
}
}
@@ -134,7 +134,7 @@
key->ct.state = state;
key->ct.zone = zone->id;
key->ct.mark = ovs_ct_get_mark(ct);
- ovs_ct_get_label(ct, &key->ct.label);
+ ovs_ct_get_labels(ct, &key->ct.labels);
}
/* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
@@ -151,6 +151,8 @@
ct = nf_ct_get(skb, &ctinfo);
if (ct) {
state = ovs_ct_get_state(ctinfo);
+ if (!nf_ct_is_confirmed(ct))
+ state |= OVS_CS_F_NEW;
if (ct->master)
state |= OVS_CS_F_RELATED;
zone = nf_ct_zone(ct);
@@ -167,7 +169,7 @@
int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
{
- if (nla_put_u8(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
+ if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
return -EMSGSIZE;
if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
@@ -179,8 +181,8 @@
return -EMSGSIZE;
if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
- nla_put(skb, OVS_KEY_ATTR_CT_LABEL, sizeof(key->ct.label),
- &key->ct.label))
+ nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(key->ct.labels),
+ &key->ct.labels))
return -EMSGSIZE;
return 0;
@@ -213,18 +215,15 @@
#endif
}
-static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
- const struct ovs_key_ct_label *label,
- const struct ovs_key_ct_label *mask)
+static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
+ const struct ovs_key_ct_labels *labels,
+ const struct ovs_key_ct_labels *mask)
{
enum ip_conntrack_info ctinfo;
struct nf_conn_labels *cl;
struct nf_conn *ct;
int err;
- if (!IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS))
- return -ENOTSUPP;
-
/* The connection could be invalid, in which case set_label is no-op.*/
ct = nf_ct_get(skb, &ctinfo);
if (!ct)
@@ -235,15 +234,15 @@
nf_ct_labels_ext_add(ct);
cl = nf_ct_labels_find(ct);
}
- if (!cl || cl->words * sizeof(long) < OVS_CT_LABEL_LEN)
+ if (!cl || cl->words * sizeof(long) < OVS_CT_LABELS_LEN)
return -ENOSPC;
- err = nf_connlabels_replace(ct, (u32 *)label, (u32 *)mask,
- OVS_CT_LABEL_LEN / sizeof(u32));
+ err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
+ OVS_CT_LABELS_LEN / sizeof(u32));
if (err)
return err;
- ovs_ct_get_label(ct, &key->ct.label);
+ ovs_ct_get_labels(ct, &key->ct.labels);
return 0;
}
@@ -294,6 +293,9 @@
return helper->help(skb, protoff, ct, ctinfo);
}
+/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
+ * value if 'skb' is freed.
+ */
static int handle_fragments(struct net *net, struct sw_flow_key *key,
u16 zone, struct sk_buff *skb)
{
@@ -309,8 +311,8 @@
return err;
ovs_cb.mru = IPCB(skb)->frag_max_size;
- } else if (key->eth.type == htons(ETH_P_IPV6)) {
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
+ } else if (key->eth.type == htons(ETH_P_IPV6)) {
enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
struct sk_buff *reasm;
@@ -319,17 +321,25 @@
if (!reasm)
return -EINPROGRESS;
- if (skb == reasm)
+ if (skb == reasm) {
+ kfree_skb(skb);
return -EINVAL;
+ }
+
+ /* Don't free 'skb' even though it is one of the original
+ * fragments, as we're going to morph it into the head.
+ */
+ skb_get(skb);
+ nf_ct_frag6_consume_orig(reasm);
key->ip.proto = ipv6_hdr(reasm)->nexthdr;
skb_morph(skb, reasm);
+ skb->next = reasm->next;
consume_skb(reasm);
ovs_cb.mru = IP6CB(skb)->frag_max_size;
-#else
- return -EPFNOSUPPORT;
#endif
} else {
+ kfree_skb(skb);
return -EPFNOSUPPORT;
}
@@ -377,7 +387,7 @@
return true;
}
-static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key,
+static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
const struct ovs_conntrack_info *info,
struct sk_buff *skb)
{
@@ -408,6 +418,8 @@
}
}
+ ovs_ct_update_key(skb, key, true);
+
return 0;
}
@@ -430,8 +442,6 @@
err = __ovs_ct_lookup(net, key, info, skb);
if (err)
return err;
-
- ovs_ct_update_key(skb, key, true);
}
return 0;
@@ -460,22 +470,23 @@
if (nf_conntrack_confirm(skb) != NF_ACCEPT)
return -EINVAL;
- ovs_ct_update_key(skb, key, true);
-
return 0;
}
-static bool label_nonzero(const struct ovs_key_ct_label *label)
+static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
{
size_t i;
- for (i = 0; i < sizeof(*label); i++)
- if (label->ct_label[i])
+ for (i = 0; i < sizeof(*labels); i++)
+ if (labels->ct_labels[i])
return true;
return false;
}
+/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
+ * value if 'skb' is freed.
+ */
int ovs_ct_execute(struct net *net, struct sk_buff *skb,
struct sw_flow_key *key,
const struct ovs_conntrack_info *info)
@@ -493,7 +504,7 @@
return err;
}
- if (info->flags & OVS_CT_F_COMMIT)
+ if (info->commit)
err = ovs_ct_commit(net, key, info, skb);
else
err = ovs_ct_lookup(net, key, info, skb);
@@ -506,11 +517,13 @@
if (err)
goto err;
}
- if (label_nonzero(&info->label.mask))
- err = ovs_ct_set_label(skb, key, &info->label.value,
- &info->label.mask);
+ if (labels_nonzero(&info->labels.mask))
+ err = ovs_ct_set_labels(skb, key, &info->labels.value,
+ &info->labels.mask);
err:
skb_push(skb, nh_ofs);
+ if (err)
+ kfree_skb(skb);
return err;
}
@@ -539,14 +552,13 @@
}
static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
- [OVS_CT_ATTR_FLAGS] = { .minlen = sizeof(u32),
- .maxlen = sizeof(u32) },
+ [OVS_CT_ATTR_COMMIT] = { .minlen = 0, .maxlen = 0 },
[OVS_CT_ATTR_ZONE] = { .minlen = sizeof(u16),
.maxlen = sizeof(u16) },
[OVS_CT_ATTR_MARK] = { .minlen = sizeof(struct md_mark),
.maxlen = sizeof(struct md_mark) },
- [OVS_CT_ATTR_LABEL] = { .minlen = sizeof(struct md_label),
- .maxlen = sizeof(struct md_label) },
+ [OVS_CT_ATTR_LABELS] = { .minlen = sizeof(struct md_labels),
+ .maxlen = sizeof(struct md_labels) },
[OVS_CT_ATTR_HELPER] = { .minlen = 1,
.maxlen = NF_CT_HELPER_NAME_LEN }
};
@@ -576,8 +588,8 @@
}
switch (type) {
- case OVS_CT_ATTR_FLAGS:
- info->flags = nla_get_u32(a);
+ case OVS_CT_ATTR_COMMIT:
+ info->commit = true;
break;
#ifdef CONFIG_NF_CONNTRACK_ZONES
case OVS_CT_ATTR_ZONE:
@@ -588,15 +600,23 @@
case OVS_CT_ATTR_MARK: {
struct md_mark *mark = nla_data(a);
+ if (!mark->mask) {
+ OVS_NLERR(log, "ct_mark mask cannot be 0");
+ return -EINVAL;
+ }
info->mark = *mark;
break;
}
#endif
#ifdef CONFIG_NF_CONNTRACK_LABELS
- case OVS_CT_ATTR_LABEL: {
- struct md_label *label = nla_data(a);
+ case OVS_CT_ATTR_LABELS: {
+ struct md_labels *labels = nla_data(a);
- info->label = *label;
+ if (!labels_nonzero(&labels->mask)) {
+ OVS_NLERR(log, "ct_labels mask cannot be 0");
+ return -EINVAL;
+ }
+ info->labels = *labels;
break;
}
#endif
@@ -633,7 +653,7 @@
attr == OVS_KEY_ATTR_CT_MARK)
return true;
if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
- attr == OVS_KEY_ATTR_CT_LABEL) {
+ attr == OVS_KEY_ATTR_CT_LABELS) {
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
return ovs_net->xt_label;
@@ -701,18 +721,19 @@
if (!start)
return -EMSGSIZE;
- if (nla_put_u32(skb, OVS_CT_ATTR_FLAGS, ct_info->flags))
+ if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
return -EMSGSIZE;
if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
return -EMSGSIZE;
- if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
+ if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
&ct_info->mark))
return -EMSGSIZE;
if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
- nla_put(skb, OVS_CT_ATTR_LABEL, sizeof(ct_info->label),
- &ct_info->label))
+ labels_nonzero(&ct_info->labels.mask) &&
+ nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
+ &ct_info->labels))
return -EMSGSIZE;
if (ct_info->helper) {
if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
@@ -737,7 +758,7 @@
void ovs_ct_init(struct net *net)
{
- unsigned int n_bits = sizeof(struct ovs_key_ct_label) * BITS_PER_BYTE;
+ unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
if (nf_connlabels_get(net, n_bits)) {
diff --git a/net/openvswitch/conntrack.h b/net/openvswitch/conntrack.h
index 43f5dd7..a7544f4 100644
--- a/net/openvswitch/conntrack.h
+++ b/net/openvswitch/conntrack.h
@@ -34,6 +34,10 @@
void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key);
int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb);
void ovs_ct_free_action(const struct nlattr *a);
+
+#define CT_SUPPORTED_MASK (OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | \
+ OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | \
+ OVS_CS_F_INVALID | OVS_CS_F_TRACKED)
#else
#include <linux/errno.h>
@@ -63,6 +67,7 @@
struct sw_flow_key *key,
const struct ovs_conntrack_info *info)
{
+ kfree_skb(skb);
return -ENOTSUPP;
}
@@ -72,7 +77,7 @@
key->ct.state = 0;
key->ct.zone = 0;
key->ct.mark = 0;
- memset(&key->ct.label, 0, sizeof(key->ct.label));
+ memset(&key->ct.labels, 0, sizeof(key->ct.labels));
}
static inline int ovs_ct_put_key(const struct sw_flow_key *key,
@@ -82,5 +87,7 @@
}
static inline void ovs_ct_free_action(const struct nlattr *a) { }
+
+#define CT_SUPPORTED_MASK 0
#endif /* CONFIG_NF_CONNTRACK */
#endif /* ovs_conntrack.h */
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index b816ff8..c5d08ee 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -490,9 +490,8 @@
if (upcall_info->egress_tun_info) {
nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY);
- err = ovs_nla_put_egress_tunnel_key(user_skb,
- upcall_info->egress_tun_info,
- upcall_info->egress_tun_opts);
+ err = ovs_nla_put_tunnel_info(user_skb,
+ upcall_info->egress_tun_info);
BUG_ON(err);
nla_nest_end(user_skb, nla);
}
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index f88038a..67bdecd 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -117,7 +117,6 @@
*/
struct dp_upcall_info {
struct ip_tunnel_info *egress_tun_info;
- const void *egress_tun_opts;
const struct nlattr *userdata;
const struct nlattr *actions;
int actions_len;
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index fe527d2..8cfa15a 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -116,7 +116,7 @@
u16 zone;
u32 mark;
u8 state;
- struct ovs_key_ct_label label;
+ struct ovs_key_ct_labels labels;
} ct;
} __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 5c030a4..38536c1 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -291,10 +291,10 @@
+ nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
+ nla_total_size(4) /* OVS_KEY_ATTR_DP_HASH */
+ nla_total_size(4) /* OVS_KEY_ATTR_RECIRC_ID */
- + nla_total_size(1) /* OVS_KEY_ATTR_CT_STATE */
+ + nla_total_size(4) /* OVS_KEY_ATTR_CT_STATE */
+ nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */
+ nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */
- + nla_total_size(16) /* OVS_KEY_ATTR_CT_LABEL */
+ + nla_total_size(16) /* OVS_KEY_ATTR_CT_LABELS */
+ nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
+ nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
+ nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
@@ -349,10 +349,10 @@
[OVS_KEY_ATTR_TUNNEL] = { .len = OVS_ATTR_NESTED,
.next = ovs_tunnel_key_lens, },
[OVS_KEY_ATTR_MPLS] = { .len = sizeof(struct ovs_key_mpls) },
- [OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u8) },
+ [OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u32) },
[OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) },
[OVS_KEY_ATTR_CT_MARK] = { .len = sizeof(u32) },
- [OVS_KEY_ATTR_CT_LABEL] = { .len = sizeof(struct ovs_key_ct_label) },
+ [OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
};
static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
@@ -717,7 +717,7 @@
if ((output->tun_flags & TUNNEL_OAM) &&
nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
return -EMSGSIZE;
- if (tun_opts) {
+ if (swkey_tun_opts_len) {
if (output->tun_flags & TUNNEL_GENEVE_OPT &&
nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
swkey_tun_opts_len, tun_opts))
@@ -749,13 +749,12 @@
return 0;
}
-int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
- const struct ip_tunnel_info *egress_tun_info,
- const void *egress_tun_opts)
+int ovs_nla_put_tunnel_info(struct sk_buff *skb,
+ struct ip_tunnel_info *tun_info)
{
- return __ipv4_tun_to_nlattr(skb, &egress_tun_info->key,
- egress_tun_opts,
- egress_tun_info->options_len);
+ return __ipv4_tun_to_nlattr(skb, &tun_info->key,
+ ip_tunnel_info_opts(tun_info),
+ tun_info->options_len);
}
static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
@@ -814,7 +813,13 @@
if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
- u8 ct_state = nla_get_u8(a[OVS_KEY_ATTR_CT_STATE]);
+ u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
+
+ if (ct_state & ~CT_SUPPORTED_MASK) {
+ OVS_NLERR(log, "ct_state flags %08x unsupported",
+ ct_state);
+ return -EINVAL;
+ }
SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask);
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
@@ -833,14 +838,14 @@
SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
}
- if (*attrs & (1 << OVS_KEY_ATTR_CT_LABEL) &&
- ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABEL)) {
- const struct ovs_key_ct_label *cl;
+ if (*attrs & (1 << OVS_KEY_ATTR_CT_LABELS) &&
+ ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABELS)) {
+ const struct ovs_key_ct_labels *cl;
- cl = nla_data(a[OVS_KEY_ATTR_CT_LABEL]);
- SW_FLOW_KEY_MEMCPY(match, ct.label, cl->ct_label,
+ cl = nla_data(a[OVS_KEY_ATTR_CT_LABELS]);
+ SW_FLOW_KEY_MEMCPY(match, ct.labels, cl->ct_labels,
sizeof(*cl), is_mask);
- *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABEL);
+ *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
}
return 0;
}
@@ -1093,6 +1098,9 @@
} else {
memset(nla_data(nla), val, nla_len(nla));
}
+
+ if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
+ *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
}
}
@@ -1973,7 +1981,7 @@
case OVS_KEY_ATTR_PRIORITY:
case OVS_KEY_ATTR_SKB_MARK:
case OVS_KEY_ATTR_CT_MARK:
- case OVS_KEY_ATTR_CT_LABEL:
+ case OVS_KEY_ATTR_CT_LABELS:
case OVS_KEY_ATTR_ETHERNET:
break;
@@ -2374,10 +2382,7 @@
if (!start)
return -EMSGSIZE;
- err = ipv4_tun_to_nlattr(skb, &tun_info->key,
- tun_info->options_len ?
- ip_tunnel_info_opts(tun_info) : NULL,
- tun_info->options_len);
+ err = ovs_nla_put_tunnel_info(skb, tun_info);
if (err)
return err;
nla_nest_end(skb, start);
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index 6ca3f0b..47dd142 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -55,9 +55,9 @@
int ovs_nla_get_match(struct net *, struct sw_flow_match *,
const struct nlattr *key, const struct nlattr *mask,
bool log);
-int ovs_nla_put_egress_tunnel_key(struct sk_buff *,
- const struct ip_tunnel_info *,
- const void *egress_tun_opts);
+
+int ovs_nla_put_tunnel_info(struct sk_buff *skb,
+ struct ip_tunnel_info *tun_info);
bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log);
int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid,
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index f2ea83b..c7f74aa 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -93,7 +93,8 @@
/* Initialize the default stat node. */
stats = kmem_cache_alloc_node(flow_stats_cache,
- GFP_KERNEL | __GFP_ZERO, 0);
+ GFP_KERNEL | __GFP_ZERO,
+ node_online(0) ? 0 : NUMA_NO_NODE);
if (!stats)
goto err;
diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c
index 2735e9c..5f8aaaa 100644
--- a/net/openvswitch/vport-geneve.c
+++ b/net/openvswitch/vport-geneve.c
@@ -52,18 +52,6 @@
return 0;
}
-static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
- struct dp_upcall_info *upcall)
-{
- struct geneve_port *geneve_port = geneve_vport(vport);
- struct net *net = ovs_dp_get_net(vport->dp);
- __be16 dport = htons(geneve_port->port_no);
- __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
-
- return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
- skb, IPPROTO_UDP, sport, dport);
-}
-
static struct vport *geneve_tnl_create(const struct vport_parms *parms)
{
struct net *net = ovs_dp_get_net(parms->dp);
@@ -130,7 +118,6 @@
.get_options = geneve_get_options,
.send = ovs_netdev_send,
.owner = THIS_MODULE,
- .get_egress_tun_info = geneve_get_egress_tun_info,
};
static int __init ovs_geneve_tnl_init(void)
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index 4d24481..64225bf 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -84,18 +84,10 @@
return ovs_netdev_link(vport, parms->name);
}
-static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
- struct dp_upcall_info *upcall)
-{
- return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
- skb, IPPROTO_GRE, 0, 0);
-}
-
static struct vport_ops ovs_gre_vport_ops = {
.type = OVS_VPORT_TYPE_GRE,
.create = gre_create,
.send = ovs_netdev_send,
- .get_egress_tun_info = gre_get_egress_tun_info,
.destroy = ovs_netdev_tunnel_destroy,
.owner = THIS_MODULE,
};
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 388b8a6..b393412 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -106,12 +106,45 @@
free_netdev(dev);
}
+static struct rtnl_link_stats64 *
+internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+ int i;
+
+ memset(stats, 0, sizeof(*stats));
+ stats->rx_errors = dev->stats.rx_errors;
+ stats->tx_errors = dev->stats.tx_errors;
+ stats->tx_dropped = dev->stats.tx_dropped;
+ stats->rx_dropped = dev->stats.rx_dropped;
+
+ for_each_possible_cpu(i) {
+ const struct pcpu_sw_netstats *percpu_stats;
+ struct pcpu_sw_netstats local_stats;
+ unsigned int start;
+
+ percpu_stats = per_cpu_ptr(dev->tstats, i);
+
+ do {
+ start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
+ local_stats = *percpu_stats;
+ } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
+
+ stats->rx_bytes += local_stats.rx_bytes;
+ stats->rx_packets += local_stats.rx_packets;
+ stats->tx_bytes += local_stats.tx_bytes;
+ stats->tx_packets += local_stats.tx_packets;
+ }
+
+ return stats;
+}
+
static const struct net_device_ops internal_dev_netdev_ops = {
.ndo_open = internal_dev_open,
.ndo_stop = internal_dev_stop,
.ndo_start_xmit = internal_dev_xmit,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = internal_dev_change_mtu,
+ .ndo_get_stats64 = internal_get_stats,
};
static struct rtnl_link_ops internal_dev_link_ops __read_mostly = {
@@ -161,6 +194,11 @@
err = -ENOMEM;
goto error_free_vport;
}
+ vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+ if (!vport->dev->tstats) {
+ err = -ENOMEM;
+ goto error_free_netdev;
+ }
dev_net_set(vport->dev, ovs_dp_get_net(vport->dp));
internal_dev = internal_dev_priv(vport->dev);
@@ -173,7 +211,7 @@
rtnl_lock();
err = register_netdevice(vport->dev);
if (err)
- goto error_free_netdev;
+ goto error_unlock;
dev_set_promiscuity(vport->dev, 1);
rtnl_unlock();
@@ -181,8 +219,10 @@
return vport;
-error_free_netdev:
+error_unlock:
rtnl_unlock();
+ free_percpu(vport->dev->tstats);
+error_free_netdev:
free_netdev(vport->dev);
error_free_vport:
ovs_vport_free(vport);
@@ -198,7 +238,7 @@
/* unregister_netdevice() waits for an RCU grace period. */
unregister_netdevice(vport->dev);
-
+ free_percpu(vport->dev->tstats);
rtnl_unlock();
}
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index c11413d..e1c9c08 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -146,31 +146,12 @@
return ovs_netdev_link(vport, parms->name);
}
-static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
- struct dp_upcall_info *upcall)
-{
- struct vxlan_dev *vxlan = netdev_priv(vport->dev);
- struct net *net = ovs_dp_get_net(vport->dp);
- __be16 dst_port = vxlan_dev_dst_port(vxlan);
- __be16 src_port;
- int port_min;
- int port_max;
-
- inet_get_local_port_range(net, &port_min, &port_max);
- src_port = udp_flow_src_port(net, skb, 0, 0, true);
-
- return ovs_tunnel_get_egress_info(upcall, net,
- skb, IPPROTO_UDP,
- src_port, dst_port);
-}
-
static struct vport_ops ovs_vxlan_netdev_vport_ops = {
.type = OVS_VPORT_TYPE_VXLAN,
.create = vxlan_create,
.destroy = ovs_netdev_tunnel_destroy,
.get_options = vxlan_get_options,
.send = ovs_netdev_send,
- .get_egress_tun_info = vxlan_get_egress_tun_info,
};
static int __init ovs_vxlan_tnl_init(void)
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index dc81dc6..320c765 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -280,35 +280,19 @@
*/
void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
{
- struct net_device *dev = vport->dev;
- int i;
+ const struct rtnl_link_stats64 *dev_stats;
+ struct rtnl_link_stats64 temp;
- memset(stats, 0, sizeof(*stats));
- stats->rx_errors = dev->stats.rx_errors;
- stats->tx_errors = dev->stats.tx_errors;
- stats->tx_dropped = dev->stats.tx_dropped;
- stats->rx_dropped = dev->stats.rx_dropped;
+ dev_stats = dev_get_stats(vport->dev, &temp);
+ stats->rx_errors = dev_stats->rx_errors;
+ stats->tx_errors = dev_stats->tx_errors;
+ stats->tx_dropped = dev_stats->tx_dropped;
+ stats->rx_dropped = dev_stats->rx_dropped;
- stats->rx_dropped += atomic_long_read(&dev->rx_dropped);
- stats->tx_dropped += atomic_long_read(&dev->tx_dropped);
-
- for_each_possible_cpu(i) {
- const struct pcpu_sw_netstats *percpu_stats;
- struct pcpu_sw_netstats local_stats;
- unsigned int start;
-
- percpu_stats = per_cpu_ptr(dev->tstats, i);
-
- do {
- start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
- local_stats = *percpu_stats;
- } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
-
- stats->rx_bytes += local_stats.rx_bytes;
- stats->rx_packets += local_stats.rx_packets;
- stats->tx_bytes += local_stats.tx_bytes;
- stats->tx_packets += local_stats.tx_packets;
- }
+ stats->rx_bytes = dev_stats->rx_bytes;
+ stats->rx_packets = dev_stats->rx_packets;
+ stats->tx_bytes = dev_stats->tx_bytes;
+ stats->tx_packets = dev_stats->tx_packets;
}
/**
@@ -460,6 +444,15 @@
OVS_CB(skb)->input_vport = vport;
OVS_CB(skb)->mru = 0;
+ if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
+ u32 mark;
+
+ mark = skb->mark;
+ skb_scrub_packet(skb, true);
+ skb->mark = mark;
+ tun_info = NULL;
+ }
+
/* Extract flow from 'skb' into 'key'. */
error = ovs_flow_key_extract(tun_info, skb, &key);
if (unlikely(error)) {
@@ -486,61 +479,3 @@
call_rcu(&vport->rcu, free_vport_rcu);
}
EXPORT_SYMBOL_GPL(ovs_vport_deferred_free);
-
-int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
- struct net *net,
- struct sk_buff *skb,
- u8 ipproto,
- __be16 tp_src,
- __be16 tp_dst)
-{
- struct ip_tunnel_info *egress_tun_info = upcall->egress_tun_info;
- const struct ip_tunnel_info *tun_info = skb_tunnel_info(skb);
- const struct ip_tunnel_key *tun_key;
- u32 skb_mark = skb->mark;
- struct rtable *rt;
- struct flowi4 fl;
-
- if (unlikely(!tun_info))
- return -EINVAL;
- if (ip_tunnel_info_af(tun_info) != AF_INET)
- return -EINVAL;
-
- tun_key = &tun_info->key;
-
- /* Route lookup to get srouce IP address.
- * The process may need to be changed if the corresponding process
- * in vports ops changed.
- */
- rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto);
- if (IS_ERR(rt))
- return PTR_ERR(rt);
-
- ip_rt_put(rt);
-
- /* Generate egress_tun_info based on tun_info,
- * saddr, tp_src and tp_dst
- */
- ip_tunnel_key_init(&egress_tun_info->key,
- fl.saddr, tun_key->u.ipv4.dst,
- tun_key->tos,
- tun_key->ttl,
- tp_src, tp_dst,
- tun_key->tun_id,
- tun_key->tun_flags);
- egress_tun_info->options_len = tun_info->options_len;
- egress_tun_info->mode = tun_info->mode;
- upcall->egress_tun_opts = ip_tunnel_info_opts(egress_tun_info);
- return 0;
-}
-EXPORT_SYMBOL_GPL(ovs_tunnel_get_egress_info);
-
-int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
- struct dp_upcall_info *upcall)
-{
- /* get_egress_tun_info() is only implemented on tunnel ports. */
- if (unlikely(!vport->ops->get_egress_tun_info))
- return -EINVAL;
-
- return vport->ops->get_egress_tun_info(vport, skb, upcall);
-}
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index a413f3a..d341ad6 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -27,7 +27,6 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/u64_stats_sync.h>
-#include <net/route.h>
#include "datapath.h"
@@ -53,16 +52,6 @@
int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *);
u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *);
-int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
- struct net *net,
- struct sk_buff *,
- u8 ipproto,
- __be16 tp_src,
- __be16 tp_dst);
-
-int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
- struct dp_upcall_info *upcall);
-
/**
* struct vport_portids - array of netlink portids of a vport.
* must be protected by rcu.
@@ -140,8 +129,6 @@
* have any configuration.
* @send: Send a packet on the device.
* zero for dropped packets or negative for error.
- * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for
- * a packet.
*/
struct vport_ops {
enum ovs_vport_type type;
@@ -154,9 +141,6 @@
int (*get_options)(const struct vport *, struct sk_buff *);
void (*send)(struct vport *, struct sk_buff *);
- int (*get_egress_tun_info)(struct vport *, struct sk_buff *,
- struct dp_upcall_info *upcall);
-
struct module *owner;
struct list_head list;
};
@@ -215,25 +199,6 @@
int ovs_vport_ops_register(struct vport_ops *ops);
void ovs_vport_ops_unregister(struct vport_ops *ops);
-static inline struct rtable *ovs_tunnel_route_lookup(struct net *net,
- const struct ip_tunnel_key *key,
- u32 mark,
- struct flowi4 *fl,
- u8 protocol)
-{
- struct rtable *rt;
-
- memset(fl, 0, sizeof(*fl));
- fl->daddr = key->u.ipv4.dst;
- fl->saddr = key->u.ipv4.src;
- fl->flowi4_tos = RT_TOS(key->tos);
- fl->flowi4_mark = mark;
- fl->flowi4_proto = protocol;
-
- rt = ip_route_output_key(net, fl);
- return rt;
-}
-
static inline void ovs_vport_send(struct vport *vport, struct sk_buff *skb)
{
vport->ops->send(vport, skb);
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c
index fbc5ef8..27a9921 100644
--- a/net/rds/tcp_recv.c
+++ b/net/rds/tcp_recv.c
@@ -214,8 +214,15 @@
}
to_copy = min(tc->t_tinc_data_rem, left);
- pskb_pull(clone, offset);
- pskb_trim(clone, to_copy);
+ if (!pskb_pull(clone, offset) ||
+ pskb_trim(clone, to_copy)) {
+ pr_warn("rds_tcp_data_recv: pull/trim failed "
+ "left %zu data_rem %zu skb_len %d\n",
+ left, tc->t_tinc_data_rem, skb->len);
+ kfree_skb(clone);
+ desc->error = -ENOMEM;
+ goto out;
+ }
skb_queue_tail(&tinc->ti_skb_list, clone);
rdsdebug("skb %p data %p len %d off %u to_copy %zu -> "
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 2d1be4a..32fcdec 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -31,13 +31,17 @@
#define MIRRED_TAB_MASK 7
static LIST_HEAD(mirred_list);
+static DEFINE_SPINLOCK(mirred_list_lock);
static void tcf_mirred_release(struct tc_action *a, int bind)
{
struct tcf_mirred *m = to_mirred(a);
struct net_device *dev = rcu_dereference_protected(m->tcfm_dev, 1);
+ /* We could be called either in a RCU callback or with RTNL lock held. */
+ spin_lock_bh(&mirred_list_lock);
list_del(&m->tcfm_list);
+ spin_unlock_bh(&mirred_list_lock);
if (dev)
dev_put(dev);
}
@@ -103,10 +107,10 @@
} else {
if (bind)
return 0;
- if (!ovr) {
- tcf_hash_release(a, bind);
+
+ tcf_hash_release(a, bind);
+ if (!ovr)
return -EEXIST;
- }
}
m = to_mirred(a);
@@ -123,7 +127,9 @@
}
if (ret == ACT_P_CREATED) {
+ spin_lock_bh(&mirred_list_lock);
list_add(&m->tcfm_list, &mirred_list);
+ spin_unlock_bh(&mirred_list_lock);
tcf_hash_insert(a);
}
@@ -173,6 +179,7 @@
skb2->skb_iif = skb->dev->ifindex;
skb2->dev = dev;
+ skb_sender_cpu_clear(skb2);
err = dev_queue_xmit(skb2);
if (err) {
@@ -221,7 +228,8 @@
struct tcf_mirred *m;
ASSERT_RTNL();
- if (event == NETDEV_UNREGISTER)
+ if (event == NETDEV_UNREGISTER) {
+ spin_lock_bh(&mirred_list_lock);
list_for_each_entry(m, &mirred_list, tcfm_list) {
if (rcu_access_pointer(m->tcfm_dev) == dev) {
dev_put(dev);
@@ -231,6 +239,8 @@
RCU_INIT_POINTER(m->tcfm_dev, NULL);
}
}
+ spin_unlock_bh(&mirred_list_lock);
+ }
return NOTIFY_DONE;
}
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index 9d15cb6..86b04e3 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -368,6 +368,15 @@
return bucket - q->buckets;
}
+static unsigned int hhf_qdisc_drop(struct Qdisc *sch)
+{
+ unsigned int prev_backlog;
+
+ prev_backlog = sch->qstats.backlog;
+ hhf_drop(sch);
+ return prev_backlog - sch->qstats.backlog;
+}
+
static int hhf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct hhf_sched_data *q = qdisc_priv(sch);
@@ -696,7 +705,7 @@
.enqueue = hhf_enqueue,
.dequeue = hhf_dequeue,
.peek = qdisc_peek_dequeued,
- .drop = hhf_drop,
+ .drop = hhf_qdisc_drop,
.init = hhf_init,
.reset = hhf_reset,
.destroy = hhf_destroy,
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 5f6ca47..f0c3ff6 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -533,7 +533,7 @@
rqstp->rq_arg.page_base = head->arg.page_base;
/* rq_respages starts after the last arg page */
- rqstp->rq_respages = &rqstp->rq_arg.pages[page_no];
+ rqstp->rq_respages = &rqstp->rq_pages[page_no];
rqstp->rq_next_page = rqstp->rq_respages + 1;
/* Rebuild rq_arg head and tail. */
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 8a477e2..5502d4d 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -543,11 +543,8 @@
}
if (memreg == RPCRDMA_FRMR) {
- /* Requires both frmr reg and local dma lkey */
- if (((devattr->device_cap_flags &
- (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) !=
- (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) ||
- (devattr->max_fast_reg_page_list_len == 0)) {
+ if (!(devattr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) ||
+ (devattr->max_fast_reg_page_list_len == 0)) {
dprintk("RPC: %s: FRMR registration "
"not supported by HCA\n", __func__);
memreg = RPCRDMA_MTHCAFMR;
@@ -557,6 +554,7 @@
if (!ia->ri_device->alloc_fmr) {
dprintk("RPC: %s: MTHCAFMR registration "
"not supported by HCA\n", __func__);
+ rc = -EINVAL;
goto out3;
}
}
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index fda38f8..77f5d17e 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -16,6 +16,7 @@
#include <linux/notifier.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
+#include <linux/if_vlan.h>
#include <net/ip_fib.h>
#include <net/switchdev.h>
@@ -634,6 +635,8 @@
if (nla_len(attr) != sizeof(struct bridge_vlan_info))
return -EINVAL;
vinfo = nla_data(attr);
+ if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
+ return -EINVAL;
vlan->flags = vinfo->flags;
if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
if (vlan->vid_begin)
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index e7000be..ed98c1f 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -94,10 +94,14 @@
goto out;
ret = register_pernet_subsys(&sysctl_pernet_ops);
if (ret)
- goto out;
+ goto out1;
register_sysctl_root(&net_sysctl_root);
out:
return ret;
+out1:
+ unregister_sysctl_table(net_header);
+ net_header = NULL;
+ goto out;
}
struct ctl_table_header *register_net_sysctl(struct net *net,
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 41042de..eadba62 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -42,7 +42,8 @@
#include "core.h"
#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
-#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
+#define BCLINK_WIN_DEFAULT 50 /* bcast link window size (default) */
+#define BCLINK_WIN_MIN 32 /* bcast minimum link window size */
const char tipc_bclink_name[] = "broadcast-link";
@@ -908,9 +909,10 @@
if (!bcl)
return -ENOPROTOOPT;
- if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN))
+ if (limit < BCLINK_WIN_MIN)
+ limit = BCLINK_WIN_MIN;
+ if (limit > TIPC_MAX_LINK_WIN)
return -EINVAL;
-
tipc_bclink_lock(net);
tipc_link_set_queue_limits(bcl, limit);
tipc_bclink_unlock(net);
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index c5ac436..5f73450 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -121,7 +121,7 @@
{
struct sk_buff *head = *headbuf;
struct sk_buff *frag = *buf;
- struct sk_buff *tail;
+ struct sk_buff *tail = NULL;
struct tipc_msg *msg;
u32 fragid;
int delta;
@@ -141,9 +141,15 @@
if (unlikely(skb_unclone(frag, GFP_ATOMIC)))
goto err;
head = *headbuf = frag;
- skb_frag_list_init(head);
- TIPC_SKB_CB(head)->tail = NULL;
*buf = NULL;
+ TIPC_SKB_CB(head)->tail = NULL;
+ if (skb_is_nonlinear(head)) {
+ skb_walk_frags(head, tail) {
+ TIPC_SKB_CB(head)->tail = tail;
+ }
+ } else {
+ skb_frag_list_init(head);
+ }
return 0;
}
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index a82c584..5351a3f 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -357,7 +357,7 @@
if (likely((usr <= TIPC_CRITICAL_IMPORTANCE) && !msg_errcode(m)))
return usr;
if ((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER))
- return msg_bits(m, 5, 13, 0x7);
+ return msg_bits(m, 9, 0, 0x7);
return TIPC_SYSTEM_IMPORTANCE;
}
@@ -366,7 +366,7 @@
int usr = msg_user(m);
if (likely((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER)))
- msg_set_bits(m, 5, 13, 0x7, i);
+ msg_set_bits(m, 9, 0, 0x7, i);
else if (i < TIPC_SYSTEM_IMPORTANCE)
msg_set_user(m, i);
else
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 703875f..2c32a83 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1116,7 +1116,7 @@
}
/* Ignore duplicate packets */
- if (less(oseqno, rcv_nxt))
+ if ((usr != LINK_PROTOCOL) && less(oseqno, rcv_nxt))
return true;
/* Initiate or update failover mode if applicable */
@@ -1146,8 +1146,8 @@
if (!pl || !tipc_link_is_up(pl))
return true;
- /* Initiate or update synch mode if applicable */
- if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG)) {
+ /* Initiate synch mode if applicable */
+ if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG) && (oseqno == 1)) {
syncpt = iseqno + exp_pkts - 1;
if (!tipc_link_is_up(l)) {
tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT);
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index c170d31..6e648d9 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -52,6 +52,8 @@
/* IANA assigned UDP port */
#define UDP_PORT_DEFAULT 6118
+#define UDP_MIN_HEADROOM 28
+
static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = {
[TIPC_NLA_UDP_UNSPEC] = {.type = NLA_UNSPEC},
[TIPC_NLA_UDP_LOCAL] = {.type = NLA_BINARY,
@@ -156,6 +158,9 @@
struct sk_buff *clone;
struct rtable *rt;
+ if (skb_headroom(skb) < UDP_MIN_HEADROOM)
+ pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC);
+
clone = skb_clone(skb, GFP_ATOMIC);
skb_set_inner_protocol(clone, htons(ETH_P_TIPC));
ub = rcu_dereference_rtnl(b->media_ptr);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index ef31b40..94f6582 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2064,6 +2064,11 @@
goto out;
}
+ if (flags & MSG_PEEK)
+ skip = sk_peek_offset(sk, flags);
+ else
+ skip = 0;
+
do {
int chunk;
struct sk_buff *skb, *last;
@@ -2112,7 +2117,6 @@
break;
}
- skip = sk_peek_offset(sk, flags);
while (skip >= unix_skb_len(skb)) {
skip -= unix_skb_len(skb);
last = skb;
@@ -2179,14 +2183,12 @@
if (UNIXCB(skb).fp)
scm.fp = scm_fp_dup(UNIXCB(skb).fp);
- if (skip) {
- sk_peek_offset_fwd(sk, chunk);
- skip -= chunk;
- }
+ sk_peek_offset_fwd(sk, chunk);
if (UNIXCB(skb).fp)
break;
+ skip = 0;
last = skb;
last_len = skb->len;
unix_state_lock(sk);
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index df5fc6b..00e8a34 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1948,13 +1948,13 @@
err = misc_register(&vsock_device);
if (err) {
pr_err("Failed to register misc device\n");
- return -ENOENT;
+ goto err_reset_transport;
}
err = proto_register(&vsock_proto, 1); /* we want our slab */
if (err) {
pr_err("Cannot register vsock protocol\n");
- goto err_misc_deregister;
+ goto err_deregister_misc;
}
err = sock_register(&vsock_family_ops);
@@ -1969,8 +1969,9 @@
err_unregister_proto:
proto_unregister(&vsock_proto);
-err_misc_deregister:
+err_deregister_misc:
misc_deregister(&vsock_device);
+err_reset_transport:
transport = NULL;
err_busy:
mutex_unlock(&vsock_register_mutex);
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index 1f63daf..7555cad 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -40,13 +40,11 @@
static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg);
static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg);
-static void vmci_transport_peer_attach_cb(u32 sub_id,
- const struct vmci_event_data *ed,
- void *client_data);
static void vmci_transport_peer_detach_cb(u32 sub_id,
const struct vmci_event_data *ed,
void *client_data);
static void vmci_transport_recv_pkt_work(struct work_struct *work);
+static void vmci_transport_cleanup(struct work_struct *work);
static int vmci_transport_recv_listen(struct sock *sk,
struct vmci_transport_packet *pkt);
static int vmci_transport_recv_connecting_server(
@@ -75,6 +73,10 @@
struct vmci_transport_packet pkt;
};
+static LIST_HEAD(vmci_transport_cleanup_list);
+static DEFINE_SPINLOCK(vmci_transport_cleanup_lock);
+static DECLARE_WORK(vmci_transport_cleanup_work, vmci_transport_cleanup);
+
static struct vmci_handle vmci_transport_stream_handle = { VMCI_INVALID_ID,
VMCI_INVALID_ID };
static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID;
@@ -791,44 +793,6 @@
return err;
}
-static void vmci_transport_peer_attach_cb(u32 sub_id,
- const struct vmci_event_data *e_data,
- void *client_data)
-{
- struct sock *sk = client_data;
- const struct vmci_event_payload_qp *e_payload;
- struct vsock_sock *vsk;
-
- e_payload = vmci_event_data_const_payload(e_data);
-
- vsk = vsock_sk(sk);
-
- /* We don't ask for delayed CBs when we subscribe to this event (we
- * pass 0 as flags to vmci_event_subscribe()). VMCI makes no
- * guarantees in that case about what context we might be running in,
- * so it could be BH or process, blockable or non-blockable. So we
- * need to account for all possible contexts here.
- */
- local_bh_disable();
- bh_lock_sock(sk);
-
- /* XXX This is lame, we should provide a way to lookup sockets by
- * qp_handle.
- */
- if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
- e_payload->handle)) {
- /* XXX This doesn't do anything, but in the future we may want
- * to set a flag here to verify the attach really did occur and
- * we weren't just sent a datagram claiming it was.
- */
- goto out;
- }
-
-out:
- bh_unlock_sock(sk);
- local_bh_enable();
-}
-
static void vmci_transport_handle_detach(struct sock *sk)
{
struct vsock_sock *vsk;
@@ -871,28 +835,38 @@
const struct vmci_event_data *e_data,
void *client_data)
{
- struct sock *sk = client_data;
+ struct vmci_transport *trans = client_data;
const struct vmci_event_payload_qp *e_payload;
- struct vsock_sock *vsk;
e_payload = vmci_event_data_const_payload(e_data);
- vsk = vsock_sk(sk);
- if (vmci_handle_is_invalid(e_payload->handle))
- return;
-
- /* Same rules for locking as for peer_attach_cb(). */
- local_bh_disable();
- bh_lock_sock(sk);
/* XXX This is lame, we should provide a way to lookup sockets by
* qp_handle.
*/
- if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
- e_payload->handle))
- vmci_transport_handle_detach(sk);
+ if (vmci_handle_is_invalid(e_payload->handle) ||
+ vmci_handle_is_equal(trans->qp_handle, e_payload->handle))
+ return;
- bh_unlock_sock(sk);
- local_bh_enable();
+ /* We don't ask for delayed CBs when we subscribe to this event (we
+ * pass 0 as flags to vmci_event_subscribe()). VMCI makes no
+ * guarantees in that case about what context we might be running in,
+ * so it could be BH or process, blockable or non-blockable. So we
+ * need to account for all possible contexts here.
+ */
+ spin_lock_bh(&trans->lock);
+ if (!trans->sk)
+ goto out;
+
+ /* Apart from here, trans->lock is only grabbed as part of sk destruct,
+ * where trans->sk isn't locked.
+ */
+ bh_lock_sock(trans->sk);
+
+ vmci_transport_handle_detach(trans->sk);
+
+ bh_unlock_sock(trans->sk);
+ out:
+ spin_unlock_bh(&trans->lock);
}
static void vmci_transport_qp_resumed_cb(u32 sub_id,
@@ -1181,7 +1155,7 @@
*/
err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH,
vmci_transport_peer_detach_cb,
- pending, &detach_sub_id);
+ vmci_trans(vpending), &detach_sub_id);
if (err < VMCI_SUCCESS) {
vmci_transport_send_reset(pending, pkt);
err = vmci_transport_error_to_vsock_error(err);
@@ -1321,7 +1295,6 @@
|| vmci_trans(vsk)->qpair
|| vmci_trans(vsk)->produce_size != 0
|| vmci_trans(vsk)->consume_size != 0
- || vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID
|| vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) {
skerr = EPROTO;
err = -EINVAL;
@@ -1389,7 +1362,6 @@
struct vsock_sock *vsk;
struct vmci_handle handle;
struct vmci_qp *qpair;
- u32 attach_sub_id;
u32 detach_sub_id;
bool is_local;
u32 flags;
@@ -1399,7 +1371,6 @@
vsk = vsock_sk(sk);
handle = VMCI_INVALID_HANDLE;
- attach_sub_id = VMCI_INVALID_ID;
detach_sub_id = VMCI_INVALID_ID;
/* If we have gotten here then we should be past the point where old
@@ -1444,23 +1415,15 @@
goto destroy;
}
- /* Subscribe to attach and detach events first.
+ /* Subscribe to detach events first.
*
* XXX We attach once for each queue pair created for now so it is easy
* to find the socket (it's provided), but later we should only
* subscribe once and add a way to lookup sockets by queue pair handle.
*/
- err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_ATTACH,
- vmci_transport_peer_attach_cb,
- sk, &attach_sub_id);
- if (err < VMCI_SUCCESS) {
- err = vmci_transport_error_to_vsock_error(err);
- goto destroy;
- }
-
err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH,
vmci_transport_peer_detach_cb,
- sk, &detach_sub_id);
+ vmci_trans(vsk), &detach_sub_id);
if (err < VMCI_SUCCESS) {
err = vmci_transport_error_to_vsock_error(err);
goto destroy;
@@ -1496,7 +1459,6 @@
vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size =
pkt->u.size;
- vmci_trans(vsk)->attach_sub_id = attach_sub_id;
vmci_trans(vsk)->detach_sub_id = detach_sub_id;
vmci_trans(vsk)->notify_ops->process_negotiate(sk);
@@ -1504,9 +1466,6 @@
return 0;
destroy:
- if (attach_sub_id != VMCI_INVALID_ID)
- vmci_event_unsubscribe(attach_sub_id);
-
if (detach_sub_id != VMCI_INVALID_ID)
vmci_event_unsubscribe(detach_sub_id);
@@ -1607,9 +1566,11 @@
vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE;
vmci_trans(vsk)->qpair = NULL;
vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size = 0;
- vmci_trans(vsk)->attach_sub_id = vmci_trans(vsk)->detach_sub_id =
- VMCI_INVALID_ID;
+ vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID;
vmci_trans(vsk)->notify_ops = NULL;
+ INIT_LIST_HEAD(&vmci_trans(vsk)->elem);
+ vmci_trans(vsk)->sk = &vsk->sk;
+ spin_lock_init(&vmci_trans(vsk)->lock);
if (psk) {
vmci_trans(vsk)->queue_pair_size =
vmci_trans(psk)->queue_pair_size;
@@ -1629,29 +1590,57 @@
return 0;
}
+static void vmci_transport_free_resources(struct list_head *transport_list)
+{
+ while (!list_empty(transport_list)) {
+ struct vmci_transport *transport =
+ list_first_entry(transport_list, struct vmci_transport,
+ elem);
+ list_del(&transport->elem);
+
+ if (transport->detach_sub_id != VMCI_INVALID_ID) {
+ vmci_event_unsubscribe(transport->detach_sub_id);
+ transport->detach_sub_id = VMCI_INVALID_ID;
+ }
+
+ if (!vmci_handle_is_invalid(transport->qp_handle)) {
+ vmci_qpair_detach(&transport->qpair);
+ transport->qp_handle = VMCI_INVALID_HANDLE;
+ transport->produce_size = 0;
+ transport->consume_size = 0;
+ }
+
+ kfree(transport);
+ }
+}
+
+static void vmci_transport_cleanup(struct work_struct *work)
+{
+ LIST_HEAD(pending);
+
+ spin_lock_bh(&vmci_transport_cleanup_lock);
+ list_replace_init(&vmci_transport_cleanup_list, &pending);
+ spin_unlock_bh(&vmci_transport_cleanup_lock);
+ vmci_transport_free_resources(&pending);
+}
+
static void vmci_transport_destruct(struct vsock_sock *vsk)
{
- if (vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID) {
- vmci_event_unsubscribe(vmci_trans(vsk)->attach_sub_id);
- vmci_trans(vsk)->attach_sub_id = VMCI_INVALID_ID;
- }
-
- if (vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) {
- vmci_event_unsubscribe(vmci_trans(vsk)->detach_sub_id);
- vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID;
- }
-
- if (!vmci_handle_is_invalid(vmci_trans(vsk)->qp_handle)) {
- vmci_qpair_detach(&vmci_trans(vsk)->qpair);
- vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE;
- vmci_trans(vsk)->produce_size = 0;
- vmci_trans(vsk)->consume_size = 0;
- }
+ /* Ensure that the detach callback doesn't use the sk/vsk
+ * we are about to destruct.
+ */
+ spin_lock_bh(&vmci_trans(vsk)->lock);
+ vmci_trans(vsk)->sk = NULL;
+ spin_unlock_bh(&vmci_trans(vsk)->lock);
if (vmci_trans(vsk)->notify_ops)
vmci_trans(vsk)->notify_ops->socket_destruct(vsk);
- kfree(vsk->trans);
+ spin_lock_bh(&vmci_transport_cleanup_lock);
+ list_add(&vmci_trans(vsk)->elem, &vmci_transport_cleanup_list);
+ spin_unlock_bh(&vmci_transport_cleanup_lock);
+ schedule_work(&vmci_transport_cleanup_work);
+
vsk->trans = NULL;
}
@@ -2146,6 +2135,9 @@
static void __exit vmci_transport_exit(void)
{
+ cancel_work_sync(&vmci_transport_cleanup_work);
+ vmci_transport_free_resources(&vmci_transport_cleanup_list);
+
if (!vmci_handle_is_invalid(vmci_transport_stream_handle)) {
if (vmci_datagram_destroy_handle(
vmci_transport_stream_handle) != VMCI_SUCCESS)
@@ -2164,6 +2156,7 @@
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMCI transport for Virtual Sockets");
+MODULE_VERSION("1.0.2.0-k");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("vmware_vsock");
MODULE_ALIAS_NETPROTO(PF_VSOCK);
diff --git a/net/vmw_vsock/vmci_transport.h b/net/vmw_vsock/vmci_transport.h
index ce6c962..2ad46f3 100644
--- a/net/vmw_vsock/vmci_transport.h
+++ b/net/vmw_vsock/vmci_transport.h
@@ -119,10 +119,12 @@
u64 queue_pair_size;
u64 queue_pair_min_size;
u64 queue_pair_max_size;
- u32 attach_sub_id;
u32 detach_sub_id;
union vmci_transport_notify notify;
struct vmci_transport_notify_ops *notify_ops;
+ struct list_head elem;
+ struct sock *sk;
+ spinlock_t lock; /* protects sk. */
};
int vmci_transport_register(void);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index a8de9e3..24e06a2 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1928,8 +1928,10 @@
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
+ struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
+ struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
- if (!lt && !rp && !re)
+ if (!lt && !rp && !re && !et && !rt)
return err;
/* pedantic mode - thou shalt sayeth replaceth */
diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h
index 3a44d3a..af44e56 100644
--- a/samples/bpf/bpf_helpers.h
+++ b/samples/bpf/bpf_helpers.h
@@ -86,5 +86,17 @@
#define PT_REGS_RC(x) ((x)->gprs[2])
#define PT_REGS_SP(x) ((x)->gprs[15])
+#elif defined(__aarch64__)
+
+#define PT_REGS_PARM1(x) ((x)->regs[0])
+#define PT_REGS_PARM2(x) ((x)->regs[1])
+#define PT_REGS_PARM3(x) ((x)->regs[2])
+#define PT_REGS_PARM4(x) ((x)->regs[3])
+#define PT_REGS_PARM5(x) ((x)->regs[4])
+#define PT_REGS_RET(x) ((x)->regs[30])
+#define PT_REGS_FP(x) ((x)->regs[29]) /* Works only with CONFIG_FRAME_POINTER */
+#define PT_REGS_RC(x) ((x)->regs[0])
+#define PT_REGS_SP(x) ((x)->sp)
+
#endif
#endif
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 0cd46e1..b967e4f 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -115,7 +115,7 @@
BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)"
# Setup the directory structure
-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir"
+rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
mkdir -m 755 -p "$tmpdir/DEBIAN"
mkdir -p "$tmpdir/lib" "$tmpdir/boot"
mkdir -p "$fwdir/lib/firmware/$version/"
@@ -408,7 +408,7 @@
\$(MAKE) KDEB_SOURCENAME=${sourcename} KDEB_PKGVERSION=${packageversion} bindeb-pkg
clean:
- rm -rf debian/*tmp
+ rm -rf debian/*tmp debian/files
mv debian/ debian.backup # debian/ might be cleaned away
\$(MAKE) clean
mv debian.backup debian
diff --git a/security/keys/gc.c b/security/keys/gc.c
index 39eac1f..addf060 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -134,8 +134,10 @@
kdebug("- %u", key->serial);
key_check(key);
- /* Throw away the key data */
- if (key->type->destroy)
+ /* Throw away the key data if the key is instantiated */
+ if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
+ !test_bit(KEY_FLAG_NEGATIVE, &key->flags) &&
+ key->type->destroy)
key->type->destroy(key);
security_key_free(key);
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 486ef6f..0d62531 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -440,6 +440,9 @@
kenter("");
+ if (ctx->index_key.type == &key_type_keyring)
+ return ERR_PTR(-EPERM);
+
user = key_user_lookup(current_fsuid());
if (!user)
return ERR_PTR(-ENOMEM);
diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c
index 4449d1a9..2433f7c 100644
--- a/sound/hda/ext/hdac_ext_bus.c
+++ b/sound/hda/ext/hdac_ext_bus.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/io.h>
#include <sound/hdaudio_ext.h>
MODULE_DESCRIPTION("HDA extended core");
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 37f43a1..a249d54 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -3367,10 +3367,8 @@
int dev, err;
err = snd_hda_codec_parse_pcms(codec);
- if (err < 0) {
- snd_hda_codec_reset(codec);
+ if (err < 0)
return err;
- }
/* attach a new PCM streams */
list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index ca03c40..2f0ec7c 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -819,6 +819,7 @@
SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD),
+ SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
index 3c2f0f8..f823eb5 100644
--- a/sound/soc/codecs/rt298.c
+++ b/sound/soc/codecs/rt298.c
@@ -50,24 +50,24 @@
};
static struct reg_default rt298_index_def[] = {
- { 0x01, 0xaaaa },
- { 0x02, 0x8aaa },
+ { 0x01, 0xa5a8 },
+ { 0x02, 0x8e95 },
{ 0x03, 0x0002 },
- { 0x04, 0xaf01 },
- { 0x08, 0x000d },
- { 0x09, 0xd810 },
- { 0x0a, 0x0120 },
+ { 0x04, 0xaf67 },
+ { 0x08, 0x200f },
+ { 0x09, 0xd010 },
+ { 0x0a, 0x0100 },
{ 0x0b, 0x0000 },
{ 0x0d, 0x2800 },
- { 0x0f, 0x0000 },
- { 0x19, 0x0a17 },
+ { 0x0f, 0x0022 },
+ { 0x19, 0x0217 },
{ 0x20, 0x0020 },
{ 0x33, 0x0208 },
{ 0x46, 0x0300 },
- { 0x49, 0x0004 },
- { 0x4f, 0x50e9 },
- { 0x50, 0x2000 },
- { 0x63, 0x2902 },
+ { 0x49, 0x4004 },
+ { 0x4f, 0x50c9 },
+ { 0x50, 0x3000 },
+ { 0x63, 0x1b02 },
{ 0x67, 0x1111 },
{ 0x68, 0x1016 },
{ 0x69, 0x273f },
@@ -1214,7 +1214,7 @@
mdelay(10);
if (!rt298->pdata.gpio2_en)
- regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x4000);
+ regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x40);
else
regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0);
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 2fbc6ef..39ebd7b 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3808,6 +3808,8 @@
wm8962_reset(wm8962);
+ regcache_mark_dirty(wm8962->regmap);
+
/* SYSCLK defaults to on; make sure it is off so we can safely
* write to registers if the device is declocked.
*/
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 100d92b..05977ae 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -207,6 +207,34 @@
EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
/**
+ * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a single mixer control, or a double
+ * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
+ * have a range that represents both positive and negative values either side
+ * of zero but without a sign bit.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+
+ snd_soc_info_volsw(kcontrol, uinfo);
+ /* Max represents the number of levels in an SX control not the
+ * maximum value, so add the minimum value back on
+ */
+ uinfo->value.integer.max += mc->min;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
+
+/**
* snd_soc_get_volsw - single mixer get callback
* @kcontrol: mixer control
* @ucontrol: control element information
diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
index d1b6475..6cae061 100644
--- a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
+++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
@@ -25,10 +25,19 @@
#define FIXUP_SECTION ".ex_fixup"
+static inline unsigned long __fls(unsigned long x);
+
#include "word-at-a-time.h"
#include "utils.h"
+static inline unsigned long __fls(unsigned long x)
+{
+ int lz;
+
+ asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x));
+ return sizeof(unsigned long) - 1 - lz;
+}
static int page_size;
static char *mem_region;
diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index 421c607..d075ea0 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -230,5 +230,9 @@
}
clearhandler(SIGSEGV);
+ /* Make sure nothing explodes if we fork. */
+ if (fork() > 0)
+ return 0;
+
return (nerrs == 0 ? 0 : 1);
}
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 48c6e1a..b9d3a32 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -137,6 +137,8 @@
void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
{
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ bool phys_active;
+ int ret;
/*
* We're about to run this vcpu again, so there is no need to
@@ -151,6 +153,23 @@
*/
if (kvm_timer_should_fire(vcpu))
kvm_timer_inject_irq(vcpu);
+
+ /*
+ * We keep track of whether the edge-triggered interrupt has been
+ * signalled to the vgic/guest, and if so, we mask the interrupt and
+ * the physical distributor to prevent the timer from raising a
+ * physical interrupt whenever we run a guest, preventing forward
+ * VCPU progress.
+ */
+ if (kvm_vgic_get_phys_irq_active(timer->map))
+ phys_active = true;
+ else
+ phys_active = false;
+
+ ret = irq_set_irqchip_state(timer->map->irq,
+ IRQCHIP_STATE_ACTIVE,
+ phys_active);
+ WARN_ON(ret);
}
/**
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 6bd1c9b..66c6616 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -531,6 +531,34 @@
return false;
}
+/*
+ * If a mapped interrupt's state has been modified by the guest such that it
+ * is no longer active or pending, without it have gone through the sync path,
+ * then the map->active field must be cleared so the interrupt can be taken
+ * again.
+ */
+static void vgic_handle_clear_mapped_irq(struct kvm_vcpu *vcpu)
+{
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+ struct list_head *root;
+ struct irq_phys_map_entry *entry;
+ struct irq_phys_map *map;
+
+ rcu_read_lock();
+
+ /* Check for PPIs */
+ root = &vgic_cpu->irq_phys_map_list;
+ list_for_each_entry_rcu(entry, root, entry) {
+ map = &entry->map;
+
+ if (!vgic_dist_irq_is_pending(vcpu, map->virt_irq) &&
+ !vgic_irq_is_active(vcpu, map->virt_irq))
+ map->active = false;
+ }
+
+ rcu_read_unlock();
+}
+
bool vgic_handle_clear_pending_reg(struct kvm *kvm,
struct kvm_exit_mmio *mmio,
phys_addr_t offset, int vcpu_id)
@@ -561,6 +589,7 @@
vcpu_id, offset);
vgic_reg_access(mmio, reg, offset, mode);
+ vgic_handle_clear_mapped_irq(kvm_get_vcpu(kvm, vcpu_id));
vgic_update_state(kvm);
return true;
}
@@ -598,6 +627,7 @@
ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
if (mmio->is_write) {
+ vgic_handle_clear_mapped_irq(kvm_get_vcpu(kvm, vcpu_id));
vgic_update_state(kvm);
return true;
}
@@ -982,6 +1012,12 @@
pend_percpu = vcpu->arch.vgic_cpu.pending_percpu;
pend_shared = vcpu->arch.vgic_cpu.pending_shared;
+ if (!dist->enabled) {
+ bitmap_zero(pend_percpu, VGIC_NR_PRIVATE_IRQS);
+ bitmap_zero(pend_shared, nr_shared);
+ return 0;
+ }
+
pending = vgic_bitmap_get_cpu_map(&dist->irq_pending, vcpu_id);
enabled = vgic_bitmap_get_cpu_map(&dist->irq_enabled, vcpu_id);
bitmap_and(pend_percpu, pending, enabled, VGIC_NR_PRIVATE_IRQS);
@@ -1009,11 +1045,6 @@
struct kvm_vcpu *vcpu;
int c;
- if (!dist->enabled) {
- set_bit(0, dist->irq_pending_on_cpu);
- return;
- }
-
kvm_for_each_vcpu(c, vcpu, kvm) {
if (compute_pending_for_cpu(vcpu))
set_bit(c, dist->irq_pending_on_cpu);
@@ -1092,6 +1123,15 @@
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_lr vlr = vgic_get_lr(vcpu, lr_nr);
+ /*
+ * We must transfer the pending state back to the distributor before
+ * retiring the LR, otherwise we may loose edge-triggered interrupts.
+ */
+ if (vlr.state & LR_STATE_PENDING) {
+ vgic_dist_irq_set_pending(vcpu, irq);
+ vlr.hwirq = 0;
+ }
+
vlr.state = 0;
vgic_set_lr(vcpu, lr_nr, vlr);
clear_bit(lr_nr, vgic_cpu->lr_used);
@@ -1132,7 +1172,8 @@
kvm_debug("Set active, clear distributor: 0x%x\n", vlr.state);
vgic_irq_clear_active(vcpu, irq);
vgic_update_state(vcpu->kvm);
- } else if (vgic_dist_irq_is_pending(vcpu, irq)) {
+ } else {
+ WARN_ON(!vgic_dist_irq_is_pending(vcpu, irq));
vlr.state |= LR_STATE_PENDING;
kvm_debug("Set pending: 0x%x\n", vlr.state);
}
@@ -1240,7 +1281,7 @@
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
unsigned long *pa_percpu, *pa_shared;
- int i, vcpu_id, lr, ret;
+ int i, vcpu_id;
int overflow = 0;
int nr_shared = vgic_nr_shared_irqs(dist);
@@ -1295,31 +1336,6 @@
*/
clear_bit(vcpu_id, dist->irq_pending_on_cpu);
}
-
- for (lr = 0; lr < vgic->nr_lr; lr++) {
- struct vgic_lr vlr;
-
- if (!test_bit(lr, vgic_cpu->lr_used))
- continue;
-
- vlr = vgic_get_lr(vcpu, lr);
-
- /*
- * If we have a mapping, and the virtual interrupt is
- * presented to the guest (as pending or active), then we must
- * set the state to active in the physical world. See
- * Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt.
- */
- if (vlr.state & LR_HW) {
- struct irq_phys_map *map;
- map = vgic_irq_map_search(vcpu, vlr.irq);
-
- ret = irq_set_irqchip_state(map->irq,
- IRQCHIP_STATE_ACTIVE,
- true);
- WARN_ON(ret);
- }
- }
}
static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
@@ -1421,7 +1437,7 @@
return 0;
map = vgic_irq_map_search(vcpu, vlr.irq);
- BUG_ON(!map || !map->active);
+ BUG_ON(!map);
ret = irq_get_irqchip_state(map->irq,
IRQCHIP_STATE_ACTIVE,
@@ -1429,13 +1445,8 @@
WARN_ON(ret);
- if (map->active) {
- ret = irq_set_irqchip_state(map->irq,
- IRQCHIP_STATE_ACTIVE,
- false);
- WARN_ON(ret);
+ if (map->active)
return 0;
- }
return 1;
}
@@ -1607,8 +1618,12 @@
} else {
if (level_triggered) {
vgic_dist_irq_clear_level(vcpu, irq_num);
- if (!vgic_dist_irq_soft_pend(vcpu, irq_num))
+ if (!vgic_dist_irq_soft_pend(vcpu, irq_num)) {
vgic_dist_irq_clear_pending(vcpu, irq_num);
+ vgic_cpu_irq_clear(vcpu, irq_num);
+ if (!compute_pending_for_cpu(vcpu))
+ clear_bit(cpuid, dist->irq_pending_on_cpu);
+ }
}
ret = false;